Author p-ganssle
Recipients Delgan, nixphix, p-ganssle, serhiy.storchaka
Date 2018-12-04.17:13:33
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1543943613.6.0.788709270274.issue35364@psf.upfronthosting.co.za>
In-reply-to
Content
> This is not easy problem, ant it doesn't have right solution. Different decisions were made for the result type of alternate constructors and operators for different classes.

It's certainly true that it occasionally makes sense to do something like this, but this one is particularly egregious. Because of an implementation detail of `fromtimestamp` (and `now`, and a few others), which is actually relying on an implementation detail of `fromutc`, which is actually relying on what *may* have been a choice in the `__add__` method of timedelta, you get a *different class* in the alternate constructor of a subclass depending on the *argument* to the alternate constructor. This is pretty solidly a bug.

I think the things we need to take into account are:

1. What do we consider the contract of the relevant functions involved
2. What do people expect the code to do?
3. Is it likely that anyone is *relying* on the existing behavior.


The most fundamental problem, timedelta addition, is also the closest call, so I think we should *start* with the analysis there.

For #1, the contract is either "x + timedelta returns a datetime if x is a datetime subclass" or "x + timedelta returns a datetime or datetime subclass" - both of these are consistent with the current behavior, and as long as "datetime subclass isa datetime", I don't see that there would be anything fundamentally backwards-incompatible about changing what is actually returned.

For #2, I think people almost universally consider it a bug or at the very least counter-intuitive that `DatetimeSubclass + timedelta` returns a datetime and not a DatetimeSubclass. There are many instances of people who create datetime subclasses like arrow and pendulum (for just two OSS examples) - all of them end up with fairly complicated implementations where they have to work around all the places where the underlying implementation has hard-coded datetime. Some of these have been fixed already, but it's a notorious game of whack-a-mole. I've never heard of a situation where someone *wants* the other behavior.

For #3, it is feasible that there are people who are accidentally relying on this behavior, but it would only be in pretty unpythonic code (like assert type(dt) == datetime), or when using broken datetime subclasses. The only situation where I can think of where this behavior might be desirable is if you have a thin datetime wrapper that only needs to be the wrapper class at the point of input, and afterwards you don't care what class it is (and as such you'd want it to be datetime, so as to take advantage of the fast paths in C code). That is far from the common case, and it's a "nice to have" - if it doesn't happen you'll get slower code, not broken code, and you can fix it the same way everyone else fixes their broken subclasses by overriding __add__ and __radd__.

I think there is a pretty compelling case for switching timedelta + datetimesubclass over to returning `datetimesubclass`.
History
Date User Action Args
2018-12-04 17:13:33p-gansslesetrecipients: + p-ganssle, serhiy.storchaka, Delgan, nixphix
2018-12-04 17:13:33p-gansslesetmessageid: <1543943613.6.0.788709270274.issue35364@psf.upfronthosting.co.za>
2018-12-04 17:13:33p-gansslelinkissue35364 messages
2018-12-04 17:13:33p-gansslecreate