Skip to content

Commit

Permalink
pythongh-97955: Migrate zoneinfo to Argument Clinic (python#97958)
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn authored and mpage committed Oct 11, 2022
1 parent 97ae2e9 commit 1096dfa
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 36 deletions.
1 change: 1 addition & 0 deletions Include/internal/pycore_global_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions Include/internal/pycore_runtime_init_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions Lib/test/test_zoneinfo/test_zoneinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Migrate :mod:`zoneinfo` to Argument Clinic.
84 changes: 48 additions & 36 deletions Modules/_zoneinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -338,20 +345,25 @@ zoneinfo_dealloc(PyObject *obj_self)
Py_TYPE(self)->tp_free((PyObject *)self);
}

/*[clinic input]
@classmethod
zoneinfo.ZoneInfo.from_file
file_obj: object
/
key: object = None
Create a ZoneInfo file from a file object.
[clinic start generated code]*/

static PyObject *
zoneinfo_from_file(PyTypeObject *type, PyObject *args, PyObject *kwargs)
zoneinfo_ZoneInfo_from_file_impl(PyTypeObject *type, PyObject *file_obj,
PyObject *key)
/*[clinic end generated code: output=68ed2022404ae5be input=ccfe73708133d2e4]*/
{
PyObject *file_obj = NULL;
PyObject *file_repr = NULL;
PyObject *key = Py_None;
PyZoneInfo_ZoneInfo *self = NULL;

static char *kwlist[] = {"", "key", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &file_obj,
&key)) {
return NULL;
}

PyObject *obj_self = (PyObject *)(type->tp_alloc(type, 0));
self = (PyZoneInfo_ZoneInfo *)obj_self;
if (self == NULL) {
Expand Down Expand Up @@ -379,35 +391,41 @@ zoneinfo_from_file(PyTypeObject *type, PyObject *args, PyObject *kwargs)
return NULL;
}

/*[clinic input]
@classmethod
zoneinfo.ZoneInfo.no_cache
key: object
Get a new instance of ZoneInfo, bypassing the cache.
[clinic start generated code]*/

static PyObject *
zoneinfo_no_cache(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
zoneinfo_ZoneInfo_no_cache_impl(PyTypeObject *type, PyObject *key)
/*[clinic end generated code: output=751c6894ad66f91b input=bb24afd84a80ba46]*/
{
static char *kwlist[] = {"key", NULL};
PyObject *key = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &key)) {
return NULL;
}

PyObject *out = zoneinfo_new_instance(cls, key);
PyObject *out = zoneinfo_new_instance(type, key);
if (out != NULL) {
((PyZoneInfo_ZoneInfo *)out)->source = SOURCE_NOCACHE;
}

return out;
}

static PyObject *
zoneinfo_clear_cache(PyObject *cls, PyObject *args, PyObject *kwargs)
{
PyObject *only_keys = NULL;
static char *kwlist[] = {"only_keys", NULL};
/*[clinic input]
@classmethod
zoneinfo.ZoneInfo.clear_cache
if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|$O", kwlist,
&only_keys))) {
return NULL;
}
*
only_keys: object = None
PyTypeObject *type = (PyTypeObject *)cls;
Clear the ZoneInfo cache.
[clinic start generated code]*/

static PyObject *
zoneinfo_ZoneInfo_clear_cache_impl(PyTypeObject *type, PyObject *only_keys)
/*[clinic end generated code: output=eec0a3276f07bd90 input=8cff0182a95f295b]*/
{
PyObject *weak_cache = get_weak_cache(type);

if (only_keys == NULL || only_keys == Py_None) {
Expand Down Expand Up @@ -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.")},
Expand Down
188 changes: 188 additions & 0 deletions Modules/clinic/_zoneinfo.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1096dfa

Please sign in to comment.