gh-136421: Load `_datetime` static types during interpreter initializ… · python/cpython@a109606

GitHub

GitHub CopilotWrite better code with AI | MCP RegistryIntegrate external tools | ActionsAutomate any workflow | CodespacesInstant dev environments | IssuesPlan and track work | Code ReviewManage code changes | Code QualityEnforce quality at merge | Why GitHub | Marketplace | View all features | Enterprises | Small and medium teams | Startups | View all use cases | View all industries | View all solutions | AI | Software Development | DevOps | Security | View all topics | Customer stories | Events & webinars | Ebooks & reports | Business insights | Trust center | Partners | View all resources

@@ -14,6 +14,7 @@

1414#include"pycore_object.h"// _PyObject_Init()

1515#include"pycore_time.h"// _PyTime_ObjectToTime_t()

1616#include"pycore_unicodeobject.h"// _PyUnicode_Copy()

17+#include"pycore_initconfig.h"// _PyStatus_OK()

17181819#include"datetime.h"

1920@@ -124,10 +125,9 @@ get_module_state(PyObject *module)

124125#defineINTERP_KEY ((PyObject *)&_Py_ID(cached_datetime_module))

125126126127staticPyObject*

127-get_current_module(PyInterpreterState*interp, int*p_reloading)

128+get_current_module(PyInterpreterState*interp)

