Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions Lib/_pydatetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
__all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo",
"MINYEAR", "MAXYEAR", "UTC")

__name__ = "datetime"


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

def _get_class_module(self):
module_name = self.__class__.__module__
if module_name == '_pydatetime':
return 'datetime'
if module_name == 'datetime':
return 'datetime.'
else:
return module_name
return ''

MINYEAR = 1
MAXYEAR = 9999
Expand Down Expand Up @@ -767,9 +769,9 @@ def __repr__(self):
args.append("microseconds=%d" % self._microseconds)
if not args:
args.append('0')
return "%s.%s(%s)" % (_get_class_module(self),
self.__class__.__qualname__,
', '.join(args))
return "%s%s(%s)" % (_get_class_module(self),
self.__class__.__qualname__,
', '.join(args))

def __str__(self):
mm, ss = divmod(self._seconds, 60)
Expand Down Expand Up @@ -1082,11 +1084,11 @@ def __repr__(self):
>>> repr(d)
'datetime.date(2010, 1, 1)'
"""
return "%s.%s(%d, %d, %d)" % (_get_class_module(self),
self.__class__.__qualname__,
self._year,
self._month,
self._day)
return "%s%s(%d, %d, %d)" % (_get_class_module(self),
self.__class__.__qualname__,
self._year,
self._month,
self._day)
# XXX These shouldn't depend on time.localtime(), because that
# clips the usable dates to [1970 .. 2038). At least ctime() is
# easily done without using strftime() -- that's better too because
Expand Down Expand Up @@ -1586,7 +1588,7 @@ def __repr__(self):
s = ", %d" % self._second
else:
s = ""
s= "%s.%s(%d, %d%s)" % (_get_class_module(self),
s = "%s%s(%d, %d%s)" % (_get_class_module(self),
self.__class__.__qualname__,
self._hour, self._minute, s)
if self._tzinfo is not None:
Expand Down Expand Up @@ -2162,9 +2164,9 @@ def __repr__(self):
del L[-1]
if L[-1] == 0:
del L[-1]
s = "%s.%s(%s)" % (_get_class_module(self),
self.__class__.__qualname__,
", ".join(map(str, L)))
s = "%s%s(%s)" % (_get_class_module(self),
self.__class__.__qualname__,
", ".join(map(str, L)))
if self._tzinfo is not None:
assert s[-1:] == ")"
s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
Expand Down Expand Up @@ -2461,12 +2463,12 @@ def __repr__(self):
if self is self.utc:
return 'datetime.timezone.utc'
if self._name is None:
return "%s.%s(%r)" % (_get_class_module(self),
self.__class__.__qualname__,
self._offset)
return "%s.%s(%r, %r)" % (_get_class_module(self),
self.__class__.__qualname__,
self._offset, self._name)
return "%s%s(%r)" % (_get_class_module(self),
self.__class__.__qualname__,
self._offset)
return "%s%s(%r, %r)" % (_get_class_module(self),
self.__class__.__qualname__,
self._offset, self._name)

def __str__(self):
return self.tzname(None)
Expand Down
43 changes: 43 additions & 0 deletions Lib/test/datetimetester.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,9 @@ def test_harmful_mixed_comparison(self):
#############################################################################
# timedelta tests

class SubclassTimeDelta(timedelta):
sub_var = 1

class TestTimeDelta(HarmlessMixedComparison, unittest.TestCase):

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

def test_repr_subclass(self):
"""Subclasses should have bare names in the repr (gh-107773)."""
td = SubclassTimeDelta(days=1)
self.assertEqual(repr(td), "SubclassTimeDelta(days=1)")
td = SubclassTimeDelta(seconds=30)
self.assertEqual(repr(td), "SubclassTimeDelta(seconds=30)")
td = SubclassTimeDelta(weeks=2)
self.assertEqual(repr(td), "SubclassTimeDelta(days=14)")

def test_roundtrip(self):
for td in (timedelta(days=999999999, hours=23, minutes=59,
seconds=59, microseconds=999999),
Expand Down Expand Up @@ -1224,6 +1236,15 @@ def test_roundtrip(self):
dt2 = self.theclass(dt.year, dt.month, dt.day)
self.assertEqual(dt, dt2)

def test_repr_subclass(self):
"""Subclasses should have bare names in the repr (gh-107773)."""
td = SubclassDate(1, 2, 3)
self.assertEqual(repr(td), "SubclassDate(1, 2, 3)")
td = SubclassDate(2014, 1, 1)
self.assertEqual(repr(td), "SubclassDate(2014, 1, 1)")
td = SubclassDate(2010, 10, day=10)
self.assertEqual(repr(td), "SubclassDate(2010, 10, 10)")

def test_ordinal_conversions(self):
# Check some fixed values.
for y, m, d, n in [(1, 1, 1, 1), # calendar origin
Expand Down Expand Up @@ -3587,6 +3608,15 @@ class DateTimeSubclass(self.theclass):
self.assertEqual(dt, dt_rt)
self.assertIsInstance(dt_rt, DateTimeSubclass)

def test_repr_subclass(self):
"""Subclasses should have bare names in the repr (gh-107773)."""
td = SubclassDatetime(2014, 1, 1)
self.assertEqual(repr(td), "SubclassDatetime(2014, 1, 1, 0, 0)")
td = SubclassDatetime(2010, 10, day=10)
self.assertEqual(repr(td), "SubclassDatetime(2010, 10, 10, 0, 0)")
td = SubclassDatetime(2010, 10, 2, second=3)
self.assertEqual(repr(td), "SubclassDatetime(2010, 10, 2, 0, 0, 3)")


class TestSubclassDateTime(TestDateTime):
theclass = SubclassDatetime
Expand Down Expand Up @@ -3897,6 +3927,19 @@ def test_repr(self):
self.assertEqual(repr(self.theclass(23, 15, 0, 0)),
"%s(23, 15)" % name)

def test_repr_subclass(self):
"""Subclasses should have bare names in the repr (gh-107773)."""
td = SubclassTime(hour=1)
self.assertEqual(repr(td), "SubclassTime(1, 0)")
td = SubclassTime(hour=2, minute=30)
self.assertEqual(repr(td), "SubclassTime(2, 30)")
td = SubclassTime(hour=2, minute=30, second=11)
self.assertEqual(repr(td), "SubclassTime(2, 30, 11)")
td = SubclassTime(minute=30, second=11, fold=0)
self.assertEqual(repr(td), "SubclassTime(0, 30, 11)")
td = SubclassTime(minute=30, second=11, fold=1)
self.assertEqual(repr(td), "SubclassTime(0, 30, 11, fold=1)")

def test_resolution_info(self):
self.assertIsInstance(self.theclass.min, self.theclass)
self.assertIsInstance(self.theclass.max, self.theclass)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Make :mod:`datetime` subclass :meth:`~object.__repr__` consistent both
implementations. Patch by Semyon Moroz.
Loading