10000 gh-117398: datetime: Access C-API via `PyInterpreterState` by neonene · Pull Request #118357 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-117398: datetime: Access C-API via PyInterpreterState #118357

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add an internal capsule
  • Loading branch information
neonene committed May 1, 2024
commit 0769c965cf6de74e1f947ffcda2533fb6b408aee
22 changes: 18 additions & 4 deletions Include/datetime.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,16 +186,30 @@ typedef struct {
} PyDateTime_CAPI;

#define PyDateTime_CAPSULE_NAME "datetime.datetime_CAPI"

PyAPI_FUNC(void) _PyDateTimeAPI_Import(void);
PyAPI_FUNC(void) _PyDateTimeAPI_Clear(void);
PyAPI_FUNC(PyDateTime_CAPI *) _PyDateTimeAPI_Get(void);
#define PyDateTime_INTERNAL_CAPSULE_NAME "datetime.datetime_CAPI_INTERNAL"

/* This block is only used as part of the public API and should not be
* included in _datetimemodule.c, which does not use the C API capsule.
* See bpo-35081 for more details.
* */
#ifndef _PY_DATETIME_IMPL
static PyDateTime_CAPI *
_PyDateTimeAPI_not_ready(void)
{
return NULL;
}
typedef PyDateTime_CAPI *(*datetime_api_getfunc)(void);
static datetime_api_getfunc _PyDateTimeAPI_Get = _PyDateTimeAPI_not_ready;

static inline void
_PyDateTimeAPI_Import(void)
{
datetime_api_getfunc (*func)(void) = PyCapsule_Import(
PyDateTime_INTERNAL_CAPSULE_NAME, 0);
if (func) {
_PyDateTimeAPI_Get = func();
}
}

#define PyDateTimeAPI _PyDateTimeAPI_Get()
#define PyDateTime_IMPORT _PyDateTimeAPI_Import()
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/datetimetester.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def test_name_cleanup(self):
if not name.startswith('__') and not name.endswith('__'))
allowed = set(['MAXYEAR', 'MINYEAR', 'date', 'datetime',
'datetime_CAPI', 'time', 'timedelta', 'timezone',
'tzinfo', 'UTC', 'sys'])
'tzinfo', 'UTC', 'sys', 'datetime_CAPI_INTERNAL'])
self.assertEqual(names - allowed, set([]))

def test_divide_and_round(self):
Expand Down
34 changes: 21 additions & 13 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,27 +69,23 @@ set_datetime_capi_by_interp(PyDateTime_CAPI *capi)
_PyInterpreterState_GET()->datetime_capi = capi;
}

void
static PyDateTime_CAPI *
_PyDateTimeAPI_Get(void)
{
return (PyDateTime_CAPI *)_PyInterpreterState_GET()->datetime_capi;
}

static void *
_PyDateTimeAPI_Import(void)
{
PyDateTime_CAPI *capi = PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0);
if (capi) {
// PyInit__datetime() is not called when the module is already loaded
// with single-phase init.
set_datetime_capi_by_interp(capi);
return _PyDateTimeAPI_Get;
}
}

PyDateTime_CAPI *
_PyDateTimeAPI_Get(void)
{
return (PyDateTime_CAPI *)_PyInterpreterState_GET()->datetime_capi;
}

void
_PyDateTimeAPI_Clear(void)
{
set_datetime_capi_by_interp(NULL);
return NULL;
}

/* We require that C int be at least 32 bits, and use int virtually
Expand Down Expand Up @@ -6972,6 +6968,18 @@ _datetime_exec(PyObject *module)
PyMem_Free(capi);
goto error;
}

capsule = PyCapsule_New(_PyDateTimeAPI_Import,
PyDateTime_INTERNAL_CAPSULE_NAME, NULL);
if (capsule == NULL) {
PyMem_Free(capi);
goto error;
}
if (PyModule_Add(module, "datetime_CAPI_INTERNAL", capsule) < 0) {
PyMem_Free(capi);
goto error;
}

/* Ensure that the newest capi is used on multi-phase init */
set_datetime_capi_by_interp(capi);

Expand Down
3 changes: 0 additions & 3 deletions Modules/_testcapi/datetime.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ static int test_run_counter = 0;
static PyObject *
test_datetime_capi(PyObject *self, PyObject *args)
{
if (!test_run_counter) {
_PyDateTimeAPI_Clear();
}
if (PyDateTimeAPI) {
if (test_run_counter) {
/* Probably regrtest.py -R */
Expand Down
2 changes: 1 addition & 1 deletion Modules/_testmultiphase.c
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ datetime_capi_import_with_error(void)
static int
datetime_capi_client_exec(PyObject *m)
{
_PyDateTimeAPI_Clear();
_PyDateTimeAPI_Get = _PyDateTimeAPI_not_ready;
if (_PyDateTimeAPI_Get() != NULL) {
PyErr_SetString(PyExc_AssertionError,
"DateTime API is expected to remain NULL.");
Expand Down
1 change: 1 addition & 0 deletions Tools/c-analyzer/cpython/globals-to-fix.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ Modules/_tkinter.c - trbInCmd -
## initialized once

## other
Include/datetime.h - _PyDateTimeAPI_Get -
Modules/_ctypes/cfield.c _ctypes_get_fielddesc initialized -
Modules/_ctypes/malloc_closure.c - _pagesize -
Modules/_cursesmodule.c - initialised -
Expand Down
0