diff options
author | Mohamed Koubaa <koubaa.m@gmail.com> | 2020-11-20 10:39:40 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-20 10:39:40 (GMT) |
commit | 2db8e35489d63b976a463fb1d2a6c29f4f965c21 (patch) | |
tree | 862c4b751345ff3a60fa78e59e5bae7986b72681 | |
parent | 5c36da78d738d0e5fdb539a758cc15abc47c843b (diff) | |
download | cpython-2db8e35489d63b976a463fb1d2a6c29f4f965c21.zip cpython-2db8e35489d63b976a463fb1d2a6c29f4f965c21.tar.gz cpython-2db8e35489d63b976a463fb1d2a6c29f4f965c21.tar.bz2 |
bpo-1635741: Enhance _datetime error handling (GH-23139)
-rw-r--r-- | Modules/_datetimemodule.c | 220 |
1 files changed, 103 insertions, 117 deletions
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index e59f89b..c3e0b52 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -6494,32 +6494,9 @@ static PyDateTime_CAPI CAPI = { new_time_ex2 }; - - -static struct PyModuleDef datetimemodule = { - PyModuleDef_HEAD_INIT, - "_datetime", - "Fast implementation of the datetime type.", - -1, - module_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__datetime(void) +static int +_datetime_exec(PyObject *module) { - PyObject *m; /* a module object */ - PyObject *d; /* its dict */ - PyObject *x; - PyObject *delta; - - m = PyModule_Create(&datetimemodule); - if (m == NULL) - return NULL; - // `&...` is not a constant expression according to a strict reading // of C standards. Fill tp_base at run-time rather than statically. // See https://bugs.python.org/issue40777 @@ -6537,98 +6514,72 @@ PyInit__datetime(void) }; for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { - if (PyModule_AddType(m, types[i]) < 0) { - return NULL; + if (PyModule_AddType(module, types[i]) < 0) { + return -1; } } if (PyType_Ready(&PyDateTime_IsoCalendarDateType) < 0) { - return NULL; + return -1; } - Py_INCREF(&PyDateTime_IsoCalendarDateType); - - /* timedelta values */ - d = PyDateTime_DeltaType.tp_dict; - - x = new_delta(0, 0, 1, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); - x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); +#define DATETIME_ADD_MACRO(dict, c, value_expr) \ + do { \ + PyObject *value = (value_expr); \ + if (value == NULL) { \ + return -1; \ + } \ + if (PyDict_SetItemString(dict, c, value) < 0) { \ + Py_DECREF(value); \ + return -1; \ + } \ + Py_DECREF(value); \ + } while(0) - x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); + /* timedelta values */ + PyObject *d = PyDateTime_DeltaType.tp_dict; + DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0)); + DATETIME_ADD_MACRO(d, "min", new_delta(-MAX_DELTA_DAYS, 0, 0, 0)); + DATETIME_ADD_MACRO(d, "max", + new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0)); /* date values */ d = PyDateTime_DateType.tp_dict; - - x = new_date(1, 1, 1); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_date(MAXYEAR, 12, 31); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(1, 0, 0, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); + DATETIME_ADD_MACRO(d, "min", new_date(1, 1, 1)); + DATETIME_ADD_MACRO(d, "max", new_date(MAXYEAR, 12, 31)); + DATETIME_ADD_MACRO(d, "resolution", new_delta(1, 0, 0, 0)); /* time values */ d = PyDateTime_TimeType.tp_dict; - - x = new_time(0, 0, 0, 0, Py_None, 0); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_time(23, 59, 59, 999999, Py_None, 0); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(0, 0, 1, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); + DATETIME_ADD_MACRO(d, "min", new_time(0, 0, 0, 0, Py_None, 0)); + DATETIME_ADD_MACRO(d, "max", new_time(23, 59, 59, 999999, Py_None, 0)); + DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0)); /* datetime values */ d = PyDateTime_DateTimeType.tp_dict; - - x = new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None, 0); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(0, 0, 1, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); + DATETIME_ADD_MACRO(d, "min", + new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0)); + DATETIME_ADD_MACRO(d, "max", new_datetime(MAXYEAR, 12, 31, 23, 59, 59, + 999999, Py_None, 0)); + DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0)); /* timezone values */ d = PyDateTime_TimeZoneType.tp_dict; + PyObject *delta = new_delta(0, 0, 0, 0); + if (delta == NULL) { + return -1; + } - delta = new_delta(0, 0, 0, 0); - if (delta == NULL) - return NULL; - x = create_timezone(delta, NULL); + PyObject *x = create_timezone(delta, NULL); Py_DECREF(delta); - if (x == NULL || PyDict_SetItemString(d, "utc", x) < 0) - return NULL; + if (x == NULL) { + return -1; + } + if (PyDict_SetItemString(d, "utc", x) < 0) { + Py_DECREF(x); + return -1; + } + PyDateTime_TimeZone_UTC = x; CAPI.TimeZone_UTC = PyDateTime_TimeZone_UTC; @@ -6636,37 +6587,47 @@ PyInit__datetime(void) * compatibility, even though the constructor will accept a wider range of * values. This may change in the future.*/ delta = new_delta(-1, 60, 0, 1); /* -23:59 */ - if (delta == NULL) - return NULL; + if (delta == NULL) { + return -1; + } + x = create_timezone(delta, NULL); Py_DECREF(delta); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); + DATETIME_ADD_MACRO(d, "min", x); delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0); /* +23:59 */ - if (delta == NULL) - return NULL; + if (delta == NULL) { + return -1; + } + x = create_timezone(delta, NULL); Py_DECREF(delta); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); + DATETIME_ADD_MACRO(d, "max", x); /* Epoch */ PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, PyDateTime_TimeZone_UTC, 0); - if (PyDateTime_Epoch == NULL) - return NULL; + if (PyDateTime_Epoch == NULL) { + return -1; + } /* module initialization */ - PyModule_AddIntMacro(m, MINYEAR); - PyModule_AddIntMacro(m, MAXYEAR); + if (PyModule_AddIntMacro(module, MINYEAR) < 0) { + return -1; + } + if (PyModule_AddIntMacro(module, MAXYEAR) < 0) { + return -1; + } x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL); - if (x == NULL) - return NULL; - PyModule_AddObject(m, "datetime_CAPI", x); + if (x == NULL) { + return -1; + } + + if (PyModule_AddObject(module, "datetime_CAPI", x) < 0) { + Py_DECREF(x); + return -1; + } /* A 4-year cycle has an extra leap day over what we'd get from * pasting together 4 single years. @@ -6691,8 +6652,9 @@ PyInit__datetime(void) us_per_minute = PyLong_FromLong(60000000); seconds_per_day = PyLong_FromLong(24 * 3600); if (us_per_ms == NULL || us_per_second == NULL || - us_per_minute == NULL || seconds_per_day == NULL) - return NULL; + us_per_minute == NULL || seconds_per_day == NULL) { + return -1; + } /* The rest are too big for 32-bit ints, but even * us_per_week fits in 40 bits, so doubles should be exact. @@ -6700,9 +6662,33 @@ PyInit__datetime(void) us_per_hour = PyLong_FromDouble(3600000000.0); us_per_day = PyLong_FromDouble(86400000000.0); us_per_week = PyLong_FromDouble(604800000000.0); - if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) + if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) { + return -1; + } + return 0; +} + +static struct PyModuleDef datetimemodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_datetime", + .m_doc = "Fast implementation of the datetime type.", + .m_size = -1, + .m_methods = module_methods, +}; + +PyMODINIT_FUNC +PyInit__datetime(void) +{ + PyObject *mod = PyModule_Create(&datetimemodule); + if (mod == NULL) return NULL; - return m; + + if (_datetime_exec(mod) < 0) { + Py_DECREF(mod); + return NULL; + } + + return mod; } /* --------------------------------------------------------------------------- |