@@ -792,46 +792,150 @@ def test_error_propagation(fmt_str):
792792 test_error_propagation ('N' )
793793 test_error_propagation ('n' )
794794
795- def test_struct_subclass_instantiation (self ):
795+ def test_custom_struct_init (self ):
796796 # Regression test for https://github.com/python/cpython/issues/112358
797797 class MyStruct (struct .Struct ):
798- def __init__ (self ):
798+ def __init__ (self , * args , ** kwargs ):
799799 super ().__init__ ('>h' )
800800
801- with self .assertWarns (DeprecationWarning ):
801+ my_struct = MyStruct ('>h' )
802+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
803+ my_struct = MyStruct (format = '>h' )
804+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
805+
806+ warnmsg = r"Different format arguments for __new__\(\) and __init__\(\) methods of Struct"
807+ with self .assertWarnsRegex (FutureWarning , warnmsg ):
808+ my_struct = MyStruct ('<h' )
809+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
810+ with self .assertWarnsRegex (FutureWarning , warnmsg ):
811+ my_struct = MyStruct (format = '<h' )
812+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
813+
814+ warnmsg = r"Struct\(\) missing required argument 'format' \(pos 1\)"
815+ with self .assertWarnsRegex (DeprecationWarning , warnmsg ):
802816 my_struct = MyStruct ()
803817 self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
818+ with self .assertWarnsRegex (DeprecationWarning , warnmsg ):
819+ my_struct = MyStruct (arg = '>h' )
820+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
821+
822+ warnmsg = r"Struct\(\) takes at most 1 argument \(2 given\)"
823+ with self .assertWarnsRegex (DeprecationWarning , warnmsg ):
824+ my_struct = MyStruct ('>h' , 42 )
825+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
826+ with self .assertWarnsRegex (DeprecationWarning , warnmsg ):
827+ my_struct = MyStruct ('>h' , arg = 42 )
828+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
829+ with self .assertWarnsRegex (DeprecationWarning , warnmsg ):
830+ my_struct = MyStruct ('>h' , format = 42 )
831+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
832+ with self .assertWarnsRegex (DeprecationWarning , warnmsg ):
833+ my_struct = MyStruct (format = '>h' , arg = 42 )
834+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
804835
836+ warnmsg = r"Invalid 'format' argument for Struct\.__new__\(\): "
837+ with self .assertWarnsRegex (DeprecationWarning , warnmsg + '.*must be' ):
838+ my_struct = MyStruct (42 )
839+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
840+ with self .assertWarnsRegex (DeprecationWarning , warnmsg + '.*must be' ):
841+ my_struct = MyStruct (format = 42 )
842+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
843+ with self .assertWarnsRegex (DeprecationWarning , warnmsg + 'bad char' ):
844+ my_struct = MyStruct ('$' )
845+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
846+ with self .assertWarnsRegex (DeprecationWarning , warnmsg + 'bad char' ):
847+ my_struct = MyStruct (format = '$' )
848+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
849+ with self .assertWarnsRegex (DeprecationWarning , warnmsg + ".*can't encode" ):
850+ my_struct = MyStruct ('\u20ac ' )
851+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
852+ with self .assertWarnsRegex (DeprecationWarning , warnmsg + ".*can't encode" ):
853+ my_struct = MyStruct (format = '\u20ac ' )
854+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
855+
856+ def test_custom_struct_new (self ):
805857 # New way, no warnings:
806858 class MyStruct (struct .Struct ):
807- def __new__ (cls ):
859+ def __new__ (cls , * args , ** kwargs ):
808860 return super ().__new__ (cls , '>h' )
861+
862+ my_struct = MyStruct ('>h' )
863+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
864+ my_struct = MyStruct ('<h' )
865+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
866+ my_struct = MyStruct (format = '<h' )
867+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
809868 my_struct = MyStruct ()
810869 self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
870+ my_struct = MyStruct (42 )
871+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
872+ my_struct = MyStruct ('$' )
873+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
874+ my_struct = MyStruct ('\u20ac ' )
875+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
876+ my_struct = MyStruct ('<h' , 42 )
877+ self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
811878
879+ def test_custom_struct_new_and_init (self ):
880+ # New way, no warnings:
812881 class MyStruct (struct .Struct ):
813- def __new__ (cls , arg ):
814- self = super ().__new__ (cls , '>h' )
815- return self
816-
817- my_struct = MyStruct (5 )
818- self .assertEqual (my_struct .pack (123 ), b'\x00 {' )
819-
820- class MyStruct (struct .Struct ):
821- def __init__ (self , * args , ** kwargs ):
822- super ().__init__ ('>h' )
882+ def __new__ (cls , newargs , initargs ):
883+ return super ().__new__ (cls , * newargs )
884+ def __init__ (self , newargs , initargs ):
885+ if initargs is not None :
886+ super ().__init__ (* initargs )
823887
824- with self .assertWarns (DeprecationWarning ):
825- my_struct = MyStruct ('<h' )
888+ my_struct = MyStruct (('>h' ,), ('>h' ,))
826889 self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
890+ with self .assertRaises (TypeError ):
891+ MyStruct ((), ())
892+ with self .assertRaises (TypeError ):
893+ MyStruct (('>h' ,), ())
894+ with self .assertRaises (TypeError ):
895+ MyStruct ((), ('>h' ,))
896+ with self .assertRaises (TypeError ):
897+ MyStruct ((42 ,), ('>h' ,))
898+ with self .assertRaises (TypeError ):
899+ with self .assertWarns (FutureWarning ):
900+ MyStruct (('>h' ,), (42 ,))
901+ with self .assertRaises (struct .error ):
902+ MyStruct (('$' ,), ('>h' ,))
903+ with self .assertRaises (struct .error ):
904+ with self .assertWarns (FutureWarning ):
905+ MyStruct (('>h' ,), ('$' ,))
906+ with self .assertRaises (UnicodeEncodeError ):
907+ MyStruct (('\u20ac ' ,), ('>h' ,))
908+ with self .assertRaises (UnicodeEncodeError ):
909+ with self .assertWarns (FutureWarning ):
910+ MyStruct (('>h' ,), ('\u20ac ' ,))
911+ with self .assertWarns (FutureWarning ):
912+ my_struct = MyStruct (('>h' ,), ('<h' ,))
913+ self .assertEqual (my_struct .pack (12345 ), b'\x39 \x30 ' )
914+
915+ def test_no_custom_struct_new_or_init (self ):
916+ class MyStruct (struct .Struct ):
917+ pass
827918
828- with self .assertWarns (DeprecationWarning ):
829- my_struct = MyStruct (5 )
919+ my_struct = MyStruct ('>h' )
830920 self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
831-
832- with self .assertWarns (DeprecationWarning ):
833- my_struct = MyStruct ('>h' )
921+ my_struct = MyStruct (format = '>h' )
834922 self .assertEqual (my_struct .pack (12345 ), b'\x30 \x39 ' )
923+ with self .assertRaises (TypeError ):
924+ MyStruct ()
925+ with self .assertRaises (TypeError ):
926+ MyStruct (42 )
927+ with self .assertRaises (struct .error ):
928+ MyStruct ('$' )
929+ with self .assertRaises (UnicodeEncodeError ):
930+ MyStruct ('\u20ac ' )
931+ with self .assertRaises (TypeError ):
932+ MyStruct ('>h' , 42 )
933+ with self .assertRaises (TypeError ):
934+ MyStruct ('>h' , arg = 42 )
935+ with self .assertRaises (TypeError ):
936+ MyStruct (arg = 42 )
937+ with self .assertRaises (TypeError ):
938+ MyStruct ('>h' , format = '>h' )
835939
836940 def test_repr (self ):
837941 s = struct .Struct ('=i2H' )
@@ -864,8 +968,7 @@ def test_endian_table_init_subinterpreters(self):
864968 self .assertListEqual (list (results ), [None ] * 5 )
865969
866970 def test_operations_on_half_initialized_Struct (self ):
867- with self .assertWarns (DeprecationWarning ):
868- S = struct .Struct .__new__ (struct .Struct )
971+ S = struct .Struct .__new__ (struct .Struct )
869972
870973 spam = array .array ('b' , b' ' )
871974 self .assertRaises (RuntimeError , S .iter_unpack , spam )
0 commit comments