@@ -672,7 +672,7 @@ def __fspath__(self):
672
672
compile ("42" , PathLike ("test_compile_pathlike" ), "single" )
673
673
674
674
675
- class TestStackSize (unittest .TestCase ):
675
+ class TestExpressionStackSize (unittest .TestCase ):
676
676
# These tests check that the computed stack size for a code object
677
677
# stays within reasonable bounds (see issue #21523 for an example
678
678
# dysfunction).
@@ -710,5 +710,294 @@ def test_func_and(self):
710
710
self .check_stack_size (code )
711
711
712
712
713
+ class TestStackSizeStability (unittest .TestCase ):
714
+ # Check that repeating certain snippets doesn't increase the stack size
715
+ # beyond what a single snippet requires.
716
+
717
+ def check_stack_size (self , snippet , async_ = False ):
718
+ def compile_snippet (i ):
719
+ ns = {}
720
+ script = """def func():\n """ + i * snippet
721
+ if async_ :
722
+ script = "async " + script
723
+ code = compile (script , "<script>" , "exec" )
724
+ exec (code , ns , ns )
725
+ return ns ['func' ].__code__
726
+
727
+ sizes = [compile_snippet (i ).co_stacksize for i in range (2 , 5 )]
728
+ if len (set (sizes )) != 1 :
729
+ import dis , io
730
+ out = io .StringIO ()
731
+ dis .dis (compile_snippet (1 ), file = out )
732
+ self .fail ("stack sizes diverge with # of consecutive snippets: "
733
+ "%s\n %s\n %s" % (sizes , snippet , out .getvalue ()))
734
+
735
+ def test_if (self ):
736
+ snippet = """
737
+ if x:
738
+ a
739
+ """
740
+ self .check_stack_size (snippet )
741
+
742
+ def test_if_else (self ):
743
+ snippet = """
744
+ if x:
745
+ a
746
+ elif y:
747
+ b
748
+ else:
749
+ c
750
+ """
751
+ self .check_stack_size (snippet )
752
+
753
+ def test_try_except_bare (self ):
754
+ snippet = """
755
+ try:
756
+ a
757
+ except:
758
+ b
759
+ """
760
+ self .check_stack_size (snippet )
761
+
762
+ def test_try_except_qualified (self ):
763
+ snippet = """
764
+ try:
765
+ a
766
+ except ImportError:
767
+ b
768
+ except:
769
+ c
770
+ else:
771
+ d
772
+ """
773
+ self .check_stack_size (snippet )
774
+
775
+ def test_try_except_as (self ):
776
+ snippet = """
777
+ try:
778
+ a
779
+ except ImportError as e:
780
+ b
781
+ except:
782
+ c
783
+ else:
784
+ d
785
+ """
786
+ self .check_stack_size (snippet )
787
+
788
+ def test_try_finally (self ):
789
+ snippet = """
790
+ try:
791
+ a
792
+ finally:
793
+ b
794
+ """
795
+ self .check_stack_size (snippet )
796
+
797
+ def test_with (self ):
798
+ snippet = """
799
+ with x as y:
800
+ a
801
+ """
802
+ self .check_stack_size (snippet )
803
+
804
+ def test_while_else (self ):
805
+ snippet = """
806
+ while x:
807
+ a
808
+ else:
809
+ b
810
+ """
811
+ self .check_stack_size (snippet )
812
+
813
+ def test_for (self ):
814
+ snippet = """
815
+ for x in y:
816
+ a
817
+ """
818
+ self .check_stack_size (snippet )
819
+
820
+ def test_for_else (self ):
821
+ snippet = """
822
+ for x in y:
823
+ a
824
+ else:
825
+ b
826
+ """
827
+ self .check_stack_size (snippet )
828
+
829
+ def test_for_break_continue (self ):
830
+ snippet = """
831
+ for x in y:
832
+ if z:
833
+ break
834
+ elif u:
835
+ continue
836
+ else:
837
+ a
838
+ else:
839
+ b
840
+ """
841
+ self .check_stack_size (snippet )
842
+
843
+ def test_for_break_continue_inside_try_finally_block (self ):
844
+ snippet = """
845
+ for x in y:
846
+ try:
847
+ if z:
848
+ break
849
+ elif u:
850
+ continue
851
+ else:
852
+ a
853
+ finally:
854
+ f
855
+ else:
856
+ b
857
+ """
858
+ self .check_stack_size (snippet )
859
+
860
+ def test_for_break_inside_finally_block (self ):
861
+ snippet = """
862
+ for x in y:
863
+ try:
864
+ t
865
+ finally:
866
+ if z:
867
+ break
868
+ else:
869
+ a
870
+ else:
871
+ b
872
+ """
873
+ self .check_stack_size (snippet )
874
+
875
+ def test_for_break_continue_inside_except_block (self ):
876
+ snippet = """
877
+ for x in y:
878
+ try:
879
+ t
880
+ except:
881
+ if z:
882
+ break
883
+ elif u:
884
+ continue
885
+ else:
886
+ a
887
+ else:
888
+ b
889
+ """
890
+ self .check_stack_size (snippet )
891
+
892
+ def test_for_break_continue_inside_with_block (self ):
893
+ snippet = """
894
+ for x in y:
895
+ with c:
896
+ if z:
897
+ break
898
+ elif u:
899
+ continue
900
+ else:
901
+ a
902
+ else:
903
+ b
904
+ """
905
+ self .check_stack_size (snippet )
906
+
907
+ def test_return_inside_try_finally_block (self ):
908
+ snippet = """
909
+ try:
910
+ if z:
911
+ return
912
+ else:
913
+ a
914
+ finally:
915
+ f
916
+ """
917
+ self .check_stack_size (snippet )
918
+
919
+ def test_return_inside_finally_block (self ):
920
+ snippet = """
921
+ try:
922
+ t
923
+ finally:
924
+ if z:
925
+ return
926
+ else:
927
+ a
928
+ """
929
+ self .check_stack_size (snippet )
930
+
931
+ def test_return_inside_except_block (self ):
932
+ snippet = """
933
+ try:
934
+ t
935
+ except:
936
+ if z:
937
+ return
938
+ else:
939
+ a
940
+ """
941
+ self .check_stack_size (snippet )
942
+
943
+ def test_return_inside_with_block (self ):
944
+ snippet = """
945
+ with c:
946
+ if z:
947
+ return
948
+ else:
949
+ a
950
+ """
951
+ self .check_stack_size (snippet )
952
+
953
+ def test_async_with (self ):
954
+ snippet = """
955
+ async with x as y:
956
+ a
957
+ """
958
+ self .check_stack_size (snippet , async_ = True )
959
+
960
+ def test_async_for (self ):
961
+ snippet = """
962
+ async for x in y:
963
+ a
964
+ """
965
+ self .check_stack_size (snippet , async_ = True )
966
+
967
+ def test_async_for_else (self ):
968
+ snippet = """
969
+ async for x in y:
970
+ a
971
+ else:
972
+ b
973
+ """
974
+ self .check_stack_size (snippet , async_ = True )
975
+
976
+ def test_for_break_continue_inside_async_with_block (self ):
977
+ snippet = """
978
+ for x in y:
979
+ async with c:
980
+ if z:
981
+ break
982
+ elif u:
983
+ continue
984
+ else:
985
+ a
986
+ else:
987
+ b
988
+ """
989
+ self .check_stack_size (snippet , async_ = True )
990
+
991
+ def test_return_inside_async_with_block (self ):
992
+ snippet = """
993
+ async with c:
994
+ if z:
995
+ return
996
+ else:
997
+ a
998
+ """
999
+ self .check_stack_size (snippet , async_ = True )
1000
+
1001
+
713
1002
if __name__ == "__main__" :
714
1003
unittest .main ()
0 commit comments