mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
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
11 changed files with 108 additions and 5 deletions
|
|
@ -10,6 +10,14 @@ Codec registry and support functions
|
||||||
As side effect, this tries to load the :mod:`encodings` package, if not yet
|
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.
|
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)
|
.. c:function:: int PyCodec_KnownEncoding(const char *encoding)
|
||||||
|
|
||||||
Return ``1`` or ``0`` depending on whether there is a registered codec for
|
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
|
:class:`CodecInfo` object. In case a search function cannot find
|
||||||
a given encoding, it should return ``None``.
|
a given encoding, it should return ``None``.
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Search function registration is not currently reversible,
|
.. function:: unregister(search_function)
|
||||||
which may cause problems in some cases, such as unit testing or
|
|
||||||
module reloading.
|
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
|
While the builtin :func:`open` and the associated :mod:`io` module are the
|
||||||
recommended approach for working with encoded text files, this module
|
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
|
Add :func:`base64.b32hexencode` and :func:`base64.b32hexdecode` to support the
|
||||||
Base32 Encoding with Extended Hex Alphabet.
|
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
|
curses
|
||||||
------
|
------
|
||||||
|
|
||||||
|
|
@ -237,6 +243,10 @@ New Features
|
||||||
:class:`datetime.time` objects.
|
:class:`datetime.time` objects.
|
||||||
(Contributed by Zackery Spytz in :issue:`30155`.)
|
(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
|
Porting to Python 3.10
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,14 @@ PyAPI_FUNC(int) PyCodec_Register(
|
||||||
PyObject *search_function
|
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.
|
/* Codec registry lookup API.
|
||||||
|
|
||||||
Looks up the given encoding and returns a CodecInfo object with
|
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)
|
||||||
self.assertRaises(TypeError, codecs.register, 42)
|
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):
|
def test_lookup(self):
|
||||||
self.assertRaises(TypeError, codecs.lookup)
|
self.assertRaises(TypeError, codecs.lookup)
|
||||||
self.assertRaises(LookupError, codecs.lookup, "__spam__")
|
self.assertRaises(LookupError, codecs.lookup, "__spam__")
|
||||||
|
|
|
||||||
|
|
@ -1575,6 +1575,7 @@ Akash Shende
|
||||||
Charlie Shepherd
|
Charlie Shepherd
|
||||||
Bruce Sherwood
|
Bruce Sherwood
|
||||||
Gregory Shevchenko
|
Gregory Shevchenko
|
||||||
|
Hai Shi
|
||||||
Alexander Shigin
|
Alexander Shigin
|
||||||
Pete Shinners
|
Pete Shinners
|
||||||
Michael Shiplett
|
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;
|
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]
|
/*[clinic input]
|
||||||
_codecs.lookup
|
_codecs.lookup
|
||||||
encoding: str
|
encoding: str
|
||||||
|
|
@ -992,6 +1013,7 @@ _codecs_lookup_error_impl(PyObject *module, const char *name)
|
||||||
|
|
||||||
static PyMethodDef _codecs_functions[] = {
|
static PyMethodDef _codecs_functions[] = {
|
||||||
_CODECS_REGISTER_METHODDEF
|
_CODECS_REGISTER_METHODDEF
|
||||||
|
_CODECS_UNREGISTER_METHODDEF
|
||||||
_CODECS_LOOKUP_METHODDEF
|
_CODECS_LOOKUP_METHODDEF
|
||||||
_CODECS_ENCODE_METHODDEF
|
_CODECS_ENCODE_METHODDEF
|
||||||
_CODECS_DECODE_METHODDEF
|
_CODECS_DECODE_METHODDEF
|
||||||
|
|
|
||||||
13
Modules/clinic/_codecsmodule.c.h
generated
13
Modules/clinic/_codecsmodule.c.h
generated
|
|
@ -15,6 +15,17 @@ PyDoc_STRVAR(_codecs_register__doc__,
|
||||||
#define _CODECS_REGISTER_METHODDEF \
|
#define _CODECS_REGISTER_METHODDEF \
|
||||||
{"register", (PyCFunction)_codecs_register, METH_O, _codecs_register__doc__},
|
{"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__,
|
PyDoc_STRVAR(_codecs_lookup__doc__,
|
||||||
"lookup($module, encoding, /)\n"
|
"lookup($module, encoding, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
|
@ -2827,4 +2838,4 @@ exit:
|
||||||
#ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF
|
#ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF
|
||||||
#define _CODECS_CODE_PAGE_ENCODE_METHODDEF
|
#define _CODECS_CODE_PAGE_ENCODE_METHODDEF
|
||||||
#endif /* !defined(_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;
|
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);
|
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
|
/* Convert a string to a normalized Python string(decoded from UTF-8): all characters are
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue