Skip to content

Commit 5e71905

Browse files
Add NO_TTINFO to global state
1 parent 4749890 commit 5e71905

File tree

2 files changed

+188
-30
lines changed

2 files changed

+188
-30
lines changed

Modules/_zoneinfo.c

Lines changed: 56 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,12 @@ typedef struct {
9797
PyObject *TIMEDELTA_CACHE;
9898
PyObject *ZONEINFO_WEAK_CACHE;
9999
StrongCacheNode *ZONEINFO_STRONG_CACHE;
100+
_ttinfo NO_TTINFO;
100101
} zoneinfo_state;
101102

102103
// Globals
103104
static zoneinfo_state global_state;
104105

105-
static _ttinfo NO_TTINFO = {NULL, NULL, NULL, 0};
106-
107106
// Constants
108107
static const int EPOCHORDINAL = 719163;
109108
static int DAYS_IN_MONTH[] = {
@@ -173,7 +172,7 @@ load_timedelta(zoneinfo_state *state, long seconds);
173172
static int
174173
get_local_timestamp(PyObject *dt, int64_t *local_ts);
175174
static _ttinfo *
176-
find_ttinfo(PyZoneInfo_ZoneInfo *self, PyObject *dt);
175+
find_ttinfo(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *dt);
177176

178177
static int
179178
ymd_to_ord(int y, int m, int d);
@@ -533,32 +532,70 @@ zoneinfo_ZoneInfo_clear_cache_impl(PyTypeObject *type, PyTypeObject *cls,
533532
Py_RETURN_NONE;
534533
}
535534

535+
/*[clinic input]
536+
zoneinfo.ZoneInfo.utcoffset
537+
538+
cls: defining_class
539+
dt: object
540+
/
541+
542+
Retrieve a timedelta representing the UTC offset in a zone at the given datetime.
543+
[clinic start generated code]*/
544+
536545
static PyObject *
537-
zoneinfo_utcoffset(PyObject *self, PyObject *dt)
546+
zoneinfo_ZoneInfo_utcoffset_impl(PyObject *self, PyTypeObject *cls,
547+
PyObject *dt)
548+
/*[clinic end generated code: output=b71016c319ba1f91 input=2bb6c5364938f19c]*/
538549
{
539-
_ttinfo *tti = find_ttinfo((PyZoneInfo_ZoneInfo *)self, dt);
550+
zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
551+
_ttinfo *tti = find_ttinfo(state, (PyZoneInfo_ZoneInfo *)self, dt);
540552
if (tti == NULL) {
541553
return NULL;
542554
}
543555
Py_INCREF(tti->utcoff);
544556
return tti->utcoff;
545557
}
546558

559+
/*[clinic input]
560+
zoneinfo.ZoneInfo.dst
561+
562+
cls: defining_class
563+
dt: object
564+
/
565+
566+
Retrieve a timedelta representing the amount of DST applied in a zone at the given datetime.
567+
[clinic start generated code]*/
568+
547569
static PyObject *
548-
zoneinfo_dst(PyObject *self, PyObject *dt)
570+
zoneinfo_ZoneInfo_dst_impl(PyObject *self, PyTypeObject *cls, PyObject *dt)
571+
/*[clinic end generated code: output=cb6168d7723a6ae6 input=2167fb80cf8645c6]*/
549572
{
550-
_ttinfo *tti = find_ttinfo((PyZoneInfo_ZoneInfo *)self, dt);
573+
zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
574+
_ttinfo *tti = find_ttinfo(state, (PyZoneInfo_ZoneInfo *)self, dt);
551575
if (tti == NULL) {
552576
return NULL;
553577
}
554578
Py_INCREF(tti->dstoff);
555579
return tti->dstoff;
556580
}
557581

582+
/*[clinic input]
583+
zoneinfo.ZoneInfo.tzname
584+
585+
cls: defining_class
586+
dt: object
587+
/
588+
589+
Retrieve a string containing the abbreviation for the time zone that applies in a zone at a given datetime.
590+
[clinic start generated code]*/
591+
558592
static PyObject *
559-
zoneinfo_tzname(PyObject *self, PyObject *dt)
593+
zoneinfo_ZoneInfo_tzname_impl(PyObject *self, PyTypeObject *cls,
594+
PyObject *dt)
595+
/*[clinic end generated code: output=3b6ae6c3053ea75a input=15a59a4f92ed1f1f]*/
560596
{
561-
_ttinfo *tti = find_ttinfo((PyZoneInfo_ZoneInfo *)self, dt);
597+
zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
598+
_ttinfo *tti = find_ttinfo(state, (PyZoneInfo_ZoneInfo *)self, dt);
562599
if (tti == NULL) {
563600
return NULL;
564601
}
@@ -2213,7 +2250,7 @@ _bisect(const int64_t value, const int64_t *arr, size_t size)
22132250

22142251
/* Find the ttinfo rules that apply at a given local datetime. */
22152252
static _ttinfo *
2216-
find_ttinfo(PyZoneInfo_ZoneInfo *self, PyObject *dt)
2253+
find_ttinfo(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *dt)
22172254
{
22182255
// datetime.time has a .tzinfo attribute that passes None as the dt
22192256
// argument; it only really has meaning for fixed-offset zones.
@@ -2222,7 +2259,7 @@ find_ttinfo(PyZoneInfo_ZoneInfo *self, PyObject *dt)
22222259
return &(self->tzrule_after.std);
22232260
}
22242261
else {
2225-
return &NO_TTINFO;
2262+
return &(state->NO_TTINFO);
22262263
}
22272264
}
22282265

@@ -2644,15 +2681,9 @@ static PyMethodDef zoneinfo_methods[] = {
26442681
ZONEINFO_ZONEINFO_CLEAR_CACHE_METHODDEF
26452682
ZONEINFO_ZONEINFO_NO_CACHE_METHODDEF
26462683
ZONEINFO_ZONEINFO_FROM_FILE_METHODDEF
2647-
{"utcoffset", (PyCFunction)zoneinfo_utcoffset, METH_O,
2648-
PyDoc_STR("Retrieve a timedelta representing the UTC offset in a zone at "
2649-
"the given datetime.")},
2650-
{"dst", (PyCFunction)zoneinfo_dst, METH_O,
2651-
PyDoc_STR("Retrieve a timedelta representing the amount of DST applied "
2652-
"in a zone at the given datetime.")},
2653-
{"tzname", (PyCFunction)zoneinfo_tzname, METH_O,
2654-
PyDoc_STR("Retrieve a string containing the abbreviation for the time "
2655-
"zone that applies in a zone at a given datetime.")},
2684+
ZONEINFO_ZONEINFO_UTCOFFSET_METHODDEF
2685+
ZONEINFO_ZONEINFO_DST_METHODDEF
2686+
ZONEINFO_ZONEINFO_TZNAME_METHODDEF
26562687
{"fromutc", (PyCFunction)zoneinfo_fromutc, METH_O,
26572688
PyDoc_STR("Given a datetime with local time in UTC, retrieve an adjusted "
26582689
"datetime in local time.")},
@@ -2711,7 +2742,7 @@ module_free(void *m)
27112742
Py_CLEAR(state->_tzpath_find_tzfile);
27122743
Py_CLEAR(state->_common_mod);
27132744

2714-
xdecref_ttinfo(&NO_TTINFO);
2745+
xdecref_ttinfo(&(state->NO_TTINFO));
27152746

27162747
if (state->TIMEDELTA_CACHE != NULL &&
27172748
Py_REFCNT(state->TIMEDELTA_CACHE) > 1)
@@ -2773,14 +2804,10 @@ zoneinfomodule_exec(PyObject *m)
27732804
goto error;
27742805
}
27752806

2776-
if (NO_TTINFO.utcoff == NULL) {
2777-
NO_TTINFO.utcoff = Py_None;
2778-
NO_TTINFO.dstoff = Py_None;
2779-
NO_TTINFO.tzname = Py_None;
2780-
2781-
for (size_t i = 0; i < 3; ++i) {
2782-
Py_INCREF(Py_None);
2783-
}
2807+
if (state->NO_TTINFO.utcoff == NULL) {
2808+
state->NO_TTINFO.utcoff = Py_NewRef(Py_None);
2809+
state->NO_TTINFO.dstoff = Py_NewRef(Py_None);
2810+
state->NO_TTINFO.tzname = Py_NewRef(Py_None);
27842811
}
27852812

27862813
if (initialize_caches(state)) {

Modules/clinic/_zoneinfo.c.h

Lines changed: 132 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)