Skip to content

Commit fefda70

Browse files
committed
add a _codecs.unregister in _codecs module
1 parent 68526fe commit fefda70

File tree

7 files changed

+74
-4
lines changed

7 files changed

+74
-4
lines changed

Doc/library/codecs.rst

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,16 @@ function:
165165

166166
.. note::
167167

168-
Search function registration is not currently reversible,
169-
which may cause problems in some cases, such as unit testing or
170-
module reloading.
168+
Search function registration is reversible since Python 3.10.
169+
You can use `codecs.unregister()` to unregister the search function.
170+
171+
.. function:: unregister(search_function)
172+
173+
Unregister a codec search function from the codecs registry. If
174+
the search function haven't registered, this function dose nothing.
175+
176+
.. versionadded:: 3.10
177+
171178

172179
While the builtin :func:`open` and the associated :mod:`io` module are the
173180
recommended approach for working with encoded text files, this module

Include/codecs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ PyAPI_FUNC(PyObject *) _PyCodec_Lookup(
5353
PyAPI_FUNC(int) _PyCodec_Forget(
5454
const char *encoding
5555
);
56+
57+
PyAPI_FUNC(PyObject *) _PyCodec_Unregister(
58+
PyObject *search_function
59+
);
5660
#endif
5761

5862
/* Codec registry encoding check API.

Lib/test/test_codecs.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,6 +1641,12 @@ def test_register(self):
16411641
self.assertRaises(TypeError, codecs.register)
16421642
self.assertRaises(TypeError, codecs.register, 42)
16431643

1644+
def test_unregister(self):
1645+
def test_encoding(encoding):
1646+
return None
1647+
codecs.register(test_encoding)
1648+
self.assertEqual(codecs.unregister(test_encoding), None)
1649+
16441650
def test_lookup(self):
16451651
self.assertRaises(TypeError, codecs.lookup)
16461652
self.assertRaises(LookupError, codecs.lookup, "__spam__")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add a :func:`_codecs.unregister` which could unregister a codec search
2+
function from the codec registry.

Modules/_codecsmodule.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,24 @@ _codecs_register(PyObject *module, PyObject *search_function)
6868
Py_RETURN_NONE;
6969
}
7070

71+
/*[clinic input]
72+
_codecs.unregister
73+
search_function: object
74+
/
75+
76+
Unregister a codec search function.
77+
78+
Unregister a codec search function from codec registry. If the search
79+
function haven't registered, this function does nothing.
80+
[clinic start generated code]*/
81+
82+
static PyObject *
83+
_codecs_unregister(PyObject *module, PyObject *search_function)
84+
/*[clinic end generated code: output=1f0edee9cf246399 input=ecb26613941e6a47]*/
85+
{
86+
return _PyCodec_Unregister(search_function);
87+
}
88+
7189
/*[clinic input]
7290
_codecs.lookup
7391
encoding: str
@@ -992,6 +1010,7 @@ _codecs_lookup_error_impl(PyObject *module, const char *name)
9921010

9931011
static PyMethodDef _codecs_functions[] = {
9941012
_CODECS_REGISTER_METHODDEF
1013+
_CODECS_UNREGISTER_METHODDEF
9951014
_CODECS_LOOKUP_METHODDEF
9961015
_CODECS_ENCODE_METHODDEF
9971016
_CODECS_DECODE_METHODDEF

Modules/clinic/_codecsmodule.c.h

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/codecs.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,26 @@ int PyCodec_Register(PyObject *search_function)
5050
return -1;
5151
}
5252

53+
PyObject *
54+
_PyCodec_Unregister(PyObject *search_function)
55+
{
56+
PyInterpreterState *interp = PyInterpreterState_Get();
57+
if (interp->codec_search_path == NULL) {
58+
Py_RETURN_NONE;
59+
}
60+
61+
Py_ssize_t n = PyList_Size(interp->codec_search_path);
62+
PyObject *list = PyList_New(0);
63+
for (Py_ssize_t i = 0; i < n; i++) {
64+
PyObject *item = PyList_GetItem(interp->codec_search_path, i);
65+
if (item != search_function) {
66+
PyList_Append(list, item);
67+
}
68+
}
69+
Py_SETREF(interp->codec_search_path, list);
70+
Py_RETURN_NONE;
71+
}
72+
5373
extern int _Py_normalize_encoding(const char *, char *, size_t);
5474

5575
/* Convert a string to a normalized Python string(decoded from UTF-8): all characters are

0 commit comments

Comments
 (0)