[Python-checkins] bpo-1635741: Port _locale extension module to multiphase initialization (PEP 489) (GH-18358)
Hai Shi
webhook-mailer at python.org
Wed Mar 11 12:46:11 EDT 2020
https://github.com/python/cpython/commit/a158168a787e82c4b7b18f6833153188e93627a5
commit: a158168a787e82c4b7b18f6833153188e93627a5
branch: master
author: Hai Shi <shihai1992 at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-03-11T17:46:06+01:00
summary:
bpo-1635741: Port _locale extension module to multiphase initialization (PEP 489) (GH-18358)
Co-authored-by: Petr Viktorin <pviktori at redhat.com>
files:
A Misc/NEWS.d/next/Core and Builtins/2020-02-05-07-55-57.bpo-1635741.H_tCC9.rst
M Modules/_localemodule.c
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-02-05-07-55-57.bpo-1635741.H_tCC9.rst b/Misc/NEWS.d/next/Core and Builtins/2020-02-05-07-55-57.bpo-1635741.H_tCC9.rst
new file mode 100644
index 0000000000000..a9e1e50da31fe
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-02-05-07-55-57.bpo-1635741.H_tCC9.rst
@@ -0,0 +1 @@
+Port _locale extension module to multiphase initialization (:pep:`489`).
\ No newline at end of file
diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c
index 036bdb301f320..f68debdb1da46 100644
--- a/Modules/_localemodule.c
+++ b/Modules/_localemodule.c
@@ -41,7 +41,17 @@ This software comes with no warranty. Use at your own risk.
PyDoc_STRVAR(locale__doc__, "Support for POSIX locales.");
-static PyObject *Error;
+typedef struct _locale_state {
+ PyObject *Error;
+} _locale_state;
+
+static inline _locale_state*
+get_locale_state(PyObject *m)
+{
+ void *state = PyModule_GetState(m);
+ assert(state != NULL);
+ return (_locale_state *)state;
+}
/* support functions for formatting floating point numbers */
@@ -94,7 +104,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args)
#if defined(MS_WINDOWS)
if (category < LC_MIN || category > LC_MAX)
{
- PyErr_SetString(Error, "invalid locale category");
+ PyErr_SetString(get_locale_state(self)->Error,
+ "invalid locale category");
return NULL;
}
#endif
@@ -104,7 +115,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args)
result = setlocale(category, locale);
if (!result) {
/* operation failed, no setting was changed */
- PyErr_SetString(Error, "unsupported locale setting");
+ PyErr_SetString(get_locale_state(self)->Error,
+ "unsupported locale setting");
return NULL;
}
result_object = PyUnicode_DecodeLocale(result, NULL);
@@ -114,7 +126,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args)
/* get locale */
result = setlocale(category, NULL);
if (!result) {
- PyErr_SetString(Error, "locale query failed");
+ PyErr_SetString(get_locale_state(self)->Error,
+ "locale query failed");
return NULL;
}
result_object = PyUnicode_DecodeLocale(result, NULL);
@@ -622,14 +635,16 @@ PyDoc_STRVAR(bindtextdomain__doc__,
"Bind the C library's domain to dir.");
static PyObject*
-PyIntl_bindtextdomain(PyObject* self,PyObject*args)
+PyIntl_bindtextdomain(PyObject* self, PyObject*args)
{
char *domain, *dirname, *current_dirname;
PyObject *dirname_obj, *dirname_bytes = NULL, *result;
+
if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj))
return 0;
if (!strlen(domain)) {
- PyErr_SetString(Error, "domain must be a non-empty string");
+ PyErr_SetString(get_locale_state(self)->Error,
+ "domain must be a non-empty string");
return 0;
}
if (dirname_obj != Py_None) {
@@ -710,31 +725,13 @@ static struct PyMethodDef PyLocale_Methods[] = {
{NULL, NULL}
};
-
-static struct PyModuleDef _localemodule = {
- PyModuleDef_HEAD_INIT,
- "_locale",
- locale__doc__,
- -1,
- PyLocale_Methods,
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-PyMODINIT_FUNC
-PyInit__locale(void)
+static int
+_locale_exec(PyObject *m)
{
- PyObject *m;
#ifdef HAVE_LANGINFO_H
int i;
#endif
- m = PyModule_Create(&_localemodule);
- if (m == NULL)
- return NULL;
-
PyModule_AddIntMacro(m, LC_CTYPE);
PyModule_AddIntMacro(m, LC_TIME);
PyModule_AddIntMacro(m, LC_COLLATE);
@@ -748,12 +745,16 @@ PyInit__locale(void)
PyModule_AddIntMacro(m, LC_ALL);
PyModule_AddIntMacro(m, CHAR_MAX);
- Error = PyErr_NewException("locale.Error", NULL, NULL);
- if (Error == NULL) {
- Py_DECREF(m);
- return NULL;
+ _locale_state *state = get_locale_state(m);
+ state->Error = PyErr_NewException("locale.Error", NULL, NULL);
+ if (state->Error == NULL) {
+ return -1;
+ }
+ Py_INCREF(get_locale_state(m)->Error);
+ if (PyModule_AddObject(m, "Error", get_locale_state(m)->Error) < 0) {
+ Py_DECREF(get_locale_state(m)->Error);
+ return -1;
}
- PyModule_AddObject(m, "Error", Error);
#ifdef HAVE_LANGINFO_H
for (i = 0; langinfo_constants[i].name; i++) {
@@ -763,10 +764,58 @@ PyInit__locale(void)
#endif
if (PyErr_Occurred()) {
- Py_DECREF(m);
- return NULL;
+ return -1;
}
- return m;
+ return 0;
+}
+
+static struct PyModuleDef_Slot _locale_slots[] = {
+ {Py_mod_exec, _locale_exec},
+ {0, NULL}
+};
+
+static int
+locale_traverse(PyObject *m, visitproc visit, void *arg)
+{
+ _locale_state *state = (_locale_state*)PyModule_GetState(m);
+ if (state) {
+ Py_VISIT(state->Error);
+ }
+ return 0;
+}
+
+static int
+locale_clear(PyObject *m)
+{
+ _locale_state *state = (_locale_state*)PyModule_GetState(m);
+ if (state) {
+ Py_CLEAR(state->Error);
+ }
+ return 0;
+}
+
+static void
+locale_free(PyObject *m)
+{
+ locale_clear(m);
+}
+
+static struct PyModuleDef _localemodule = {
+ PyModuleDef_HEAD_INIT,
+ "_locale",
+ locale__doc__,
+ sizeof(_locale_state),
+ PyLocale_Methods,
+ _locale_slots,
+ locale_traverse,
+ locale_clear,
+ (freefunc)locale_free,
+};
+
+PyMODINIT_FUNC
+PyInit__locale(void)
+{
+ return PyModuleDef_Init(&_localemodule);
}
/*
More information about the Python-checkins
mailing list