Skip to content

Commit b12073b

Browse files
committed
[GR-72161] Implement native datetime subclasses
PullRequest: graalpython/4162
2 parents 633d573 + 202600a commit b12073b

File tree

23 files changed

+1939
-1167
lines changed

23 files changed

+1939
-1167
lines changed

graalpython/com.oracle.graal.python.cext/src/datetime.c

Lines changed: 87 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -2762,28 +2762,22 @@ delta_reduce(PyDateTime_Delta* self, PyObject *Py_UNUSED(ignored))
27622762
{
27632763
return Py_BuildValue("ON", Py_TYPE(self), delta_getstate(self));
27642764
}
2765-
#endif // GraalPy change
27662765

27672766
#define OFFSET(field) offsetof(PyDateTime_Delta, field)
27682767

2769-
// GraalPy change: different members
27702768
static PyMemberDef delta_members[] = {
27712769

2772-
{"_days", T_INT, OFFSET(days), 0,
2770+
{"days", T_INT, OFFSET(days), READONLY,
27732771
PyDoc_STR("Number of days.")},
27742772

2775-
{"_seconds", T_INT, OFFSET(seconds), 0,
2773+
{"seconds", T_INT, OFFSET(seconds), READONLY,
27762774
PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")},
27772775

2778-
{"_microseconds", T_INT, OFFSET(microseconds), 0,
2776+
{"microseconds", T_INT, OFFSET(microseconds), READONLY,
27792777
PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")},
2780-
2781-
{"_hashcode", T_PYSSIZET, OFFSET(hashcode), 0,
2782-
PyDoc_STR("hashcode")},
27832778
{NULL}
27842779
};
27852780

2786-
#if 0 // GraalPy change
27872781
static PyMethodDef delta_methods[] = {
27882782
{"total_seconds", delta_total_seconds, METH_NOARGS,
27892783
PyDoc_STR("Total seconds in the duration.")},
@@ -2867,7 +2861,7 @@ static PyTypeObject PyDateTime_DeltaType = {
28672861
0, /* tp_iter */
28682862
0, /* tp_iternext */
28692863
0, /* tp_methods */ // GraalPy change: nulled
2870-
delta_members, /* tp_members */
2864+
0, /* tp_members */ // GraalPy change: nulled
28712865
0, /* tp_getset */
28722866
0, /* tp_base */
28732867
0, /* tp_dict */
@@ -2880,6 +2874,7 @@ static PyTypeObject PyDateTime_DeltaType = {
28802874
0, /* tp_free */
28812875
};
28822876

2877+
#if 0 // GraalPy change
28832878
/*
28842879
* PyDateTime_Date implementation.
28852880
*/
@@ -2904,70 +2899,13 @@ date_day(PyDateTime_Date *self, void *unused)
29042899
return PyLong_FromLong(GET_DAY(self));
29052900
}
29062901

2907-
// GraalPy-specific
2908-
static int
2909-
set_date_year(PyDateTime_Date *self, PyObject *value, void *unused)
2910-
{
2911-
int ival = _PyLong_AsInt(value);
2912-
if (check_date_args(ival, 1, 1) < 0) {
2913-
return -1;
2914-
}
2915-
self->hashcode = -1;
2916-
SET_YEAR(self, ival);
2917-
return 0;
2918-
}
2919-
2920-
// GraalPy-specific
2921-
static int
2922-
set_date_month(PyDateTime_Date *self, PyObject *value, void *unused)
2923-
{
2924-
int ival = _PyLong_AsInt(value);
2925-
if (check_date_args(MINYEAR, ival, 1) < 0) {
2926-
return -1;
2927-
}
2928-
self->hashcode = -1;
2929-
SET_MONTH(self, ival);
2930-
return 0;
2931-
}
2932-
2933-
// GraalPy-specific
2934-
static int
2935-
set_date_day(PyDateTime_Date *self, PyObject *value, void *unused)
2936-
{
2937-
int ival = _PyLong_AsInt(value);
2938-
if (check_date_args(MINYEAR, 1, ival) < 0) {
2939-
return -1;
2940-
}
2941-
self->hashcode = -1;
2942-
SET_DAY(self, ival);
2943-
return 0;
2944-
}
2945-
2946-
// GraalPy-specific
2947-
static PyObject *
2948-
base_hashcode(_PyDateTime_BaseTZInfo *self, void *unused)
2949-
{
2950-
return PyLong_FromSsize_t(self->hashcode);
2951-
}
2952-
2953-
// GraalPy-specific
2954-
static int
2955-
set_base_hashcode(_PyDateTime_BaseTZInfo *self, PyObject *value, void *unused)
2956-
{
2957-
self->hashcode = (Py_hash_t) PyLong_AsSsize_t(value);
2958-
return 0;
2959-
}
2960-
2961-
// GraalPy change: different members
29622902
static PyGetSetDef date_getset[] = {
2963-
{"_year", (getter)date_year, (setter)set_date_year},
2964-
{"_month", (getter)date_month, (setter)set_date_month},
2965-
{"_day", (getter)date_day, (setter)set_date_day},
2966-
{"_hashcode", (getter)base_hashcode, (setter)set_base_hashcode},
2903+
{"year", (getter)date_year},
2904+
{"month", (getter)date_month},
2905+
{"day", (getter)date_day},
29672906
{NULL}
29682907
};
29692908

2970-
#if 0 // GraalPy change
29712909
/* Constructors. */
29722910

29732911
static char *date_kws[] = {"year", "month", "day", NULL};
@@ -3581,7 +3519,6 @@ date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
35813519
Py_DECREF(tuple);
35823520
return clone;
35833521
}
3584-
#endif // GraalPy change
35853522

35863523
static Py_hash_t
35873524
generic_hash(unsigned char *data, int len)
@@ -3603,7 +3540,6 @@ date_hash(PyDateTime_Date *self)
36033540
return self->hashcode;
36043541
}
36053542

3606-
#if 0 // GraalPy change
36073543
static PyObject *
36083544
date_toordinal(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
36093545
{
@@ -3735,7 +3671,7 @@ static PyTypeObject PyDateTime_DateType = {
37353671
0, /* tp_as_number */ // GraalPy change: nulled
37363672
0, /* tp_as_sequence */
37373673
0, /* tp_as_mapping */
3738-
(hashfunc)date_hash, /* tp_hash */
3674+
0, /* tp_hash */ // GraalPy change: nulled
37393675
0, /* tp_call */
37403676
0, /* tp_str */ // GraalPy change: nulled
37413677
0, /* tp_getattro */ // GraalPy change: nulled
@@ -3751,7 +3687,7 @@ static PyTypeObject PyDateTime_DateType = {
37513687
0, /* tp_iternext */
37523688
0, /* tp_methods */ // GraalPy change: nulled
37533689
0, /* tp_members */
3754-
date_getset, /* tp_getset */
3690+
0, /* tp_getset */ // GraalPy change: nulled
37553691
0, /* tp_base */
37563692
0, /* tp_dict */
37573693
0, /* tp_descr_get */
@@ -4223,7 +4159,6 @@ static PyTypeObject PyDateTime_TimeZoneType = {
42234159
0, /* tp_alloc */
42244160
timezone_new, /* tp_new */
42254161
};
4226-
#endif // GraalPy change
42274162

42284163
/*
42294164
* PyDateTime_Time implementation.
@@ -4270,100 +4205,20 @@ time_fold(PyDateTime_Time *self, void *unused)
42704205
return PyLong_FromLong(TIME_GET_FOLD(self));
42714206
}
42724207

4273-
// GraalPy-specific
4274-
static PyObject *
4275-
set_time_hour(PyDateTime_Time *self, PyObject* value, void *unused)
4276-
{
4277-
int ival = _PyLong_AsInt(value);
4278-
if (check_time_args(ival, 0, 0, 0, 0) < 0) {
4279-
return -1;
4280-
}
4281-
self->hashcode = -1;
4282-
TIME_SET_HOUR(self, ival);
4283-
return 0;
4284-
}
4285-
4286-
// GraalPy-specific
4287-
static PyObject *
4288-
set_time_minute(PyDateTime_Time *self, PyObject* value, void *unused)
4289-
{
4290-
int ival = _PyLong_AsInt(value);
4291-
if (check_time_args(0, ival, 0, 0, 0) < 0) {
4292-
return -1;
4293-
}
4294-
self->hashcode = -1;
4295-
TIME_SET_MINUTE(self, ival);
4296-
return 0;
4297-
}
4298-
4299-
// GraalPy-specific
4300-
/* The name time_second conflicted with some platform header file. */
4301-
static PyObject *
4302-
set_py_time_second(PyDateTime_Time *self, PyObject* value, void *unused)
4303-
{
4304-
int ival = _PyLong_AsInt(value);
4305-
if (check_time_args(0, 0, ival, 0, 0) < 0) {
4306-
return -1;
4307-
}
4308-
self->hashcode = -1;
4309-
TIME_SET_SECOND(self, ival);
4310-
return 0;
4311-
}
4312-
4313-
// GraalPy-specific
4314-
static PyObject *
4315-
set_time_microsecond(PyDateTime_Time *self, PyObject* value, void *unused)
4316-
{
4317-
int ival = _PyLong_AsInt(value);
4318-
if (check_time_args(0, 0, 0, ival, 0) < 0) {
4319-
return -1;
4320-
}
4321-
self->hashcode = -1;
4322-
TIME_SET_MICROSECOND(self, ival);
4323-
return 0;
4324-
}
4325-
4326-
// GraalPy-specific
4327-
static PyObject *
4328-
set_time_tzinfo(PyDateTime_Time *self, PyObject* value, void *unused)
4329-
{
4330-
if (value != Py_None) {
4331-
Py_INCREF(value);
4332-
self->tzinfo = value;
4333-
}
4334-
return 0;
4335-
}
4336-
4337-
// GraalPy-specific
4338-
static PyObject *
4339-
set_time_fold(PyDateTime_Time *self, PyObject* value, void *unused)
4340-
{
4341-
int ival = _PyLong_AsInt(value);
4342-
if (check_time_args(0, 0, 0, 0, ival) < 0) {
4343-
return -1;
4344-
}
4345-
self->hashcode = -1;
4346-
TIME_SET_FOLD(self, ival);
4347-
return 0;
4348-
}
4349-
4350-
// GraalPy change: different members
43514208
static PyGetSetDef time_getset[] = {
4352-
{"_hour", (getter)time_hour, (setter)set_time_hour},
4353-
{"_minute", (getter)time_minute, (setter)set_time_minute},
4354-
{"_second", (getter)py_time_second, (setter)set_py_time_second},
4355-
{"_microsecond", (getter)time_microsecond, (setter)set_time_microsecond},
4356-
{"_tzinfo", (getter)time_tzinfo, (setter)set_time_tzinfo},
4357-
{"_fold", (getter)time_fold, (setter)set_time_fold},
4358-
{"_hashcode", (getter)base_hashcode, (setter)set_base_hashcode},
4209+
{"hour", (getter)time_hour},
4210+
{"minute", (getter)time_minute},
4211+
{"second", (getter)py_time_second},
4212+
{"microsecond", (getter)time_microsecond},
4213+
{"tzinfo", (getter)time_tzinfo},
4214+
{"fold", (getter)time_fold},
43594215
{NULL}
43604216
};
43614217

43624218
/*
43634219
* Constructors.
43644220
*/
43654221

4366-
#if 0 // GraalPy change
43674222
static char *time_kws[] = {"hour", "minute", "second", "microsecond",
43684223
"tzinfo", "fold", NULL};
43694224

@@ -4966,7 +4821,7 @@ static PyTypeObject PyDateTime_TimeType = {
49664821
0, /* tp_iternext */
49674822
0, /* tp_methods */ // GraalPy change: nulled
49684823
0, /* tp_members */
4969-
time_getset, /* tp_getset */
4824+
0, /* tp_getset */ // GraalPy change: nulled
49704825
0, /* tp_base */
49714826
0, /* tp_dict */
49724827
0, /* tp_descr_get */
@@ -4978,6 +4833,7 @@ static PyTypeObject PyDateTime_TimeType = {
49784833
0, /* tp_free */
49794834
};
49804835

4836+
#if 0 // GraalPy change
49814837
/*
49824838
* PyDateTime_DateTime implementation.
49834839
*/
@@ -5108,7 +4964,6 @@ static PyGetSetDef datetime_getset[] = {
51084964
* Constructors.
51094965
*/
51104966

5111-
#if 0 // GraalPy change
51124967
static char *datetime_kws[] = {
51134968
"year", "month", "day", "hour", "minute", "second",
51144969
"microsecond", "tzinfo", "fold", NULL
@@ -6917,7 +6772,7 @@ static PyTypeObject PyDateTime_DateTimeType = {
69176772
0, /* tp_iternext */
69186773
0, /* tp_methods */ // GraalPy change: nulled
69196774
0, /* tp_members */
6920-
datetime_getset, /* tp_getset */
6775+
0, /* tp_getset */ // GraalPy change: nulled
69216776
&PyDateTime_DateType, /* tp_base */
69226777
0, /* tp_dict */
69236778
0, /* tp_descr_get */
@@ -7456,3 +7311,71 @@ GraalPyPrivate_InitNativeDateTime()
74567311
GraalPyPrivate_Set_Native_Slots(&PyDateTime_TimeType, getsets_time, NULL);
74577312
GraalPyPrivate_Set_Native_Slots(&PyDateTime_DeltaType, NULL, members_delta);
74587313
}
7314+
7315+
// Used from Java to initialize native subtypes
7316+
PyAPI_FUNC(PyObject*)
7317+
GraalPyPrivate_Time_SubtypeNew(PyTypeObject* type, int hour, int minute, int second, int usecond, PyObject* tzinfo, int fold) {
7318+
char aware = tzinfo != NULL;
7319+
PyDateTime_Time *self = (PyDateTime_Time *) (type->tp_alloc(type, aware));
7320+
if (self != NULL) {
7321+
self->hastzinfo = aware;
7322+
self->hashcode = -1;
7323+
TIME_SET_HOUR(self, hour);
7324+
TIME_SET_MINUTE(self, minute);
7325+
TIME_SET_SECOND(self, second);
7326+
TIME_SET_MICROSECOND(self, usecond);
7327+
if (aware) {
7328+
self->tzinfo = Py_NewRef(tzinfo);
7329+
}
7330+
TIME_SET_FOLD(self, fold);
7331+
}
7332+
return (PyObject *)self;
7333+
}
7334+
7335+
PyAPI_FUNC(PyObject*)
7336+
GraalPyPrivate_Date_SubtypeNew(PyTypeObject* type, int year, int month, int day) {
7337+
PyDateTime_Date *self = (PyDateTime_Date *)(type->tp_alloc(type, 0));
7338+
if (self) {
7339+
self->hashcode = -1;
7340+
SET_YEAR(self, year);
7341+
SET_MONTH(self, month);
7342+
SET_DAY(self, day);
7343+
}
7344+
return (PyObject *)self;
7345+
}
7346+
7347+
PyAPI_FUNC(PyObject*)
7348+
GraalPyPrivate_DateTime_SubtypeNew(PyTypeObject* type, int year, int month, int day, int hour, int minute, int second, int usecond, PyObject* tzinfo, int fold) {
7349+
char aware = tzinfo != NULL;
7350+
PyDateTime_DateTime *self = (PyDateTime_DateTime *) (type->tp_alloc(type, aware));
7351+
if (self != NULL) {
7352+
self->hastzinfo = aware;
7353+
self->hashcode = -1;
7354+
/* Date fields */
7355+
SET_YEAR((PyDateTime_Date *)self, year);
7356+
SET_MONTH((PyDateTime_Date *)self, month);
7357+
SET_DAY((PyDateTime_Date *)self, day);
7358+
/* Time fields */
7359+
DATE_SET_HOUR(self, hour);
7360+
DATE_SET_MINUTE(self, minute);
7361+
DATE_SET_SECOND(self, second);
7362+
DATE_SET_MICROSECOND(self, usecond);
7363+
if (aware) {
7364+
self->tzinfo = Py_NewRef(tzinfo);
7365+
}
7366+
DATE_SET_FOLD(self, fold);
7367+
}
7368+
return (PyObject *)self;
7369+
}
7370+
7371+
PyAPI_FUNC(PyObject*)
7372+
GraalPyPrivate_TimeDelta_SubtypeNew(PyTypeObject* type, int days, int seconds, int microseconds) {
7373+
PyDateTime_Delta *self = (PyDateTime_Delta *) (type->tp_alloc(type, 0));
7374+
if (self != NULL) {
7375+
self->hashcode = -1;
7376+
SET_TD_DAYS(self, days);
7377+
SET_TD_SECONDS(self, seconds);
7378+
SET_TD_MICROSECONDS(self, microseconds);
7379+
}
7380+
return (PyObject *) self;
7381+
}

0 commit comments

Comments
 (0)