10000 gh-71587: Isolate `_datetime` by erlend-aasland · Pull Request #102995 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-71587: Isolate _datetime #102995

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

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
00c0ef0
Consistency: use explicit initialiser for m_base
erlend-aasland Feb 15, 2023
d1bbebb
Add module state stub; establish global state on stack
erlend-aasland Feb 15, 2023
efeea77
Put conversion factors in state struct
erlend-aasland Feb 15, 2023
ef4a4c2
Move PyDateTime_TimeZone_UTC to state
erlend-aasland Feb 15, 2023
9e3f693
Move PyDateTime_Epoch to state struct
erlend-aasland Feb 15, 2023
5bd60b2
Remove datetime_strptime globals entry
erlend-aasland Feb 15, 2023
b5c051b
Add heap type machinery
erlend-aasland Feb 15, 2023
0b23934
PyDateTime_DateTimeType
erlend-aasland Feb 21, 2023
9184c37
PyDateTime_DateType
erlend-aasland Feb 21, 2023
d890013
PyDateTime_DeltaType
erlend-aasland Feb 21, 2023
780f261
PyDateTime_IsoCalendarDateType
erlend-aasland Feb 21, 2023
2d16589
Regen clinic
erlend-aasland Feb 21, 2023
5566ce5
PyDateTime_TZInfoType and PyDateTime_TimeZoneType
erlend-aasland Feb 21, 2023
89775f3
PyDateTime_TimeType
erlend-aasland Feb 21, 2023
e798939
Visit and clear all types
erlend-aasland Feb 21, 2023
78e0023
Get rid of GLOBAL_STATE
erlend-aasland Feb 21, 2023
d392c1a
Fix binary ops
erlend-aasland Feb 25, 2023
7aaf57f
Unexpose IsoCalendarType
erlend-aasland Feb 25, 2023
206cdcc
_PyType_GetModuleState
erlend-aasland Feb 25, 2023
304ca28
Pull in main
erlend-aasland Mar 24, 2023
8c53fa1
Remove time/datetime memory optimisation
erlend-aasland Mar 24, 2023
b583954
Remove unused get_module_state_by_cls() helper
erlend-aasland Mar 24, 2023
32211b8
Move _strptime import to state
erlend-aasland Mar 24, 2023
47862e8
Add NEWS
erlend-aasland Mar 24, 2023
4eee17c
Pull in main
erlend-aasland Apr 28, 2023
2be3e95
Pull in main
erlend-aasland Oct 6, 2023
d97dfb0
Fix merge
erlend-aasland Oct 6, 2023
f024817
Apply suggestions from code review
erlend-aasland Oct 6, 2023
c23dd20
Address review: remove unused clinic_state() macro
erlend-aasland Oct 6, 2023
a30bfdb
Improve CREATE_TYPE macro
erlend-aasland Oct 6, 2023
d152b4c
Address review: Py_CLEAR state
erlend-aasland Oct 6, 2023
18b9007
Address review: visit and clear module state in member order
erlend-aasland Oct 6, 2023
0ee2374
Regen clinic
erlend-aasland Oct 6, 2023
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
Prev Previous commit
Next Next commit
PyDateTime_TZInfoType and PyDateTime_TimeZoneType
  • Loading branch information
erlend-aasland committed Feb 25, 2023
commit 5566ce5871fc06d2937ae8a8c738a2846bf10c78
189 changes: 91 additions & 98 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,9 @@
#define PyTime_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_TimeType)

#define PyDelta_Check(st, op) PyObject_TypeCheck(op, (st)->PyDateTime_DeltaType)
#define PyTZInfo_Check(st, op) PyObject_TypeCheck(op, (st)->PyDateTime_TZInfoType)

#define PyTZInfo_Check(op) PyObject_TypeCheck(op, &PyDateTime_TZInfoType)
#define PyTZInfo_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_TZInfoType)

#define PyTimezone_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeZoneType)
#define PyTimezone_Check(st, op) PyObject_TypeCheck(op, (st)->PyDateTime_TimeZoneType)

