From 2c5fb1711818926862d0d7b2e5effcaa5a5eb002 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye <33177550+nanjekyejoannah@users.noreply.github.com> Date: Thu, 29 Aug 2019 09:54:46 -0300 Subject: [PATCH] bpo-36833: Add tests for Datetime C API Macros (GH-14842) Added tests for PyDateTime_xxx_GET_xxx() macros of the C API of the datetime module. --- Lib/test/datetimetester.py | 59 +++++++++++++++++++ .../2019-07-18-14-52-58.bpo-36833.Zoe9ek.rst | 2 + Modules/_testcapimodule.c | 53 +++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 Misc/NEWS.d/next/Tests/2019-07-18-14-52-58.bpo-36833.Zoe9ek.rst diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index b440e5ab5fa..d09255d79bf 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -5941,6 +5941,65 @@ class CapiTest(unittest.TestCase): self.assertEqual(dt1.astimezone(timezone.utc), dt_utc) + def test_PyDateTime_DELTA_GET(self): + class TimeDeltaSubclass(timedelta): + pass + + for klass in [timedelta, TimeDeltaSubclass]: + for args in [(26, 55, 99999), (26, 55, 99999)]: + d = klass(*args) + with self.subTest(cls=klass, date=args): + days, seconds, microseconds = _testcapi.PyDateTime_DELTA_GET(d) + + self.assertEqual(days, d.days) + self.assertEqual(seconds, d.seconds) + self.assertEqual(microseconds, d.microseconds) + + def test_PyDateTime_GET(self): + class DateSubclass(date): + pass + + for klass in [date, DateSubclass]: + for args in [(2000, 1, 2), (2012, 2, 29)]: + d = klass(*args) + with self.subTest(cls=klass, date=args): + year, month, day = _testcapi.PyDateTime_GET(d) + + self.assertEqual(year, d.year) + self.assertEqual(month, d.month) + self.assertEqual(day, d.day) + + def test_PyDateTime_DATE_GET(self): + class DateTimeSubclass(datetime): + pass + + for klass in [datetime, DateTimeSubclass]: + for args in [(1993, 8, 26, 22, 12, 55, 99999), + (1993, 8, 26, 22, 12, 55, 99999)]: + d = klass(*args) + with self.subTest(cls=klass, date=args): + hour, minute, second, microsecond = _testcapi.PyDateTime_DATE_GET(d) + + self.assertEqual(hour, d.hour) + self.assertEqual(minute, d.minute) + self.assertEqual(second, d.second) + self.assertEqual(microsecond, d.microsecond) + + def test_PyDateTime_TIME_GET(self): + class TimeSubclass(time): + pass + + for klass in [time, TimeSubclass]: + for args in [(12, 30, 20, 10), (12, 30, 20, 10)]: + d = klass(*args) + with self.subTest(cls=klass, date=args): + hour, minute, second, microsecond = _testcapi.PyDateTime_TIME_GET(d) + + self.assertEqual(hour, d.hour) + self.assertEqual(minute, d.minute) + self.assertEqual(second, d.second) + self.assertEqual(microsecond, d.microsecond) + def test_timezones_offset_zero(self): utc0, utc1, non_utc = _testcapi.get_timezones_offset_zero() diff --git a/Misc/NEWS.d/next/Tests/2019-07-18-14-52-58.bpo-36833.Zoe9ek.rst b/Misc/NEWS.d/next/Tests/2019-07-18-14-52-58.bpo-36833.Zoe9ek.rst new file mode 100644 index 00000000000..3632f98f34f --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-07-18-14-52-58.bpo-36833.Zoe9ek.rst @@ -0,0 +1,2 @@ +Added tests for PyDateTime_xxx_GET_xxx() macros of the C API of +the :mod:`datetime` module. Patch by Joannah Nanjekye. \ No newline at end of file diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 84f2651641c..cc3b089a0d7 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2629,6 +2629,55 @@ get_datetime_fromtimestamp(PyObject* self, PyObject *args) return rv; } +static PyObject * +test_PyDateTime_GET(PyObject *self, PyObject *obj) +{ + int year, month, day; + + year = PyDateTime_GET_YEAR(obj); + month = PyDateTime_GET_MONTH(obj); + day = PyDateTime_GET_DAY(obj); + + return Py_BuildValue("(lll)", year, month, day); +} + +static PyObject * +test_PyDateTime_DATE_GET(PyObject *self, PyObject *obj) +{ + int hour, minute, second, microsecond; + + hour = PyDateTime_DATE_GET_HOUR(obj); + minute = PyDateTime_DATE_GET_MINUTE(obj); + second = PyDateTime_DATE_GET_SECOND(obj); + microsecond = PyDateTime_DATE_GET_MICROSECOND(obj); + + return Py_BuildValue("(llll)", hour, minute, second, microsecond); +} + +static PyObject * +test_PyDateTime_TIME_GET(PyObject *self, PyObject *obj) +{ + int hour, minute, second, microsecond; + + hour = PyDateTime_TIME_GET_HOUR(obj); + minute = PyDateTime_TIME_GET_MINUTE(obj); + second = PyDateTime_TIME_GET_SECOND(obj); + microsecond = PyDateTime_TIME_GET_MICROSECOND(obj); + + return Py_BuildValue("(llll)", hour, minute, second, microsecond); +} + +static PyObject * +test_PyDateTime_DELTA_GET(PyObject *self, PyObject *obj) +{ + int days, seconds, microseconds; + + days = PyDateTime_DELTA_GET_DAYS(obj); + seconds = PyDateTime_DELTA_GET_SECONDS(obj); + microseconds = PyDateTime_DELTA_GET_MICROSECONDS(obj); + + return Py_BuildValue("(lll)", days, seconds, microseconds); +} /* test_thread_state spawns a thread of its own, and that thread releases * `thread_done` when it's finished. The driver code has to know when the @@ -5138,6 +5187,10 @@ static PyMethodDef TestMethods[] = { {"get_delta_fromdsu", get_delta_fromdsu, METH_VARARGS}, {"get_date_fromtimestamp", get_date_fromtimestamp, METH_VARARGS}, {"get_datetime_fromtimestamp", get_datetime_fromtimestamp, METH_VARARGS}, + {"PyDateTime_GET", test_PyDateTime_GET, METH_O}, + {"PyDateTime_DATE_GET", test_PyDateTime_DATE_GET, METH_O}, + {"PyDateTime_TIME_GET", test_PyDateTime_TIME_GET, METH_O}, + {"PyDateTime_DELTA_GET", test_PyDateTime_DELTA_GET, METH_O}, {"test_list_api", test_list_api, METH_NOARGS}, {"test_dict_iteration", test_dict_iteration, METH_NOARGS}, {"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS},