mirror of https://github.com/python/cpython.git
gh-97955: Migrate `zoneinfo` to Argument Clinic (#97958)
This commit is contained in:
parent
002252c4ad
commit
24a6645894
|
@ -494,6 +494,7 @@ struct _Py_global_strings {
|
|||
STRUCT_FOR_ID(offset_src)
|
||||
STRUCT_FOR_ID(on_type_read)
|
||||
STRUCT_FOR_ID(onceregistry)
|
||||
STRUCT_FOR_ID(only_keys)
|
||||
STRUCT_FOR_ID(oparg)
|
||||
STRUCT_FOR_ID(opcode)
|
||||
STRUCT_FOR_ID(open)
|
||||
|
|
|
@ -1003,6 +1003,7 @@ extern "C" {
|
|||
INIT_ID(offset_src), \
|
||||
INIT_ID(on_type_read), \
|
||||
INIT_ID(onceregistry), \
|
||||
INIT_ID(only_keys), \
|
||||
INIT_ID(oparg), \
|
||||
INIT_ID(opcode), \
|
||||
INIT_ID(open), \
|
||||
|
@ -2313,6 +2314,8 @@ _PyUnicode_InitStaticStrings(void) {
|
|||
PyUnicode_InternInPlace(&string);
|
||||
string = &_Py_ID(onceregistry);
|
||||
PyUnicode_InternInPlace(&string);
|
||||
string = &_Py_ID(only_keys);
|
||||
PyUnicode_InternInPlace(&string);
|
||||
string = &_Py_ID(oparg);
|
||||
PyUnicode_InternInPlace(&string);
|
||||
string = &_Py_ID(opcode);
|
||||
|
@ -6554,6 +6557,10 @@ _PyStaticObjects_CheckRefcnt(void) {
|
|||
_PyObject_Dump((PyObject *)&_Py_ID(onceregistry));
|
||||
Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT");
|
||||
};
|
||||
if (Py_REFCNT((PyObject *)&_Py_ID(only_keys)) < _PyObject_IMMORTAL_REFCNT) {
|
||||
_PyObject_Dump((PyObject *)&_Py_ID(only_keys));
|
||||
Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT");
|
||||
};
|
||||
if (Py_REFCNT((PyObject *)&_Py_ID(oparg)) < _PyObject_IMMORTAL_REFCNT) {
|
||||
_PyObject_Dump((PyObject *)&_Py_ID(oparg));
|
||||
Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT");
|
||||
|
|
|
@ -404,6 +404,19 @@ def test_time_fixed_offset(self):
|
|||
class CZoneInfoTest(ZoneInfoTest):
|
||||
module = c_zoneinfo
|
||||
|
||||
def test_signatures(self):
|
||||
"""Ensure that C module has valid method signatures."""
|
||||
import inspect
|
||||
|
||||
must_have_signatures = (
|
||||
self.klass.clear_cache,
|
||||
self.klass.no_cache,
|
||||
self.klass.from_file,
|
||||
)
|
||||
for method in must_have_signatures:
|
||||
with self.subTest(method=method):
|
||||
inspect.Signature.from_callable(method)
|
||||
|
||||
def test_fold_mutate(self):
|
||||
"""Test that fold isn't mutated when no change is necessary.
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Migrate :mod:`zoneinfo` to Argument Clinic.
|
|
@ -12,6 +12,13 @@
|
|||
|
||||
#include "datetime.h"
|
||||
|
||||
#include "clinic/_zoneinfo.c.h"
|
||||
/*[clinic input]
|
||||
module zoneinfo
|
||||
class zoneinfo.ZoneInfo "PyObject *" "PyTypeObject *"
|
||||
[clinic start generated code]*/
|
||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d12c73c0eef36df8]*/
|
||||
|
||||
// Imports
|
||||
static PyObject *io_open = NULL;
|
||||
static PyObject *_tzpath_find_tzfile = NULL;
|
||||
|
@ -338,19 +345,24 @@ zoneinfo_dealloc(PyObject *obj_self)
|
|||
Py_TYPE(self)->tp_free((PyObject *)self);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
zoneinfo_from_file(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
PyObject *file_obj = NULL;
|
||||
PyObject *file_repr = NULL;
|
||||
PyObject *key = Py_None;
|
||||
PyZoneInfo_ZoneInfo *self = NULL;
|
||||
/*[clinic input]
|
||||
@classmethod
|
||||
zoneinfo.ZoneInfo.from_file
|
||||
|
||||
static char *kwlist[] = {"", "key", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &file_obj,
|
||||
&key)) {
|
||||
return NULL;
|
||||
}
|
||||
file_obj: object
|
||||
/
|
||||
key: object = None
|
||||
|
||||
Create a ZoneInfo file from a file object.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
zoneinfo_ZoneInfo_from_file_impl(PyTypeObject *type, PyObject *file_obj,
|
||||
PyObject *key)
|
||||
/*[clinic end generated code: output=68ed2022404ae5be input=ccfe73708133d2e4]*/
|
||||
{
|
||||
PyObject *file_repr = NULL;
|
||||
PyZoneInfo_ZoneInfo *self = NULL;
|
||||
|
||||
PyObject *obj_self = (PyObject *)(type->tp_alloc(type, 0));
|
||||
self = (PyZoneInfo_ZoneInfo *)obj_self;
|
||||
|
@ -379,16 +391,20 @@ zoneinfo_from_file(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
zoneinfo_no_cache(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"key", NULL};
|
||||
PyObject *key = NULL;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &key)) {
|
||||
return NULL;
|
||||
}
|
||||
/*[clinic input]
|
||||
@classmethod
|
||||
zoneinfo.ZoneInfo.no_cache
|
||||
|
||||
PyObject *out = zoneinfo_new_instance(cls, key);
|
||||
key: object
|
||||
|
||||
Get a new instance of ZoneInfo, bypassing the cache.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
zoneinfo_ZoneInfo_no_cache_impl(PyTypeObject *type, PyObject *key)
|
||||
/*[clinic end generated code: output=751c6894ad66f91b input=bb24afd84a80ba46]*/
|
||||
{
|
||||
PyObject *out = zoneinfo_new_instance(type, key);
|
||||
if (out != NULL) {
|
||||
((PyZoneInfo_ZoneInfo *)out)->source = SOURCE_NOCACHE;
|
||||
}
|
||||
|
@ -396,18 +412,20 @@ zoneinfo_no_cache(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
|
|||
return out;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
@classmethod
|
||||
zoneinfo.ZoneInfo.clear_cache
|
||||
|
||||
*
|
||||
only_keys: object = None
|
||||
|
||||
Clear the ZoneInfo cache.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
zoneinfo_clear_cache(PyObject *cls, PyObject *args, PyObject *kwargs)
|
||||
zoneinfo_ZoneInfo_clear_cache_impl(PyTypeObject *type, PyObject *only_keys)
|
||||
/*[clinic end generated code: output=eec0a3276f07bd90 input=8cff0182a95f295b]*/
|
||||
{
|
||||
PyObject *only_keys = NULL;
|
||||
static char *kwlist[] = {"only_keys", NULL};
|
||||
|
||||
if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|$O", kwlist,
|
||||
&only_keys))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyTypeObject *type = (PyTypeObject *)cls;
|
||||
PyObject *weak_cache = get_weak_cache(type);
|
||||
|
||||
if (only_keys == NULL || only_keys == Py_None) {
|
||||
|
@ -2545,15 +2563,9 @@ zoneinfo_init_subclass(PyTypeObject *cls, PyObject *args, PyObject **kwargs)
|
|||
/////
|
||||
// Specify the ZoneInfo type
|
||||
static PyMethodDef zoneinfo_methods[] = {
|
||||
{"clear_cache", (PyCFunction)(void (*)(void))zoneinfo_clear_cache,
|
||||
METH_VARARGS | METH_KEYWORDS | METH_CLASS,
|
||||
PyDoc_STR("Clear the ZoneInfo cache.")},
|
||||
{"no_cache", (PyCFunction)(void (*)(void))zoneinfo_no_cache,
|
||||
METH_VARARGS | METH_KEYWORDS | METH_CLASS,
|
||||
PyDoc_STR("Get a new instance of ZoneInfo, bypassing the cache.")},
|
||||
{"from_file", (PyCFunction)(void (*)(void))zoneinfo_from_file,
|
||||
METH_VARARGS | METH_KEYWORDS | METH_CLASS,
|
||||
PyDoc_STR("Create a ZoneInfo file from a file object.")},
|
||||
ZONEINFO_ZONEINFO_CLEAR_CACHE_METHODDEF
|
||||
ZONEINFO_ZONEINFO_NO_CACHE_METHODDEF
|
||||
ZONEINFO_ZONEINFO_FROM_FILE_METHODDEF
|
||||
{"utcoffset", (PyCFunction)zoneinfo_utcoffset, METH_O,
|
||||
PyDoc_STR("Retrieve a timedelta representing the UTC offset in a zone at "
|
||||
"the given datetime.")},
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
/*[clinic input]
|
||||
preserve
|
||||
[clinic start generated code]*/
|
||||
|
||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
# include "pycore_gc.h" // PyGC_Head
|
||||
# include "pycore_runtime.h" // _Py_ID()
|
||||
#endif
|
||||
|
||||
|
||||
PyDoc_STRVAR(zoneinfo_ZoneInfo_from_file__doc__,
|
||||
"from_file($type, file_obj, /, key=None)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Create a ZoneInfo file from a file object.");
|
||||
|
||||
#define ZONEINFO_ZONEINFO_FROM_FILE_METHODDEF \
|
||||
{"from_file", _PyCFunction_CAST(zoneinfo_ZoneInfo_from_file), METH_FASTCALL|METH_KEYWORDS|METH_CLASS, zoneinfo_ZoneInfo_from_file__doc__},
|
||||
|
||||
static PyObject *
|
||||
zoneinfo_ZoneInfo_from_file_impl(PyTypeObject *type, PyObject *file_obj,
|
||||
PyObject *key);
|
||||
|
||||
static PyObject *
|
||||
zoneinfo_ZoneInfo_from_file(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
|
||||
#define NUM_KEYWORDS 1
|
||||
static struct {
|
||||
PyGC_Head _this_is_not_used;
|
||||
PyObject_VAR_HEAD
|
||||
PyObject *ob_item[NUM_KEYWORDS];
|
||||
} _kwtuple = {
|
||||
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
|
||||
.ob_item = { &_Py_ID(key), },
|
||||
};
|
||||
#undef NUM_KEYWORDS
|
||||
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
|
||||
|
||||
#else // !Py_BUILD_CORE
|
||||
# define KWTUPLE NULL
|
||||
#endif // !Py_BUILD_CORE
|
||||
|
||||
static const char * const _keywords[] = {"", "key", NULL};
|
||||
static _PyArg_Parser _parser = {
|
||||
.keywords = _keywords,
|
||||
.fname = "from_file",
|
||||
.kwtuple = KWTUPLE,
|
||||
};
|
||||
#undef KWTUPLE
|
||||
PyObject *argsbuf[2];
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
|
||||
PyObject *file_obj;
|
||||
PyObject *key = Py_None;
|
||||
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
|
||||
if (!args) {
|
||||
goto exit;
|
||||
}
|
||||
file_obj = args[0];
|
||||
if (!noptargs) {
|
||||
goto skip_optional_pos;
|
||||
}
|
||||
key = args[1];
|
||||
skip_optional_pos:
|
||||
return_value = zoneinfo_ZoneInfo_from_file_impl(type, file_obj, key);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(zoneinfo_ZoneInfo_no_cache__doc__,
|
||||
"no_cache($type, /, key)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Get a new instance of ZoneInfo, bypassing the cache.");
|
||||
|
||||
#define ZONEINFO_ZONEINFO_NO_CACHE_METHODDEF \
|
||||
{"no_cache", _PyCFunction_CAST(zoneinfo_ZoneInfo_no_cache), METH_FASTCALL|METH_KEYWORDS|METH_CLASS, zoneinfo_ZoneInfo_no_cache__doc__},
|
||||
|
||||
static PyObject *
|
||||
zoneinfo_ZoneInfo_no_cache_impl(PyTypeObject *type, PyObject *key);
|
||||
|
||||
static PyObject *
|
||||
zoneinfo_ZoneInfo_no_cache(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
|
||||
#define NUM_KEYWORDS 1
|
||||
static struct {
|
||||
PyGC_Head _this_is_not_used;
|
||||
PyObject_VAR_HEAD
|
||||
PyObject *ob_item[NUM_KEYWORDS];
|
||||
} _kwtuple = {
|
||||
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
|
||||
.ob_item = { &_Py_ID(key), },
|
||||
};
|
||||
#undef NUM_KEYWORDS
|
||||
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
|
||||
|
||||
#else // !Py_BUILD_CORE
|
||||
# define KWTUPLE NULL
|
||||
#endif // !Py_BUILD_CORE
|
||||
|
||||
static const char * const _keywords[] = {"key", NULL};
|
||||
static _PyArg_Parser _parser = {
|
||||
.keywords = _keywords,
|
||||
.fname = "no_cache",
|
||||
.kwtuple = KWTUPLE,
|
||||
};
|
||||
#undef KWTUPLE
|
||||
PyObject *argsbuf[1];
|
||||
PyObject *key;
|
||||
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
|
||||
if (!args) {
|
||||
goto exit;
|
||||
}
|
||||
key = args[0];
|
||||
return_value = zoneinfo_ZoneInfo_no_cache_impl(type, key);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(zoneinfo_ZoneInfo_clear_cache__doc__,
|
||||
"clear_cache($type, /, *, only_keys=None)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Clear the ZoneInfo cache.");
|
||||
|
||||
#define ZONEINFO_ZONEINFO_CLEAR_CACHE_METHODDEF \
|
||||
{"clear_cache", _PyCFunction_CAST(zoneinfo_ZoneInfo_clear_cache), METH_FASTCALL|METH_KEYWORDS|METH_CLASS, zoneinfo_ZoneInfo_clear_cache__doc__},
|
||||
|
||||
static PyObject *
|
||||
zoneinfo_ZoneInfo_clear_cache_impl(PyTypeObject *type, PyObject *only_keys);
|
||||
|
||||
static PyObject *
|
||||
zoneinfo_ZoneInfo_clear_cache(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
|
||||
#define NUM_KEYWORDS 1
|
||||
static struct {
|
||||
PyGC_Head _this_is_not_used;
|
||||
PyObject_VAR_HEAD
|
||||
PyObject *ob_item[NUM_KEYWORDS];
|
||||
} _kwtuple = {
|
||||
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
|
||||
.ob_item = { &_Py_ID(only_keys), },
|
||||
};
|
||||
#undef NUM_KEYWORDS
|
||||
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
|
||||
|
||||
#else // !Py_BUILD_CORE
|
||||
# define KWTUPLE NULL
|
||||
#endif // !Py_BUILD_CORE
|
||||
|
||||
static const char * const _keywords[] = {"only_keys", NULL};
|
||||
static _PyArg_Parser _parser = {
|
||||
.keywords = _keywords,
|
||||
.fname = "clear_cache",
|
||||
.kwtuple = KWTUPLE,
|
||||
};
|
||||
#undef KWTUPLE
|
||||
PyObject *argsbuf[1];
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
|
||||
PyObject *only_keys = Py_None;
|
||||
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
|
||||
if (!args) {
|
||||
goto exit;
|
||||
}
|
||||
if (!noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
only_keys = args[0];
|
||||
skip_optional_kwonly:
|
||||
return_value = zoneinfo_ZoneInfo_clear_cache_impl(type, only_keys);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=d2da73ef66146b83 input=a9049054013a1b77]*/
|
Loading…
Reference in New Issue