Re: [Datetime-SIG] Another round on error-checking
[Tim]
PEP 495 specifies resolving such cases by magic, in essentially arbitrary (from the user's point of view) ways. This isn't for backward compatibility, because 495-compliant tzinfos don't currently exist
[Alex]
.. but tzinfo.fromutc() [1] does exist
I know - I wrote it ;-)
and the first thing happening in that code is an unguarded call to utcoffset() on a UTC datetime with a transplanted tzinfo. [2] A trick like this have been valid in datetime since its introduction and has been used in numerous places since.
But "continuing to never raise an exception" does not imply "continuing to work as intended". All such code needs to be carefully audited in a PEP-495 world to ensure that the problem-case return values work as intended with the old code and the new PEP 495 behavior _if_ a 495-compliant tzinfo object is used.
You know that with a little effort universal .fromutc() can be rewritten to be PEP 495 compliant.
If you think allowing datetime.utcoffset() to raise an exception is an option, let's first see how one can rewrite universal tzinfo.fromutc() for that design. Even though I don't think reusing a universal .fromutc() is a good option for tzinfo implementers, it gives an example of simple but non-trivial datetime manipulation code which PEP 495 is designed not to break.
Eh,. _If_ .utcoffet() could raise exceptions, then the obvious way would be to catch the exceptions and, in each exceptional case, implement whichever behavior is most appropriate in context. That could be used to implement any desired behavior whatsoever.
[1]: https://hg.python.org/cpython/file/v3.5.0rc2/Lib/datetime.py#l957 [2]: https://hg.python.org/cpython/file/v3.5.0rc2/Lib/datetime.py#l965
BTW, it just occurred to me that PEP 495 has already broken datetime.__hash__. That is, the fundamental invariant a hash implementation must satisfy is: A == B implies hash(A) == hash(B) But, under 495, equality of datetimes ignores `fold`, but .utcoffset() does not, and def __hash__(self): tzoff = self.utcoffset() if tzoff is None: ... else: ... self._hashcode = hash(timedelta(days, seconds, self.microsecond) - tzoff) So two datetimes in a fold, one with fold=0 and the other with fold=1, will compare equal but almost certainly have different hashes. That's a real puzzle. But the kind of error-checking I'm discussing doesn't make that _worse_ ;-) WRT the current __hash__ problem, perhaps it's enough for the PEP to note that ... in some number of cases including hash(), `fold` does a make difference ;-)
participants (1)
-
Tim Peters