Skip to content

Commit 0b5a23a

Browse files
gh-136571: Convert more code in datetime to Argument Clinic
This adds signatures for some classes and methods. date.fromisocalendar() can now raise OverflowError for arguments that don't fit in the C int.
1 parent c7d24b8 commit 0b5a23a

File tree

7 files changed

+2333
-656
lines changed

7 files changed

+2333
-656
lines changed

Doc/library/datetime.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2383,7 +2383,7 @@ locations where different offsets are used in different days of the year or
23832383
where historical changes have been made to civil time.
23842384

23852385

2386-
.. class:: timezone(offset, name=None)
2386+
.. class:: timezone(offset[, name])
23872387

23882388
The *offset* argument must be specified as a :class:`timedelta`
23892389
object representing the difference between the local time and UTC. It must

Lib/_pydatetime.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,7 @@ def fromisocalendar(cls, year, week, day):
10831083

10841084
@classmethod
10851085
def strptime(cls, date_string, format):
1086-
"""Parse a date string according to the given format (like time.strptime())."""
1086+
"""Parse string according to the given date format (like time.strptime())."""
10871087
import _strptime
10881088
return _strptime._strptime_datetime_date(cls, date_string, format)
10891089

@@ -1310,7 +1310,7 @@ def __reduce__(self):
13101310

13111311

13121312
class tzinfo:
1313-
"""Abstract base class for time zone info classes.
1313+
"""Abstract base class for time zone info objects.
13141314
13151315
Subclasses must override the tzname(), utcoffset() and dst() methods.
13161316
"""
@@ -1468,7 +1468,7 @@ def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold
14681468

14691469
@classmethod
14701470
def strptime(cls, date_string, format):
1471-
"""string, format -> new time parsed from a string (like time.strptime())."""
1471+
"""Parse string according to the given time format (like time.strptime())."""
14721472
import _strptime
14731473
return _strptime._strptime_datetime_time(cls, date_string, format)
14741474

@@ -1776,7 +1776,7 @@ def __reduce__(self):
17761776

17771777

17781778
class datetime(date):
1779-
"""datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
1779+
"""A combination of a date and a time.
17801780
17811781
The year, month and day arguments are required. tzinfo may be None, or an
17821782
instance of a tzinfo subclass. The remaining arguments may be ints.
@@ -2209,7 +2209,7 @@ def __str__(self):
22092209

22102210
@classmethod
22112211
def strptime(cls, date_string, format):
2212-
'string, format -> new datetime parsed from a string (like time.strptime()).'
2212+
"""Parse string according to the given date and time format (like time.strptime())."""
22132213
import _strptime
22142214
return _strptime._strptime_datetime_datetime(cls, date_string, format)
22152215

@@ -2435,6 +2435,8 @@ def _isoweek1monday(year):
24352435

24362436

24372437
class timezone(tzinfo):
2438+
"""Fixed offset from UTC implementation of tzinfo."""
2439+
24382440
__slots__ = '_offset', '_name'
24392441

24402442
# Sentinel value to disallow None

Lib/test/datetimetester.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,14 +2147,20 @@ def test_fromisocalendar_value_errors(self):
21472147
(10000, 1, 1),
21482148
(0, 1, 1),
21492149
(9999999, 1, 1),
2150+
]
2151+
for isocal in isocals:
2152+
with self.subTest(isocal=isocal):
2153+
with self.assertRaises(ValueError):
2154+
self.theclass.fromisocalendar(*isocal)
2155+
2156+
isocals = [
21502157
(2<<32, 1, 1),
21512158
(2019, 2<<32, 1),
21522159
(2019, 1, 2<<32),
21532160
]
2154-
21552161
for isocal in isocals:
21562162
with self.subTest(isocal=isocal):
2157-
with self.assertRaises(ValueError):
2163+
with self.assertRaises((ValueError, OverflowError)):
21582164
self.theclass.fromisocalendar(*isocal)
21592165

21602166
def test_fromisocalendar_type_errors(self):
@@ -2301,7 +2307,7 @@ def test_isoformat_timezone(self):
23012307
dt = dt_base.replace(tzinfo=tzi)
23022308
exp = exp_base + exp_tz
23032309
with self.subTest(tzi=tzi):
2304-
assert dt.isoformat() == exp
2310+
self.assertEqual(dt.isoformat(), exp)
23052311

23062312
def test_format(self):
23072313
dt = self.theclass(2007, 9, 10, 4, 5, 1, 123)
@@ -3349,7 +3355,7 @@ def test_fromisoformat_timezone(self):
33493355

33503356
with self.subTest(tstr=dtstr):
33513357
dt_rt = self.theclass.fromisoformat(dtstr)
3352-
assert dt == dt_rt, dt_rt
3358+
self.assertEqual(dt_rt, dt)
33533359

33543360
def test_fromisoformat_separators(self):
33553361
separators = [
@@ -3865,7 +3871,7 @@ def test_isoformat_timezone(self):
38653871
t = t_base.replace(tzinfo=tzi)
38663872
exp = exp_base + exp_tz
38673873
with self.subTest(tzi=tzi):
3868-
assert t.isoformat() == exp
3874+
self.assertEqual(t.isoformat(), exp)
38693875

38703876
def test_1653736(self):
38713877
# verify it doesn't accept extra keyword arguments
@@ -4350,7 +4356,7 @@ def utcoffset(self, t):
43504356
elif x is d2:
43514357
expected = -1
43524358
else:
4353-
assert y is d2
4359+
self.assertIs(y, d2)
43544360
expected = 1
43554361
self.assertEqual(got, expected)
43564362

@@ -4678,7 +4684,7 @@ def test_fromisoformat_timezone(self):
46784684

46794685
with self.subTest(tstr=tstr):
46804686
t_rt = self.theclass.fromisoformat(tstr)
4681-
assert t == t_rt
4687+
self.assertEqual(t_rt, t)
46824688

46834689
def test_fromisoformat_timespecs(self):
46844690
time_bases = [
@@ -5515,7 +5521,7 @@ def utcoffset(self, t):
55155521
elif x is d2:
55165522
expected = timedelta(minutes=(11-59)-0)
55175523
else:
5518-
assert y is d2
5524+
self.assertIs(y, d2)
55195525
expected = timedelta(minutes=0-(11-59))
55205526
self.assertEqual(got, expected)
55215527

Lib/test/test_inspect/test_inspect.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5830,6 +5830,19 @@ def test_collections_abc_module_has_signatures(self):
58305830
import collections.abc
58315831
self._test_module_has_signatures(collections.abc)
58325832

5833+
def test_datetime_module_has_signatures(self):
5834+
import datetime
5835+
no_signature = {'tzinfo'}
5836+
unsupported_signature = {'timezone'}
5837+
methods_unsupported_signature = {
5838+
'date': {'replace'},
5839+
'time': {'replace'},
5840+
'datetime': {'replace', 'combine'},
5841+
}
5842+
self._test_module_has_signatures(datetime,
5843+
no_signature, unsupported_signature,
5844+
methods_unsupported_signature=methods_unsupported_signature)
5845+
58335846
def test_errno_module_has_signatures(self):
58345847
import errno
58355848
self._test_module_has_signatures(errno)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:meth:`datetime.date.fromisocalendar` can now raise OverflowError for out of
2+
range arguments.

0 commit comments

Comments
 (0)