typedef struct {
/* Conversion factors. */
Expand All @@ -57,6 +55,8 @@ typedef struct {
PyTypeObject *PyDateTime_DateType;
PyTypeObject *PyDateTime_DeltaType;
PyTypeObject *PyDateTime_IsoCalendarDateType;
PyTypeObject *PyDateTime_TZInfoType;
PyTypeObject *PyDateTime_TimeZoneType;
} datetime_state;

static datetime_state global_state;
Expand Down Expand Up @@ -156,8 +156,6 @@ class datetime.IsoCalendarDate "PyDateTime_IsoCalendarDate *" "clinic_state()->P

/* Forward declarations. */
static PyTypeObject PyDateTime_TimeType;
static PyTypeObject PyDateTime_TZInfoType;
static PyTypeObject PyDateTime_TimeZoneType;

static int check_tzinfo_subclass(PyObject *p);

Expand Down Expand Up @@ -1169,9 +1167,9 @@ typedef struct
static PyObject *
create_timezone(PyObject *offset, PyObject *name)
{
PyDateTime_TimeZone *self;
PyTypeObject *type = &PyDateTime_TimeZoneType;
datetime_state *st = GLOBAL_STATE();
PyDateTime_TimeZone *self;
PyTypeObject *type = st->PyDateTime_TimeZoneType;
assert(offset != NULL);
assert(PyDelta_Check(st, offset));
assert(name == NULL || PyUnicode_Check(name));
Expand Down Expand Up @@ -1223,7 +1221,8 @@ new_timezone(PyObject *offset, PyObject *name)
static int
check_tzinfo_subclass(PyObject *p)
{
if (p == Py_None || PyTZInfo_Check(p))
datetime_state *st = GLOBAL_STATE();
if (p == Py_None || PyTZInfo_Check(st, p))
return 0;
PyErr_Format(PyExc_TypeError,
"tzinfo argument must be None or of a tzinfo subclass, "
Expand Down Expand Up @@ -1262,16 +1261,16 @@ call_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg)
{
PyObject *offset;

datetime_state *st = GLOBAL_STATE();
assert(tzinfo != NULL);
assert(PyTZInfo_Check(tzinfo) || tzinfo == Py_None);
assert(PyTZInfo_Check(st, tzinfo) || tzinfo == Py_None);
assert(tzinfoarg != NULL);

if (tzinfo == Py_None)
Py_RETURN_NONE;
offset = PyObject_CallMethod(tzinfo, name, "O", tzinfoarg);
if (offset == Py_None || offset == NULL)
return offset;
datetime_state *st = GLOBAL_STATE();
if (PyDelta_Check(st, offset)) {
if ((GET_TD_DAYS(offset) == -1 &&
GET_TD_SECONDS(offset) == 0 &&
Expand Down Expand Up @@ -3844,6 +3843,22 @@ tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
return Py_BuildValue("(ONN)", Py_TYPE(self), args, state);
}

static int
tzinfo_traverse(PyObject *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
return 0;
}

static void
tzinfo_dealloc(PyObject *self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
tp->tp_free(self);
Py_DECREF(tp);
}

static PyMethodDef tzinfo_methods[] = {

{"tzname", (PyCFunction)tzinfo_tzname, METH_O,
Expand All @@ -3868,46 +3883,22 @@ static PyMethodDef tzinfo_methods[] = {
static const char tzinfo_doc[] =
PyDoc_STR("Abstract base class for time zone info objects.");

static PyTypeObject PyDateTime_TZInfoType = {
PyVarObject_HEAD_INIT(NULL, 0)
"datetime.tzinfo", /* tp_name */
sizeof(PyDateTime_TZInfo), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
tzinfo_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
tzinfo_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
0, /* tp_free */
static PyType_Slot tzinfo_slots[] = {
{Py_tp_doc, (void *)tzinfo_doc},
{Py_tp_methods, tzinfo_methods},
{Py_tp_dealloc, tzinfo_dealloc},
{Py_tp_traverse, tzinfo_traverse},
{0, NULL},
};

static PyType_Spec tzinfo_spec = {
.name = "datetime.tzinfo",
.basicsize = sizeof(PyDateTime_TZInfo),
.flags = (Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = tzinfo_slots,
};

static char *timezone_kws[] = {"offset", "name", NULL};
Expand All @@ -3925,12 +3916,31 @@ timezone_new(PyTypeObject *type, PyObject *args, PyObject *kw)
return NULL;
}

static void
timezone_dealloc(PyDateTime_TimeZone *self)
static int
timezone_traverse(PyDateTime_TimeZone *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->offset);
Py_VISIT(self->name);
return 0;
}

static int
timezone_clear(PyDateTime_TimeZone *self)
{
Py_CLEAR(self->offset);
Py_CLEAR(self->name);
return 0;
}

static void
timezone_dealloc(PyDateTime_TimeZone *self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
(void)timezone_clear(self);
Py_TYPE(self)->tp_free((PyObject *)self);
Py_DECREF(tp);
}

static PyObject *
Expand All @@ -3939,7 +3949,8 @@ timezone_richcompare(PyDateTime_TimeZone *self,
{
if (op != Py_EQ && op != Py_NE)
Py_RETURN_NOTIMPLEMENTED;
if (!PyTimezone_Check(other)) {
datetime_state *st = GLOBAL_STATE();
if (!PyTimezone_Check(st, other)) {
Py_RETURN_NOTIMPLEMENTED;
}
return delta_richcompare(self->offset, other->offset, op);
Expand Down Expand Up @@ -4106,45 +4117,27 @@ static PyMethodDef timezone_methods[] = {
static const char timezone_doc[] =
PyDoc_STR("Fixed offset from UTC implementation of tzinfo.");

static PyTypeObject PyDateTime_TimeZoneType = {
PyVarObject_HEAD_INIT(NULL, 0)
"datetime.timezone", /* tp_name */
sizeof(PyDateTime_TimeZone), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)timezone_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)timezone_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)timezone_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)timezone_str, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
timezone_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)timezone_richcompare,/* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
timezone_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base; filled in PyInit__datetime */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
timezone_new, /* tp_new */
static PyType_Slot timezone_slots[] = {
{Py_tp_dealloc, timezone_dealloc},
{Py_tp_traverse, timezone_traverse},
{Py_tp_clear, timezone_clear},
{Py_tp_repr, timezone_repr},
{Py_tp_hash, timezone_hash},
{Py_tp_str, timezone_str},
{Py_tp_doc, (void *)timezone_doc},
{Py_tp_richcompare, timezone_richcompare},
{Py_tp_methods, timezone_methods},
{Py_tp_new, timezone_new},
{0, NULL},
};

static PyType_Spec timezone_spec = {
.name = "datetime.timezone",
.basicsize = sizeof(PyDateTime_TimeZone),
.flags = (Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = timezone_slots,
};

/*
Expand Down Expand Up @@ -6694,7 +6687,7 @@ get_datetime_capi(datetime_state *st)
capi->DateTimeType = st->PyDateTime_DateTimeType;
capi->TimeType = &PyDateTime_TimeType;
capi->DeltaType = st->PyDateTime_DeltaType;
capi->TZInfoType = &PyDateTime_TZInfoType;
capi->TZInfoType = st->PyDateTime_TZInfoType;
capi->Date_FromDate = new_date_ex;
capi->DateTime_FromDateAndTime = new_datetime_ex;
capi->Time_FromTime = new_time_ex;
Expand Down Expand Up @@ -6738,12 +6731,9 @@ _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_TimeZoneType.tp_base = &PyDateTime_TZInfoType;

PyTypeObject *types[] = {
&PyDateTime_TimeType,
&PyDateTime_TZInfoType,
&PyDateTime_TimeZoneType,
};

for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) {
Expand All @@ -6752,6 +6742,9 @@ _datetime_exec(PyObject *module)
}
}

ADD_TYPE(module, st->PyDateTime_TZInfoType, &tzinfo_spec, NULL);
ADD_TYPE(module, st->PyDateTime_TimeZoneType, &timezone_spec,
st->PyDateTime_TZInfoType);
ADD_TYPE(module, st->PyDateTime_IsoCalendarDateType, &isocal_spec,
&PyTuple_Type);
ADD_TYPE(module, st->PyDateTime_DeltaType, &delta_spec, NULL);
Expand Down Expand Up @@ -6802,7 +6795,7 @@ _datetime_exec(PyObject *module)
DATETIME_ADD_MACRO(d, "resolution", new_delta(st, 0, 0, 1, 0));

/* timezone values */
d = PyDateTime_TimeZoneType.tp_dict;
d = st->PyDateTime_TimeZoneType->tp_dict;
PyObject *delta = new_delta(st, 0, 0, 0, 0);
if (delta == NULL) {
return -1;
Expand Down
2 changes: 0 additions & 2 deletions Tools/c-analyzer/cpython/globals-to-fix.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,7 @@ Modules/_ctypes/ctypes.h - _ctypes_ptrtype_cache -
Modules/_ctypes/ctypes.h - basespec_string -
Modules/_ctypes/stgdict.c - PyCStgDict_Type -
Modules/_cursesmodule.c - PyCursesWindow_Type -
Modules/_datetimemodule.c - PyDateTime_TZInfoType -
Modules/_datetimemodule.c - PyDateTime_TimeType -
Modules/_datetimemodule.c - PyDateTime_TimeZoneType -
Modules/_decimal/_decimal.c - PyDecContextManager_Type -
Modules/_decimal/_decimal.c - PyDecContext_Type -
Modules/_decimal/_decimal.c - PyDecSignalDictMixin_Type -
Expand Down
0