<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>