128129{

129130PyObject*mod=NULL;

130-intreloading=0;

131131132132PyObject*dict=PyInterpreterState_GetDict(interp);

133133if (dict==NULL) {

@@ -138,7 +138,6 @@ get_current_module(PyInterpreterState *interp, int *p_reloading)

138138 goto error;

139139 }

140140if (ref!=NULL) {

141-reloading=1;

142141if (ref!=Py_None) {

143142 (void)PyWeakref_GetRef(ref, &mod);

144143if (mod==Py_None) {

@@ -147,9 +146,6 @@ get_current_module(PyInterpreterState *interp, int *p_reloading)

147146Py_DECREF(ref);

148147 }

149148 }

150-if (p_reloading!=NULL) {

151-*p_reloading=reloading;

152- }

153149returnmod;

154150155151error:

@@ -163,7 +159,7 @@ static datetime_state *

163159_get_current_state(PyObject**p_mod)

164160{

165161PyInterpreterState*interp=PyInterpreterState_Get();

166-PyObject*mod=get_current_module(interp, NULL);

162+PyObject*mod=get_current_module(interp);

167163if (mod==NULL) {

168164assert(!PyErr_Occurred());

169165if (PyErr_Occurred()) {

@@ -4482,7 +4478,7 @@ static PyTypeObject PyDateTime_TimeZoneType = {

44824478timezone_methods, /* tp_methods */

448344790, /* tp_members */

448444800, /* tp_getset */

4485-0, /* tp_base; filled in PyInit__datetime */

4481+&PyDateTime_TZInfoType, /* tp_base */

448644820, /* tp_dict */

448744830, /* tp_descr_get */

448844840, /* tp_descr_set */

@@ -7147,8 +7143,7 @@ static PyTypeObject PyDateTime_DateTimeType = {

71477143datetime_methods, /* tp_methods */

714871440, /* tp_members */

71497145datetime_getset, /* tp_getset */

7150-0, /* tp_base; filled in

7151- PyInit__datetime */

7146+&PyDateTime_DateType, /* tp_base */

715271470, /* tp_dict */

715371480, /* tp_descr_get */

715471490, /* tp_descr_set */

@@ -7329,29 +7324,82 @@ clear_state(datetime_state *st)

73297324}

73307325733173267332-staticint

7333-init_static_types(PyInterpreterState*interp, intreloading)

7327+PyStatus

7328+_PyDateTime_InitTypes(PyInterpreterState*interp)

73347329{

7335-if (reloading) {

7336-return0;

7337- }

7338-7339-// `&...` is not a constant expression according to a strict reading

7340-// of C standards. Fill tp_base at run-time rather than statically.

7341-// See https://bugs.python.org/issue40777

7342-PyDateTime_TimeZoneType.tp_base=&PyDateTime_TZInfoType;

7343-PyDateTime_DateTimeType.tp_base=&PyDateTime_DateType;

7344-73457330/* Bases classes must be initialized before subclasses,

73467331 * so capi_types must have the types in the appropriate order. */

73477332for (size_ti=0; i<Py_ARRAY_LENGTH(capi_types); i++) {

73487333PyTypeObject*type=capi_types[i];

73497334if (_PyStaticType_InitForExtension(interp, type) <0) {

7350-return-1;

7335+return_PyStatus_ERR("could not initialize static types");

73517336 }

73527337 }

735373387354-return0;

7339+#defineDATETIME_ADD_MACRO(dict, c, value_expr) \

7340+ do { \

7341+ assert(!PyErr_Occurred()); \

7342+ PyObject *value = (value_expr); \

7343+ if (value == NULL) { \

7344+ goto error; \

7345+ } \

7346+ if (PyDict_SetItemString(dict, c, value) < 0) { \

7347+ Py_DECREF(value); \

7348+ goto error; \

7349+ } \

7350+ Py_DECREF(value); \

7351+ } while(0)

7352+7353+/* timedelta values */

7354+PyObject*d=_PyType_GetDict(&PyDateTime_DeltaType);

7355+DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));

7356+DATETIME_ADD_MACRO(d, "min", new_delta(-MAX_DELTA_DAYS, 0, 0, 0));

7357+DATETIME_ADD_MACRO(d, "max",

7358+new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0));

7359+7360+/* date values */

7361+d=_PyType_GetDict(&PyDateTime_DateType);

7362+DATETIME_ADD_MACRO(d, "min", new_date(1, 1, 1));

7363+DATETIME_ADD_MACRO(d, "max", new_date(MAXYEAR, 12, 31));

7364+DATETIME_ADD_MACRO(d, "resolution", new_delta(1, 0, 0, 0));

7365+7366+/* time values */

7367+d=_PyType_GetDict(&PyDateTime_TimeType);

7368+DATETIME_ADD_MACRO(d, "min", new_time(0, 0, 0, 0, Py_None, 0));

7369+DATETIME_ADD_MACRO(d, "max", new_time(23, 59, 59, 999999, Py_None, 0));

7370+DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));

7371+7372+/* datetime values */

7373+d=_PyType_GetDict(&PyDateTime_DateTimeType);

7374+DATETIME_ADD_MACRO(d, "min",

7375+new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0));

7376+DATETIME_ADD_MACRO(d, "max", new_datetime(MAXYEAR, 12, 31, 23, 59, 59,

7377+999999, Py_None, 0));

7378+DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));

7379+7380+/* timezone values */

7381+d=_PyType_GetDict(&PyDateTime_TimeZoneType);

7382+if (PyDict_SetItemString(d, "utc", (PyObject*)&utc_timezone) <0) {

7383+ goto error;

7384+ }

7385+7386+/* bpo-37642: These attributes are rounded to the nearest minute for backwards

7387+ * compatibility, even though the constructor will accept a wider range of

7388+ * values. This may change in the future.*/

7389+7390+/* -23:59 */

7391+DATETIME_ADD_MACRO(d, "min", create_timezone_from_delta(-1, 60, 0, 1));

7392+7393+/* +23:59 */

7394+DATETIME_ADD_MACRO(

7395+d, "max", create_timezone_from_delta(0, (23*60+59) *60, 0, 0));

7396+7397+#undef DATETIME_ADD_MACRO

7398+7399+return_PyStatus_OK();

7400+7401+error:

7402+return_PyStatus_NO_MEMORY();

73557403}

7356740473577405@@ -7369,20 +7417,15 @@ _datetime_exec(PyObject *module)

