From 4ce0c7c825b3ab010e46ad4b863f7a82b3e2ce34 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Wed, 5 Feb 2020 15:48:06 +0800 Subject: [PATCH 1/6] Port _locale extension module to multiphase initialization (PEP 489) --- Modules/_localemodule.c | 98 +++++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 34 deletions(-) diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index 036bdb301f3203..e0344817010f91 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -41,7 +41,9 @@ 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; /* support functions for formatting floating point numbers */ @@ -87,6 +89,7 @@ PyLocale_setlocale(PyObject* self, PyObject* args) int category; char *locale = NULL, *result; PyObject *result_object; + _locale_state *state; if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale)) return NULL; @@ -94,7 +97,11 @@ PyLocale_setlocale(PyObject* self, PyObject* args) #if defined(MS_WINDOWS) if (category < LC_MIN || category > LC_MAX) { - PyErr_SetString(Error, "invalid locale category"); + state = PyModule_GetState(self); + if (state == NULL) { + return NULL; + } + PyErr_SetString(state->Error, "invalid locale category"); return NULL; } #endif @@ -104,7 +111,11 @@ PyLocale_setlocale(PyObject* self, PyObject* args) result = setlocale(category, locale); if (!result) { /* operation failed, no setting was changed */ - PyErr_SetString(Error, "unsupported locale setting"); + state = PyModule_GetState(self); + if (state == NULL) { + return NULL; + } + PyErr_SetString(state->Error, "unsupported locale setting"); return NULL; } result_object = PyUnicode_DecodeLocale(result, NULL); @@ -114,7 +125,11 @@ PyLocale_setlocale(PyObject* self, PyObject* args) /* get locale */ result = setlocale(category, NULL); if (!result) { - PyErr_SetString(Error, "locale query failed"); + state = PyModule_GetState(self); + if (state == NULL) { + return NULL; + } + PyErr_SetString(state->Error, "locale query failed"); return NULL; } result_object = PyUnicode_DecodeLocale(result, NULL); @@ -622,14 +637,20 @@ 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; + _locale_state *state; + if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj)) return 0; if (!strlen(domain)) { - PyErr_SetString(Error, "domain must be a non-empty string"); + state = PyModule_GetState(self); + if (state == NULL) { + return NULL; + } + PyErr_SetString(state->Error, "domain must be a non-empty string"); return 0; } if (dirname_obj != Py_None) { @@ -710,30 +731,16 @@ 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; + _locale_state *state = PyModule_GetState(m); + if (state == NULL) { + return -1; + } PyModule_AddIntMacro(m, LC_CTYPE); PyModule_AddIntMacro(m, LC_TIME); @@ -748,12 +755,13 @@ 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; + state->Error = PyErr_NewException("locale.Error", NULL, NULL); + if (state->Error == NULL) { + return -1; + } + if (PyModule_AddObject(m, "Error", state->Error) < 0) { + return -1; } - PyModule_AddObject(m, "Error", Error); #ifdef HAVE_LANGINFO_H for (i = 0; langinfo_constants[i].name; i++) { @@ -763,10 +771,32 @@ 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 struct PyModuleDef _localemodule = { + PyModuleDef_HEAD_INIT, + "_locale", + locale__doc__, + sizeof(_locale_state), + PyLocale_Methods, + _locale_slots, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit__locale(void) +{ + return PyModuleDef_Init(&_localemodule); } /* From c0e0174f5e8bc0733ea37eb5424cb56e5f255592 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 5 Feb 2020 07:55:59 +0000 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Core and Builtins/2020-02-05-07-55-57.bpo-1635741.H_tCC9.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-02-05-07-55-57.bpo-1635741.H_tCC9.rst 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 00000000000000..a9e1e50da31fe9 --- /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 From 3aaf4881148600747055e06d9c268f9bb2e740d9 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Mon, 17 Feb 2020 22:52:04 +0800 Subject: [PATCH 3/6] add get_locale_state() --- Modules/_localemodule.c | 48 ++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index e0344817010f91..eee1adc32c56b2 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -45,6 +45,14 @@ 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 */ PyDoc_STRVAR(setlocale__doc__, @@ -89,7 +97,6 @@ PyLocale_setlocale(PyObject* self, PyObject* args) int category; char *locale = NULL, *result; PyObject *result_object; - _locale_state *state; if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale)) return NULL; @@ -97,11 +104,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args) #if defined(MS_WINDOWS) if (category < LC_MIN || category > LC_MAX) { - state = PyModule_GetState(self); - if (state == NULL) { - return NULL; - } - PyErr_SetString(state->Error, "invalid locale category"); + PyErr_SetString(get_locale_state(self)->Error, + "invalid locale category"); return NULL; } #endif @@ -111,11 +115,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args) result = setlocale(category, locale); if (!result) { /* operation failed, no setting was changed */ - state = PyModule_GetState(self); - if (state == NULL) { - return NULL; - } - PyErr_SetString(state->Error, "unsupported locale setting"); + PyErr_SetString(get_locale_state(self)->Error, + "unsupported locale setting"); return NULL; } result_object = PyUnicode_DecodeLocale(result, NULL); @@ -125,11 +126,8 @@ PyLocale_setlocale(PyObject* self, PyObject* args) /* get locale */ result = setlocale(category, NULL); if (!result) { - state = PyModule_GetState(self); - if (state == NULL) { - return NULL; - } - PyErr_SetString(state->Error, "locale query failed"); + PyErr_SetString(get_locale_state(self)->Error, + "locale query failed"); return NULL; } result_object = PyUnicode_DecodeLocale(result, NULL); @@ -641,16 +639,12 @@ PyIntl_bindtextdomain(PyObject* self, PyObject*args) { char *domain, *dirname, *current_dirname; PyObject *dirname_obj, *dirname_bytes = NULL, *result; - _locale_state *state; if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj)) return 0; if (!strlen(domain)) { - state = PyModule_GetState(self); - if (state == NULL) { - return NULL; - } - PyErr_SetString(state->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) { @@ -737,10 +731,6 @@ _locale_exec(PyObject *m) #ifdef HAVE_LANGINFO_H int i; #endif - _locale_state *state = PyModule_GetState(m); - if (state == NULL) { - return -1; - } PyModule_AddIntMacro(m, LC_CTYPE); PyModule_AddIntMacro(m, LC_TIME); @@ -755,11 +745,11 @@ _locale_exec(PyObject *m) PyModule_AddIntMacro(m, LC_ALL); PyModule_AddIntMacro(m, CHAR_MAX); - state->Error = PyErr_NewException("locale.Error", NULL, NULL); - if (state->Error == NULL) { + get_locale_state(m)->Error = PyErr_NewException("locale.Error", NULL, NULL); + if (get_locale_state(m)->Error == NULL) { return -1; } - if (PyModule_AddObject(m, "Error", state->Error) < 0) { + if (PyModule_AddObject(m, "Error", get_locale_state(m)->Error) < 0) { return -1; } From 2a4ac1b0b56eec2f1050499c876491e4cabefd1c Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Tue, 18 Feb 2020 08:04:49 +0800 Subject: [PATCH 4/6] fix format bug --- Modules/_localemodule.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index eee1adc32c56b2..cc2a94b6d7af0a 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -105,7 +105,7 @@ PyLocale_setlocale(PyObject* self, PyObject* args) if (category < LC_MIN || category > LC_MAX) { PyErr_SetString(get_locale_state(self)->Error, - "invalid locale category"); + "invalid locale category"); return NULL; } #endif @@ -116,7 +116,7 @@ PyLocale_setlocale(PyObject* self, PyObject* args) if (!result) { /* operation failed, no setting was changed */ PyErr_SetString(get_locale_state(self)->Error, - "unsupported locale setting"); + "unsupported locale setting"); return NULL; } result_object = PyUnicode_DecodeLocale(result, NULL); @@ -127,7 +127,7 @@ PyLocale_setlocale(PyObject* self, PyObject* args) result = setlocale(category, NULL); if (!result) { PyErr_SetString(get_locale_state(self)->Error, - "locale query failed"); + "locale query failed"); return NULL; } result_object = PyUnicode_DecodeLocale(result, NULL); @@ -644,7 +644,7 @@ PyIntl_bindtextdomain(PyObject* self, PyObject*args) return 0; if (!strlen(domain)) { PyErr_SetString(get_locale_state(self)->Error, - "domain must be a non-empty string"); + "domain must be a non-empty string"); return 0; } if (dirname_obj != Py_None) { @@ -745,8 +745,9 @@ _locale_exec(PyObject *m) PyModule_AddIntMacro(m, LC_ALL); PyModule_AddIntMacro(m, CHAR_MAX); - get_locale_state(m)->Error = PyErr_NewException("locale.Error", NULL, NULL); - if (get_locale_state(m)->Error == NULL) { + _locale_state *state = get_locale_state(m); + state->Error = PyErr_NewException("locale.Error", NULL, NULL); + if (state->Error == NULL) { return -1; } if (PyModule_AddObject(m, "Error", get_locale_state(m)->Error) < 0) { From 70fddf4c8eab7b0418573e270accfa5de25c97eb Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Tue, 18 Feb 2020 22:59:50 +0800 Subject: [PATCH 5/6] locale extension module add clean slots --- Modules/_localemodule.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index cc2a94b6d7af0a..af7a157911917b 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -49,7 +49,6 @@ static inline _locale_state* get_locale_state(PyObject *m) { void *state = PyModule_GetState(m); - assert(state != NULL); return (_locale_state *)state; } @@ -750,7 +749,9 @@ _locale_exec(PyObject *m) 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; } @@ -772,6 +773,31 @@ static struct PyModuleDef_Slot _locale_slots[] = { {0, NULL} }; +static int +locale_traverse(PyObject *m, visitproc visit, void *arg) +{ + _locale_state *state = get_locale_state(m); + if (state == NULL) { + return -1; + } + Py_VISIT(state->Error); + return 0; +} + +static int +locale_clear(PyObject *m) +{ + _locale_state *state = get_locale_state(m); + Py_CLEAR(state->Error); + return 0; +} + +static void +locale_free(PyObject *m) +{ + locale_clear(m); +} + static struct PyModuleDef _localemodule = { PyModuleDef_HEAD_INIT, "_locale", @@ -779,9 +805,9 @@ static struct PyModuleDef _localemodule = { sizeof(_locale_state), PyLocale_Methods, _locale_slots, - NULL, - NULL, - NULL + locale_traverse, + locale_clear, + (freefunc)locale_free }; PyMODINIT_FUNC From f3a1d08ac4192d83b35391bb11127132dc8ea1d7 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 25 Feb 2020 14:47:54 +0100 Subject: [PATCH 6/6] Add back assertion in get_locale_state --- Modules/_localemodule.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index af7a157911917b..f68debdb1da460 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -49,6 +49,7 @@ static inline _locale_state* get_locale_state(PyObject *m) { void *state = PyModule_GetState(m); + assert(state != NULL); return (_locale_state *)state; } @@ -776,19 +777,20 @@ static struct PyModuleDef_Slot _locale_slots[] = { static int locale_traverse(PyObject *m, visitproc visit, void *arg) { - _locale_state *state = get_locale_state(m); - if (state == NULL) { - return -1; + _locale_state *state = (_locale_state*)PyModule_GetState(m); + if (state) { + Py_VISIT(state->Error); } - Py_VISIT(state->Error); return 0; } static int locale_clear(PyObject *m) { - _locale_state *state = get_locale_state(m); - Py_CLEAR(state->Error); + _locale_state *state = (_locale_state*)PyModule_GetState(m); + if (state) { + Py_CLEAR(state->Error); + } return 0; } @@ -807,7 +809,7 @@ static struct PyModuleDef _localemodule = { _locale_slots, locale_traverse, locale_clear, - (freefunc)locale_free + (freefunc)locale_free, }; PyMODINIT_FUNC