From fefda7041bd2a53d058a6f263cc9c52146741cf6 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Tue, 22 Sep 2020 21:12:22 +0800 Subject: [PATCH 01/14] add a _codecs.unregister in _codecs module --- Doc/library/codecs.rst | 13 +++++++++--- Include/codecs.h | 4 ++++ Lib/test/test_codecs.py | 6 ++++++ .../2020-09-22-20-54-18.bpo-39337.zX2e5M.rst | 2 ++ Modules/_codecsmodule.c | 19 ++++++++++++++++++ Modules/clinic/_codecsmodule.c.h | 14 ++++++++++++- Python/codecs.c | 20 +++++++++++++++++++ 7 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-09-22-20-54-18.bpo-39337.zX2e5M.rst diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index f071057293eece..9e6b86cf590202 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -165,9 +165,16 @@ function: .. note:: - Search function registration is not currently reversible, - which may cause problems in some cases, such as unit testing or - module reloading. + Search function registration is reversible since Python 3.10. + You can use `codecs.unregister()` to unregister the search function. + +.. function:: unregister(search_function) + + Unregister a codec search function from the codecs registry. If + the search function haven't registered, this function dose nothing. + + .. versionadded:: 3.10 + While the builtin :func:`open` and the associated :mod:`io` module are the recommended approach for working with encoded text files, this module diff --git a/Include/codecs.h b/Include/codecs.h index 3ad0f2b5aae79c..e31bef8939c7ea 100644 --- a/Include/codecs.h +++ b/Include/codecs.h @@ -53,6 +53,10 @@ PyAPI_FUNC(PyObject *) _PyCodec_Lookup( PyAPI_FUNC(int) _PyCodec_Forget( const char *encoding ); + +PyAPI_FUNC(PyObject *) _PyCodec_Unregister( + PyObject *search_function + ); #endif /* Codec registry encoding check API. diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 3dd56820cd1078..420391255d5a4f 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1641,6 +1641,12 @@ def test_register(self): self.assertRaises(TypeError, codecs.register) self.assertRaises(TypeError, codecs.register, 42) + def test_unregister(self): + def test_encoding(encoding): + return None + codecs.register(test_encoding) + self.assertEqual(codecs.unregister(test_encoding), None) + def test_lookup(self): self.assertRaises(TypeError, codecs.lookup) self.assertRaises(LookupError, codecs.lookup, "__spam__") diff --git a/Misc/NEWS.d/next/Library/2020-09-22-20-54-18.bpo-39337.zX2e5M.rst b/Misc/NEWS.d/next/Library/2020-09-22-20-54-18.bpo-39337.zX2e5M.rst new file mode 100644 index 00000000000000..86b3d8dc13ce54 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-09-22-20-54-18.bpo-39337.zX2e5M.rst @@ -0,0 +1,2 @@ +Add a :func:`_codecs.unregister` which could unregister a codec search +function from the codec registry. diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c index 952072102d5d8d..0d062baefc11b4 100644 --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -68,6 +68,24 @@ _codecs_register(PyObject *module, PyObject *search_function) Py_RETURN_NONE; } +/*[clinic input] +_codecs.unregister + search_function: object + / + +Unregister a codec search function. + +Unregister a codec search function from codec registry. If the search +function haven't registered, this function does nothing. +[clinic start generated code]*/ + +static PyObject * +_codecs_unregister(PyObject *module, PyObject *search_function) +/*[clinic end generated code: output=1f0edee9cf246399 input=ecb26613941e6a47]*/ +{ + return _PyCodec_Unregister(search_function); +} + /*[clinic input] _codecs.lookup encoding: str @@ -992,6 +1010,7 @@ _codecs_lookup_error_impl(PyObject *module, const char *name) static PyMethodDef _codecs_functions[] = { _CODECS_REGISTER_METHODDEF + _CODECS_UNREGISTER_METHODDEF _CODECS_LOOKUP_METHODDEF _CODECS_ENCODE_METHODDEF _CODECS_DECODE_METHODDEF diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h index 249065c9fd05a4..1810319b65e0ce 100644 --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -15,6 +15,18 @@ PyDoc_STRVAR(_codecs_register__doc__, #define _CODECS_REGISTER_METHODDEF \ {"register", (PyCFunction)_codecs_register, METH_O, _codecs_register__doc__}, +PyDoc_STRVAR(_codecs_unregister__doc__, +"unregister($module, search_function, /)\n" +"--\n" +"\n" +"Unregister a codec search function.\n" +"\n" +"Unregister a codec search function from codec registry. If the search\n" +"function haven\'t registered, this function does nothing."); + +#define _CODECS_UNREGISTER_METHODDEF \ + {"unregister", (PyCFunction)_codecs_unregister, METH_O, _codecs_unregister__doc__}, + PyDoc_STRVAR(_codecs_lookup__doc__, "lookup($module, encoding, /)\n" "--\n" @@ -2827,4 +2839,4 @@ _codecs_lookup_error(PyObject *module, PyObject *arg) #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF #define _CODECS_CODE_PAGE_ENCODE_METHODDEF #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ -/*[clinic end generated code: output=eeead01414be6e42 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b2d6d8e9caa87da7 input=a9049054013a1b77]*/ diff --git a/Python/codecs.c b/Python/codecs.c index 0f18c27e5fe461..57edc2851055b4 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -50,6 +50,26 @@ int PyCodec_Register(PyObject *search_function) return -1; } +PyObject * +_PyCodec_Unregister(PyObject *search_function) +{ + PyInterpreterState *interp = PyInterpreterState_Get(); + if (interp->codec_search_path == NULL) { + Py_RETURN_NONE; + } + + Py_ssize_t n = PyList_Size(interp->codec_search_path); + PyObject *list = PyList_New(0); + for (Py_ssize_t i = 0; i < n; i++) { + PyObject *item = PyList_GetItem(interp->codec_search_path, i); + if (item != search_function) { + PyList_Append(list, item); + } + } + Py_SETREF(interp->codec_search_path, list); + Py_RETURN_NONE; +} + extern int _Py_normalize_encoding(const char *, char *, size_t); /* Convert a string to a normalized Python string(decoded from UTF-8): all characters are From f7775c09869738ca0341098ee0bea203a6345fae Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Wed, 23 Sep 2020 22:54:00 +0800 Subject: [PATCH 02/14] apply victor's comment --- Doc/library/codecs.rst | 9 +++------ Doc/whatsnew/3.10.rst | 5 +++++ Include/codecs.h | 2 +- .../2020-09-22-20-54-18.bpo-39337.zX2e5M.rst | 2 -- .../2020-09-23-22-52-24.bpo-41842.lIuhC9.rst | 1 + Modules/_codecsmodule.c | 11 +++++++---- Modules/clinic/_codecsmodule.c.h | 5 ++--- Python/codecs.c | 14 +++++++------- 8 files changed, 26 insertions(+), 23 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2020-09-22-20-54-18.bpo-39337.zX2e5M.rst create mode 100644 Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index 9e6b86cf590202..9fb90761febbc4 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -163,15 +163,12 @@ function: :class:`CodecInfo` object. In case a search function cannot find a given encoding, it should return ``None``. - .. note:: - - Search function registration is reversible since Python 3.10. - You can use `codecs.unregister()` to unregister the search function. .. function:: unregister(search_function) - Unregister a codec search function from the codecs registry. If - the search function haven't registered, this function dose nothing. + Unregister a codec search function from the codecs registry. + If the search function is not registered, do nothing. + Clear the registry's cache if the codec search function is removed. .. versionadded:: 3.10 diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index ce888fec1d8c97..832e2dc5dc171a 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -109,6 +109,11 @@ base64 Add :func:`base64.b32hexencode` and :func:`base64.b32hexdecode` to support the Base32 Encoding with Extended Hex Alphabet. +codecs +------ + +Add :func:`_codecs.unregister` to unregister a codec search function. + curses ------ diff --git a/Include/codecs.h b/Include/codecs.h index e31bef8939c7ea..4ed664a058275d 100644 --- a/Include/codecs.h +++ b/Include/codecs.h @@ -54,7 +54,7 @@ PyAPI_FUNC(int) _PyCodec_Forget( const char *encoding ); -PyAPI_FUNC(PyObject *) _PyCodec_Unregister( +PyAPI_FUNC(int) _PyCodec_Unregister( PyObject *search_function ); #endif diff --git a/Misc/NEWS.d/next/Library/2020-09-22-20-54-18.bpo-39337.zX2e5M.rst b/Misc/NEWS.d/next/Library/2020-09-22-20-54-18.bpo-39337.zX2e5M.rst deleted file mode 100644 index 86b3d8dc13ce54..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-09-22-20-54-18.bpo-39337.zX2e5M.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add a :func:`_codecs.unregister` which could unregister a codec search -function from the codec registry. diff --git a/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst b/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst new file mode 100644 index 00000000000000..bfc279aba3d090 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst @@ -0,0 +1 @@ +Add a :func:`_codecs.unregister` to unregister a codec search function. diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c index 0d062baefc11b4..fa12e68b9bc714 100644 --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -75,15 +75,18 @@ _codecs.unregister Unregister a codec search function. -Unregister a codec search function from codec registry. If the search -function haven't registered, this function does nothing. +If the search function is not registered, do nothing. [clinic start generated code]*/ static PyObject * _codecs_unregister(PyObject *module, PyObject *search_function) -/*[clinic end generated code: output=1f0edee9cf246399 input=ecb26613941e6a47]*/ +/*[clinic end generated code: output=1f0edee9cf246399 input=8bfb99685e00d653]*/ { - return _PyCodec_Unregister(search_function); + if (_PyCodec_Unregister(search_function)) { + return NULL; + } + + Py_RETURN_NONE; } /*[clinic input] diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h index 1810319b65e0ce..7974af32f4556e 100644 --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -21,8 +21,7 @@ PyDoc_STRVAR(_codecs_unregister__doc__, "\n" "Unregister a codec search function.\n" "\n" -"Unregister a codec search function from codec registry. If the search\n" -"function haven\'t registered, this function does nothing."); +"If the search function is not registered, do nothing."); #define _CODECS_UNREGISTER_METHODDEF \ {"unregister", (PyCFunction)_codecs_unregister, METH_O, _codecs_unregister__doc__}, @@ -2839,4 +2838,4 @@ _codecs_lookup_error(PyObject *module, PyObject *arg) #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF #define _CODECS_CODE_PAGE_ENCODE_METHODDEF #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ -/*[clinic end generated code: output=b2d6d8e9caa87da7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=47d275cbfe79eea2 input=a9049054013a1b77]*/ diff --git a/Python/codecs.c b/Python/codecs.c index 57edc2851055b4..39af3e6c36a4ec 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -50,24 +50,24 @@ int PyCodec_Register(PyObject *search_function) return -1; } -PyObject * +int _PyCodec_Unregister(PyObject *search_function) { PyInterpreterState *interp = PyInterpreterState_Get(); + /* Do nothing if codec_search_path is not created yet or was created. */ if (interp->codec_search_path == NULL) { - Py_RETURN_NONE; + return 0; } Py_ssize_t n = PyList_Size(interp->codec_search_path); - PyObject *list = PyList_New(0); for (Py_ssize_t i = 0; i < n; i++) { PyObject *item = PyList_GetItem(interp->codec_search_path, i); - if (item != search_function) { - PyList_Append(list, item); + if (item == search_function) { + return PyList_SetSlice(interp->codec_search_path, i, i+1, NULL); } } - Py_SETREF(interp->codec_search_path, list); - Py_RETURN_NONE; + PyDict_Clear(interp->codec_search_cache); + return 0; } extern int _Py_normalize_encoding(const char *, char *, size_t); From 71b624e3b6d09884b80670b98896d6638826db42 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Thu, 24 Sep 2020 00:59:30 +0800 Subject: [PATCH 03/14] apply victor's comment --- Doc/library/codecs.rst | 3 +-- Doc/whatsnew/3.10.rst | 2 +- Include/codecs.h | 14 ++++++++++---- Lib/test/test_codecs.py | 9 +++++---- .../2020-09-23-22-52-24.bpo-41842.lIuhC9.rst | 2 +- Modules/_codecsmodule.c | 6 +++--- Modules/clinic/_codecsmodule.c.h | 4 ++-- Python/codecs.c | 4 ++-- 8 files changed, 25 insertions(+), 19 deletions(-) diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index 9fb90761febbc4..a0265135205901 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -166,9 +166,8 @@ function: .. function:: unregister(search_function) - Unregister a codec search function from the codecs registry. + Unregister a codec search function and clear the registry's cache. If the search function is not registered, do nothing. - Clear the registry's cache if the codec search function is removed. .. versionadded:: 3.10 diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 832e2dc5dc171a..fac139d77ee354 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -112,7 +112,7 @@ Base32 Encoding with Extended Hex Alphabet. codecs ------ -Add :func:`_codecs.unregister` to unregister a codec search function. +Add :func:`codecs.unregister` to unregister a codec search function. curses ------ diff --git a/Include/codecs.h b/Include/codecs.h index 4ed664a058275d..1cfcf8c4fd1274 100644 --- a/Include/codecs.h +++ b/Include/codecs.h @@ -27,6 +27,16 @@ PyAPI_FUNC(int) PyCodec_Register( PyObject *search_function ); +/* Unregister a codec search function. + + Unregister a codec search function and clear the registry's cache. + If the search function is not registered, do nothing. + */ + +PyAPI_FUNC(int) PyCodec_Unregister( + PyObject *search_function + ); + /* Codec registry lookup API. Looks up the given encoding and returns a CodecInfo object with @@ -53,10 +63,6 @@ PyAPI_FUNC(PyObject *) _PyCodec_Lookup( PyAPI_FUNC(int) _PyCodec_Forget( const char *encoding ); - -PyAPI_FUNC(int) _PyCodec_Unregister( - PyObject *search_function - ); #endif /* Codec registry encoding check API. diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 420391255d5a4f..1acafc2f1a2f1b 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1642,10 +1642,11 @@ def test_register(self): self.assertRaises(TypeError, codecs.register, 42) def test_unregister(self): - def test_encoding(encoding): - return None - codecs.register(test_encoding) - self.assertEqual(codecs.unregister(test_encoding), None) + search_function = mock.Mock(return_value=(1, 2, 3, 4)) + codecs.register(search_function) + codecs.unregister(search_function) + self.assertRaises(LookupError, codecs.lookup, "test") + search_function.assert_not_called() def test_lookup(self): self.assertRaises(TypeError, codecs.lookup) diff --git a/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst b/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst index bfc279aba3d090..e214175f49929c 100644 --- a/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst +++ b/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst @@ -1 +1 @@ -Add a :func:`_codecs.unregister` to unregister a codec search function. +Add a :func:`codecs.unregister` to unregister a codec search function. diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c index fa12e68b9bc714..08a3d4ab024cc2 100644 --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -73,16 +73,16 @@ _codecs.unregister search_function: object / -Unregister a codec search function. +Unregister a codec search function and clear the registry's cache. If the search function is not registered, do nothing. [clinic start generated code]*/ static PyObject * _codecs_unregister(PyObject *module, PyObject *search_function) -/*[clinic end generated code: output=1f0edee9cf246399 input=8bfb99685e00d653]*/ +/*[clinic end generated code: output=1f0edee9cf246399 input=dd7c004c652d345e]*/ { - if (_PyCodec_Unregister(search_function)) { + if (PyCodec_Unregister(search_function) < 0) { return NULL; } diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h index 7974af32f4556e..e2ebb6861299e4 100644 --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -19,7 +19,7 @@ PyDoc_STRVAR(_codecs_unregister__doc__, "unregister($module, search_function, /)\n" "--\n" "\n" -"Unregister a codec search function.\n" +"Unregister a codec search function and clear the registry\'s cache.\n" "\n" "If the search function is not registered, do nothing."); @@ -2838,4 +2838,4 @@ _codecs_lookup_error(PyObject *module, PyObject *arg) #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF #define _CODECS_CODE_PAGE_ENCODE_METHODDEF #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ -/*[clinic end generated code: output=47d275cbfe79eea2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9a97e2ddf3e69072 input=a9049054013a1b77]*/ diff --git a/Python/codecs.c b/Python/codecs.c index 39af3e6c36a4ec..05dfa013edaea1 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -51,7 +51,7 @@ int PyCodec_Register(PyObject *search_function) } int -_PyCodec_Unregister(PyObject *search_function) +PyCodec_Unregister(PyObject *search_function) { PyInterpreterState *interp = PyInterpreterState_Get(); /* Do nothing if codec_search_path is not created yet or was created. */ @@ -63,10 +63,10 @@ _PyCodec_Unregister(PyObject *search_function) for (Py_ssize_t i = 0; i < n; i++) { PyObject *item = PyList_GetItem(interp->codec_search_path, i); if (item == search_function) { + PyDict_Clear(interp->codec_search_cache); return PyList_SetSlice(interp->codec_search_path, i, i+1, NULL); } } - PyDict_Clear(interp->codec_search_cache); return 0; } From d186726753b556ccb75646b7d6ee7235e29bc489 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Thu, 24 Sep 2020 12:45:12 +0800 Subject: [PATCH 04/14] apply victor's comment --- Doc/c-api/codec.rst | 10 ++++++++++ Doc/whatsnew/3.10.rst | 3 ++- Include/codecs.h | 2 +- Lib/test/test_codecs.py | 2 +- .../Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst | 3 ++- Python/codecs.c | 2 +- 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Doc/c-api/codec.rst b/Doc/c-api/codec.rst index 172dcb326a4bc4..ed07254e5a64d1 100644 --- a/Doc/c-api/codec.rst +++ b/Doc/c-api/codec.rst @@ -10,6 +10,16 @@ Codec registry and support functions As side effect, this tries to load the :mod:`encodings` package, if not yet done, to make sure that it is always first in the list of search functions. +.. c:function:: int PyCodec_Unregister(PyObject *search_function) + + Unregister a codec search function. + + Unregister a codec search function and clear the registry's cache. + If the search function is not registered, do nothing. + Return 0 on success. Raise an exception and return -1 on success. + + .. versionadded:: 3.10 + .. c:function:: int PyCodec_KnownEncoding(const char *encoding) Return ``1`` or ``0`` depending on whether there is a registered codec for diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index fac139d77ee354..8c1b1ddd8a3388 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -112,7 +112,8 @@ Base32 Encoding with Extended Hex Alphabet. codecs ------ -Add :func:`codecs.unregister` to unregister a codec search function. +Add :func:`codecs.unregister` and :c:func:`PyCodec_Unregister` to unregister +a codec search function. curses ------ diff --git a/Include/codecs.h b/Include/codecs.h index 1cfcf8c4fd1274..a17ebfbb24b39b 100644 --- a/Include/codecs.h +++ b/Include/codecs.h @@ -31,7 +31,7 @@ PyAPI_FUNC(int) PyCodec_Register( Unregister a codec search function and clear the registry's cache. If the search function is not registered, do nothing. - */ + Return 0 on success. Raise an exception and return -1 on success. */ PyAPI_FUNC(int) PyCodec_Unregister( PyObject *search_function diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 1acafc2f1a2f1b..bc78ced28f74d3 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1645,7 +1645,7 @@ def test_unregister(self): search_function = mock.Mock(return_value=(1, 2, 3, 4)) codecs.register(search_function) codecs.unregister(search_function) - self.assertRaises(LookupError, codecs.lookup, "test") + self.assertRaises(LookupError, codecs.lookup, "nonexistent_codec_name") search_function.assert_not_called() def test_lookup(self): diff --git a/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst b/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst index e214175f49929c..790227417b3c31 100644 --- a/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst +++ b/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst @@ -1 +1,2 @@ -Add a :func:`codecs.unregister` to unregister a codec search function. +Add :func:`codecs.unregister` and :c:func:`PyCodec_Unregister` to unregister +a codec search function. diff --git a/Python/codecs.c b/Python/codecs.c index 05dfa013edaea1..c876cf87726013 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -54,7 +54,7 @@ int PyCodec_Unregister(PyObject *search_function) { PyInterpreterState *interp = PyInterpreterState_Get(); - /* Do nothing if codec_search_path is not created yet or was created. */ + /* Do nothing if codec_search_path is not created yet or was cleared. */ if (interp->codec_search_path == NULL) { return 0; } From f8e912bdd87cd0288005a04b9459250ae78dd0f9 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Thu, 24 Sep 2020 13:37:00 +0800 Subject: [PATCH 05/14] retrigger checks From 40666fc49e51ab73a19048d8d90968b6bf00463d Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Thu, 24 Sep 2020 19:27:51 +0800 Subject: [PATCH 06/14] apply victor's comment --- Doc/c-api/codec.rst | 2 -- Doc/whatsnew/3.10.rst | 6 ++++-- Include/codecs.h | 2 +- Lib/test/test_codecs.py | 8 ++++++-- Misc/ACKS | 1 + 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Doc/c-api/codec.rst b/Doc/c-api/codec.rst index ed07254e5a64d1..5c3a60ec1fd529 100644 --- a/Doc/c-api/codec.rst +++ b/Doc/c-api/codec.rst @@ -12,8 +12,6 @@ Codec registry and support functions .. c:function:: int PyCodec_Unregister(PyObject *search_function) - Unregister a codec search function. - Unregister a codec search function and clear the registry's cache. If the search function is not registered, do nothing. Return 0 on success. Raise an exception and return -1 on success. diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 8c1b1ddd8a3388..a5d830da594df6 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -112,8 +112,7 @@ Base32 Encoding with Extended Hex Alphabet. codecs ------ -Add :func:`codecs.unregister` and :c:func:`PyCodec_Unregister` to unregister -a codec search function. +Add a :func:`codecs.unregister` to unregister a codec search function. curses ------ @@ -229,6 +228,9 @@ New Features Python executable. (Contributed by Victor Stinner in :issue:`23427`.) +* Add a c:func:`PyCodec_Unregister` to unregister a codec search function. + (Contributed by Hai Shi in :issue:`41842`.) + Porting to Python 3.10 ---------------------- diff --git a/Include/codecs.h b/Include/codecs.h index a17ebfbb24b39b..f9e305ad665bbe 100644 --- a/Include/codecs.h +++ b/Include/codecs.h @@ -31,7 +31,7 @@ PyAPI_FUNC(int) PyCodec_Register( Unregister a codec search function and clear the registry's cache. If the search function is not registered, do nothing. - Return 0 on success. Raise an exception and return -1 on success. */ + Return 0 on success. Raise an exception and return -1 on error. */ PyAPI_FUNC(int) PyCodec_Unregister( PyObject *search_function diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index bc78ced28f74d3..d2a27b8159eec5 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1642,10 +1642,14 @@ def test_register(self): self.assertRaises(TypeError, codecs.register, 42) def test_unregister(self): - search_function = mock.Mock(return_value=(1, 2, 3, 4)) + name = "nonexistent_codec_name" + search_function = mock.Mock() codecs.register(search_function) + self.assertRaises(TypeError, codecs.lookup, name) + search_function.assert_called_with(name) + search_function.reset_mock() codecs.unregister(search_function) - self.assertRaises(LookupError, codecs.lookup, "nonexistent_codec_name") + self.assertRaises(LookupError, codecs.lookup, name) search_function.assert_not_called() def test_lookup(self): diff --git a/Misc/ACKS b/Misc/ACKS index 01ee1cb42d39d0..566ab9f5c4f488 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1574,6 +1574,7 @@ Akash Shende Charlie Shepherd Bruce Sherwood Gregory Shevchenko +Hai Shi Alexander Shigin Pete Shinners Michael Shiplett From 3257b6c2ca5fbcdf6c1bbc4a131a1efcca8f1787 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Thu, 24 Sep 2020 19:35:56 +0800 Subject: [PATCH 07/14] update doc --- Include/codecs.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Include/codecs.h b/Include/codecs.h index f9e305ad665bbe..37ecfb4ab757b4 100644 --- a/Include/codecs.h +++ b/Include/codecs.h @@ -27,9 +27,7 @@ PyAPI_FUNC(int) PyCodec_Register( PyObject *search_function ); -/* Unregister a codec search function. - - Unregister a codec search function and clear the registry's cache. +/* Unregister a codec search function and clear the registry's cache. If the search function is not registered, do nothing. Return 0 on success. Raise an exception and return -1 on error. */ From a493a35bc56d4cc1437cdce7ee157ac3191761f8 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Thu, 24 Sep 2020 19:37:12 +0800 Subject: [PATCH 08/14] update doc --- Doc/c-api/codec.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/codec.rst b/Doc/c-api/codec.rst index 5c3a60ec1fd529..235c77c945cc5b 100644 --- a/Doc/c-api/codec.rst +++ b/Doc/c-api/codec.rst @@ -14,7 +14,7 @@ Codec registry and support functions Unregister a codec search function and clear the registry's cache. If the search function is not registered, do nothing. - Return 0 on success. Raise an exception and return -1 on success. + Return 0 on success. Raise an exception and return -1 on error. .. versionadded:: 3.10 From db4631ef2edc122eb472b56e2f363cf7f9d5f20c Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Thu, 24 Sep 2020 20:54:08 +0800 Subject: [PATCH 09/14] update doc --- Doc/whatsnew/3.10.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 68619945401368..8a3e33ace1f020 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -242,7 +242,7 @@ New Features :class:`datetime.time` objects. (Contributed by Zackery Spytz in :issue:`30155`.) -* Add a c:func:`PyCodec_Unregister` to unregister a codec search function. +* Add a :c:func:`PyCodec_Unregister` to unregister a codec search function. (Contributed by Hai Shi in :issue:`41842`.) ======= From 5efff220fb0ba9c3bac3454ecbce56fb7f87edf0 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Thu, 24 Sep 2020 21:20:50 +0800 Subject: [PATCH 10/14] apply victor's comment --- Doc/whatsnew/3.10.rst | 3 +-- Lib/test/test_codecs.py | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 8a3e33ace1f020..69a9d40a34762e 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -113,6 +113,7 @@ codecs ------ Add a :func:`codecs.unregister` to unregister a codec search function. +(Contributed by Hai Shi in :issue:`41842`.) curses ------ @@ -245,8 +246,6 @@ New Features * Add a :c:func:`PyCodec_Unregister` to unregister a codec search function. (Contributed by Hai Shi in :issue:`41842`.) -======= - Porting to Python 3.10 ---------------------- diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index d2a27b8159eec5..ed508f36ad4234 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1648,6 +1648,7 @@ def test_unregister(self): self.assertRaises(TypeError, codecs.lookup, name) search_function.assert_called_with(name) search_function.reset_mock() + codecs.unregister(search_function) self.assertRaises(LookupError, codecs.lookup, name) search_function.assert_not_called() From f18cd4f9f2dc12476069975c4b9ab955cd5c13f9 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Sat, 26 Sep 2020 08:45:41 +0800 Subject: [PATCH 11/14] apply Dong-hee Na's comment --- Python/codecs.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Python/codecs.c b/Python/codecs.c index c876cf87726013..f3a75cf110af4f 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -54,17 +54,18 @@ int PyCodec_Unregister(PyObject *search_function) { PyInterpreterState *interp = PyInterpreterState_Get(); + PyObject *codec_search_path = interp->codec_search_path; /* Do nothing if codec_search_path is not created yet or was cleared. */ - if (interp->codec_search_path == NULL) { + if (codec_search_path == NULL) { return 0; } - Py_ssize_t n = PyList_Size(interp->codec_search_path); + Py_ssize_t n = PyList_Size(codec_search_path); for (Py_ssize_t i = 0; i < n; i++) { - PyObject *item = PyList_GetItem(interp->codec_search_path, i); + PyObject *item = PyList_GetItem(codec_search_path, i); if (item == search_function) { PyDict_Clear(interp->codec_search_cache); - return PyList_SetSlice(interp->codec_search_path, i, i+1, NULL); + return PyList_SetSlice(codec_search_path, i, i+1, NULL); } } return 0; From 8f6dc4d62b0f9c5b8750a2206179ef20a965e3fa Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Sun, 27 Sep 2020 00:02:16 +0800 Subject: [PATCH 12/14] apply victor and Zackery's comment --- Doc/whatsnew/3.10.rst | 5 +++-- Python/codecs.c | 10 +++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 69a9d40a34762e..f74dd1aa247a34 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -112,7 +112,7 @@ Base32 Encoding with Extended Hex Alphabet. codecs ------ -Add a :func:`codecs.unregister` to unregister a codec search function. +Add a :func:`codecs.unregister` function to unregister a codec search function. (Contributed by Hai Shi in :issue:`41842`.) curses @@ -243,7 +243,8 @@ New Features :class:`datetime.time` objects. (Contributed by Zackery Spytz in :issue:`30155`.) -* Add a :c:func:`PyCodec_Unregister` to unregister a codec search function. +* Add a :c:func:`PyCodec_Unregister` function to unregister a codec + search function. (Contributed by Hai Shi in :issue:`41842`.) Porting to Python 3.10 diff --git a/Python/codecs.c b/Python/codecs.c index f3a75cf110af4f..a2e3eac36d06db 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -60,11 +60,15 @@ PyCodec_Unregister(PyObject *search_function) return 0; } - Py_ssize_t n = PyList_Size(codec_search_path); + assert(PyList_CheckExact(codec_search_path)); + Py_ssize_t n = PyList_GET_SIZE(codec_search_path); for (Py_ssize_t i = 0; i < n; i++) { - PyObject *item = PyList_GetItem(codec_search_path, i); + PyObject *item = PyList_GET_ITEM(codec_search_path, i); if (item == search_function) { - PyDict_Clear(interp->codec_search_cache); + if (interp->codec_search_cache != NULL) { + assert(PyDict_Check(interp->codec_search_cache)); + PyDict_Clear(interp->codec_search_cache); + } return PyList_SetSlice(codec_search_path, i, i+1, NULL); } } From 4308ea8fc744e377bfeab38157767cecfe377e10 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Sun, 27 Sep 2020 00:20:50 +0800 Subject: [PATCH 13/14] apply victor's comment --- Python/codecs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/codecs.c b/Python/codecs.c index a2e3eac36d06db..a8233a73c4ed3f 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -66,7 +66,7 @@ PyCodec_Unregister(PyObject *search_function) PyObject *item = PyList_GET_ITEM(codec_search_path, i); if (item == search_function) { if (interp->codec_search_cache != NULL) { - assert(PyDict_Check(interp->codec_search_cache)); + assert(PyDict_CheckExact(interp->codec_search_cache)); PyDict_Clear(interp->codec_search_cache); } return PyList_SetSlice(codec_search_path, i, i+1, NULL); From c9a0c99c4d380b548c17b2933003c687f69245a5 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Sun, 27 Sep 2020 20:43:53 +0800 Subject: [PATCH 14/14] apply victor's comment --- .../NEWS.d/next/C API/2020-09-27-20-43-16.bpo-41842.bCakAj.rst | 2 ++ .../next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-09-27-20-43-16.bpo-41842.bCakAj.rst diff --git a/Misc/NEWS.d/next/C API/2020-09-27-20-43-16.bpo-41842.bCakAj.rst b/Misc/NEWS.d/next/C API/2020-09-27-20-43-16.bpo-41842.bCakAj.rst new file mode 100644 index 00000000000000..116d08f4908596 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-09-27-20-43-16.bpo-41842.bCakAj.rst @@ -0,0 +1,2 @@ +Add :c:func:`PyCodec_Unregister` function to unregister a codec search +function. diff --git a/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst b/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst index 790227417b3c31..306b02d76fffe2 100644 --- a/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst +++ b/Misc/NEWS.d/next/Library/2020-09-23-22-52-24.bpo-41842.lIuhC9.rst @@ -1,2 +1 @@ -Add :func:`codecs.unregister` and :c:func:`PyCodec_Unregister` to unregister -a codec search function. +Add :func:`codecs.unregister` function to unregister a codec search function.