bpo-1635741: Port _locale extension module to multiphase initialization (PEP 489) (GH-18358)

Co-authored-by: Petr Viktorin <pviktori@redhat.com>
This commit is contained in:
Hai Shi 2020-03-12 00:46:06 +08:00 committed by GitHub
parent 704e2065f8
commit a158168a78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 34 deletions

View File

@ -0,0 +1 @@
Port _locale extension module to multiphase initialization (:pep:`489`).

View File

@ -41,7 +41,17 @@ This software comes with no warranty. Use at your own risk.
PyDoc_STRVAR(locale__doc__, "Support for POSIX locales."); 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 */ /* support functions for formatting floating point numbers */
@ -94,7 +104,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args)
#if defined(MS_WINDOWS) #if defined(MS_WINDOWS)
if (category < LC_MIN || category > LC_MAX) 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; return NULL;
} }
#endif #endif
@ -104,7 +115,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args)
result = setlocale(category, locale); result = setlocale(category, locale);
if (!result) { if (!result) {
/* operation failed, no setting was changed */ /* operation failed, no setting was changed */
PyErr_SetString(Error, "unsupported locale setting"); PyErr_SetString(get_locale_state(self)->Error,
"unsupported locale setting");
return NULL; return NULL;
} }
result_object = PyUnicode_DecodeLocale(result, NULL); result_object = PyUnicode_DecodeLocale(result, NULL);
@ -114,7 +126,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args)
/* get locale */ /* get locale */
result = setlocale(category, NULL); result = setlocale(category, NULL);
if (!result) { if (!result) {
PyErr_SetString(Error, "locale query failed"); PyErr_SetString(get_locale_state(self)->Error,
"locale query failed");
return NULL; return NULL;
} }
result_object = PyUnicode_DecodeLocale(result, NULL); result_object = PyUnicode_DecodeLocale(result, NULL);
@ -622,14 +635,16 @@ PyDoc_STRVAR(bindtextdomain__doc__,
"Bind the C library's domain to dir."); "Bind the C library's domain to dir.");
static PyObject* static PyObject*
PyIntl_bindtextdomain(PyObject* self,PyObject*args) PyIntl_bindtextdomain(PyObject* self, PyObject*args)
{ {
char *domain, *dirname, *current_dirname; char *domain, *dirname, *current_dirname;
PyObject *dirname_obj, *dirname_bytes = NULL, *result; PyObject *dirname_obj, *dirname_bytes = NULL, *result;
if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj)) if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj))
return 0; return 0;
if (!strlen(domain)) { 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; return 0;
} }
if (dirname_obj != Py_None) { if (dirname_obj != Py_None) {
@ -710,31 +725,13 @@ static struct PyMethodDef PyLocale_Methods[] = {
{NULL, NULL} {NULL, NULL}
}; };
static int
static struct PyModuleDef _localemodule = { _locale_exec(PyObject *m)
PyModuleDef_HEAD_INIT,
"_locale",
locale__doc__,
-1,
PyLocale_Methods,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC
PyInit__locale(void)
{ {
PyObject *m;
#ifdef HAVE_LANGINFO_H #ifdef HAVE_LANGINFO_H
int i; int i;
#endif #endif
m = PyModule_Create(&_localemodule);
if (m == NULL)
return NULL;
PyModule_AddIntMacro(m, LC_CTYPE); PyModule_AddIntMacro(m, LC_CTYPE);
PyModule_AddIntMacro(m, LC_TIME); PyModule_AddIntMacro(m, LC_TIME);
PyModule_AddIntMacro(m, LC_COLLATE); PyModule_AddIntMacro(m, LC_COLLATE);
@ -748,12 +745,16 @@ PyInit__locale(void)
PyModule_AddIntMacro(m, LC_ALL); PyModule_AddIntMacro(m, LC_ALL);
PyModule_AddIntMacro(m, CHAR_MAX); PyModule_AddIntMacro(m, CHAR_MAX);
Error = PyErr_NewException("locale.Error", NULL, NULL); _locale_state *state = get_locale_state(m);
if (Error == NULL) { state->Error = PyErr_NewException("locale.Error", NULL, NULL);
Py_DECREF(m); if (state->Error == NULL) {
return 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 #ifdef HAVE_LANGINFO_H
for (i = 0; langinfo_constants[i].name; i++) { for (i = 0; langinfo_constants[i].name; i++) {
@ -763,10 +764,58 @@ PyInit__locale(void)
#endif #endif
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
Py_DECREF(m); return -1;
return NULL;
} }
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);
} }
/* /*