Skip to content

Commit b1c9a20

Browse files
authored
Revert "bpo-41919, test_codecs: Move codecs.register calls to setUp() (GH-22513)"
This reverts commit c9f696c.
1 parent 4a9c637 commit b1c9a20

File tree

7 files changed

+112
-16
lines changed

7 files changed

+112
-16
lines changed

Lib/test/test_charmapcodec.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,12 @@ def codec_search_function(encoding):
2020
return tuple(testcodec.getregentry())
2121
return None
2222

23+
codecs.register(codec_search_function)
24+
2325
# test codec's name (see test/testcodec.py)
2426
codecname = 'testcodec'
2527

2628
class CharmapCodecTest(unittest.TestCase):
27-
28-
def setUp(self):
29-
codecs.register(codec_search_function)
30-
self.addCleanup(codecs.unregister, codec_search_function)
31-
3229
def test_constructorx(self):
3330
self.assertEqual(str(b'abc', codecname), 'abc')
3431
self.assertEqual(str(b'xdef', codecname), 'abcdef')

Lib/test/test_codecs.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2766,14 +2766,29 @@ def test_uu_invalid(self):
27662766

27672767
def _get_test_codec(codec_name):
27682768
return _TEST_CODECS.get(codec_name)
2769+
codecs.register(_get_test_codec) # Returns None, not usable as a decorator
2770+
2771+
try:
2772+
# Issue #22166: Also need to clear the internal cache in CPython
2773+
from _codecs import _forget_codec
2774+
except ImportError:
2775+
def _forget_codec(codec_name):
2776+
pass
27692777

27702778

27712779
class ExceptionChainingTest(unittest.TestCase):
27722780

27732781
def setUp(self):
2774-
self.codec_name = 'exception_chaining_test'
2775-
codecs.register(_get_test_codec)
2776-
self.addCleanup(codecs.unregister, _get_test_codec)
2782+
# There's no way to unregister a codec search function, so we just
2783+
# ensure we render this one fairly harmless after the test
2784+
# case finishes by using the test case repr as the codec name
2785+
# The codecs module normalizes codec names, although this doesn't
2786+
# appear to be formally documented...
2787+
# We also make sure we use a truly unique id for the custom codec
2788+
# to avoid issues with the codec cache when running these tests
2789+
# multiple times (e.g. when hunting for refleaks)
2790+
unique_id = repr(self) + str(id(self))
2791+
self.codec_name = encodings.normalize_encoding(unique_id).lower()
27772792

27782793
# We store the object to raise on the instance because of a bad
27792794
# interaction between the codec caching (which means we can't
@@ -2788,6 +2803,10 @@ def tearDown(self):
27882803
_TEST_CODECS.pop(self.codec_name, None)
27892804
# Issue #22166: Also pop from caches to avoid appearance of ref leaks
27902805
encodings._cache.pop(self.codec_name, None)
2806+
try:
2807+
_forget_codec(self.codec_name)
2808+
except KeyError:
2809+
pass
27912810

27922811
def set_codec(self, encode, decode):
27932812
codec_info = codecs.CodecInfo(encode, decode,

Lib/test/test_io.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2529,6 +2529,10 @@ def lookupTestDecoder(cls, name):
25292529
streamreader=None, streamwriter=None,
25302530
incrementaldecoder=cls)
25312531

2532+
# Register the previous decoder for testing.
2533+
# Disabled by default, tests will enable it.
2534+
codecs.register(StatefulIncrementalDecoder.lookupTestDecoder)
2535+
25322536

25332537
class StatefulIncrementalDecoderTest(unittest.TestCase):
25342538
"""
@@ -2579,9 +2583,6 @@ def setUp(self):
25792583
self.testdata = b"AAA\r\nBBB\rCCC\r\nDDD\nEEE\r\n"
25802584
self.normalized = b"AAA\nBBB\nCCC\nDDD\nEEE\n".decode("ascii")
25812585
os_helper.unlink(os_helper.TESTFN)
2582-
codecs.register(StatefulIncrementalDecoder.lookupTestDecoder)
2583-
self.addCleanup(codecs.unregister,
2584-
StatefulIncrementalDecoder.lookupTestDecoder)
25852586

25862587
def tearDown(self):
25872588
os_helper.unlink(os_helper.TESTFN)

Lib/test/test_unicode.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def decode2(input, errors="strict"):
3636
return (encode2, decode2, None, None)
3737
else:
3838
return None
39+
codecs.register(search_function)
3940

4041
def duplicate_string(text):
4142
"""
@@ -57,10 +58,6 @@ class UnicodeTest(string_tests.CommonTest,
5758

5859
type2test = str
5960

60-
def setUp(self):
61-
codecs.register(search_function)
62-
self.addCleanup(codecs.unregister, search_function)
63-
6461
def checkequalnofix(self, result, object, methodname, *args):
6562
method = getattr(object, methodname)
6663
realresult = method(*args)

Modules/_codecsmodule.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,25 @@ _codecs_decode_impl(PyObject *module, PyObject *obj, const char *encoding,
160160

161161
/* --- Helpers ------------------------------------------------------------ */
162162

163+
/*[clinic input]
164+
_codecs._forget_codec
165+
166+
encoding: str
167+
/
168+
169+
Purge the named codec from the internal codec lookup cache
170+
[clinic start generated code]*/
171+
172+
static PyObject *
173+
_codecs__forget_codec_impl(PyObject *module, const char *encoding)
174+
/*[clinic end generated code: output=0bde9f0a5b084aa2 input=18d5d92d0e386c38]*/
175+
{
176+
if (_PyCodec_Forget(encoding) < 0) {
177+
return NULL;
178+
};
179+
Py_RETURN_NONE;
180+
}
181+
163182
static
164183
PyObject *codec_tuple(PyObject *decoded,
165184
Py_ssize_t len)
@@ -1038,6 +1057,7 @@ static PyMethodDef _codecs_functions[] = {
10381057
_CODECS_CODE_PAGE_DECODE_METHODDEF
10391058
_CODECS_REGISTER_ERROR_METHODDEF
10401059
_CODECS_LOOKUP_ERROR_METHODDEF
1060+
_CODECS__FORGET_CODEC_METHODDEF
10411061
{NULL, NULL} /* sentinel */
10421062
};
10431063

Modules/clinic/_codecsmodule.c.h

Lines changed: 38 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: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,31 @@ PyObject *_PyCodec_Lookup(const char *encoding)
208208
return NULL;
209209
}
210210

211+
int _PyCodec_Forget(const char *encoding)
212+
{
213+
PyObject *v;
214+
int result;
215+
216+
PyInterpreterState *interp = _PyInterpreterState_GET();
217+
if (interp->codec_search_path == NULL) {
218+
return -1;
219+
}
220+
221+
/* Convert the encoding to a normalized Python string: all
222+
characters are converted to lower case, spaces and hyphens are
223+
replaced with underscores. */
224+
v = normalizestring(encoding);
225+
if (v == NULL) {
226+
return -1;
227+
}
228+
229+
/* Drop the named codec from the internal cache */
230+
result = PyDict_DelItem(interp->codec_search_cache, v);
231+
Py_DECREF(v);
232+
233+
return result;
234+
}
235+
211236
/* Codec registry encoding check API. */
212237

213238
int PyCodec_KnownEncoding(const char *encoding)

0 commit comments

Comments
 (0)