26
26
#endif
27
27
28
28
typedef struct {
29
+ /* Static types exposed by the datetime C-API. */
29
30
PyTypeObject * date_type ;
30
31
PyTypeObject * datetime_type ;
31
32
PyTypeObject * delta_type ;
32
- PyTypeObject * isocalendar_date_type ;
33
33
PyTypeObject * time_type ;
34
34
PyTypeObject * tzinfo_type ;
35
+ /* Exposed indirectly via TimeZone_UTC. */
35
36
PyTypeObject * timezone_type ;
36
37
38
+ /* Other module classes. */
39
+ PyTypeObject * isocalendar_date_type ;
40
+
37
41
/* Conversion factors. */
38
42
PyObject * us_per_ms ; // 1_000
39
43
PyObject * us_per_second ; // 1_000_000
@@ -3460,17 +3464,40 @@ static PyMethodDef iso_calendar_date_methods[] = {
3460
3464
{NULL , NULL },
3461
3465
};
3462
3466
3463
- static PyTypeObject PyDateTime_IsoCalendarDateType = {
3464
- PyVarObject_HEAD_INIT (NULL , 0 )
3465
- .tp_name = "datetime.IsoCalendarDate" ,
3466
- .tp_basicsize = sizeof (PyDateTime_IsoCalendarDate ),
3467
- .tp_repr = (reprfunc ) iso_calendar_date_repr ,
3468
- .tp_flags = Py_TPFLAGS_DEFAULT ,
3469
- .tp_doc = iso_calendar_date__doc__ ,
3470
- .tp_methods = iso_calendar_date_methods ,
3471
- .tp_getset = iso_calendar_date_getset ,
3472
- // .tp_base = &PyTuple_Type, // filled in PyInit__datetime
3473
- .tp_new = iso_calendar_date_new ,
3467
+ static int
3468
+ iso_calendar_date_traverse (PyDateTime_IsoCalendarDate * self , visitproc visit ,
3469
+ void * arg )
3470
+ {
3471
+ Py_VISIT (Py_TYPE (self ));
3472
+ return PyTuple_Type .tp_traverse ((PyObject * )self , visit , arg );
3473
+ }
3474
+
3475
+ static void
3476
+ iso_calendar_date_dealloc (PyDateTime_IsoCalendarDate * self )
3477
+ {
3478
+ PyTypeObject * tp = Py_TYPE (self );
3479
+ PyTuple_Type .tp_dealloc ((PyObject * )self ); // delegate GC-untrack as well
3480
+ Py_DECREF (tp );
3481
+ }
3482
+
3483
+ static PyType_Slot isocal_slots [] = {
3484
+ {Py_tp_repr , iso_calendar_date_repr },
3485
+ {Py_tp_doc , (void * )iso_calendar_date__doc__ },
3486
+ {Py_tp_methods , iso_calendar_date_methods },
3487
+ {Py_tp_getset , iso_calendar_date_getset },
3488
+ {Py_tp_new , iso_calendar_date_new },
3489
+ {Py_tp_dealloc , iso_calendar_date_dealloc },
3490
+ {Py_tp_traverse , iso_calendar_date_traverse },
3491
+ {0 , NULL },
3492
+ };
3493
+
3494
+ static PyType_Spec isocal_spec = {
3495
+ .name = "datetime.IsoCalendarDate" ,
3496
+ .basicsize = sizeof (PyDateTime_IsoCalendarDate ),
3497
+ .flags = (Py_TPFLAGS_DEFAULT |
3498
+ Py_TPFLAGS_HAVE_GC |
3499
+ Py_TPFLAGS_IMMUTABLETYPE ),
3500
+ .slots = isocal_slots ,
3474
3501
};
3475
3502
3476
3503
/*[clinic input]
@@ -6842,22 +6869,25 @@ create_timezone_from_delta(int days, int sec, int ms, int normalize)
6842
6869
}
6843
6870
6844
6871
static int
6845
- init_state (datetime_state * st )
6872
+ init_state (datetime_state * st , PyTypeObject * PyDateTime_IsoCalendarDateType )
6846
6873
{
6847
6874
// While datetime uses global module "state", we unly initialize it once.
6848
6875
// The PyLong objects created here (once per process) are not decref'd.
6849
6876
if (st -> initialized ) {
6850
6877
return 0 ;
6851
6878
}
6852
6879
6880
+ /* Static types exposed by the C-API. */
6853
6881
st -> date_type = & PyDateTime_DateType ;
6854
6882
st -> datetime_type = & PyDateTime_DateTimeType ;
6855
6883
st -> delta_type = & PyDateTime_DeltaType ;
6856
- st -> isocalendar_date_type = & PyDateTime_IsoCalendarDateType ;
6857
6884
st -> time_type = & PyDateTime_TimeType ;
6858
6885
st -> tzinfo_type = & PyDateTime_TZInfoType ;
6859
6886
st -> timezone_type = & PyDateTime_TimeZoneType ;
6860
6887
6888
+ /* Per-module heap types. */
6889
+ st -> isocalendar_date_type = PyDateTime_IsoCalendarDateType ;
6890
+
6861
6891
st -> us_per_ms = PyLong_FromLong (1000 );
6862
6892
if (st -> us_per_ms == NULL ) {
6863
6893
return -1 ;
@@ -6914,11 +6944,10 @@ _datetime_exec(PyObject *module)
6914
6944
// `&...` is not a constant expression according to a strict reading
6915
6945
// of C standards. Fill tp_base at run-time rather than statically.
6916
6946
// See https://bugs.python.org/issue40777
6917
- PyDateTime_IsoCalendarDateType .tp_base = & PyTuple_Type ;
6918
6947
PyDateTime_TimeZoneType .tp_base = & PyDateTime_TZInfoType ;
6919
6948
PyDateTime_DateTimeType .tp_base = & PyDateTime_DateType ;
6920
6949
6921
- PyTypeObject * types [] = {
6950
+ PyTypeObject * capi_types [] = {
6922
6951
& PyDateTime_DateType ,
6923
6952
& PyDateTime_DateTimeType ,
6924
6953
& PyDateTime_TimeType ,
@@ -6927,18 +6956,27 @@ _datetime_exec(PyObject *module)
6927
6956
& PyDateTime_TimeZoneType ,
6928
6957
};
6929
6958
6930
- for (size_t i = 0 ; i < Py_ARRAY_LENGTH (types ); i ++ ) {
6931
- if (PyModule_AddType (module , types [i ]) < 0 ) {
6959
+ for (size_t i = 0 ; i < Py_ARRAY_LENGTH (capi_types ); i ++ ) {
6960
+ if (PyModule_AddType (module , capi_types [i ]) < 0 ) {
6932
6961
goto error ;
6933
6962
}
6934
6963
}
6935
6964
6936
- if (PyType_Ready (& PyDateTime_IsoCalendarDateType ) < 0 ) {
6937
- goto error ;
6938
- }
6965
+ #define CREATE_TYPE (VAR , SPEC , BASE ) \
6966
+ do { \
6967
+ VAR = (PyTypeObject *)PyType_FromModuleAndSpec( \
6968
+ module, SPEC, (PyObject *)BASE); \
6969
+ if (VAR == NULL) { \
6970
+ goto error; \
6971
+ } \
6972
+ } while (0)
6973
+
6974
+ PyTypeObject * PyDateTime_IsoCalendarDateType = NULL ;
6975
+ CREATE_TYPE (PyDateTime_IsoCalendarDateType , & isocal_spec , & PyTuple_Type );
6976
+ #undef CREATE_TYPE
6939
6977
6940
6978
datetime_state * st = get_datetime_state ();
6941
- if (init_state (st ) < 0 ) {
6979
+ if (init_state (st , PyDateTime_IsoCalendarDateType ) < 0 ) {
6942
6980
goto error ;
6943
6981
}
6944
6982
0 commit comments