73697417{

73707418intrc=-1;

73717419datetime_state*st=get_module_state(module);

7372-intreloading=0;

7373742073747421PyInterpreterState*interp=PyInterpreterState_Get();

7375-PyObject*old_module=get_current_module(interp, &reloading);

7422+PyObject*old_module=get_current_module(interp);

73767423if (PyErr_Occurred()) {

73777424assert(old_module==NULL);

73787425 goto error;

73797426 }

73807427/* We actually set the "current" module right before a successful return. */

738174287382-if (init_static_types(interp, reloading) <0) {

7383- goto error;

7384- }

7385-73867429for (size_ti=0; i<Py_ARRAY_LENGTH(capi_types); i++) {

73877430PyTypeObject*type=capi_types[i];

73887431constchar*name=_PyType_Name(type);

@@ -7396,68 +7439,6 @@ _datetime_exec(PyObject *module)

73967439 goto error;

73977440 }

739874417399-#defineDATETIME_ADD_MACRO(dict, c, value_expr) \

7400- do { \

7401- assert(!PyErr_Occurred()); \

7402- PyObject *value = (value_expr); \

7403- if (value == NULL) { \

7404- goto error; \

7405- } \

7406- if (PyDict_SetItemString(dict, c, value) < 0) { \

7407- Py_DECREF(value); \

7408- goto error; \

7409- } \

7410- Py_DECREF(value); \

7411- } while(0)

7412-7413-if (!reloading) {

7414-/* timedelta values */

7415-PyObject*d=_PyType_GetDict(&PyDateTime_DeltaType);

7416-DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));

7417-DATETIME_ADD_MACRO(d, "min", new_delta(-MAX_DELTA_DAYS, 0, 0, 0));

7418-DATETIME_ADD_MACRO(d, "max",

7419-new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0));

7420-7421-/* date values */

7422-d=_PyType_GetDict(&PyDateTime_DateType);

7423-DATETIME_ADD_MACRO(d, "min", new_date(1, 1, 1));

7424-DATETIME_ADD_MACRO(d, "max", new_date(MAXYEAR, 12, 31));

7425-DATETIME_ADD_MACRO(d, "resolution", new_delta(1, 0, 0, 0));

7426-7427-/* time values */

7428-d=_PyType_GetDict(&PyDateTime_TimeType);

7429-DATETIME_ADD_MACRO(d, "min", new_time(0, 0, 0, 0, Py_None, 0));

7430-DATETIME_ADD_MACRO(d, "max", new_time(23, 59, 59, 999999, Py_None, 0));

7431-DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));

7432-7433-/* datetime values */

7434-d=_PyType_GetDict(&PyDateTime_DateTimeType);

7435-DATETIME_ADD_MACRO(d, "min",

7436-new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0));

7437-DATETIME_ADD_MACRO(d, "max", new_datetime(MAXYEAR, 12, 31, 23, 59, 59,

7438-999999, Py_None, 0));

7439-DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));

7440-7441-/* timezone values */

7442-d=_PyType_GetDict(&PyDateTime_TimeZoneType);

7443-if (PyDict_SetItemString(d, "utc", (PyObject*)&utc_timezone) <0) {

7444- goto error;

7445- }

7446-7447-/* bpo-37642: These attributes are rounded to the nearest minute for backwards

7448- * compatibility, even though the constructor will accept a wider range of

7449- * values. This may change in the future.*/

7450-7451-/* -23:59 */

7452-DATETIME_ADD_MACRO(d, "min", create_timezone_from_delta(-1, 60, 0, 1));

7453-7454-/* +23:59 */

7455-DATETIME_ADD_MACRO(

7456-d, "max", create_timezone_from_delta(0, (23*60+59) *60, 0, 0));

7457- }

7458-7459-#undef DATETIME_ADD_MACRO

7460-74617442/* Add module level attributes */

74627443if (PyModule_AddIntMacro(module, MINYEAR) <0) {

74637444 goto error;