Thanks to visit codestin.com
Credit goes to github.com

Skip to content

bpo-1635741: Enhance _datetime error handling #23139

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 20, 2020
Merged
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
220 changes: 103 additions & 117 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -6537,136 +6514,120 @@ 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;

/* bpo-37642: These attributes are rounded to the nearest minute for backwards
* 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.
Expand All @@ -6691,18 +6652,43 @@ 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.
*/
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;
}

/* ---------------------------------------------------------------------------
Expand Down