<div dir="ltr">I recommend that you submit a PR so we can get it into 3.8 alpha 2.<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Feb 4, 2019 at 5:50 AM Paul Ganssle <<a href="mailto:paul@ganssle.io">paul@ganssle.io</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div bgcolor="#FFFFFF">
<p>Hey all,</p>
<p>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.</p>
<p>Have we got agreement to go ahead with this change? Are we still
targeting Python 3.8 here?</p>
<p>For those who don't want to dig through your old e-mails, here's
the archive link for this thread:
<a class="gmail-m_8165555785083225151moz-txt-link-freetext" href="https://mail.python.org/pipermail/python-dev/2019-January/155984.html" target="_blank">https://mail.python.org/pipermail/python-dev/2019-January/155984.html</a><br>
<br>
If you want to start commenting on the actual implementation, it's
available here (though it's pretty simple):
<a class="gmail-m_8165555785083225151moz-txt-link-freetext" href="https://github.com/python/cpython/pull/10902" target="_blank">https://github.com/python/cpython/pull/10902</a><br>
<br>
Best,</p>
<p>Paul</p>
<p><br>
</p>
<div class="gmail-m_8165555785083225151moz-cite-prefix">On 1/6/19 7:17 PM, Guido van Rossum
wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr">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.<br>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr">On Sun, Jan 6, 2019 at 11:02 AM Paul Ganssle <<a href="mailto:paul@ganssle.io" target="_blank">paul@ganssle.io</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote">
<div>
<p>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 <i>cannot</i> handled the class
being created this way would be broken in myriad ways.<br>
<br>
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:<br>
<br>
Python 3.6.6:<br>
<br>
>>> class D(datetime.datetime):<br>
... def __new__(cls):<br>
... return cls.now()<br>
... <br>
>>> D()<br>
D(2019, 1, 6, 13, 49, 38, 842033)<br>
<br>
Python 3.7.2:<br>
<br>
>>> class D(datetime.datetime):<br>
... def __new__(cls):<br>
... return cls.now()<br>
... <br>
>>> D()<br>
Traceback (most recent call last):<br>
File "<stdin>", line 1, in <module><br>
File "<stdin>", line 3, in __new__<br>
TypeError: __new__() takes 1 positional argument but 9
were given</p>
<p><br>
We haven't seen any bug reports about this sort of thing;
what we <i>have</i> been getting is bug reports that
subclassing datetime doesn't retain the subclass in
various ways (because people <i>are</i> 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).</p>
<p>If we're <i>really</i> concerned with this backward
compatibility breaking, we could do the equivalent of:<br>
<tt><br>
</tt><tt>try:</tt><tt><br>
</tt><tt> return new_behavior(...)</tt><tt><br>
</tt><tt>except TypeError:</tt><tt><br>
</tt><tt> warnings.warn("The semantics of timedelta
addition have "</tt><tt><br>
</tt><tt> "changed in a way that raises
an error in "<br>
"this subclass. Please implement
__add__ "<br>
"if you need the old behavior.",
DeprecationWarning)<br>
<br>
</tt>Then after a suitable notice period drop the warning
and turn it to a hard error.<br>
</p>
<p>Best,</p>
<p>Paul<br>
</p>
<div class="gmail-m_8165555785083225151gmail-m_-344422180359162179moz-cite-prefix">On
1/6/19 1:43 PM, Guido van Rossum wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr">
<div dir="ltr">
<div dir="ltr">
<div dir="ltr">
<div>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.<br>
</div>
<div><br>
</div>
<div>Note that the same problem already happens
with the .fromordinal() class method, though it
doesn't happen with .fromdatetime() or .now():</div>
<div><br>
</div>
<div>>>> class D(datetime.datetime):<br>
... def __new__(cls): return cls.now()<br>
... <br>
>>> D()<br>
D(2019, 1, 6, 10, 33, 37, 161606)<br>
>>> D.fromordinal(100)<br>
Traceback (most recent call last):<br>
File "<stdin>", line 1, in
<module><br>
TypeError: __new__() takes 1 positional argument
but 4 were given<br>
>>> D.fromtimestamp(123456789)<br>
D(1973, 11, 29, 13, 33, 9)<br>
>>> <br>
</div>
</div>
</div>
</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr">On Sun, Jan 6, 2019 at 9:05 AM Paul
Ganssle <<a href="mailto:paul@ganssle.io" target="_blank">paul@ganssle.io</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote">
<div>
<p>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 <i>all</i> arithmetic types
<i>should</i> have some form of this change.<br>
</p>
<p>That said, I would say that the biggest
difference between datetime and builtins (other
than the fact that datetime is <i>not</i> a
builtin, and as such doesn't necessarily need to
be categorized in this group), is that unlike
almost all other arithmetic types, <i>datetime</i>
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:<br>
<br>
>>> F(1.2) + 3.4<br>
<br>
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:<br>
<br>
datetime - datetime -> timedelta<br>
datetime ± timedelta -> datetime<br>
timedelta ± timedelta -> timedelta<br>
<br>
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.</p>
<p>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 <i>in
this respect</i>. 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.<br>
<br>
Best,<br>
Paul<br>
</p>
<div class="gmail-m_8165555785083225151gmail-m_-344422180359162179gmail-m_-6009346472102158879moz-cite-prefix">On
1/5/19 3:55 AM, Alexander Belopolsky wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr">
<div dir="ltr">
<div dir="ltr">
<div dir="ltr"><br>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr">On Wed, Jan 2, 2019 at
10:18 PM Paul Ganssle <<a href="mailto:paul@ganssle.io" target="_blank">paul@ganssle.io</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote">
<div>
<p>.. 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.</p>
</div>
</blockquote>
<div>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:</div>
<div>
<div><br>
</div>
<div>>>> class F(float):</div>
<div>... pass</div>
<div>...</div>
</div>
<div>
<div>>>> type(F.fromhex('AA'))</div>
<div><class '__main__.F'></div>
<div>>>> type(F(1) + F(2))</div>
<div><class 'float'></div>
</div>
<div><br>
</div>
<blockquote class="gmail_quote">
<div>
<p> 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).</p>
</div>
</blockquote>
<div><br>
</div>
<div>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. </div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
_______________________________________________<br>
Python-Dev mailing list<br>
<a href="mailto:Python-Dev@python.org" target="_blank">Python-Dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-dev" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-dev</a><br>
Unsubscribe: <a href="https://mail.python.org/mailman/options/python-dev/guido%40python.org" rel="noreferrer" target="_blank">https://mail.python.org/mailman/options/python-dev/guido%40python.org</a><br>
</blockquote>
</div>
<br>
<br>
-- <br>
<div dir="ltr" class="gmail-m_8165555785083225151gmail-m_-344422180359162179gmail_signature">--Guido
van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</blockquote>
</div>
_______________________________________________<br>
Python-Dev mailing list<br>
<a href="mailto:Python-Dev@python.org" target="_blank">Python-Dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-dev" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-dev</a><br>
Unsubscribe: <a href="https://mail.python.org/mailman/options/python-dev/guido%40python.org" rel="noreferrer" target="_blank">https://mail.python.org/mailman/options/python-dev/guido%40python.org</a><br>
</blockquote>
</div>
<br>
<br>
-- <br>
<div dir="ltr" class="gmail-m_8165555785083225151gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</blockquote>
</div>
_______________________________________________<br>
Python-Dev mailing list<br>
<a href="mailto:Python-Dev@python.org" target="_blank">Python-Dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-dev" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-dev</a><br>
Unsubscribe: <a href="https://mail.python.org/mailman/options/python-dev/guido%40python.org" rel="noreferrer" target="_blank">https://mail.python.org/mailman/options/python-dev/guido%40python.org</a><br>
</blockquote></div><br clear="all"><br>-- <br><div dir="ltr" class="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>