summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2024-05-30 16:53:09 (GMT)
committerGitHub <noreply@github.com>2024-05-30 16:53:09 (GMT)
commit5a037b79597e127426a882a333d013bff6b313f6 (patch)
tree3fb620f4386c0da2b0620af3c3412ce501feb6e6 /Modules
parenta7327b31e32f72dccbabac196b3b63d514821944 (diff)
downloadcpython-5a037b79597e127426a882a333d013bff6b313f6.zip
cpython-5a037b79597e127426a882a333d013bff6b313f6.tar.gz
cpython-5a037b79597e127426a882a333d013bff6b313f6.tar.bz2
[3.13] gh-117398: Convert datetime.IsoCalendarDate To A Heap Type (gh-119637) (gh-119695)
This is the only static type in the module that we will not keep static. (cherry picked from commit 548a11d5cf1dbb32d86ce0c045130c77f50c1427) (cherry-picked from commit 34f9b3e7244615d2372614b20e10250e68cc8e61) Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com> Co-authored by: Kirill Podoprigora <kirill.bast9@mail.ru>
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_datetimemodule.c85
1 files changed, 63 insertions, 22 deletions
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index 54383ca..466382b 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -26,14 +26,18 @@
#endif
typedef struct {
+ /* Static types exposed by the datetime C-API. */
PyTypeObject *date_type;
PyTypeObject *datetime_type;
PyTypeObject *delta_type;
- PyTypeObject *isocalendar_date_type;
PyTypeObject *time_type;
PyTypeObject *tzinfo_type;
+ /* Exposed indirectly via TimeZone_UTC. */
PyTypeObject *timezone_type;
+ /* Other module classes. */
+ PyTypeObject *isocalendar_date_type;
+
/* Conversion factors. */
PyObject *us_per_ms; // 1_000
PyObject *us_per_second; // 1_000_000
@@ -3460,17 +3464,40 @@ static PyMethodDef iso_calendar_date_methods[] = {
{NULL, NULL},
};
-static PyTypeObject PyDateTime_IsoCalendarDateType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "datetime.IsoCalendarDate",
- .tp_basicsize = sizeof(PyDateTime_IsoCalendarDate),
- .tp_repr = (reprfunc) iso_calendar_date_repr,
- .tp_flags = Py_TPFLAGS_DEFAULT,
- .tp_doc = iso_calendar_date__doc__,
- .tp_methods = iso_calendar_date_methods,
- .tp_getset = iso_calendar_date_getset,
- // .tp_base = &PyTuple_Type, // filled in PyInit__datetime
- .tp_new = iso_calendar_date_new,
+static int
+iso_calendar_date_traverse(PyDateTime_IsoCalendarDate *self, visitproc visit,
+ void *arg)
+{
+ Py_VISIT(Py_TYPE(self));
+ return PyTuple_Type.tp_traverse((PyObject *)self, visit, arg);
+}
+
+static void
+iso_calendar_date_dealloc(PyDateTime_IsoCalendarDate *self)
+{
+ PyTypeObject *tp = Py_TYPE(self);
+ PyTuple_Type.tp_dealloc((PyObject *)self); // delegate GC-untrack as well
+ Py_DECREF(tp);
+}
+
+static PyType_Slot isocal_slots[] = {
+ {Py_tp_repr, iso_calendar_date_repr},
+ {Py_tp_doc, (void *)iso_calendar_date__doc__},
+ {Py_tp_methods, iso_calendar_date_methods},
+ {Py_tp_getset, iso_calendar_date_getset},
+ {Py_tp_new, iso_calendar_date_new},
+ {Py_tp_dealloc, iso_calendar_date_dealloc},
+ {Py_tp_traverse, iso_calendar_date_traverse},
+ {0, NULL},
+};
+
+static PyType_Spec isocal_spec = {
+ .name = "datetime.IsoCalendarDate",
+ .basicsize = sizeof(PyDateTime_IsoCalendarDate),
+ .flags = (Py_TPFLAGS_DEFAULT |
+ Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = isocal_slots,
};
/*[clinic input]
@@ -6842,7 +6869,7 @@ create_timezone_from_delta(int days, int sec, int ms, int normalize)
}
static int
-init_state(datetime_state *st)
+init_state(datetime_state *st, PyTypeObject *PyDateTime_IsoCalendarDateType)
{
// While datetime uses global module "state", we unly initialize it once.
// The PyLong objects created here (once per process) are not decref'd.
@@ -6850,14 +6877,17 @@ init_state(datetime_state *st)
return 0;
}
+ /* Static types exposed by the C-API. */
st->date_type = &PyDateTime_DateType;
st->datetime_type = &PyDateTime_DateTimeType;
st->delta_type = &PyDateTime_DeltaType;
- st->isocalendar_date_type = &PyDateTime_IsoCalendarDateType;
st->time_type = &PyDateTime_TimeType;
st->tzinfo_type = &PyDateTime_TZInfoType;
st->timezone_type = &PyDateTime_TimeZoneType;
+ /* Per-module heap types. */
+ st->isocalendar_date_type = PyDateTime_IsoCalendarDateType;
+
st->us_per_ms = PyLong_FromLong(1000);
if (st->us_per_ms == NULL) {
return -1;
@@ -6914,11 +6944,10 @@ _datetime_exec(PyObject *module)
// `&...` 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
- PyDateTime_IsoCalendarDateType.tp_base = &PyTuple_Type;
PyDateTime_TimeZoneType.tp_base = &PyDateTime_TZInfoType;
PyDateTime_DateTimeType.tp_base = &PyDateTime_DateType;
- PyTypeObject *types[] = {
+ PyTypeObject *capi_types[] = {
&PyDateTime_DateType,
&PyDateTime_DateTimeType,
&PyDateTime_TimeType,
@@ -6927,18 +6956,30 @@ _datetime_exec(PyObject *module)
&PyDateTime_TimeZoneType,
};
- for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) {
- if (PyModule_AddType(module, types[i]) < 0) {
+ for (size_t i = 0; i < Py_ARRAY_LENGTH(capi_types); i++) {
+ if (PyModule_AddType(module, capi_types[i]) < 0) {
goto error;
}
}
- if (PyType_Ready(&PyDateTime_IsoCalendarDateType) < 0) {
- goto error;
- }
+#define CREATE_TYPE(VAR, SPEC, BASE) \
+ do { \
+ VAR = (PyTypeObject *)PyType_FromModuleAndSpec( \
+ module, SPEC, (PyObject *)BASE); \
+ if (VAR == NULL) { \
+ goto error; \
+ } \
+ } while (0)
+ PyTypeObject *PyDateTime_IsoCalendarDateType = NULL;
datetime_state *st = get_datetime_state();
- if (init_state(st) < 0) {
+
+ if (!st->initialized) {
+ CREATE_TYPE(PyDateTime_IsoCalendarDateType, &isocal_spec, &PyTuple_Type);
+ }
+#undef CREATE_TYPE
+
+ if (init_state(st, PyDateTime_IsoCalendarDateType) < 0) {
goto error;
}