diff options
| author | Paul Ganssle <pganssle@users.noreply.github.com> | 2018-01-16 13:06:31 -0500 |
|---|---|---|
| committer | Alexander Belopolsky <abalkin@users.noreply.github.com> | 2018-01-16 13:06:31 -0500 |
| commit | 9f1b7b93f5f0ef589e7b272e127cacf4ce5d23f1 (patch) | |
| tree | 60cf60454cad0f99056713510c1c91744d7e7ff8 /Lib/test/datetimetester.py | |
| parent | 6b5a27975a415108a5eac12ee302bf2b3233f4d4 (diff) | |
| download | cpython-git-9f1b7b93f5f0ef589e7b272e127cacf4ce5d23f1.tar.gz | |
bpo-32403: Faster date and datetime constructors (#4993)
* Add tests for date subclass alternate constructors
* Switch over alternate date constructors to fast path
* Switch datetime constructors to fastpath, fix bpo-32404
* Add fast path for datetime in date subclass constructor
* Set fold in constructor in datetime.combine
* Add news entries.
Diffstat (limited to 'Lib/test/datetimetester.py')
| -rw-r--r-- | Lib/test/datetimetester.py | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 1d0c1c5bd2..e8ed79e8b3 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -1552,6 +1552,50 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase): self.assertEqual(dt1.toordinal(), dt2.toordinal()) self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month - 7) + def test_subclass_alternate_constructors(self): + # Test that alternate constructors call the constructor + class DateSubclass(self.theclass): + def __new__(cls, *args, **kwargs): + result = self.theclass.__new__(cls, *args, **kwargs) + result.extra = 7 + + return result + + args = (2003, 4, 14) + d_ord = 731319 # Equivalent ordinal date + d_isoformat = '2003-04-14' # Equivalent isoformat() + + base_d = DateSubclass(*args) + self.assertIsInstance(base_d, DateSubclass) + self.assertEqual(base_d.extra, 7) + + # Timestamp depends on time zone, so we'll calculate the equivalent here + ts = datetime.combine(base_d, time(0)).timestamp() + + test_cases = [ + ('fromordinal', (d_ord,)), + ('fromtimestamp', (ts,)), + ('fromisoformat', (d_isoformat,)), + ] + + for constr_name, constr_args in test_cases: + for base_obj in (DateSubclass, base_d): + # Test both the classmethod and method + with self.subTest(base_obj_type=type(base_obj), + constr_name=constr_name): + constr = getattr(base_obj, constr_name) + + dt = constr(*constr_args) + + # Test that it creates the right subclass + self.assertIsInstance(dt, DateSubclass) + + # Test that it's equal to the base object + self.assertEqual(dt, base_d) + + # Test that it called the constructor + self.assertEqual(dt.extra, 7) + def test_pickling_subclass_date(self): args = 6, 7, 23 @@ -2420,6 +2464,54 @@ class TestDateTime(TestDate): self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month + dt1.second - 7) + def test_subclass_alternate_constructors_datetime(self): + # Test that alternate constructors call the constructor + class DateTimeSubclass(self.theclass): + def __new__(cls, *args, **kwargs): + result = self.theclass.__new__(cls, *args, **kwargs) + result.extra = 7 + + return result + + args = (2003, 4, 14, 12, 30, 15, 123456) + d_isoformat = '2003-04-14T12:30:15.123456' # Equivalent isoformat() + utc_ts = 1050323415.123456 # UTC timestamp + + base_d = DateTimeSubclass(*args) + self.assertIsInstance(base_d, DateTimeSubclass) + self.assertEqual(base_d.extra, 7) + + # Timestamp depends on time zone, so we'll calculate the equivalent here + ts = base_d.timestamp() + + test_cases = [ + ('fromtimestamp', (ts,)), + # See https://bugs.python.org/issue32417 + # ('fromtimestamp', (ts, timezone.utc)), + ('utcfromtimestamp', (utc_ts,)), + ('fromisoformat', (d_isoformat,)), + ('strptime', (d_isoformat, '%Y-%m-%dT%H:%M:%S.%f')), + ('combine', (date(*args[0:3]), time(*args[3:]))), + ] + + for constr_name, constr_args in test_cases: + for base_obj in (DateTimeSubclass, base_d): + # Test both the classmethod and method + with self.subTest(base_obj_type=type(base_obj), + constr_name=constr_name): + constr = getattr(base_obj, constr_name) + + dt = constr(*constr_args) + + # Test that it creates the right subclass + self.assertIsInstance(dt, DateTimeSubclass) + + # Test that it's equal to the base object + self.assertEqual(dt, base_d.replace(tzinfo=None)) + + # Test that it called the constructor + self.assertEqual(dt.extra, 7) + def test_fromisoformat_datetime(self): # Test that isoformat() is reversible base_dates = [ |
