8000 gh-107773: Make `datetime` subclass `repr` consistent both implementa… · python/cpython@81a9b53 · GitHub
[go: up one dir, main page]

Skip to content

Commit 81a9b53

Browse files
donBarbosjaraco
andauthored
gh-107773: Make datetime subclass repr consistent both implementations (#130308)
--------- Co-authored-by: Jason R. Coombs <jaraco@jaraco.com>
1 parent 9f81f82 commit 81a9b53

File tree

3 files changed

+68
-21
lines changed

3 files changed

+68
-21
lines changed

Lib/_pydatetime.py

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
__all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo",
44
"MINYEAR", "MAXYEAR", "UTC")
55

6+
__name__ = "datetime"
7+
68

79
import time as _time
810
import math as _math
@@ -14,10 +16,10 @@ def _cmp(x, y):
1416

1517
def _get_class_module(self):
1618
module_name = self.__class__.__module__
17-
if module_name == '_pydatetime':
18-
return 'datetime'
19+
if module_name == 'datetime':
20+
return 'datetime.'
1921
else:
20-
return module_name
22+
return ''
2123

2224
MINYEAR = 1
2325
MAXYEAR = 9999
@@ -767,9 +769,9 @@ def __repr__(self):
767769
args.append("microseconds=%d" % self._microseconds)
768770
if not args:
769771
args.append('0')
770-
return "%s.%s(%s)" % (_get_class_module(self),
771-
self.__class__.__qualname__,
772-
', '.join(args))
772+
return "%s%s(%s)" % (_get_class_module(self),
773+
self.__class__.__qualname__,
774+
', '.join(args))
773775

