@@ -2766,14 +2766,29 @@ def test_uu_invalid(self):
27662766
27672767def _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
27712779class 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 ,
0 commit comments