[pypy-commit] pypy default: Improve the test, and fix:

amauryfa pypy.commits at gmail.com
Fri Jul 1 13:35:51 EDT 2016


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r85498:f616e095f87e
Date: 2016-07-01 19:34 +0200
http://bitbucket.org/pypy/pypy/changeset/f616e095f87e/

Log:	Improve the test, and fix: The subclass __init__ and __new__ should
	not be called.

	Thanks Armin!

diff --git a/lib_pypy/datetime.py b/lib_pypy/datetime.py
--- a/lib_pypy/datetime.py
+++ b/lib_pypy/datetime.py
@@ -839,7 +839,7 @@
             month = self._month
         if day is None:
             day = self._day
-        return type(self)(year, month, day)
+        return date.__new__(type(self), year, month, day)
 
     # Comparisons of date objects with other.
 
@@ -1356,7 +1356,8 @@
             microsecond = self.microsecond
         if tzinfo is True:
             tzinfo = self.tzinfo
-        return type(self)(hour, minute, second, microsecond, tzinfo)
+        return time.__new__(type(self),
+                            hour, minute, second, microsecond, tzinfo)
 
     def __nonzero__(self):
         if self.second or self.microsecond:
@@ -1566,8 +1567,9 @@
             microsecond = self.microsecond
         if tzinfo is True:
             tzinfo = self.tzinfo
-        return type(self)(year, month, day, hour, minute, second, microsecond,
-                        tzinfo)
+        return datetime.__new__(type(self),
+                                year, month, day, hour, minute, second,
+                                microsecond, tzinfo)
 
     def astimezone(self, tz):
         if not isinstance(tz, tzinfo):
diff --git a/pypy/module/test_lib_pypy/test_datetime.py b/pypy/module/test_lib_pypy/test_datetime.py
--- a/pypy/module/test_lib_pypy/test_datetime.py
+++ b/pypy/module/test_lib_pypy/test_datetime.py
@@ -315,13 +315,50 @@
         class sub(datetime.timedelta): pass
         assert type(+sub()) is datetime.timedelta
 
-    def test_subclass(self):
-        class MyDate(datetime.date): pass
-        class MyTime(datetime.time): pass
-        class MyDateTime(datetime.datetime): pass
-        assert type(MyDate.today().replace(day=1)) is MyDate
-        assert type(MyTime().replace(hour=1)) is MyTime
-        assert type(MyDateTime.now().replace(day=1, hour=1)) is MyDateTime
+    def test_subclass_date(self):
+        # replace() should return a subclass but not call __new__ or __init__.
+        class MyDate(datetime.date):
+            forbidden = False
+            def __new__(cls):
+                if cls.forbidden: FAIL
+                return datetime.date.__new__(cls, 2016, 2, 3)
+            def __init__(self, *args):
+                if self.forbidden: FAIL
+        d = MyDate()
+        d.forbidden = True
+        d2 = d.replace(day=5)
+        assert type(d2) is MyDate
+        assert d2 == datetime.date(2016, 2, 5)
+
+    def test_subclass_time(self):
+        # replace() should return a subclass but not call __new__ or __init__.
+        class MyTime(datetime.time):
+            forbidden = False
+            def __new__(cls):
+                if cls.forbidden: FAIL
+                return datetime.time.__new__(cls, 1, 2, 3)
+            def __init__(self, *args):
+                if self.forbidden: FAIL
+        d = MyTime()
+        d.forbidden = True
+        d2 = d.replace(hour=5)
+        assert type(d2) is MyTime
+        assert d2 == datetime.time(5, 2, 3)
+
+    def test_subclass_datetime(self):
+        # replace() should return a subclass but not call __new__ or __init__.
+        class MyDatetime(datetime.datetime):
+            forbidden = False
+            def __new__(cls):
+                if cls.forbidden: FAIL
+                return datetime.datetime.__new__(cls, 2016, 4, 5, 1, 2, 3)
+            def __init__(self, *args):
+                if self.forbidden: FAIL
+        d = MyDatetime()
+        d.forbidden = True
+        d2 = d.replace(hour=7)
+        assert type(d2) is MyDatetime
+        assert d2 == datetime.datetime(2016, 4, 5, 7, 2, 3)
 
 
 class TestDatetimeHost(BaseTestDatetime):


More information about the pypy-commit mailing list