774776
def __str__(self):
775777
mm, ss = divmod(self._seconds, 60)
@@ -1082,11 +1084,11 @@ def __repr__(self):
10821084
>>> repr(d)
10831085
'datetime.date(2010, 1, 1)'
10841086
"""
1085-
return "%s.%s(%d, %d, %d)" % (_get_class_module(self),
1086-
self.__class__.__qualname__,
1087-
self._year,
1088-
self._month,
1089-
self._day)
1087+
return "%s%s(%d, %d, %d)" % (_get_class_module(self),
1088+
self.__class__.__qualname__,
1089+
self._year,
1090+
self._month,
1091+
self._day)
10901092
# XXX These shouldn't depend on time.localtime(), because that
10911093
# clips the usable dates to [1970 .. 2038). At least ctime() is
10921094
# easily done without using strftime() -- that's better too because
@@ -1586,7 +1588,7 @@ def __repr__(self):
15861588
s = ", %d" % self._second
15871589
else:
15881590
s = ""
1589-
s= "%s.%s(%d, %d%s)" % (_get_class_module(self),
1591+
s = "%s%s(%d, %d%s)" % (_get_class_module(self),
15901592
self.__class__.__qualname__,
15911593
self._hour, self._minute, s)
15921594
if self._tzinfo is not None:
@@ -2162,9 +2164,9 @@ def __repr__(self):
21622164
del L[-1]
21632165
if L[-1] == 0:
21642166
del L[-1]
2165-
s = "%s.%s(%s)" % (_get_class_module(self),
2166-
self.__class__.__qualname__,
2167-
", ".join(map(str, L)))
2167+
s = "%s%s(%s)" % (_get_class_module(self),
2168+
self.__class__.__qualname__,
2169+
", ".join(map(str, L)))
21682170
if self._tzinfo is not None:
21692171
assert s[-1:] == ")"
21702172
s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
@@ -2461,12 +2463,12 @@ def __repr__(self):
24612463
if self is self.utc:
24622464
return 'datetime.timezone.utc'
24632465
if self._name is None:
2464-
return "%s.%s(%r)" % (_get_class_module(self),
2465-
self.__class__.__qualname__,
2466-
self._offset)
2467-
return "%s.%s(%r, %r)" % (_get_class_module(self),
2468-
self.__class__.__qualname__,
2469-
self._offset, self._name)
2466+
return "%s%s(%r)" % (_get_class_module(self),
2467+
self.__class__.__qualname__,
2468+
self._offset)
2469+
return "%s%s(%r, %r)" % (_get_class_module(self),
2470+
self.__class__.__qualname__,
2471+
self._offset, self._name)
24702472

24712473
def __str__(self):
24722474
return self.tzname(None)

Lib/test/datetimetester.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,9 @@ def test_harmful_mixed_comparison(self):
504504
#############################################################################
505505
# timedelta tests
506506

507+
class SubclassTimeDelta(timedelta):
508+
sub_var = 1
509+
507510
class TestTimeDelta(HarmlessMixedComparison, unittest.TestCase):
508511

509512
theclass = timedelta
@@ -788,6 +791,15 @@ def test_repr(self):
788791
self.assertEqual(repr(self.theclass(seconds=1, microseconds=100)),
789792
"%s(seconds=1, microseconds=100)" % name)
790793

794+
def test_repr_subclass(self):
795+
"""Subclasses should have bare names in the repr (gh-107773)."""
796+
td = SubclassTimeDelta(days=1)
797+
self.assertEqual(repr(td), "SubclassTimeDelta(days=1)")
798+
td = SubclassTimeDelta(seconds=30)
799+
self.assertEqual(repr(td), "SubclassTimeDelta(seconds=30)")
800+
td = SubclassTimeDelta(weeks=2)
801+
self.assertEqual(repr(td), "SubclassTimeDelta(days=14)")
802+
791803
def test_roundtrip(self):
792804
for td in (timedelta(days=999999999, hours=23, minutes=59,
793805
seconds=59, microseconds=999999),
@@ -1224,6 +1236,15 @@ def test_roundtrip(self):
12241236
dt2 = self.theclass(dt.year, dt.month, dt.day)
12251237
self.assertEqual(dt, dt2)
12261238

1239+
def test_repr_subclass(self):
1240+
"""Subclasses should have bare names in the repr (gh-107773)."""
1241+
td = SubclassDate(1, 2, 3)
1242+
self.assertEqual(repr(td), "SubclassDate(1, 2, 3)")
1243+
td = SubclassDate(2014, 1, 1)
1244+
self.assertEqual(repr(td), "SubclassDate(2014, 1, 1)")
1245+
td = SubclassDate(2010, 10, day=10)
1246+
self.assertEqual(repr(td), "SubclassDate(2010, 10, 10)")
1247+
12271248
def test_ordinal_conversions(self):
12281249
# Check some fixed values.
12291250
for y, m, d, n in [(1, 1, 1, 1), # calendar origin
@@ -3587,6 +3608,15 @@ class DateTimeSubclass(self.theclass):
35873608
self.assertEqual(dt, dt_rt)
35883609
self.assertIsInstance(dt_rt, DateTimeSubclass)
35893610

3611+
def test_repr_subclass(self):
3612+
"""Subclasses should have bare names in the repr (gh-107773)."""
3613+
td = SubclassDatetime(2014, 1, 1)
3614+
self.assertEqual(repr(td), "SubclassDatetime(2014, 1, 1, 0, 0)")
3615+
td = SubclassDatetime(2010, 10, day=10)
3616+
self.assertEqual(repr(td), "SubclassDatetime(2010, 10, 10, 0, 0)")
3617+
td = SubclassDatetime(2010, 10, 2, second=3)
3618+
self.assertEqual(repr(td), "SubclassDatetime(2010, 10, 2, 0, 0, 3)")
3619+
35903620

35913621
class TestSubclassDateTime(TestDateTime):
35923622
theclass = SubclassDatetime
@@ -3897,6 +3927,19 @@ def test_repr(self):
38973927
self.assertEqual(repr(self.theclass(23, 15, 0, 0)),
38983928
"%s(23, 15)" % name)
38993929

3930+
def test_repr_subclass(self):
3931+
"""Subclasses should have bare names in the repr (gh-107773)."""
3932+
td = SubclassTime(hour=1)
3933+
self.assertEqual(repr(td), "SubclassTime(1, 0)")
3934+
td = SubclassTime(hour=2, minute=30)
3935+
self.assertEqua A074 l(repr(td), "SubclassTime(2, 30)")
3936+
td = SubclassTime(hour=2, minute=30, second=11)
3937+
self.assertEqual(repr(td), "SubclassTime(2, 30, 11)")
3938+
td = SubclassTime(minute=30, second=11, fold=0)
3939+
self.assertEqual(repr(td), "SubclassTime(0, 30, 11)")
3940+
td = SubclassTime(minute=30, second=11, fold=1)
3941+
self.assertEqual(repr(td), "SubclassTime(0, 30, 11, fold=1)")
3942+
39003943
def test_resolution_info(self):
39013944
self.assertIsInstance(self.theclass.min, self.theclass)
39023945
self.assertIsInstance(self.theclass.max, self.theclass)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Make :mod:`datetime` subclass :meth:`~object.__repr__` consistent both
2+
implementations. Patch by Semyon Moroz.

0 commit comments

Comments
 (0)
0