diff options
author | Batuhan Taskaya <batuhan@python.org> | 2021-07-28 17:14:45 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-28 17:14:45 (GMT) |
commit | 31bec6f1b178dadec3cb43353274b4e958a8f015 (patch) | |
tree | 007bb1ecbe4c69a0719a42076a18aa2fb8e098b6 /Lib/test/test_ast.py | |
parent | 53b9458f2e9314703a5406ca817d757f1509882a (diff) | |
download | cpython-31bec6f1b178dadec3cb43353274b4e958a8f015.zip cpython-31bec6f1b178dadec3cb43353274b4e958a8f015.tar.gz cpython-31bec6f1b178dadec3cb43353274b4e958a8f015.tar.bz2 |
bpo-43897: AST validation for pattern matching nodes (GH24771)
Diffstat (limited to 'Lib/test/test_ast.py')
-rw-r--r-- | Lib/test/test_ast.py | 143 |
1 files changed, 142 insertions, 1 deletions
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 5f1ee75..925bb88 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -696,7 +696,7 @@ class AST_Tests(unittest.TestCase): for constant in "True", "False", "None": expr = ast.Expression(ast.Name(constant, ast.Load())) ast.fix_missing_locations(expr) - with self.assertRaisesRegex(ValueError, f"Name node can't be used with '{constant}' constant"): + with self.assertRaisesRegex(ValueError, f"identifier field can't represent '{constant}' constant"): compile(expr, "<test>", "eval") def test_precedence_enum(self): @@ -1507,6 +1507,147 @@ class ASTValidatorTests(unittest.TestCase): mod = ast.parse(source, fn) compile(mod, fn, "exec") + constant_1 = ast.Constant(1) + pattern_1 = ast.MatchValue(constant_1) + + constant_x = ast.Constant('x') + pattern_x = ast.MatchValue(constant_x) + + constant_true = ast.Constant(True) + pattern_true = ast.MatchSingleton(True) + + name_carter = ast.Name('carter', ast.Load()) + + _MATCH_PATTERNS = [ + ast.MatchValue( + ast.Attribute( + ast.Attribute( + ast.Name('x', ast.Store()), + 'y', ast.Load() + ), + 'z', ast.Load() + ) + ), + ast.MatchValue( + ast.Attribute( + ast.Attribute( + ast.Name('x', ast.Load()), + 'y', ast.Store() + ), + 'z', ast.Load() + ) + ), + ast.MatchValue( + ast.Constant(...) + ), + ast.MatchValue( + ast.Constant(True) + ), + ast.MatchValue( + ast.Constant((1,2,3)) + ), + ast.MatchSingleton('string'), + ast.MatchSequence([ + ast.MatchSingleton('string') + ]), + ast.MatchSequence( + [ + ast.MatchSequence( + [ + ast.MatchSingleton('string') + ] + ) + ] + ), + ast.MatchMapping( + [constant_1, constant_true], + [pattern_x] + ), + ast.MatchMapping( + [constant_true, constant_1], + [pattern_x, pattern_1], + rest='True' + ), + ast.MatchMapping( + [constant_true, ast.Starred(ast.Name('lol', ast.Load()), ast.Load())], + [pattern_x, pattern_1], + rest='legit' + ), + ast.MatchClass( + ast.Attribute( + ast.Attribute( + constant_x, + 'y', ast.Load()), + 'z', ast.Load()), + patterns=[], kwd_attrs=[], kwd_patterns=[] + ), + ast.MatchClass( + name_carter, + patterns=[], + kwd_attrs=['True'], + kwd_patterns=[pattern_1] + ), + ast.MatchClass( + name_carter, + patterns=[], + kwd_attrs=[], + kwd_patterns=[pattern_1] + ), + ast.MatchClass( + name_carter, + patterns=[ast.MatchSingleton('string')], + kwd_attrs=[], + kwd_patterns=[] + ), + ast.MatchClass( + name_carter, + patterns=[ast.MatchStar()], + kwd_attrs=[], + kwd_patterns=[] + ), + ast.MatchClass( + name_carter, + patterns=[], + kwd_attrs=[], + kwd_patterns=[ast.MatchStar()] + ), + ast.MatchSequence( + [ + ast.MatchStar("True") + ] + ), + ast.MatchAs( + name='False' + ), + ast.MatchOr( + [] + ), + ast.MatchOr( + [pattern_1] + ), + ast.MatchOr( + [pattern_1, pattern_x, ast.MatchSingleton('xxx')] + ) + ] + + def test_match_validation_pattern(self): + name_x = ast.Name('x', ast.Load()) + for pattern in self._MATCH_PATTERNS: + with self.subTest(ast.dump(pattern, indent=4)): + node = ast.Match( + subject=name_x, + cases = [ + ast.match_case( + pattern=pattern, + body = [ast.Pass()] + ) + ] + ) + node = ast.fix_missing_locations(node) + module = ast.Module([node], []) + with self.assertRaises(ValueError): + compile(module, "<test>", "exec") + class ConstantTests(unittest.TestCase): """Tests on the ast.Constant node type.""" |