1
1
import ast
2
2
import dis
3
3
import os
4
+ import random
4
5
import sys
6
+ import tokenize
5
7
import unittest
6
8
import warnings
7
9
import weakref
@@ -25,6 +27,9 @@ def to_tuple(t):
25
27
result .append (to_tuple (getattr (t , f )))
26
28
return tuple (result )
27
29
30
+ STDLIB = os .path .dirname (ast .__file__ )
31
+ STDLIB_FILES = [fn for fn in os .listdir (STDLIB ) if fn .endswith (".py" )]
32
+ STDLIB_FILES .extend (["test/test_grammar.py" , "test/test_unpack_ex.py" ])
28
33
29
34
# These tests are compiled through "exec"
30
35
# There should be at least one test per statement
@@ -654,6 +659,110 @@ def test_ast_asdl_signature(self):
654
659
expressions [0 ] = f"expr = { ast .expr .__subclasses__ ()[0 ].__doc__ } "
655
660
self .assertCountEqual (ast .expr .__doc__ .split ("\n " ), expressions )
656
661
662
+ self .assertTrue (ast .compare (ast .parse ("x = 10" ), ast .parse ("x = 10" )))
663
+ self .assertFalse (ast .compare (ast .parse ("x = 10" ), ast .parse ("" )))
664
+ self .assertFalse (ast .compare (ast .parse ("x = 10" ), ast .parse ("x" )))
665
+ self .assertFalse (
666
+ ast .compare (ast .parse ("x = 10;y = 20" ), ast .parse ("class C:pass" ))
667
+ )
668
+
669
+ def test_compare_literals (self ):
670
+ constants = (
671
+ - 20 ,
672
+ 20 ,
673
+ 20.0 ,
674
+ 1 ,
675
+ 1.0 ,
676
+ True ,
677
+ 0 ,
678
+ False ,
679
+ frozenset (),
680
+ tuple (),
681
+ "ABCD" ,
682
+ "abcd" ,
683
+ "中文字" ,
684
+ 1e1000 ,
685
+ - 1e1000 ,
686
+ )
687
+ for next_index , constant in enumerate (constants [:- 1 ], 1 ):
688
+ next_constant = constants [next_index ]
689
+ with self .subTest (literal = constant , next_literal = next_constant ):
690
+ self .assertTrue (
691
+ ast .compare (ast .Constant (constant ), ast .Constant (constant ))
692
+ )
693
+ self .assertFalse (
694
+ ast .compare (
695
+ ast .Constant (constant ), ast .Constant (next_constant )
696
+ )
697
+ )
698
+
699
+ same_looking_literal_cases = [
700
+ {1 , 1.0 , True , 1 + 0j },
701
+ {0 , 0.0 , False , 0 + 0j },
702
+ ]
703
+ for same_looking_literals in same_looking_literal_cases :
704
+ for literal in same_looking_literals :
705
+ for same_looking_literal in same_looking_literals - {literal }:
706
+ self .assertFalse (
707
+ ast .compare (
708
+ ast .Constant (literal ),
709
+ ast .Constant (same_looking_literal ),
710
+ )
711
+ )
712
+
713
+ def test_compare_fieldless (self ):
714
+ self .assertTrue (ast .compare (ast .Add (), ast .Add ()))
715
+ self .assertFalse (ast .compare (ast .Sub (), ast .Add ()))
716
+ self .assertFalse (ast .compare (ast .Sub (), ast .Constant ()))
717
+
718
+ def test_compare_stdlib (self ):
719
+ if support .is_resource_enabled ("cpu" ):
720
+ files = STDLIB_FILES
721
+ else :
722
+ files = random .sample (STDLIB_FILES , 10 )
723
+
724
+ for module in files :
725
+ with self .subTest (module ):
726
+ fn = os .path .join (STDLIB , module )
727
+ with tokenize .open (fn ) as fp :
728
+ source = fp .read ()
729
+ a = ast .parse (source , fn )
730
+ b = ast .parse (source , fn )
731
+ self .assertTrue (
732
+ ast .compare (a , b ), f"{ ast .dump (a )} != { ast .dump (b )} "
733
+ )
734
+
735
+ def test_compare_tests (self ):
736
+ for mode , sources in (
737
+ ("exec" , exec_tests ),
738
+ ("eval" , eval_tests ),
739
+ ("single" , single_tests ),
740
+ ):
741
+ for source in sources :
742
+ a = ast .parse (source , mode = mode )
743
+ b = ast .parse (source , mode = mode )
744
+ self .assertTrue (
745
+ ast .compare (a , b ), f"{ ast .dump (a )} != { ast .dump (b )} "
746
+ )
747
+
748
+ def test_compare_options (self ):
749
+ def parse (a , b ):
750
+ return ast .parse (a ), ast .parse (b )
751
+
752
+ a , b = parse ("2 + 2" , "2+2" )
753
+ self .assertTrue (ast .compare (a , b , compare_attributes = False ))
754
+ self .assertFalse (ast .compare (a , b , compare_attributes = True ))
755
+
756
+ a , b = parse ("1" , "1.0" )
757
+ self .assertTrue (ast .compare (a , b , compare_types = False ))
758
+ self .assertFalse (ast .compare (a , b , compare_types = True ))
759
+
760
+ a , b = parse ("1" , "2" )
761
+ self .assertTrue (ast .compare (a , b , compare_fields = False , compare_attributes = False ))
762
+ self .assertTrue (ast .compare (a , b , compare_fields = False , compare_attributes = True ))
763
+ self .assertFalse (ast .compare (a , b , compare_fields = True , compare_attributes = False ))
764
+ self .assertFalse (ast .compare (a , b , compare_fields = True , compare_attributes = True ))
765
+
657
766
658
767
class ASTHelpers_Test (unittest .TestCase ):
659
768
maxDiff = None
@@ -1369,12 +1478,9 @@ def test_nameconstant(self):
1369
1478
self .expr (ast .NameConstant (4 ))
1370
1479
1371
1480
def test_stdlib_validates (self ):
1372
- stdlib = os .path .dirname (ast .__file__ )
1373
- tests = [fn for fn in os .listdir (stdlib ) if fn .endswith (".py" )]
1374
- tests .extend (["test/test_grammar.py" , "test/test_unpack_ex.py" ])
1375
- for module in tests :
1481
+ for module in STDLIB_FILES :
1376
1482
with self .subTest (module ):
1377
- fn = os .path .join (stdlib , module )
1483
+ fn = os .path .join (STDLIB , module )
1378
1484
with open (fn , "r" , encoding = "utf-8" ) as fp :
1379
1485
source = fp .read ()
1380
1486
mod = ast .parse (source , fn )
0 commit comments