@@ -2819,24 +2819,19 @@ def test_binary_to_text_denylists_text_transforms(self):
2819
2819
self .assertIsNone (failure .exception .__cause__ )
2820
2820
2821
2821
@unittest .skipUnless (zlib , "Requires zlib support" )
2822
- def test_custom_zlib_error_is_wrapped (self ):
2822
+ def test_custom_zlib_error_is_noted (self ):
2823
2823
# Check zlib codec gives a good error for malformed input
2824
- msg = "^ decoding with 'zlib_codec' codec failed"
2825
- with self .assertRaisesRegex (Exception , msg ) as failure :
2824
+ msg = "decoding with 'zlib_codec' codec failed"
2825
+ with self .assertRaises (Exception ) as failure :
2826
2826
codecs .decode (b"hello" , "zlib_codec" )
2827
- self .assertIsInstance (failure .exception .__cause__ ,
2828
- type (failure .exception ))
2827
+ self .assertEqual (msg , failure .exception .__notes__ [0 ])
2829
2828
2830
- def test_custom_hex_error_is_wrapped (self ):
2829
+ def test_custom_hex_error_is_noted (self ):
2831
2830
# Check hex codec gives a good error for malformed input
2832
- msg = "^ decoding with 'hex_codec' codec failed"
2833
- with self .assertRaisesRegex (Exception , msg ) as failure :
2831
+ msg = "decoding with 'hex_codec' codec failed"
2832
+ with self .assertRaises (Exception ) as failure :
2834
2833
codecs .decode (b"hello" , "hex_codec" )
2835
- self .assertIsInstance (failure .exception .__cause__ ,
2836
- type (failure .exception ))
2837
-
2838
- # Unfortunately, the bz2 module throws OSError, which the codec
2839
- # machinery currently can't wrap :(
2834
+ self .assertEqual (msg , failure .exception .__notes__ [0 ])
2840
2835
2841
2836
# Ensure codec aliases from http://bugs.python.org/issue7475 work
2842
2837
def test_aliases (self ):
@@ -2860,11 +2855,8 @@ def test_uu_invalid(self):
2860
2855
self .assertRaises (ValueError , codecs .decode , b"" , "uu-codec" )
2861
2856
2862
2857
2863
- # The codec system tries to wrap exceptions in order to ensure the error
2864
- # mentions the operation being performed and the codec involved. We
2865
- # currently *only* want this to happen for relatively stateless
2866
- # exceptions, where the only significant information they contain is their
2867
- # type and a single str argument.
2858
+ # The codec system tries to add notes to exceptions in order to ensure
2859
+ # the error mentions the operation being performed and the codec involved.
2868
2860
2869
2861
# Use a local codec registry to avoid appearing to leak objects when
2870
2862
# registering multiple search functions
@@ -2874,10 +2866,10 @@ def _get_test_codec(codec_name):
2874
2866
return _TEST_CODECS .get (codec_name )
2875
2867
2876
2868
2877
- class ExceptionChainingTest (unittest .TestCase ):
2869
+ class ExceptionNotesTest (unittest .TestCase ):
2878
2870
2879
2871
def setUp (self ):
2880
- self .codec_name = 'exception_chaining_test '
2872
+ self .codec_name = 'exception_notes_test '
2881
2873
codecs .register (_get_test_codec )
2882
2874
self .addCleanup (codecs .unregister , _get_test_codec )
2883
2875
@@ -2901,91 +2893,77 @@ def set_codec(self, encode, decode):
2901
2893
_TEST_CODECS [self .codec_name ] = codec_info
2902
2894
2903
2895
@contextlib .contextmanager
2904
- def assertWrapped (self , operation , exc_type , msg ):
2905
- full_msg = r"{} with {!r} codec failed \({}: {}\) " .format (
2906
- operation , self .codec_name , exc_type . __name__ , msg )
2907
- with self .assertRaisesRegex (exc_type , full_msg ) as caught :
2896
+ def assertNoted (self , operation , exc_type , msg ):
2897
+ full_msg = r"{} with {!r} codec failed" .format (
2898
+ operation , self .codec_name )
2899
+ with self .assertRaises (exc_type ) as caught :
2908
2900
yield caught
2909
- self .assertIsInstance ( caught .exception .__cause__ , exc_type )
2910
- self . assertIsNotNone ( caught .exception .__cause__ . __traceback__ )
2901
+ self .assertIn ( full_msg , caught .exception .__notes__ [ 0 ] )
2902
+ caught .exception .__notes__ . clear ( )
2911
2903
2912
2904
def raise_obj (self , * args , ** kwds ):
2913
2905
# Helper to dynamically change the object raised by a test codec
2914
2906
raise self .obj_to_raise
2915
2907
2916
- def check_wrapped (self , obj_to_raise , msg , exc_type = RuntimeError ):
2908
+ def check_note (self , obj_to_raise , msg , exc_type = RuntimeError ):
2917
2909
self .obj_to_raise = obj_to_raise
2918
2910
self .set_codec (self .raise_obj , self .raise_obj )
2919
- with self .assertWrapped ("encoding" , exc_type , msg ):
2911
+ with self .assertNoted ("encoding" , exc_type , msg ):
2920
2912
"str_input" .encode (self .codec_name )
2921
- with self .assertWrapped ("encoding" , exc_type , msg ):
2913
+ with self .assertNoted ("encoding" , exc_type , msg ):
2922
2914
codecs .encode ("str_input" , self .codec_name )
2923
- with self .assertWrapped ("decoding" , exc_type , msg ):
2915
+ with self .assertNoted ("decoding" , exc_type , msg ):
2924
2916
b"bytes input" .decode (self .codec_name )
2925
- with self .assertWrapped ("decoding" , exc_type , msg ):
2917
+ with self .assertNoted ("decoding" , exc_type , msg ):
2926
2918
codecs .decode (b"bytes input" , self .codec_name )
2927
2919
2928
2920
def test_raise_by_type (self ):
2929
- self .check_wrapped (RuntimeError , "" )
2921
+ self .check_note (RuntimeError , "" )
2930
2922
2931
2923
def test_raise_by_value (self ):
2932
- msg = "This should be wrapped "
2933
- self .check_wrapped (RuntimeError (msg ), msg )
2924
+ msg = "This should be noted "
2925
+ self .check_note (RuntimeError (msg ), msg )
2934
2926
2935
2927
def test_raise_grandchild_subclass_exact_size (self ):
2936
- msg = "This should be wrapped "
2928
+ msg = "This should be noted "
2937
2929
class MyRuntimeError (RuntimeError ):
2938
2930
__slots__ = ()
2939
- self .check_wrapped (MyRuntimeError (msg ), msg , MyRuntimeError )
2931
+ self .check_note (MyRuntimeError (msg ), msg , MyRuntimeError )
2940
2932
2941
2933
def test_raise_subclass_with_weakref_support (self ):
2942
- msg = "This should be wrapped "
2934
+ msg = "This should be noted "
2943
2935
class MyRuntimeError (RuntimeError ):
2944
2936
pass
2945
- self .check_wrapped (MyRuntimeError (msg ), msg , MyRuntimeError )
2946
-
2947
- def check_not_wrapped (self , obj_to_raise , msg ):
2948
- def raise_obj (* args , ** kwds ):
2949
- raise obj_to_raise
2950
- self .set_codec (raise_obj , raise_obj )
2951
- with self .assertRaisesRegex (RuntimeError , msg ):
2952
- "str input" .encode (self .codec_name )
2953
- with self .assertRaisesRegex (RuntimeError , msg ):
2954
- codecs .encode ("str input" , self .codec_name )
2955
- with self .assertRaisesRegex (RuntimeError , msg ):
2956
- b"bytes input" .decode (self .codec_name )
2957
- with self .assertRaisesRegex (RuntimeError , msg ):
2958
- codecs .decode (b"bytes input" , self .codec_name )
2937
+ self .check_note (MyRuntimeError (msg ), msg , MyRuntimeError )
2959
2938
2960
- def test_init_override_is_not_wrapped (self ):
2939
+ def test_init_override (self ):
2961
2940
class CustomInit (RuntimeError ):
2962
2941
def __init__ (self ):
2963
2942
pass
2964
- self .check_not_wrapped (CustomInit , "" )
2943
+ self .check_note (CustomInit , "" )
2965
2944
2966
- def test_new_override_is_not_wrapped (self ):
2945
+ def test_new_override (self ):
2967
2946
class CustomNew (RuntimeError ):
2968
2947
def __new__ (cls ):
2969
2948
return super ().__new__ (cls )
2970
- self .check_not_wrapped (CustomNew , "" )
2949
+ self .check_note (CustomNew , "" )
2971
2950
2972
- def test_instance_attribute_is_not_wrapped (self ):
2973
- msg = "This should NOT be wrapped "
2951
+ def test_instance_attribute (self ):
2952
+ msg = "This should be noted "
2974
2953
exc = RuntimeError (msg )
2975
2954
exc .attr = 1
2976
- self .check_not_wrapped (exc , "^{}$" .format (msg ))
2955
+ self .check_note (exc , "^{}$" .format (msg ))
2977
2956
2978
- def test_non_str_arg_is_not_wrapped (self ):
2979
- self .check_not_wrapped (RuntimeError (1 ), "1" )
2957
+ def test_non_str_arg (self ):
2958
+ self .check_note (RuntimeError (1 ), "1" )
2980
2959
2981
- def test_multiple_args_is_not_wrapped (self ):
2960
+ def test_multiple_args (self ):
2982
2961
msg_re = r"^\('a', 'b', 'c'\)$"
2983
- self .check_not_wrapped (RuntimeError ('a' , 'b' , 'c' ), msg_re )
2962
+ self .check_note (RuntimeError ('a' , 'b' , 'c' ), msg_re )
2984
2963
2985
2964
# http://bugs.python.org/issue19609
2986
- def test_codec_lookup_failure_not_wrapped (self ):
2965
+ def test_codec_lookup_failure (self ):
2987
2966
msg = "^unknown encoding: {}$" .format (self .codec_name )
2988
- # The initial codec lookup should not be wrapped
2989
2967
with self .assertRaisesRegex (LookupError , msg ):
2990
2968
"str input" .encode (self .codec_name )
2991
2969
with self .assertRaisesRegex (LookupError , msg ):
0 commit comments