@@ -49,6 +49,10 @@ typedef struct {
4949
5050 /* The interned Unix epoch datetime instance */
5151 PyObject * epoch ;
52+
53+ /* Reference to the interpreter's dict where the current module will be
54+ * reserved even after the referent dict becomes NULL at shutdown. */
55+ PyObject * interp_dict ;
5256} datetime_state ;
5357
5458/* The module has a fixed number of static objects, due to being exposed
@@ -133,18 +137,13 @@ get_current_module(PyInterpreterState *interp, int *p_reloading)
133137 if (dict == NULL ) {
134138 goto error ;
135139 }
136- PyObject * ref = NULL ;
137- if (PyDict_GetItemRef (dict , INTERP_KEY , & ref ) < 0 ) {
140+ if (PyDict_GetItemRef (dict , INTERP_KEY , & mod ) < 0 ) {
138141 goto error ;
139142 }
140- if (ref != NULL ) {
143+ if (mod != NULL ) {
141144 reloading = 1 ;
142- if (ref != Py_None ) {
143- (void )PyWeakref_GetRef (ref , & mod );
144- if (mod == Py_None ) {
145- Py_CLEAR (mod );
146- }
147- Py_DECREF (ref );
145+ if (mod == Py_None ) {
146+ mod = NULL ;
148147 }
149148 }
150149 if (p_reloading != NULL ) {
@@ -159,124 +158,59 @@ get_current_module(PyInterpreterState *interp, int *p_reloading)
159158
160159static PyModuleDef datetimemodule ;
161160
162- static datetime_state *
163- _get_current_state ( PyObject * * p_mod )
161+ static inline datetime_state *
162+ get_current_state ( )
164163{
165164 PyInterpreterState * interp = PyInterpreterState_Get ();
166- PyObject * mod = get_current_module (interp , NULL );
167- if (mod == NULL ) {
168- assert (!PyErr_Occurred ());
169- if (PyErr_Occurred ()) {
170- return NULL ;
171- }
172- /* The static types can outlive the module,
173- * so we must re-import the module. */
174- mod = PyImport_ImportModule ("_datetime" );
175- if (mod == NULL ) {
176- PyErr_Clear ();
177- /* Create a module at shutdown */
178- PyObject * dict = PyInterpreterState_GetDict (interp );
179- if (dict == NULL ) {
180- return NULL ;
181- }
182- PyObject * spec ;
183- if (PyDict_GetItemStringRef (dict , "datetime_module_spec" , & spec ) != 1 ) {
184- return NULL ;
185- }
186- mod = PyModule_FromDefAndSpec (& datetimemodule , spec );
187- if (mod == NULL ) {
188- Py_DECREF (spec );
189- return NULL ;
190- }
191- Py_DECREF (spec );
192-
193- /* The module will be held by heaptypes. Prefer
194- * it not to be stored in the interpreter's dict. */
195- if (PyModule_ExecDef (mod , & datetimemodule ) < 0 ) {
196- return NULL ;
197- }
198- }
199- }
200- datetime_state * st = get_module_state (mod );
201- * p_mod = mod ;
202- return st ;
165+ void * state = interp -> datetime_module_state ;
166+ assert (state != NULL );
167+ return (datetime_state * )state ;
203168}
204169
205- #define GET_CURRENT_STATE (MOD_VAR ) \
206- _get_current_state(&MOD_VAR)
207- #define RELEASE_CURRENT_STATE (ST_VAR , MOD_VAR ) \
208- Py_DECREF(MOD_VAR)
209-
210170static int
211- set_current_module (PyInterpreterState * interp , PyObject * mod )
171+ set_current_module (datetime_state * st ,
172+ PyInterpreterState * interp , PyObject * mod )
212173{
213174 assert (mod != NULL );
214- PyObject * dict = PyInterpreterState_GetDict ( interp ) ;
175+ PyObject * dict = st -> interp_dict ;
215176 if (dict == NULL ) {
216177 return -1 ;
217178 }
218- PyObject * ref = PyWeakref_NewRef (mod , NULL );
219- if (ref == NULL ) {
220- return -1 ;
221- }
222- if (PyDict_SetItem (dict , INTERP_KEY , ref ) < 0 ) {
223- Py_DECREF (ref );
224- return -1 ;
225- }
226- Py_DECREF (ref );
227-
228- /* Make the module spec remain in the interpreter's dict. Not required,
229- * but reserve the new one for memory efficiency. */
230- PyObject * mod_dict = PyModule_GetDict (mod );
231- if (mod_dict == NULL ) {
232- return -1 ;
233- }
234- PyObject * spec ;
235- if (PyDict_GetItemRef (mod_dict , & _Py_ID (__spec__ ), & spec ) != 1 ) {
236- return -1 ;
237- }
238- if (PyDict_SetItemString (dict , "datetime_module_spec" , spec ) < 0 ) {
239- Py_DECREF (spec );
179+ if (PyDict_SetItem (dict , INTERP_KEY , mod ) < 0 ) {
240180 return -1 ;
241181 }
242- Py_DECREF ( spec ) ;
182+ interp -> datetime_module_state = st ;
243183 return 0 ;
244184}
245185
246186static void
247- clear_current_module (PyInterpreterState * interp , PyObject * expected )
187+ clear_current_module (datetime_state * st ,
188+ PyInterpreterState * interp , PyObject * expected )
248189{
249- PyObject * exc = PyErr_GetRaisedException ();
250-
251- PyObject * dict = PyInterpreterState_GetDict (interp );
190+ PyObject * dict = st -> interp_dict ;
252191 if (dict == NULL ) {
253- goto error ;
192+ return ; /* Already cleared */
254193 }
255194
195+ PyObject * exc = PyErr_GetRaisedException ();
196+
256197 if (expected != NULL ) {
257- PyObject * ref = NULL ;
258- if (PyDict_GetItemRef (dict , INTERP_KEY , & ref ) < 0 ) {
198+ PyObject * current ;
199+ if (PyDict_GetItemRef (dict , INTERP_KEY , & current ) < 0 ) {
259200 goto error ;
260201 }
261- if (ref != NULL ) {
262- PyObject * current = NULL ;
263- int rc = PyWeakref_GetRef (ref , & current );
264- /* We only need "current" for pointer comparison. */
265- Py_XDECREF (current );
266- Py_DECREF (ref );
267- if (rc < 0 ) {
268- goto error ;
269- }
270- if (current != expected ) {
271- goto finally ;
272- }
202+ /* We only need "current" for pointer comparison. */
203+ Py_XDECREF (current );
204+ if (current != expected ) {
205+ goto finally ;
273206 }
274207 }
275208
276209 /* We use None to identify that the module was previously loaded. */
277210 if (PyDict_SetItem (dict , INTERP_KEY , Py_None ) < 0 ) {
278211 goto error ;
279212 }
213+ interp -> datetime_module_state = NULL ;
280214
281215 goto finally ;
282216
@@ -2147,8 +2081,7 @@ delta_to_microseconds(PyDateTime_Delta *self)
21472081 PyObject * x3 = NULL ;
21482082 PyObject * result = NULL ;
21492083
2150- PyObject * current_mod = NULL ;
2151- datetime_state * st = GET_CURRENT_STATE (current_mod );
2084+ datetime_state * st = get_current_state ();
21522085
21532086 x1 = PyLong_FromLong (GET_TD_DAYS (self ));
21542087 if (x1 == NULL )
@@ -2186,7 +2119,6 @@ delta_to_microseconds(PyDateTime_Delta *self)
21862119 Py_XDECREF (x1 );
21872120 Py_XDECREF (x2 );
21882121 Py_XDECREF (x3 );
2189- RELEASE_CURRENT_STATE (st , current_mod );
21902122 return result ;
21912123}
21922124
@@ -2226,8 +2158,7 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
22262158 PyObject * num = NULL ;
22272159 PyObject * result = NULL ;
22282160
2229- PyObject * current_mod = NULL ;
2230- datetime_state * st = GET_CURRENT_STATE (current_mod );
2161+ datetime_state * st = get_current_state ();
22312162
22322163 tuple = checked_divmod (pyus , CONST_US_PER_SECOND (st ));
22332164 if (tuple == NULL ) {
@@ -2272,7 +2203,6 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
22722203Done :
22732204 Py_XDECREF (tuple );
22742205 Py_XDECREF (num );
2275- RELEASE_CURRENT_STATE (st , current_mod );
22762206 return result ;
22772207
22782208BadDivmod :
@@ -2811,8 +2741,7 @@ delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
28112741{
28122742 PyObject * self = NULL ;
28132743
2814- PyObject * current_mod = NULL ;
2815- datetime_state * st = GET_CURRENT_STATE (current_mod );
2744+ datetime_state * st = get_current_state ();
28162745
28172746 /* Argument objects. */
28182747 PyObject * day = NULL ;
@@ -2917,7 +2846,6 @@ delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
29172846 Py_DECREF (x );
29182847
29192848Done :
2920- RELEASE_CURRENT_STATE (st , current_mod );
29212849 return self ;
29222850
29232851#undef CLEANUP
@@ -3030,12 +2958,10 @@ delta_total_seconds(PyObject *op, PyObject *Py_UNUSED(dummy))
30302958 if (total_microseconds == NULL )
30312959 return NULL ;
30322960
3033- PyObject * current_mod = NULL ;
3034- datetime_state * st = GET_CURRENT_STATE (current_mod );
2961+ datetime_state * st = get_current_state ();
30352962
30362963 total_seconds = PyNumber_TrueDivide (total_microseconds , CONST_US_PER_SECOND (st ));
30372964
3038- RELEASE_CURRENT_STATE (st , current_mod );
30392965 Py_DECREF (total_microseconds );
30402966 return total_seconds ;
30412967}
@@ -3813,12 +3739,10 @@ date_isocalendar(PyObject *self, PyObject *Py_UNUSED(dummy))
38133739 week = 0 ;
38143740 }
38153741
3816- PyObject * current_mod = NULL ;
3817- datetime_state * st = GET_CURRENT_STATE (current_mod );
3742+ datetime_state * st = get_current_state ();
38183743
38193744 PyObject * v = iso_calendar_date_new_impl (ISOCALENDAR_DATE_TYPE (st ),
38203745 year , week + 1 , day + 1 );
3821- RELEASE_CURRENT_STATE (st , current_mod );
38223746 if (v == NULL ) {
38233747 return NULL ;
38243748 }
@@ -6638,11 +6562,9 @@ local_timezone(PyDateTime_DateTime *utc_time)
66386562 PyObject * one_second ;
66396563 PyObject * seconds ;
66406564
6641- PyObject * current_mod = NULL ;
6642- datetime_state * st = GET_CURRENT_STATE (current_mod );
6565+ datetime_state * st = get_current_state ();
66436566
66446567 delta = datetime_subtract ((PyObject * )utc_time , CONST_EPOCH (st ));
6645- RELEASE_CURRENT_STATE (st , current_mod );
66466568 if (delta == NULL )
66476569 return NULL ;
66486570
@@ -6882,12 +6804,10 @@ datetime_timestamp(PyObject *op, PyObject *Py_UNUSED(dummy))
68826804 PyObject * result ;
68836805
68846806 if (HASTZINFO (self ) && self -> tzinfo != Py_None ) {
6885- PyObject * current_mod = NULL ;
6886- datetime_state * st = GET_CURRENT_STATE (current_mod );
6807+ datetime_state * st = get_current_state ();
68876808
68886809 PyObject * delta ;
68896810 delta = datetime_subtract (op , CONST_EPOCH (st ));
6890- RELEASE_CURRENT_STATE (st , current_mod );
68916811 if (delta == NULL )
68926812 return NULL ;
68936813 result = delta_total_seconds (delta , NULL );
@@ -7252,8 +7172,15 @@ create_timezone_from_delta(int days, int sec, int ms, int normalize)
72527172 */
72537173
72547174static int
7255- init_state (datetime_state * st , PyObject * module , PyObject * old_module )
7175+ init_state (datetime_state * st ,
7176+ PyInterpreterState * interp , PyObject * module , PyObject * old_module )
72567177{
7178+ PyObject * dict = PyInterpreterState_GetDict (interp );
7179+ if (dict == NULL ) {
7180+ return -1 ;
7181+ }
7182+ st -> interp_dict = Py_NewRef (dict );
7183+
72577184 /* Each module gets its own heap types. */
72587185#define ADD_TYPE (FIELD , SPEC , BASE ) \
72597186 do { \
@@ -7272,6 +7199,7 @@ init_state(datetime_state *st, PyObject *module, PyObject *old_module)
72727199 assert (old_module != module );
72737200 datetime_state * st_old = get_module_state (old_module );
72747201 * st = (datetime_state ){
7202+ .interp_dict = st -> interp_dict ,
72757203 .isocalendar_date_type = st -> isocalendar_date_type ,
72767204 .us_per_ms = Py_NewRef (st_old -> us_per_ms ),
72777205 .us_per_second = Py_NewRef (st_old -> us_per_second ),
@@ -7331,9 +7259,8 @@ init_state(datetime_state *st, PyObject *module, PyObject *old_module)
73317259static int
73327260traverse_state (datetime_state * st , visitproc visit , void * arg )
73337261{
7334- /* heap types */
73357262 Py_VISIT (st -> isocalendar_date_type );
7336-
7263+ Py_VISIT ( st -> interp_dict );
73377264 return 0 ;
73387265}
73397266
@@ -7349,6 +7276,7 @@ clear_state(datetime_state *st)
73497276 Py_CLEAR (st -> us_per_week );
73507277 Py_CLEAR (st -> seconds_per_day );
73517278 Py_CLEAR (st -> epoch );
7279+ Py_CLEAR (st -> interp_dict );
73527280 return 0 ;
73537281}
73547282
@@ -7416,7 +7344,7 @@ _datetime_exec(PyObject *module)
74167344 }
74177345 }
74187346
7419- if (init_state (st , module , old_module ) < 0 ) {
7347+ if (init_state (st , interp , module , old_module ) < 0 ) {
74207348 goto error ;
74217349 }
74227350
@@ -7522,7 +7450,7 @@ _datetime_exec(PyObject *module)
75227450 static_assert (DI100Y == 25 * DI4Y - 1 , "DI100Y" );
75237451 assert (DI100Y == days_before_year (100 + 1 ));
75247452
7525- if (set_current_module (interp , module ) < 0 ) {
7453+ if (set_current_module (st , interp , module ) < 0 ) {
75267454 goto error ;
75277455 }
75287456
@@ -7556,10 +7484,9 @@ static int
75567484module_clear (PyObject * mod )
75577485{
75587486 datetime_state * st = get_module_state (mod );
7559- clear_state (st );
7560-
75617487 PyInterpreterState * interp = PyInterpreterState_Get ();
7562- clear_current_module (interp , mod );
7488+ clear_current_module (st , interp , mod );
7489+ clear_state (st );
75637490
75647491 // The runtime takes care of the static types for us.
75657492 // See _PyTypes_FiniExtTypes()..
0 commit comments