bpo-41842: Add codecs.unregister() function (GH-22360)
Add codecs.unregister() and PyCodec_Unregister() functions to unregister a codec search function.
This commit is contained in:
parent
24ba3b0df5
commit
d332e7b816
|
@ -10,6 +10,14 @@ 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 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.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
.. c:function:: int PyCodec_KnownEncoding(const char *encoding)
|
||||
|
||||
Return ``1`` or ``0`` depending on whether there is a registered codec for
|
||||
|
|
|
@ -163,11 +163,14 @@ function:
|
|||
:class:`CodecInfo` object. In case a search function cannot find
|
||||
a given encoding, it should return ``None``.
|
||||
|
||||
.. note::
|
||||
|
||||
Search function registration is not currently reversible,
|
||||
which may cause problems in some cases, such as unit testing or
|
||||
module reloading.
|
||||
.. function:: unregister(search_function)
|
||||
|
||||
Unregister a codec search function and clear the registry's cache.
|
||||
If the search function is not registered, do 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
|
||||
|
|
|
@ -109,6 +109,12 @@ base64
|
|||
Add :func:`base64.b32hexencode` and :func:`base64.b32hexdecode` to support the
|
||||
Base32 Encoding with Extended Hex Alphabet.
|
||||
|
||||
codecs
|
||||
------
|
||||
|
||||
Add a :func:`codecs.unregister` function to unregister a codec search function.
|
||||
(Contributed by Hai Shi in :issue:`41842`.)
|
||||
|
||||
curses
|
||||
------
|
||||
|
||||
|
@ -237,6 +243,10 @@ New Features
|
|||
:class:`datetime.time` objects.
|
||||
(Contributed by Zackery Spytz in :issue:`30155`.)
|
||||
|
||||
* 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
|
||||
----------------------
|
||||
|
||||
|
|
|
@ -27,6 +27,14 @@ PyAPI_FUNC(int) PyCodec_Register(
|
|||
PyObject *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 error. */
|
||||
|
||||
PyAPI_FUNC(int) PyCodec_Unregister(
|
||||
PyObject *search_function
|
||||
);
|
||||
|
||||
/* Codec registry lookup API.
|
||||
|
||||
Looks up the given encoding and returns a CodecInfo object with
|
||||
|
|
|
@ -1641,6 +1641,18 @@ class CodecsModuleTest(unittest.TestCase):
|
|||
self.assertRaises(TypeError, codecs.register)
|
||||
self.assertRaises(TypeError, codecs.register, 42)
|
||||
|
||||
def test_unregister(self):
|
||||
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, name)
|
||||
search_function.assert_not_called()
|
||||
|
||||
def test_lookup(self):
|
||||
self.assertRaises(TypeError, codecs.lookup)
|
||||
self.assertRaises(LookupError, codecs.lookup, "__spam__")
|
||||
|
|
|
@ -1575,6 +1575,7 @@ Akash Shende
|
|||
Charlie Shepherd
|
||||
Bruce Sherwood
|
||||
Gregory Shevchenko
|
||||
Hai Shi
|
||||
Alexander Shigin
|
||||
Pete Shinners
|
||||
Michael Shiplett
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Add :c:func:`PyCodec_Unregister` function to unregister a codec search
|
||||
function.
|
|
@ -0,0 +1 @@
|
|||
Add :func:`codecs.unregister` function to unregister a codec search function.
|
|
@ -68,6 +68,27 @@ _codecs_register(PyObject *module, PyObject *search_function)
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
_codecs.unregister
|
||||
search_function: object
|
||||
/
|
||||
|
||||
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=dd7c004c652d345e]*/
|
||||
{
|
||||
if (PyCodec_Unregister(search_function) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
_codecs.lookup
|
||||
encoding: str
|
||||
|
@ -992,6 +1013,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
|
||||
|
|
|
@ -15,6 +15,17 @@ 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 and clear the registry\'s cache.\n"
|
||||
"\n"
|
||||
"If the search function is not registered, do 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 +2838,4 @@ exit:
|
|||
#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=9a97e2ddf3e69072 input=a9049054013a1b77]*/
|
||||
|
|
|
@ -50,6 +50,31 @@ int PyCodec_Register(PyObject *search_function)
|
|||
return -1;
|
||||
}
|
||||
|
||||
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 (codec_search_path == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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_GET_ITEM(codec_search_path, i);
|
||||
if (item == search_function) {
|
||||
if (interp->codec_search_cache != NULL) {
|
||||
assert(PyDict_CheckExact(interp->codec_search_cache));
|
||||
PyDict_Clear(interp->codec_search_cache);
|
||||
}
|
||||
return PyList_SetSlice(codec_search_path, i, i+1, NULL);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue