Skip to content

Commit

Permalink
bpo-1635741: Port _locale extension module to multiphase initializati…
Browse files Browse the repository at this point in the history
…on (PEP 489) (GH-18358)

Co-authored-by: Petr Viktorin <[email protected]>
  • Loading branch information
shihai1991 and encukou authored Mar 11, 2020
1 parent 704e206 commit a158168
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Port _locale extension module to multiphase initialization (:pep:`489`).
117 changes: 83 additions & 34 deletions Modules/_localemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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++) {
Expand All @@ -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);
}

/*
Expand Down

0 comments on commit a158168

Please sign in to comment.