OK, I approved the PR. Can some other core dev ensure that it gets merged? No backports though!
On Mon, Feb 4, 2019 at 8:46 AM Paul Ganssle <p...@ganssle.io> wrote: > There's already a PR, actually, #10902: > https://github.com/python/cpython/pull/10902 > > Victor reviewed and approved it, I think before I started this thread, so > now it's just waiting on merge. > On 2/4/19 11:38 AM, Guido van Rossum wrote: > > I recommend that you submit a PR so we can get it into 3.8 alpha 2. > > On Mon, Feb 4, 2019 at 5:50 AM Paul Ganssle <p...@ganssle.io> wrote: > >> Hey all, >> >> This thread about the return type of datetime operations seems to have >> stopped without any explicit decision - I think I responded to everyone who >> had objections, but I think only Guido has given a +1 to whether or not we >> should go ahead. >> >> Have we got agreement to go ahead with this change? Are we still >> targeting Python 3.8 here? >> >> For those who don't want to dig through your old e-mails, here's the >> archive link for this thread: >> https://mail.python.org/pipermail/python-dev/2019-January/155984.html >> >> If you want to start commenting on the actual implementation, it's >> available here (though it's pretty simple): >> https://github.com/python/cpython/pull/10902 >> >> Best, >> >> Paul >> >> >> On 1/6/19 7:17 PM, Guido van Rossum wrote: >> >> OK, I concede your point (and indeed I only tested this on 3.6). If we >> could break the backward compatibility for now() we presumably can break it >> for this purpose. >> >> On Sun, Jan 6, 2019 at 11:02 AM Paul Ganssle <p...@ganssle.io> wrote: >> >>> I did address this in the original post - the assumption that the >>> subclass constructor will have the same arguments as the base constructor >>> is baked into many alternate constructors of datetime. I acknowledge that >>> this is a breaking change, but it is a small one - anyone creating such a >>> subclass that *cannot* handled the class being created this way would >>> be broken in myriad ways. >>> >>> We have also in recent years changed several alternate constructors >>> (including `replace`) to retain the original subclass, which by your same >>> standard would be a breaking change. I believe there have been no >>> complaints. In fact, between Python 3.6 and 3.7, the very example you >>> showed broke: >>> >>> Python 3.6.6: >>> >>> >>> class D(datetime.datetime): >>> ... def __new__(cls): >>> ... return cls.now() >>> ... >>> >>> D() >>> D(2019, 1, 6, 13, 49, 38, 842033) >>> >>> Python 3.7.2: >>> >>> >>> class D(datetime.datetime): >>> ... def __new__(cls): >>> ... return cls.now() >>> ... >>> >>> D() >>> Traceback (most recent call last): >>> File "<stdin>", line 1, in <module> >>> File "<stdin>", line 3, in __new__ >>> TypeError: __new__() takes 1 positional argument but 9 were given >>> >>> >>> We haven't seen any bug reports about this sort of thing; what we *have* >>> been getting is bug reports that subclassing datetime doesn't retain the >>> subclass in various ways (because people *are* using datetime >>> subclasses). This is likely to cause very little in the way of problems, >>> but it will improve convenience for people making datetime subclasses and >>> almost certainly performance for people using them (e.g. pendulum and >>> arrow, which now need to take a slow pure python route in many situations >>> to work around this problem). >>> >>> If we're *really* concerned with this backward compatibility breaking, >>> we could do the equivalent of: >>> >>> try: >>> return new_behavior(...) >>> except TypeError: >>> warnings.warn("The semantics of timedelta addition have " >>> "changed in a way that raises an error in " >>> "this subclass. Please implement __add__ " >>> "if you need the old behavior.", DeprecationWarning) >>> >>> Then after a suitable notice period drop the warning and turn it to a >>> hard error. >>> >>> Best, >>> >>> Paul >>> On 1/6/19 1:43 PM, Guido van Rossum wrote: >>> >>> I don't think datetime and builtins like int necessarily need to be >>> aligned. But I do see a problem -- the __new__ and __init__ methods defined >>> in the subclass (if any) should allow for being called with the same >>> signature as the base datetime class. Currently you can have a subclass of >>> datetime whose __new__ has no arguments (or, more realistically, interprets >>> its arguments differently). Instances of such a class can still be added to >>> a timedelta. The proposal would cause this to break (since such an addition >>> has to create a new instance, which calls __new__ and __init__). Since this >>> is a backwards incompatibility, I don't see how it can be done -- and I >>> also don't see many use cases, so I think it's not worth pursuing further. >>> >>> Note that the same problem already happens with the .fromordinal() class >>> method, though it doesn't happen with .fromdatetime() or .now(): >>> >>> >>> class D(datetime.datetime): >>> ... def __new__(cls): return cls.now() >>> ... >>> >>> D() >>> D(2019, 1, 6, 10, 33, 37, 161606) >>> >>> D.fromordinal(100) >>> Traceback (most recent call last): >>> File "<stdin>", line 1, in <module> >>> TypeError: __new__() takes 1 positional argument but 4 were given >>> >>> D.fromtimestamp(123456789) >>> D(1973, 11, 29, 13, 33, 9) >>> >>> >>> >>> On Sun, Jan 6, 2019 at 9:05 AM Paul Ganssle <p...@ganssle.io> wrote: >>> >>>> I can think of many reasons why datetime is different from builtins, >>>> though to be honest I'm not sure that consistency for its own sake is >>>> really a strong argument for keeping a counter-intuitive behavior - and to >>>> be honest I'm open to the idea that *all* arithmetic types *should* >>>> have some form of this change. >>>> >>>> That said, I would say that the biggest difference between datetime and >>>> builtins (other than the fact that datetime is *not* a builtin, and as >>>> such doesn't necessarily need to be categorized in this group), is that >>>> unlike almost all other arithmetic types, *datetime* has a special, >>>> dedicated type for describing differences in datetimes. Using your example >>>> of a float subclass, consider that without the behavior of "addition of >>>> floats returns floats", it would be hard to predict what would happen in >>>> this situation: >>>> >>>> >>> F(1.2) + 3.4 >>>> >>>> Would that always return a float, even though F(1.2) + F(3.4) returns >>>> an F? Would that return an F because F is the left-hand operand? Would it >>>> return a float because float is the right-hand operand? Would you walk the >>>> MROs and find the lowest type in common between the operands and return >>>> that? It's not entirely clear which subtype predominates. With datetime, >>>> you have: >>>> >>>> datetime - datetime -> timedelta >>>> datetime ± timedelta -> datetime >>>> timedelta ± timedelta -> timedelta >>>> >>>> There's no operation between two datetime objects that would return a >>>> datetime object, so it's always clear: operations between datetime >>>> subclasses return timedelta, operations between a datetime object and a >>>> timedelta return the subclass of the datetime that it was added to or >>>> subtracted from. >>>> >>>> Of course, the real way to resolve whether datetime should be different >>>> from int/float/string/etc is to look at why this choice was actually made >>>> for those types in the first place, and decide whether datetime is like >>>> them *in this respect*. The heterogeneous operations problem may be a >>>> reasonable justification for leaving the other builtins alone but changing >>>> datetime, but if someone knows of other fundamental reasons why the >>>> decision to have arithmetic operations always create the base class was >>>> chosen, please let me know. >>>> >>>> Best, >>>> Paul >>>> On 1/5/19 3:55 AM, Alexander Belopolsky wrote: >>>> >>>> >>>> >>>> On Wed, Jan 2, 2019 at 10:18 PM Paul Ganssle <p...@ganssle.io> wrote: >>>> >>>>> .. the original objection was that this implementation assumes that >>>>> the datetime subclass has a constructor with the same (or a sufficiently >>>>> similar) signature as datetime. >>>>> >>>> While this was used as a possible rationale for the way standard types >>>> behave, the main objection to changing datetime classes is that it will >>>> make them behave differently from builtins. For example: >>>> >>>> >>> class F(float): >>>> ... pass >>>> ... >>>> >>> type(F.fromhex('AA')) >>>> <class '__main__.F'> >>>> >>> type(F(1) + F(2)) >>>> <class 'float'> >>>> >>>> This may be a legitimate gripe, but unfortunately that ship has sailed >>>>> long ago. All of datetime's alternate constructors make this assumption. >>>>> Any subclass that does not meet this requirement must have worked around >>>>> it >>>>> long ago (or they don't care about alternate constructors). >>>>> >>>> >>>> This is right, but the same argument is equally applicable to int, >>>> float, etc. subclasses. If you want to limit your change to datetime types >>>> you should explain what makes these types special. >>>> >>>> _______________________________________________ >>>> Python-Dev mailing list >>>> Python-Dev@python.org >>>> https://mail.python.org/mailman/listinfo/python-dev >>>> Unsubscribe: >>>> https://mail.python.org/mailman/options/python-dev/guido%40python.org >>>> >>> >>> >>> -- >>> --Guido van Rossum (python.org/~guido) >>> >>> _______________________________________________ >>> Python-Dev mailing list >>> Python-Dev@python.org >>> https://mail.python.org/mailman/listinfo/python-dev >>> Unsubscribe: >>> https://mail.python.org/mailman/options/python-dev/guido%40python.org >>> >> >> >> -- >> --Guido van Rossum (python.org/~guido) >> >> _______________________________________________ >> Python-Dev mailing list >> Python-Dev@python.org >> https://mail.python.org/mailman/listinfo/python-dev >> Unsubscribe: >> https://mail.python.org/mailman/options/python-dev/guido%40python.org >> > > > -- > --Guido van Rossum (python.org/~guido) > > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/guido%40python.org > -- --Guido van Rossum (python.org/~guido)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com