Skip to content

Commit a158168

Browse files
shihai1991encukou
andauthored
bpo-1635741: Port _locale extension module to multiphase initialization (PEP 489) (GH-18358)
Co-authored-by: Petr Viktorin <pviktori@redhat.com>
1 parent 704e206 commit a158168

File tree

2 files changed

+84
-34
lines changed

2 files changed

+84
-34
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Port _locale extension module to multiphase initialization (:pep:`489`).

Modules/_localemodule.c

Lines changed: 83 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,17 @@ This software comes with no warranty. Use at your own risk.
4141

4242
PyDoc_STRVAR(locale__doc__, "Support for POSIX locales.");
4343

44-
static PyObject *Error;
44+
typedef struct _locale_state {
45+
PyObject *Error;
46+
} _locale_state;
47+
48+
static inline _locale_state*
49+
get_locale_state(PyObject *m)
50+
{
51+
void *state = PyModule_GetState(m);
52+
assert(state != NULL);
53+
return (_locale_state *)state;
54+
}
4555

4656
/* support functions for formatting floating point numbers */
4757

@@ -94,7 +104,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args)
94104
#if defined(MS_WINDOWS)
95105
if (category < LC_MIN || category > LC_MAX)
96106
{
97-
PyErr_SetString(Error, "invalid locale category");
107+
PyErr_SetString(get_locale_state(self)->Error,
108+
"invalid locale category");
98109
return NULL;
99110
}
100111
#endif
@@ -104,7 +115,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args)
104115
result = setlocale(category, locale);
105116
if (!result) {
106117
/* operation failed, no setting was changed */
107-
PyErr_SetString(Error, "unsupported locale setting");
118+
PyErr_SetString(get_locale_state(self)->Error,
119+
"unsupported locale setting");
108120
return NULL;
109121
}
110122
result_object = PyUnicode_DecodeLocale(result, NULL);
@@ -114,7 +126,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args)
114126
/* get locale */
115127
result = setlocale(category, NULL);
116128
if (!result) {
117-
PyErr_SetString(Error, "locale query failed");
129+
PyErr_SetString(get_locale_state(self)->Error,
130+
"locale query failed");
118131
return NULL;
119132
}
120133
result_object = PyUnicode_DecodeLocale(result, NULL);
@@ -622,14 +635,16 @@ PyDoc_STRVAR(bindtextdomain__doc__,
622635
"Bind the C library's domain to dir.");
623636

624637
static PyObject*
625-
PyIntl_bindtextdomain(PyObject* self,PyObject*args)
638+
PyIntl_bindtextdomain(PyObject* self, PyObject*args)
626639
{
627640
char *domain, *dirname, *current_dirname;
628641
PyObject *dirname_obj, *dirname_bytes = NULL, *result;
642+
629643
if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj))
630644
return 0;
631645
if (!strlen(domain)) {
632-
PyErr_SetString(Error, "domain must be a non-empty string");
646+
PyErr_SetString(get_locale_state(self)->Error,
647+
"domain must be a non-empty string");
633648
return 0;
634649
}
635650
if (dirname_obj != Py_None) {
@@ -710,31 +725,13 @@ static struct PyMethodDef PyLocale_Methods[] = {
710725
{NULL, NULL}
711726
};
712727

713-
714-
static struct PyModuleDef _localemodule = {
715-
PyModuleDef_HEAD_INIT,
716-
"_locale",
717-
locale__doc__,
718-
-1,
719-
PyLocale_Methods,
720-
NULL,
721-
NULL,
722-
NULL,
723-
NULL
724-
};
725-
726-
PyMODINIT_FUNC
727-
PyInit__locale(void)
728+
static int
729+
_locale_exec(PyObject *m)
728730
{
729-
PyObject *m;
730731
#ifdef HAVE_LANGINFO_H
731732
int i;
732733
#endif
733734

734-
m = PyModule_Create(&_localemodule);
735-
if (m == NULL)
736-
return NULL;
737-
738735
PyModule_AddIntMacro(m, LC_CTYPE);
739736
PyModule_AddIntMacro(m, LC_TIME);
740737
PyModule_AddIntMacro(m, LC_COLLATE);
@@ -748,12 +745,16 @@ PyInit__locale(void)
748745
PyModule_AddIntMacro(m, LC_ALL);
749746
PyModule_AddIntMacro(m, CHAR_MAX);
750747

751-
Error = PyErr_NewException("locale.Error", NULL, NULL);
752-
if (Error == NULL) {
753-
Py_DECREF(m);
754-
return NULL;
748+
_locale_state *state = get_locale_state(m);
749+
state->Error = PyErr_NewException("locale.Error", NULL, NULL);
750+
if (state->Error == NULL) {
751+
return -1;
752+
}
753+
Py_INCREF(get_locale_state(m)->Error);
754+
if (PyModule_AddObject(m, "Error", get_locale_state(m)->Error) < 0) {
755+
Py_DECREF(get_locale_state(m)->Error);
756+
return -1;
755757
}
756-
PyModule_AddObject(m, "Error", Error);
757758

758759
#ifdef HAVE_LANGINFO_H
759760
for (i = 0; langinfo_constants[i].name; i++) {
@@ -763,10 +764,58 @@ PyInit__locale(void)
763764
#endif
764765

765766
if (PyErr_Occurred()) {
766-
Py_DECREF(m);
767-
return NULL;
767+
return -1;
768768
}
769-
return m;
769+
return 0;
770+
}
771+
772+
static struct PyModuleDef_Slot _locale_slots[] = {
773+
{Py_mod_exec, _locale_exec},
774+
{0, NULL}
775+
};
776+
777+
static int
778+
locale_traverse(PyObject *m, visitproc visit, void *arg)
779+
{
780+
_locale_state *state = (_locale_state*)PyModule_GetState(m);
781+
if (state) {
782+
Py_VISIT(state->Error);
783+
}
784+
return 0;
785+
}
786+
787+
static int
788+
locale_clear(PyObject *m)
789+
{
790+
_locale_state *state = (_locale_state*)PyModule_GetState(m);
791+
if (state) {
792+
Py_CLEAR(state->Error);
793+
}
794+
return 0;
795+
}
796+
797+
static void
798+
locale_free(PyObject *m)
799+
{
800+
locale_clear(m);
801+
}
802+
803+
static struct PyModuleDef _localemodule = {
804+
PyModuleDef_HEAD_INIT,
805+
"_locale",
806+
locale__doc__,
807+
sizeof(_locale_state),
808+
PyLocale_Methods,
809+
_locale_slots,
810+
locale_traverse,
811+
locale_clear,
812+
(freefunc)locale_free,
813+
};
814+
815+
PyMODINIT_FUNC
816+
PyInit__locale(void)
817+
{
818+
return PyModuleDef_Init(&_localemodule);
770819
}
771820

772821
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy