https://github.com/python/cpython/commit/8da9920a80c60fb3fc326c623e0f217c84011c1d
commit: 8da9920a80c60fb3fc326c623e0f217c84011c1d
branch: main
author: Beomsoo Kim <[email protected]>
committer: sobolevn <[email protected]>
date: 2024-11-19T22:40:52+03:00
summary:

gh-126947: Typechecking for _pydatetime.timedelta.__new__ arguments (#126949)

Co-authored-by: sobolevn <[email protected]>
Co-authored-by: Peter Bierma <[email protected]>

files:
A Misc/NEWS.d/next/Library/2024-11-18-19-03-46.gh-issue-126947.NiDYUe.rst
M Lib/_pydatetime.py
M Lib/test/datetimetester.py

diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py
index 78e03e32896740..ed01670cfece43 100644
--- a/Lib/_pydatetime.py
+++ b/Lib/_pydatetime.py
@@ -651,7 +651,19 @@ def __new__(cls, days=0, seconds=0, microseconds=0,
         # guide the C implementation; it's way more convoluted than speed-
         # ignoring auto-overflow-to-long idiomatic Python could be.
 
-        # XXX Check that all inputs are ints or floats.
+        for name, value in (
+            ("days", days),
+            ("seconds", seconds),
+            ("microseconds", microseconds),
+            ("milliseconds", milliseconds),
+            ("minutes", minutes),
+            ("hours", hours),
+            ("weeks", weeks)
+        ):
+            if not isinstance(value, (int, float)):
+                raise TypeError(
+                    f"unsupported type for timedelta {name} component: 
{type(value).__name__}"
+                )
 
         # Final values, all integer.
         # s and us fit in 32-bit signed ints; d isn't bounded.
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index dbe25ef57dea83..25a3015c4e19ce 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -510,6 +510,7 @@ class TestTimeDelta(HarmlessMixedComparison, 
unittest.TestCase):
 
     def test_constructor(self):
         eq = self.assertEqual
+        ra = self.assertRaises
         td = timedelta
 
         # Check keyword args to constructor
@@ -533,6 +534,15 @@ def test_constructor(self):
         eq(td(seconds=0.001), td(milliseconds=1))
         eq(td(milliseconds=0.001), td(microseconds=1))
 
+        # Check type of args to constructor
+        ra(TypeError, lambda: td(weeks='1'))
+        ra(TypeError, lambda: td(days='1'))
+        ra(TypeError, lambda: td(hours='1'))
+        ra(TypeError, lambda: td(minutes='1'))
+        ra(TypeError, lambda: td(seconds='1'))
+        ra(TypeError, lambda: td(milliseconds='1'))
+        ra(TypeError, lambda: td(microseconds='1'))
+
     def test_computations(self):
         eq = self.assertEqual
         td = timedelta
diff --git 
a/Misc/NEWS.d/next/Library/2024-11-18-19-03-46.gh-issue-126947.NiDYUe.rst 
b/Misc/NEWS.d/next/Library/2024-11-18-19-03-46.gh-issue-126947.NiDYUe.rst
new file mode 100644
index 00000000000000..29ba4f21454fe1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-11-18-19-03-46.gh-issue-126947.NiDYUe.rst
@@ -0,0 +1,2 @@
+Raise :exc:`TypeError` in :meth:`!_pydatetime.timedelta.__new__` if the passed 
arguments are not :class:`int` or :class:`float`, so that the Python
+implementation is in line with the C implementation.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to