Merge pull request #4042 from youknowone/ast

Update ast and dict changes including unpack & kw_defaults
This commit is contained in:
Jeong YunWon
2022-08-19 04:54:03 +09:00
committed by GitHub
39 changed files with 1776 additions and 437 deletions

1
Cargo.lock generated
View File

@@ -1723,6 +1723,7 @@ name = "rustpython-ast"
version = "0.1.0"
dependencies = [
"num-bigint",
"rustpython-bytecode",
"rustpython-common",
]

109
Lib/ast.py vendored
View File

@@ -47,8 +47,8 @@ def parse(source, filename='<unknown>', mode='exec', *,
elif feature_version is None:
feature_version = -1
# Else it should be an int giving the minor version for 3.x.
return compile(source, filename, mode, flags)
# _feature_version=feature_version)
return compile(source, filename, mode, flags,
_feature_version=feature_version)
def literal_eval(node_or_string):
@@ -59,11 +59,14 @@ def literal_eval(node_or_string):
sets, booleans, and None.
"""
if isinstance(node_or_string, str):
node_or_string = parse(node_or_string, mode='eval')
node_or_string = parse(node_or_string.lstrip(" \t"), mode='eval')
if isinstance(node_or_string, Expression):
node_or_string = node_or_string.body
def _raise_malformed_node(node):
raise ValueError(f'malformed node or string: {node!r}')
msg = "malformed node or string"
if lno := getattr(node, 'lineno', None):
msg += f' on line {lno}'
raise ValueError(msg + f': {node!r}')
def _convert_num(node):
if not isinstance(node, Constant) or type(node.value) not in (int, float, complex):
_raise_malformed_node(node)
@@ -794,6 +797,9 @@ class _Unparser(NodeVisitor):
else:
super().visit(node)
# Note: as visit() resets the output text, do NOT rely on
# NodeVisitor.generic_visit to handle any nodes (as it calls back in to
# the subclass visit() method, which resets self._source to an empty list)
def visit(self, node):
"""Outputs a source code string that, if converted back to an ast
(using ast.parse) will generate an AST equivalent to *node*"""
@@ -1483,6 +1489,13 @@ class _Unparser(NodeVisitor):
self.write(":")
self.traverse(node.step)
def visit_Match(self, node):
self.fill("match ")
self.traverse(node.subject)
with self.block():
for case in node.cases:
self.traverse(case)
def visit_arg(self, node):
self.write(node.arg)
if node.annotation:
@@ -1567,6 +1580,94 @@ class _Unparser(NodeVisitor):
self.write(" as ")
self.traverse(node.optional_vars)
def visit_match_case(self, node):
self.fill("case ")
self.traverse(node.pattern)
if node.guard:
self.write(" if ")
self.traverse(node.guard)
with self.block():
self.traverse(node.body)
def visit_MatchValue(self, node):
self.traverse(node.value)
def visit_MatchSingleton(self, node):
self._write_constant(node.value)
def visit_MatchSequence(self, node):
with self.delimit("[", "]"):
self.interleave(
lambda: self.write(", "), self.traverse, node.patterns
)
def visit_MatchStar(self, node):
name = node.name
if name is None:
name = "_"
self.write(f"*{name}")
def visit_MatchMapping(self, node):
def write_key_pattern_pair(pair):
k, p = pair
self.traverse(k)
self.write(": ")
self.traverse(p)
with self.delimit("{", "}"):
keys = node.keys
self.interleave(
lambda: self.write(", "),
write_key_pattern_pair,
zip(keys, node.patterns, strict=True),
)
rest = node.rest
if rest is not None:
if keys:
self.write(", ")
self.write(f"**{rest}")
def visit_MatchClass(self, node):
self.set_precedence(_Precedence.ATOM, node.cls)
self.traverse(node.cls)
with self.delimit("(", ")"):
patterns = node.patterns
self.interleave(
lambda: self.write(", "), self.traverse, patterns
)
attrs = node.kwd_attrs
if attrs:
def write_attr_pattern(pair):
attr, pattern = pair
self.write(f"{attr}=")
self.traverse(pattern)
if patterns:
self.write(", ")
self.interleave(
lambda: self.write(", "),
write_attr_pattern,
zip(attrs, node.kwd_patterns, strict=True),
)
def visit_MatchAs(self, node):
name = node.name
pattern = node.pattern
if name is None:
self.write("_")
elif pattern is None:
self.write(node.name)
else:
with self.require_parens(_Precedence.TEST, node):
self.set_precedence(_Precedence.BOR, node.pattern)
self.traverse(node.pattern)
self.write(f" as {node.name}")
def visit_MatchOr(self, node):
with self.require_parens(_Precedence.BOR, node):
self.set_precedence(_Precedence.BOR.next(), *node.patterns)
self.interleave(lambda: self.write(" | "), self.traverse, node.patterns)
def unparse(ast_obj):
unparser = _Unparser()
return unparser.visit(ast_obj)

700
Lib/test/test_ast.py vendored
View File

@@ -1,7 +1,9 @@
import ast
import builtins
import dis
import os
import sys
import types
import unittest
import warnings
import weakref
@@ -17,6 +19,8 @@ def to_tuple(t):
result = [t.__class__.__name__]
if hasattr(t, 'lineno') and hasattr(t, 'col_offset'):
result.append((t.lineno, t.col_offset))
if hasattr(t, 'end_lineno') and hasattr(t, 'end_col_offset'):
result[-1] += (t.end_lineno, t.end_col_offset)
if t._fields is None:
return tuple(result)
for f in t._fields:
@@ -245,6 +249,13 @@ eval_tests = [
class AST_Tests(unittest.TestCase):
def _is_ast_node(self, name, node):
if not isinstance(node, type):
return False
if "ast" not in node.__module__:
return False
return name != 'AST' and name[0].isupper()
def _assertTrueorder(self, ast_node, parent_pos):
if not isinstance(ast_node, ast.AST) or ast_node._fields is None:
return
@@ -262,6 +273,7 @@ class AST_Tests(unittest.TestCase):
self._assertTrueorder(child, first_pos)
elif value is not None:
self._assertTrueorder(value, parent_pos)
self.assertEqual(ast_node._fields, ast_node.__match_args__)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@@ -276,7 +288,7 @@ class AST_Tests(unittest.TestCase):
x.vararg
with self.assertRaises(TypeError):
# "_ast.AST constructor takes 0 positional arguments"
# "ast.AST constructor takes 0 positional arguments"
ast.AST(2)
# TODO: RUSTPYTHON
@@ -329,6 +341,28 @@ class AST_Tests(unittest.TestCase):
mod.body[0].module = " __future__ ".strip()
compile(mod, "<test>", "exec")
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_alias(self):
im = ast.parse("from bar import y").body[0]
self.assertEqual(len(im.names), 1)
alias = im.names[0]
self.assertEqual(alias.name, 'y')
self.assertIsNone(alias.asname)
self.assertEqual(alias.lineno, 1)
self.assertEqual(alias.end_lineno, 1)
self.assertEqual(alias.col_offset, 16)
self.assertEqual(alias.end_col_offset, 17)
im = ast.parse("from bar import *").body[0]
alias = im.names[0]
self.assertEqual(alias.name, '*')
self.assertIsNone(alias.asname)
self.assertEqual(alias.lineno, 1)
self.assertEqual(alias.end_lineno, 1)
self.assertEqual(alias.col_offset, 16)
self.assertEqual(alias.end_col_offset, 17)
def test_base_classes(self):
self.assertTrue(issubclass(ast.For, ast.stmt))
self.assertTrue(issubclass(ast.Name, ast.expr))
@@ -341,7 +375,11 @@ class AST_Tests(unittest.TestCase):
@unittest.expectedFailure
def test_field_attr_existence(self):
for name, item in ast.__dict__.items():
if isinstance(item, type) and name != 'AST' and name[0].isupper():
if self._is_ast_node(name, item):
if name == 'Index':
# Index(value) just returns value now.
# The argument is required.
continue
x = item()
if isinstance(x, ast.AST):
self.assertEqual(type(x._fields), tuple)
@@ -354,9 +392,11 @@ class AST_Tests(unittest.TestCase):
'kw_defaults', 'kwarg', 'defaults'))
with self.assertRaises(AttributeError):
x.vararg
x.args
self.assertIsNone(x.vararg)
x = ast.arguments(*range(1, 8))
self.assertEqual(x.args, 2)
self.assertEqual(x.vararg, 3)
def test_field_attr_writable(self):
@@ -587,17 +627,26 @@ class AST_Tests(unittest.TestCase):
m = ast.Module([ast.Expr(ast.expr(**pos), **pos)], [])
with self.assertRaises(TypeError) as cm:
compile(m, "<test>", "exec")
self.assertIn("but got <_ast.expr", str(cm.exception))
self.assertIn("but got <ast.expr", str(cm.exception))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_invalid_identitifer(self):
def test_invalid_identifier(self):
m = ast.Module([ast.Expr(ast.Name(42, ast.Load()))], [])
ast.fix_missing_locations(m)
with self.assertRaises(TypeError) as cm:
compile(m, "<test>", "exec")
self.assertIn("identifier must be of type str", str(cm.exception))
def test_invalid_constant(self):
for invalid_constant in int, (1, 2, int), frozenset((1, 2, int)):
e = ast.Expression(body=ast.Constant(invalid_constant))
ast.fix_missing_locations(e)
with self.assertRaisesRegex(
TypeError, "invalid type in Constant: type"
):
compile(e, "<test>", "eval")
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_empty_yield_from(self):
@@ -606,7 +655,7 @@ class AST_Tests(unittest.TestCase):
empty_yield_from.body[0].body[0].value.value = None
with self.assertRaises(ValueError) as cm:
compile(empty_yield_from, "<test>", "exec")
self.assertIn("field value is required", str(cm.exception))
self.assertIn("field 'value' is required", str(cm.exception))
@support.cpython_only
def test_issue31592(self):
@@ -658,6 +707,27 @@ class AST_Tests(unittest.TestCase):
attr_b = tree.body[0].decorator_list[0].value
self.assertEqual(attr_b.end_col_offset, 4)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_ast_asdl_signature(self):
self.assertEqual(ast.withitem.__doc__, "withitem(expr context_expr, expr? optional_vars)")
self.assertEqual(ast.GtE.__doc__, "GtE")
self.assertEqual(ast.Name.__doc__, "Name(identifier id, expr_context ctx)")
self.assertEqual(ast.cmpop.__doc__, "cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn")
expressions = [f" | {node.__doc__}" for node in ast.expr.__subclasses__()]
expressions[0] = f"expr = {ast.expr.__subclasses__()[0].__doc__}"
self.assertCountEqual(ast.expr.__doc__.split("\n"), expressions)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_parenthesized_with_feature_version(self):
ast.parse('with (CtxManager() as example): ...', feature_version=(3, 10))
# While advertised as a feature in Python 3.10, this was allowed starting 3.9
ast.parse('with (CtxManager() as example): ...', feature_version=(3, 9))
with self.assertRaises(SyntaxError):
ast.parse('with (CtxManager() as example): ...', feature_version=(3, 8))
ast.parse('with CtxManager() as example: ...', feature_version=(3, 8))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_issue40614_feature_version(self):
@@ -665,13 +735,20 @@ class AST_Tests(unittest.TestCase):
with self.assertRaises(SyntaxError):
ast.parse('f"{x=}"', feature_version=(3, 7))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_assignment_expression_feature_version(self):
ast.parse('(x := 0)', feature_version=(3, 8))
with self.assertRaises(SyntaxError):
ast.parse('(x := 0)', feature_version=(3, 7))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_constant_as_name(self):
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")
@@ -699,23 +776,86 @@ class ASTHelpers_Test(unittest.TestCase):
node = ast.parse('spam(eggs, "and cheese")')
self.assertEqual(ast.dump(node),
"Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), "
"args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese', kind=None)], "
"args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')], "
"keywords=[]))], type_ignores=[])"
)
self.assertEqual(ast.dump(node, annotate_fields=False),
"Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), "
"Constant('and cheese', None)], []))], [])"
"Constant('and cheese')], []))], [])"
)
self.assertEqual(ast.dump(node, include_attributes=True),
"Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), "
"lineno=1, col_offset=0, end_lineno=1, end_col_offset=4), "
"args=[Name(id='eggs', ctx=Load(), lineno=1, col_offset=5, "
"end_lineno=1, end_col_offset=9), Constant(value='and cheese', kind=None, "
"end_lineno=1, end_col_offset=9), Constant(value='and cheese', "
"lineno=1, col_offset=11, end_lineno=1, end_col_offset=23)], keywords=[], "
"lineno=1, col_offset=0, end_lineno=1, end_col_offset=24), "
"lineno=1, col_offset=0, end_lineno=1, end_col_offset=24)], type_ignores=[])"
)
# TODO: RUSTPYTHON; redundant kind for Contant node
@unittest.expectedFailure
def test_dump_indent(self):
node = ast.parse('spam(eggs, "and cheese")')
self.assertEqual(ast.dump(node, indent=3), """\
Module(
body=[
Expr(
value=Call(
func=Name(id='spam', ctx=Load()),
args=[
Name(id='eggs', ctx=Load()),
Constant(value='and cheese')],
keywords=[]))],
type_ignores=[])""")
self.assertEqual(ast.dump(node, annotate_fields=False, indent='\t'), """\
Module(
\t[
\t\tExpr(
\t\t\tCall(
\t\t\t\tName('spam', Load()),
\t\t\t\t[
\t\t\t\t\tName('eggs', Load()),
\t\t\t\t\tConstant('and cheese')],
\t\t\t\t[]))],
\t[])""")
self.assertEqual(ast.dump(node, include_attributes=True, indent=3), """\
Module(
body=[
Expr(
value=Call(
func=Name(
id='spam',
ctx=Load(),
lineno=1,
col_offset=0,
end_lineno=1,
end_col_offset=4),
args=[
Name(
id='eggs',
ctx=Load(),
lineno=1,
col_offset=5,
end_lineno=1,
end_col_offset=9),
Constant(
value='and cheese',
lineno=1,
col_offset=11,
end_lineno=1,
end_col_offset=23)],
keywords=[],
lineno=1,
col_offset=0,
end_lineno=1,
end_col_offset=24),
lineno=1,
col_offset=0,
end_lineno=1,
end_col_offset=24)],
type_ignores=[])""")
def test_dump_incomplete(self):
node = ast.Raise(lineno=3, col_offset=4)
self.assertEqual(ast.dump(node),
@@ -751,16 +891,13 @@ class ASTHelpers_Test(unittest.TestCase):
src = ast.parse('1 + 1', mode='eval')
src.body.right = ast.copy_location(ast.Num(2), src.body.right)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Constant(value=1, kind=None, lineno=1, col_offset=0, '
'Expression(body=BinOp(left=Constant(value=1, lineno=1, col_offset=0, '
'end_lineno=1, end_col_offset=1), op=Add(), right=Constant(value=2, '
'lineno=1, col_offset=4, end_lineno=1, end_col_offset=5), lineno=1, '
'col_offset=0, end_lineno=1, end_col_offset=5))'
)
src = ast.Call(col_offset=1, lineno=1, end_lineno=1, end_col_offset=1)
new = ast.copy_location(src, ast.Call(
col_offset=None, lineno=None,
end_lineno=None, end_col_offset=None
))
new = ast.copy_location(src, ast.Call(col_offset=None, lineno=None))
self.assertIsNone(new.end_lineno)
self.assertIsNone(new.end_col_offset)
self.assertEqual(new.lineno, 1)
@@ -777,7 +914,7 @@ class ASTHelpers_Test(unittest.TestCase):
self.assertEqual(ast.dump(src, include_attributes=True),
"Module(body=[Expr(value=Call(func=Name(id='write', ctx=Load(), "
"lineno=1, col_offset=0, end_lineno=1, end_col_offset=5), "
"args=[Constant(value='spam', kind=None, lineno=1, col_offset=6, end_lineno=1, "
"args=[Constant(value='spam', lineno=1, col_offset=6, end_lineno=1, "
"end_col_offset=12)], keywords=[], lineno=1, col_offset=0, end_lineno=1, "
"end_col_offset=13), lineno=1, col_offset=0, end_lineno=1, "
"end_col_offset=13), Expr(value=Call(func=Name(id='spam', ctx=Load(), "
@@ -794,8 +931,8 @@ class ASTHelpers_Test(unittest.TestCase):
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src, n=3), src)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Constant(value=1, kind=None, lineno=4, col_offset=0, '
'end_lineno=4, end_col_offset=1), op=Add(), right=Constant(value=1, kind=None, '
'Expression(body=BinOp(left=Constant(value=1, lineno=4, col_offset=0, '
'end_lineno=4, end_col_offset=1), op=Add(), right=Constant(value=1, '
'lineno=4, col_offset=4, end_lineno=4, end_col_offset=5), lineno=4, '
'col_offset=0, end_lineno=4, end_col_offset=5))'
)
@@ -803,14 +940,13 @@ class ASTHelpers_Test(unittest.TestCase):
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src.body, n=3), src.body)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Constant(value=1, kind=None, lineno=4, col_offset=0, '
'end_lineno=4, end_col_offset=1), op=Add(), right=Constant(value=1, kind=None, '
'Expression(body=BinOp(left=Constant(value=1, lineno=4, col_offset=0, '
'end_lineno=4, end_col_offset=1), op=Add(), right=Constant(value=1, '
'lineno=4, col_offset=4, end_lineno=4, end_col_offset=5), lineno=4, '
'col_offset=0, end_lineno=4, end_col_offset=5))'
)
src = ast.Call(
func=ast.Name("test", ast.Load()), args=[], keywords=[],
lineno=1, end_lineno=None
func=ast.Name("test", ast.Load()), args=[], keywords=[], lineno=1
)
self.assertEqual(ast.increment_lineno(src).lineno, 2)
self.assertIsNone(ast.increment_lineno(src).end_lineno)
@@ -821,6 +957,8 @@ class ASTHelpers_Test(unittest.TestCase):
self.assertEqual(d.pop('func').id, 'foo')
self.assertEqual(d, {'keywords': [], 'args': []})
# TODO: RUSTPYTHON; redundant kind for Contant node
@unittest.expectedFailure
def test_iter_child_nodes(self):
node = ast.parse("spam(23, 42, eggs='leek')", mode='eval')
self.assertEqual(len(list(ast.iter_child_nodes(node.body))), 4)
@@ -829,7 +967,7 @@ class ASTHelpers_Test(unittest.TestCase):
self.assertEqual(next(iterator).value, 23)
self.assertEqual(next(iterator).value, 42)
self.assertEqual(ast.dump(next(iterator)),
"keyword(arg='eggs', value=Constant(value='leek', kind=None))"
"keyword(arg='eggs', value=Constant(value='leek'))"
)
def test_get_docstring(self):
@@ -923,6 +1061,7 @@ class ASTHelpers_Test(unittest.TestCase):
self.assertEqual(ast.literal_eval('(True, False, None)'), (True, False, None))
self.assertEqual(ast.literal_eval('{1, 2, 3}'), {1, 2, 3})
self.assertEqual(ast.literal_eval('b"hi"'), b"hi")
self.assertEqual(ast.literal_eval('set()'), set())
self.assertRaises(ValueError, ast.literal_eval, 'foo()')
self.assertEqual(ast.literal_eval('6'), 6)
self.assertEqual(ast.literal_eval('+6'), 6)
@@ -962,6 +1101,35 @@ class ASTHelpers_Test(unittest.TestCase):
malformed = ast.Dict(keys=[ast.Constant(1)], values=[ast.Constant(2), ast.Constant(3)])
self.assertRaises(ValueError, ast.literal_eval, malformed)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_literal_eval_trailing_ws(self):
self.assertEqual(ast.literal_eval(" -1"), -1)
self.assertEqual(ast.literal_eval("\t\t-1"), -1)
self.assertEqual(ast.literal_eval(" \t -1"), -1)
self.assertRaises(IndentationError, ast.literal_eval, "\n -1")
def test_literal_eval_malformed_lineno(self):
msg = r'malformed node or string on line 3:'
with self.assertRaisesRegex(ValueError, msg):
ast.literal_eval("{'a': 1,\n'b':2,\n'c':++3,\n'd':4}")
node = ast.UnaryOp(
ast.UAdd(), ast.UnaryOp(ast.UAdd(), ast.Constant(6)))
self.assertIsNone(getattr(node, 'lineno', None))
msg = r'malformed node or string:'
with self.assertRaisesRegex(ValueError, msg):
ast.literal_eval(node)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_literal_eval_syntax_errors(self):
with self.assertRaisesRegex(SyntaxError, "unexpected indent"):
ast.literal_eval(r'''
\
(\
\ ''')
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_bad_integer(self):
@@ -975,11 +1143,10 @@ class ASTHelpers_Test(unittest.TestCase):
compile(mod, 'test', 'exec')
self.assertIn("invalid integer value: None", str(cm.exception))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_level_as_none(self):
body = [ast.ImportFrom(module='time',
names=[ast.alias(name='sleep')],
names=[ast.alias(name='sleep',
lineno=0, col_offset=0)],
level=None,
lineno=0, col_offset=0)]
mod = ast.Module(body, [])
@@ -988,6 +1155,24 @@ class ASTHelpers_Test(unittest.TestCase):
exec(code, ns)
self.assertIn('sleep', ns)
@unittest.skip("TODO: RUSTPYTHON; crash")
def test_recursion_direct(self):
e = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0)
e.operand = e
with self.assertRaises(RecursionError):
with support.infinite_recursion():
compile(ast.Expression(e), "<test>", "eval")
@unittest.skip("TODO: RUSTPYTHON; crash")
def test_recursion_indirect(self):
e = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0)
f = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0)
e.operand = f
f.operand = e
with self.assertRaises(RecursionError):
with support.infinite_recursion():
compile(ast.Expression(e), "<test>", "eval")
class ASTValidatorTests(unittest.TestCase):
@@ -1398,11 +1583,11 @@ class ASTValidatorTests(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_subscript(self):
sub = ast.Subscript(ast.Name("x", ast.Store()), ast.Index(ast.Num(3)),
sub = ast.Subscript(ast.Name("x", ast.Store()), ast.Num(3),
ast.Load())
self.expr(sub, "must have Load context")
x = ast.Name("x", ast.Load())
sub = ast.Subscript(x, ast.Index(ast.Name("y", ast.Store())),
sub = ast.Subscript(x, ast.Name("y", ast.Store()),
ast.Load())
self.expr(sub, "must have Load context")
s = ast.Name("x", ast.Store())
@@ -1410,9 +1595,9 @@ class ASTValidatorTests(unittest.TestCase):
sl = ast.Slice(*args)
self.expr(ast.Subscript(x, sl, ast.Load()),
"must have Load context")
sl = ast.ExtSlice([])
self.expr(ast.Subscript(x, sl, ast.Load()), "empty dims on ExtSlice")
sl = ast.ExtSlice([ast.Index(s)])
sl = ast.Tuple([], ast.Load())
self.expr(ast.Subscript(x, sl, ast.Load()))
sl = ast.Tuple([s], ast.Load())
self.expr(ast.Subscript(x, sl, ast.Load()), "must have Load context")
# TODO: RUSTPYTHON
@@ -1455,6 +1640,151 @@ 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')]
),
ast.MatchAs(name="_"),
ast.MatchStar(name="x"),
ast.MatchSequence([ast.MatchStar("_")]),
ast.MatchMapping([], [], rest="_"),
]
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."""
@@ -1783,6 +2113,7 @@ class EndPositionTests(unittest.TestCase):
''').strip()
imp = ast.parse(s).body[0]
self._check_end_pos(imp, 3, 1)
self._check_end_pos(imp.names[2], 2, 16)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@@ -1796,11 +2127,11 @@ class EndPositionTests(unittest.TestCase):
''').strip()
i1, i2, im = map(self._parse_value, (s1, s2, sm))
self._check_content(s1, i1.value, 'f()[1, 2]')
self._check_content(s1, i1.value.slice.value, '1, 2')
self._check_content(s1, i1.value.slice, '1, 2')
self._check_content(s2, i2.slice.lower, 'a.b')
self._check_content(s2, i2.slice.upper, 'c.d')
self._check_content(sm, im.slice.dims[0].upper, 'f ()')
self._check_content(sm, im.slice.dims[1].lower, 'g ()')
self._check_content(sm, im.slice.elts[0].upper, 'f ()')
self._check_content(sm, im.slice.elts[1].lower, 'g ()')
self._check_end_pos(im, 3, 3)
# TODO: RUSTPYTHON
@@ -1980,6 +2311,19 @@ class EndPositionTests(unittest.TestCase):
cdef = ast.parse(s).body[0]
self.assertEqual(ast.get_source_segment(s, cdef.body[0], padded=True), s_method)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_source_segment_missing_info(self):
s = 'v = 1\r\nw = 1\nx = 1\n\ry = 1\r\n'
v, w, x, y = ast.parse(s).body
del v.lineno
del w.end_lineno
del x.col_offset
del y.end_col_offset
self.assertIsNone(ast.get_source_segment(s, v))
self.assertIsNone(ast.get_source_segment(s, w))
self.assertIsNone(ast.get_source_segment(s, x))
self.assertIsNone(ast.get_source_segment(s, y))
class NodeVisitorTests(unittest.TestCase):
def test_old_constant_nodes(self):
@@ -2031,6 +2375,88 @@ class NodeVisitorTests(unittest.TestCase):
])
@support.cpython_only
class ModuleStateTests(unittest.TestCase):
# bpo-41194, bpo-41261, bpo-41631: The _ast module uses a global state.
def check_ast_module(self):
# Check that the _ast module still works as expected
code = 'x + 1'
filename = '<string>'
mode = 'eval'
# Create _ast.AST subclasses instances
ast_tree = compile(code, filename, mode, flags=ast.PyCF_ONLY_AST)
# Call PyAST_Check()
code = compile(ast_tree, filename, mode)
self.assertIsInstance(code, types.CodeType)
def test_reload_module(self):
# bpo-41194: Importing the _ast module twice must not crash.
with support.swap_item(sys.modules, '_ast', None):
del sys.modules['_ast']
import _ast as ast1
del sys.modules['_ast']
import _ast as ast2
self.check_ast_module()
# Unloading the two _ast module instances must not crash.
del ast1
del ast2
support.gc_collect()
self.check_ast_module()
def test_sys_modules(self):
# bpo-41631: Test reproducing a Mercurial crash when PyAST_Check()
# imported the _ast module internally.
lazy_mod = object()
def my_import(name, *args, **kw):
sys.modules[name] = lazy_mod
return lazy_mod
with support.swap_item(sys.modules, '_ast', None):
del sys.modules['_ast']
with support.swap_attr(builtins, '__import__', my_import):
# Test that compile() does not import the _ast module
self.check_ast_module()
self.assertNotIn('_ast', sys.modules)
# Sanity check of the test itself
import _ast
self.assertIs(_ast, lazy_mod)
def test_subinterpreter(self):
# bpo-41631: Importing and using the _ast module in a subinterpreter
# must not crash.
code = dedent('''
import _ast
import ast
import gc
import sys
import types
# Create _ast.AST subclasses instances and call PyAST_Check()
ast_tree = compile('x+1', '<string>', 'eval',
flags=ast.PyCF_ONLY_AST)
code = compile(ast_tree, 'string', 'eval')
if not isinstance(code, types.CodeType):
raise AssertionError
# Unloading the _ast module must not crash.
del ast, _ast
del sys.modules['ast'], sys.modules['_ast']
gc.collect()
''')
res = support.run_in_subinterp(code)
self.assertEqual(res, 0)
def main():
if __name__ != '__main__':
return
@@ -2048,112 +2474,112 @@ def main():
#### EVERYTHING BELOW IS GENERATED BY python Lib/test/test_ast.py -g #####
exec_results = [
('Module', [('Expr', (1, 0), ('Constant', (1, 0), None, None))], []),
('Module', [('Expr', (1, 0), ('Constant', (1, 0), 'module docstring', None))], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9), ('Constant', (1, 9), 'function docstring', None))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [('arg', (1, 6), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [('arg', (1, 6), 'a', None, None)], None, [], [], None, [('Constant', (1, 8), 0, None)]), [('Pass', (1, 12))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [], ('arg', (1, 7), 'args', None, None), [], [], None, []), [('Pass', (1, 14))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], ('arg', (1, 8), 'kwargs', None, None), []), [('Pass', (1, 17))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [('arg', (1, 6), 'a', None, None), ('arg', (1, 9), 'b', None, None), ('arg', (1, 14), 'c', None, None), ('arg', (1, 22), 'd', None, None), ('arg', (1, 28), 'e', None, None)], ('arg', (1, 35), 'args', None, None), [('arg', (1, 41), 'f', None, None)], [('Constant', (1, 43), 42, None)], ('arg', (1, 49), 'kwargs', None, None), [('Constant', (1, 11), 1, None), ('Constant', (1, 16), None, None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Expr', (1, 58), ('Constant', (1, 58), 'doc for f()', None))], [], None, None)], []),
('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [])], []),
('Module', [('ClassDef', (1, 0), 'C', [], [], [('Expr', (1, 9), ('Constant', (1, 9), 'docstring for class C', None))], [])], []),
('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [])], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8), ('Constant', (1, 15), 1, None))], [], None, None)], []),
('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])], []),
('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Constant', (1, 4), 1, None), None)], []),
('Module', [('Assign', (1, 0), [('Tuple', (1, 0), [('Name', (1, 0), 'a', ('Store',)), ('Name', (1, 2), 'b', ('Store',))], ('Store',))], ('Name', (1, 6), 'c', ('Load',)), None)], []),
('Module', [('Assign', (1, 0), [('Tuple', (1, 0), [('Name', (1, 1), 'a', ('Store',)), ('Name', (1, 3), 'b', ('Store',))], ('Store',))], ('Name', (1, 8), 'c', ('Load',)), None)], []),
('Module', [('Assign', (1, 0), [('List', (1, 0), [('Name', (1, 1), 'a', ('Store',)), ('Name', (1, 3), 'b', ('Store',))], ('Store',))], ('Name', (1, 8), 'c', ('Load',)), None)], []),
('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Constant', (1, 5), 1, None))], []),
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [], None)], []),
('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])], []),
('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])], []),
('Module', [('If', (1, 0), ('Name', (1, 3), 'a', ('Load',)), [('Pass', (2, 2))], [('If', (3, 0), ('Name', (3, 5), 'b', ('Load',)), [('Pass', (4, 2))], [])])], []),
('Module', [('If', (1, 0), ('Name', (1, 3), 'a', ('Load',)), [('Pass', (2, 2))], [('If', (3, 0), ('Name', (3, 5), 'b', ('Load',)), [('Pass', (4, 2))], [('Pass', (6, 2))])])], []),
('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))], None)], []),
('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))], None)], []),
('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Constant', (1, 16), 'string', None)], []), None)], []),
('Module', [('Try', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [], [])], []),
('Module', [('Try', (1, 0), [('Pass', (2, 2))], [], [], [('Pass', (4, 2))])], []),
('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)], []),
('Module', [('Import', (1, 0), [('alias', 'sys', None)])], []),
('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)], []),
('Module', [('Global', (1, 0), ['v'])], []),
('Module', [('Expr', (1, 0), ('Constant', (1, 0), 1, None))], []),
('Module', [('Pass', (1, 0))], []),
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Break', (1, 11))], [], None)], []),
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Continue', (1, 11))], [], None)], []),
('Module', [('For', (1, 0), ('Tuple', (1, 4), [('Name', (1, 4), 'a', ('Store',)), ('Name', (1, 6), 'b', ('Store',))], ('Store',)), ('Name', (1, 11), 'c', ('Load',)), [('Pass', (1, 14))], [], None)], []),
('Module', [('For', (1, 0), ('Tuple', (1, 4), [('Name', (1, 5), 'a', ('Store',)), ('Name', (1, 7), 'b', ('Store',))], ('Store',)), ('Name', (1, 13), 'c', ('Load',)), [('Pass', (1, 16))], [], None)], []),
('Module', [('For', (1, 0), ('List', (1, 4), [('Name', (1, 5), 'a', ('Store',)), ('Name', (1, 7), 'b', ('Store',))], ('Store',)), ('Name', (1, 13), 'c', ('Load',)), [('Pass', (1, 16))], [], None)], []),
('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 0), ('Tuple', (2, 4), [('Name', (3, 4), 'Aa', ('Load',)), ('Name', (5, 7), 'Bb', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (8, 4), [('Name', (8, 4), 'Aa', ('Store',)), ('Name', (10, 4), 'Bb', ('Store',))], ('Store',)), ('Name', (10, 10), 'Cc', ('Load',)), [], 0)]))], []),
('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Name', (1, 11), 'w', ('Store',)), ('Name', (1, 16), 'x', ('Load',)), [], 0), ('comprehension', ('Name', (1, 22), 'm', ('Store',)), ('Name', (1, 27), 'p', ('Load',)), [('Name', (1, 32), 'g', ('Load',))], 0)]))], []),
('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [], 0)]))], []),
('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))], 0)]))], []),
('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [], 0)]))], []),
('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1), ('Constant', (2, 1), 'async function', None)), ('Expr', (3, 1), ('Await', (3, 1), ('Call', (3, 7), ('Name', (3, 7), 'something', ('Load',)), [], [])))], [], None, None)], []),
('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Constant', (2, 19), 1, None))], [('Expr', (3, 7), ('Constant', (3, 7), 2, None))], None)], [], None, None)], []),
('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Constant', (2, 20), 1, None))], None)], [], None, None)], []),
('Module', [('Expr', (1, 0), ('Dict', (1, 0), [None, ('Constant', (1, 10), 2, None)], [('Dict', (1, 3), [('Constant', (1, 4), 1, None)], [('Constant', (1, 6), 2, None)]), ('Constant', (1, 12), 3, None)]))], []),
('Module', [('Expr', (1, 0), ('Set', (1, 0), [('Starred', (1, 1), ('Set', (1, 2), [('Constant', (1, 3), 1, None), ('Constant', (1, 6), 2, None)]), ('Load',)), ('Constant', (1, 10), 3, None)]))], []),
('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1), ('ListComp', (2, 1), ('Name', (2, 2), 'i', ('Load',)), [('comprehension', ('Name', (2, 14), 'b', ('Store',)), ('Name', (2, 19), 'c', ('Load',)), [], 1)]))], [], None, None)], []),
('Module', [('FunctionDef', (4, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 9))], [('Name', (1, 1), 'deco1', ('Load',)), ('Call', (2, 1), ('Name', (2, 1), 'deco2', ('Load',)), [], []), ('Call', (3, 1), ('Name', (3, 1), 'deco3', ('Load',)), [('Constant', (3, 7), 1, None)], [])], None, None)], []),
('Module', [('AsyncFunctionDef', (4, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 15))], [('Name', (1, 1), 'deco1', ('Load',)), ('Call', (2, 1), ('Name', (2, 1), 'deco2', ('Load',)), [], []), ('Call', (3, 1), ('Name', (3, 1), 'deco3', ('Load',)), [('Constant', (3, 7), 1, None)], [])], None, None)], []),
('Module', [('ClassDef', (4, 0), 'C', [], [], [('Pass', (4, 9))], [('Name', (1, 1), 'deco1', ('Load',)), ('Call', (2, 1), ('Name', (2, 1), 'deco2', ('Load',)), [], []), ('Call', (3, 1), ('Name', (3, 1), 'deco3', ('Load',)), [('Constant', (3, 7), 1, None)], [])])], []),
('Module', [('FunctionDef', (2, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9))], [('Call', (1, 1), ('Name', (1, 1), 'deco', ('Load',)), [('GeneratorExp', (1, 5), ('Name', (1, 6), 'a', ('Load',)), [('comprehension', ('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 17), 'b', ('Load',)), [], 0)])], [])], None, None)], []),
('Module', [('FunctionDef', (2, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9))], [('Attribute', (1, 1), ('Attribute', (1, 1), ('Name', (1, 1), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',))], None, None)], []),
('Module', [('Expr', (1, 0), ('NamedExpr', (1, 1), ('Name', (1, 1), 'a', ('Store',)), ('Constant', (1, 6), 1, None)))], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 14))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [('arg', (1, 12), 'c', None, None), ('arg', (1, 15), 'd', None, None), ('arg', (1, 18), 'e', None, None)], None, [], [], None, []), [('Pass', (1, 22))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [('arg', (1, 12), 'c', None, None)], None, [('arg', (1, 18), 'd', None, None), ('arg', (1, 21), 'e', None, None)], [None, None], None, []), [('Pass', (1, 25))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [('arg', (1, 12), 'c', None, None)], None, [('arg', (1, 18), 'd', None, None), ('arg', (1, 21), 'e', None, None)], [None, None], ('arg', (1, 26), 'kwargs', None, None), []), [('Pass', (1, 35))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8), 1, None)]), [('Pass', (1, 16))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [('arg', (1, 14), 'b', None, None), ('arg', (1, 19), 'c', None, None)], None, [], [], None, [('Constant', (1, 8), 1, None), ('Constant', (1, 16), 2, None), ('Constant', (1, 21), 4, None)]), [('Pass', (1, 25))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [('arg', (1, 14), 'b', None, None)], None, [('arg', (1, 22), 'c', None, None)], [('Constant', (1, 24), 4, None)], None, [('Constant', (1, 8), 1, None), ('Constant', (1, 16), 2, None)]), [('Pass', (1, 28))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [('arg', (1, 14), 'b', None, None)], None, [('arg', (1, 22), 'c', None, None)], [None], None, [('Constant', (1, 8), 1, None), ('Constant', (1, 16), 2, None)]), [('Pass', (1, 26))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [('arg', (1, 14), 'b', None, None)], None, [('arg', (1, 22), 'c', None, None)], [('Constant', (1, 24), 4, None)], ('arg', (1, 29), 'kwargs', None, None), [('Constant', (1, 8), 1, None), ('Constant', (1, 16), 2, None)]), [('Pass', (1, 38))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [('arg', (1, 14), 'b', None, None)], None, [('arg', (1, 22), 'c', None, None)], [None], ('arg', (1, 27), 'kwargs', None, None), [('Constant', (1, 8), 1, None), ('Constant', (1, 16), 2, None)]), [('Pass', (1, 36))], [], None, None)], []),
('Module', [('Expr', (1, 0, 1, 4), ('Constant', (1, 0, 1, 4), None, None))], []),
('Module', [('Expr', (1, 0, 1, 18), ('Constant', (1, 0, 1, 18), 'module docstring', None))], []),
('Module', [('FunctionDef', (1, 0, 1, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9, 1, 13))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9, 1, 29), ('Constant', (1, 9, 1, 29), 'function docstring', None))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 14), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10, 1, 14))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 0, None)]), [('Pass', (1, 12, 1, 16))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 11), 'args', None, None), [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 21), 'f', ('arguments', [], [], None, [], [], ('arg', (1, 8, 1, 14), 'kwargs', None, None), []), [('Pass', (1, 17, 1, 21))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 71), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None), ('arg', (1, 9, 1, 10), 'b', None, None), ('arg', (1, 14, 1, 15), 'c', None, None), ('arg', (1, 22, 1, 23), 'd', None, None), ('arg', (1, 28, 1, 29), 'e', None, None)], ('arg', (1, 35, 1, 39), 'args', None, None), [('arg', (1, 41, 1, 42), 'f', None, None)], [('Constant', (1, 43, 1, 45), 42, None)], ('arg', (1, 49, 1, 55), 'kwargs', None, None), [('Constant', (1, 11, 1, 12), 1, None), ('Constant', (1, 16, 1, 20), None, None), ('List', (1, 24, 1, 26), [], ('Load',)), ('Dict', (1, 30, 1, 32), [], [])]), [('Expr', (1, 58, 1, 71), ('Constant', (1, 58, 1, 71), 'doc for f()', None))], [], None, None)], []),
('Module', [('ClassDef', (1, 0, 1, 12), 'C', [], [], [('Pass', (1, 8, 1, 12))], [])], []),
('Module', [('ClassDef', (1, 0, 1, 32), 'C', [], [], [('Expr', (1, 9, 1, 32), ('Constant', (1, 9, 1, 32), 'docstring for class C', None))], [])], []),
('Module', [('ClassDef', (1, 0, 1, 21), 'C', [('Name', (1, 8, 1, 14), 'object', ('Load',))], [], [('Pass', (1, 17, 1, 21))], [])], []),
('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8, 1, 16), ('Constant', (1, 15, 1, 16), 1, None))], [], None, None)], []),
('Module', [('Delete', (1, 0, 1, 5), [('Name', (1, 4, 1, 5), 'v', ('Del',))])], []),
('Module', [('Assign', (1, 0, 1, 5), [('Name', (1, 0, 1, 1), 'v', ('Store',))], ('Constant', (1, 4, 1, 5), 1, None), None)], []),
('Module', [('Assign', (1, 0, 1, 7), [('Tuple', (1, 0, 1, 3), [('Name', (1, 0, 1, 1), 'a', ('Store',)), ('Name', (1, 2, 1, 3), 'b', ('Store',))], ('Store',))], ('Name', (1, 6, 1, 7), 'c', ('Load',)), None)], []),
('Module', [('Assign', (1, 0, 1, 9), [('Tuple', (1, 0, 1, 5), [('Name', (1, 1, 1, 2), 'a', ('Store',)), ('Name', (1, 3, 1, 4), 'b', ('Store',))], ('Store',))], ('Name', (1, 8, 1, 9), 'c', ('Load',)), None)], []),
('Module', [('Assign', (1, 0, 1, 9), [('List', (1, 0, 1, 5), [('Name', (1, 1, 1, 2), 'a', ('Store',)), ('Name', (1, 3, 1, 4), 'b', ('Store',))], ('Store',))], ('Name', (1, 8, 1, 9), 'c', ('Load',)), None)], []),
('Module', [('AugAssign', (1, 0, 1, 6), ('Name', (1, 0, 1, 1), 'v', ('Store',)), ('Add',), ('Constant', (1, 5, 1, 6), 1, None))], []),
('Module', [('For', (1, 0, 1, 15), ('Name', (1, 4, 1, 5), 'v', ('Store',)), ('Name', (1, 9, 1, 10), 'v', ('Load',)), [('Pass', (1, 11, 1, 15))], [], None)], []),
('Module', [('While', (1, 0, 1, 12), ('Name', (1, 6, 1, 7), 'v', ('Load',)), [('Pass', (1, 8, 1, 12))], [])], []),
('Module', [('If', (1, 0, 1, 9), ('Name', (1, 3, 1, 4), 'v', ('Load',)), [('Pass', (1, 5, 1, 9))], [])], []),
('Module', [('If', (1, 0, 4, 6), ('Name', (1, 3, 1, 4), 'a', ('Load',)), [('Pass', (2, 2, 2, 6))], [('If', (3, 0, 4, 6), ('Name', (3, 5, 3, 6), 'b', ('Load',)), [('Pass', (4, 2, 4, 6))], [])])], []),
('Module', [('If', (1, 0, 6, 6), ('Name', (1, 3, 1, 4), 'a', ('Load',)), [('Pass', (2, 2, 2, 6))], [('If', (3, 0, 6, 6), ('Name', (3, 5, 3, 6), 'b', ('Load',)), [('Pass', (4, 2, 4, 6))], [('Pass', (6, 2, 6, 6))])])], []),
('Module', [('With', (1, 0, 1, 17), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',)))], [('Pass', (1, 13, 1, 17))], None)], []),
('Module', [('With', (1, 0, 1, 25), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',))), ('withitem', ('Name', (1, 13, 1, 14), 'z', ('Load',)), ('Name', (1, 18, 1, 19), 'q', ('Store',)))], [('Pass', (1, 21, 1, 25))], None)], []),
('Module', [('Raise', (1, 0, 1, 25), ('Call', (1, 6, 1, 25), ('Name', (1, 6, 1, 15), 'Exception', ('Load',)), [('Constant', (1, 16, 1, 24), 'string', None)], []), None)], []),
('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [('ExceptHandler', (3, 0, 4, 6), ('Name', (3, 7, 3, 16), 'Exception', ('Load',)), None, [('Pass', (4, 2, 4, 6))])], [], [])], []),
('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [], [], [('Pass', (4, 2, 4, 6))])], []),
('Module', [('Assert', (1, 0, 1, 8), ('Name', (1, 7, 1, 8), 'v', ('Load',)), None)], []),
('Module', [('Import', (1, 0, 1, 10), [('alias', (1, 7, 1, 10), 'sys', None)])], []),
('Module', [('ImportFrom', (1, 0, 1, 17), 'sys', [('alias', (1, 16, 1, 17), 'v', None)], 0)], []),
('Module', [('Global', (1, 0, 1, 8), ['v'])], []),
('Module', [('Expr', (1, 0, 1, 1), ('Constant', (1, 0, 1, 1), 1, None))], []),
('Module', [('Pass', (1, 0, 1, 4))], []),
('Module', [('For', (1, 0, 1, 16), ('Name', (1, 4, 1, 5), 'v', ('Store',)), ('Name', (1, 9, 1, 10), 'v', ('Load',)), [('Break', (1, 11, 1, 16))], [], None)], []),
('Module', [('For', (1, 0, 1, 19), ('Name', (1, 4, 1, 5), 'v', ('Store',)), ('Name', (1, 9, 1, 10), 'v', ('Load',)), [('Continue', (1, 11, 1, 19))], [], None)], []),
('Module', [('For', (1, 0, 1, 18), ('Tuple', (1, 4, 1, 7), [('Name', (1, 4, 1, 5), 'a', ('Store',)), ('Name', (1, 6, 1, 7), 'b', ('Store',))], ('Store',)), ('Name', (1, 11, 1, 12), 'c', ('Load',)), [('Pass', (1, 14, 1, 18))], [], None)], []),
('Module', [('For', (1, 0, 1, 20), ('Tuple', (1, 4, 1, 9), [('Name', (1, 5, 1, 6), 'a', ('Store',)), ('Name', (1, 7, 1, 8), 'b', ('Store',))], ('Store',)), ('Name', (1, 13, 1, 14), 'c', ('Load',)), [('Pass', (1, 16, 1, 20))], [], None)], []),
('Module', [('For', (1, 0, 1, 20), ('List', (1, 4, 1, 9), [('Name', (1, 5, 1, 6), 'a', ('Store',)), ('Name', (1, 7, 1, 8), 'b', ('Store',))], ('Store',)), ('Name', (1, 13, 1, 14), 'c', ('Load',)), [('Pass', (1, 16, 1, 20))], [], None)], []),
('Module', [('Expr', (1, 0, 11, 5), ('GeneratorExp', (1, 0, 11, 5), ('Tuple', (2, 4, 6, 5), [('Name', (3, 4, 3, 6), 'Aa', ('Load',)), ('Name', (5, 7, 5, 9), 'Bb', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (8, 4, 10, 6), [('Name', (8, 4, 8, 6), 'Aa', ('Store',)), ('Name', (10, 4, 10, 6), 'Bb', ('Store',))], ('Store',)), ('Name', (10, 10, 10, 12), 'Cc', ('Load',)), [], 0)]))], []),
('Module', [('Expr', (1, 0, 1, 34), ('DictComp', (1, 0, 1, 34), ('Name', (1, 1, 1, 2), 'a', ('Load',)), ('Name', (1, 5, 1, 6), 'b', ('Load',)), [('comprehension', ('Name', (1, 11, 1, 12), 'w', ('Store',)), ('Name', (1, 16, 1, 17), 'x', ('Load',)), [], 0), ('comprehension', ('Name', (1, 22, 1, 23), 'm', ('Store',)), ('Name', (1, 27, 1, 28), 'p', ('Load',)), [('Name', (1, 32, 1, 33), 'g', ('Load',))], 0)]))], []),
('Module', [('Expr', (1, 0, 1, 20), ('DictComp', (1, 0, 1, 20), ('Name', (1, 1, 1, 2), 'a', ('Load',)), ('Name', (1, 5, 1, 6), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'v', ('Store',)), ('Name', (1, 13, 1, 14), 'w', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'x', ('Load',)), [], 0)]))], []),
('Module', [('Expr', (1, 0, 1, 19), ('SetComp', (1, 0, 1, 19), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 12, 1, 13), 'x', ('Load',)), [('Name', (1, 17, 1, 18), 'g', ('Load',))], 0)]))], []),
('Module', [('Expr', (1, 0, 1, 16), ('SetComp', (1, 0, 1, 16), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7, 1, 10), [('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 9, 1, 10), 'm', ('Store',))], ('Store',)), ('Name', (1, 14, 1, 15), 'x', ('Load',)), [], 0)]))], []),
('Module', [('AsyncFunctionDef', (1, 0, 3, 18), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 17), ('Constant', (2, 1, 2, 17), 'async function', None)), ('Expr', (3, 1, 3, 18), ('Await', (3, 1, 3, 18), ('Call', (3, 7, 3, 18), ('Name', (3, 7, 3, 16), 'something', ('Load',)), [], [])))], [], None, None)], []),
('Module', [('AsyncFunctionDef', (1, 0, 3, 8), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1, 3, 8), ('Name', (2, 11, 2, 12), 'e', ('Store',)), ('Name', (2, 16, 2, 17), 'i', ('Load',)), [('Expr', (2, 19, 2, 20), ('Constant', (2, 19, 2, 20), 1, None))], [('Expr', (3, 7, 3, 8), ('Constant', (3, 7, 3, 8), 2, None))], None)], [], None, None)], []),
('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1, 2, 21), [('withitem', ('Name', (2, 12, 2, 13), 'a', ('Load',)), ('Name', (2, 17, 2, 18), 'b', ('Store',)))], [('Expr', (2, 20, 2, 21), ('Constant', (2, 20, 2, 21), 1, None))], None)], [], None, None)], []),
('Module', [('Expr', (1, 0, 1, 14), ('Dict', (1, 0, 1, 14), [None, ('Constant', (1, 10, 1, 11), 2, None)], [('Dict', (1, 3, 1, 8), [('Constant', (1, 4, 1, 5), 1, None)], [('Constant', (1, 6, 1, 7), 2, None)]), ('Constant', (1, 12, 1, 13), 3, None)]))], []),
('Module', [('Expr', (1, 0, 1, 12), ('Set', (1, 0, 1, 12), [('Starred', (1, 1, 1, 8), ('Set', (1, 2, 1, 8), [('Constant', (1, 3, 1, 4), 1, None), ('Constant', (1, 6, 1, 7), 2, None)]), ('Load',)), ('Constant', (1, 10, 1, 11), 3, None)]))], []),
('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 21), ('ListComp', (2, 1, 2, 21), ('Name', (2, 2, 2, 3), 'i', ('Load',)), [('comprehension', ('Name', (2, 14, 2, 15), 'b', ('Store',)), ('Name', (2, 19, 2, 20), 'c', ('Load',)), [], 1)]))], [], None, None)], []),
('Module', [('FunctionDef', (4, 0, 4, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
('Module', [('AsyncFunctionDef', (4, 0, 4, 19), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 15, 4, 19))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
('Module', [('ClassDef', (4, 0, 4, 13), 'C', [], [], [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])])], []),
('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Call', (1, 1, 1, 19), ('Name', (1, 1, 1, 5), 'deco', ('Load',)), [('GeneratorExp', (1, 5, 1, 19), ('Name', (1, 6, 1, 7), 'a', ('Load',)), [('comprehension', ('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 17, 1, 18), 'b', ('Load',)), [], 0)])], [])], None, None)], []),
('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Attribute', (1, 1, 1, 6), ('Attribute', (1, 1, 1, 4), ('Name', (1, 1, 1, 2), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',))], None, None)], []),
('Module', [('Expr', (1, 0, 1, 8), ('NamedExpr', (1, 1, 1, 7), ('Name', (1, 1, 1, 2), 'a', ('Store',)), ('Constant', (1, 6, 1, 7), 1, None)))], []),
('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 26), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None), ('arg', (1, 15, 1, 16), 'd', None, None), ('arg', (1, 18, 1, 19), 'e', None, None)], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], None, []), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 39), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], ('arg', (1, 26, 1, 32), 'kwargs', None, None), []), [('Pass', (1, 35, 1, 39))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 20), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None)]), [('Pass', (1, 16, 1, 20))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None), ('arg', (1, 19, 1, 20), 'c', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None), ('Constant', (1, 21, 1, 22), 4, None)]), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 32), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 28, 1, 32))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 30), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 26, 1, 30))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 42), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], ('arg', (1, 29, 1, 35), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 38, 1, 42))], [], None, None)], []),
('Module', [('FunctionDef', (1, 0, 1, 40), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], ('arg', (1, 27, 1, 33), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 36, 1, 40))], [], None, None)], []),
]
single_results = [
('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Constant', (1, 0), 1, None), ('Add',), ('Constant', (1, 2), 2, None)))]),
('Interactive', [('Expr', (1, 0, 1, 3), ('BinOp', (1, 0, 1, 3), ('Constant', (1, 0, 1, 1), 1, None), ('Add',), ('Constant', (1, 2, 1, 3), 2, None)))]),
]
eval_results = [
('Expression', ('Constant', (1, 0), None, None)),
('Expression', ('BoolOp', (1, 0), ('And',), [('Name', (1, 0), 'a', ('Load',)), ('Name', (1, 6), 'b', ('Load',))])),
('Expression', ('BinOp', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Add',), ('Name', (1, 4), 'b', ('Load',)))),
('Expression', ('UnaryOp', (1, 0), ('Not',), ('Name', (1, 4), 'v', ('Load',)))),
('Expression', ('Lambda', (1, 0), ('arguments', [], [], None, [], [], None, []), ('Constant', (1, 7), None, None))),
('Expression', ('Dict', (1, 0), [('Constant', (1, 2), 1, None)], [('Constant', (1, 4), 2, None)])),
('Expression', ('Dict', (1, 0), [], [])),
('Expression', ('Set', (1, 0), [('Constant', (1, 1), None, None)])),
('Expression', ('Dict', (1, 0), [('Constant', (2, 6), 1, None)], [('Constant', (4, 10), 2, None)])),
('Expression', ('ListComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))], 0)])),
('Expression', ('GeneratorExp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))], 0)])),
('Expression', ('ListComp', (1, 0), ('Tuple', (1, 1), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)])),
('Expression', ('ListComp', (1, 0), ('Tuple', (1, 1), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)])),
('Expression', ('ListComp', (1, 0), ('Tuple', (1, 1), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('List', (1, 11), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)])),
('Expression', ('SetComp', (1, 0), ('Tuple', (1, 1), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)])),
('Expression', ('SetComp', (1, 0), ('Tuple', (1, 1), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)])),
('Expression', ('SetComp', (1, 0), ('Tuple', (1, 1), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('List', (1, 11), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)])),
('Expression', ('GeneratorExp', (1, 0), ('Tuple', (1, 1), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)])),
('Expression', ('GeneratorExp', (1, 0), ('Tuple', (1, 1), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)])),
('Expression', ('GeneratorExp', (1, 0), ('Tuple', (1, 1), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('List', (1, 11), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)])),
('Expression', ('Compare', (1, 0), ('Constant', (1, 0), 1, None), [('Lt',), ('Lt',)], [('Constant', (1, 4), 2, None), ('Constant', (1, 8), 3, None)])),
('Expression', ('Call', (1, 0), ('Name', (1, 0), 'f', ('Load',)), [('Constant', (1, 2), 1, None), ('Constant', (1, 4), 2, None), ('Starred', (1, 10), ('Name', (1, 11), 'd', ('Load',)), ('Load',))], [('keyword', 'c', ('Constant', (1, 8), 3, None)), ('keyword', None, ('Name', (1, 15), 'e', ('Load',)))])),
('Expression', ('Call', (1, 0), ('Name', (1, 0), 'f', ('Load',)), [('Starred', (1, 2), ('List', (1, 3), [('Constant', (1, 4), 0, None), ('Constant', (1, 7), 1, None)], ('Load',)), ('Load',))], [])),
('Expression', ('Call', (1, 0), ('Name', (1, 0), 'f', ('Load',)), [('GeneratorExp', (1, 1), ('Name', (1, 2), 'a', ('Load',)), [('comprehension', ('Name', (1, 8), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Load',)), [], 0)])], [])),
('Expression', ('Constant', (1, 0), 10, None)),
('Expression', ('Constant', (1, 0), 'string', None)),
('Expression', ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',))),
('Expression', ('Subscript', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Slice', ('Name', (1, 2), 'b', ('Load',)), ('Name', (1, 4), 'c', ('Load',)), None), ('Load',))),
('Expression', ('Name', (1, 0), 'v', ('Load',))),
('Expression', ('List', (1, 0), [('Constant', (1, 1), 1, None), ('Constant', (1, 3), 2, None), ('Constant', (1, 5), 3, None)], ('Load',))),
('Expression', ('List', (1, 0), [], ('Load',))),
('Expression', ('Tuple', (1, 0), [('Constant', (1, 0), 1, None), ('Constant', (1, 2), 2, None), ('Constant', (1, 4), 3, None)], ('Load',))),
('Expression', ('Tuple', (1, 0), [('Constant', (1, 1), 1, None), ('Constant', (1, 3), 2, None), ('Constant', (1, 5), 3, None)], ('Load',))),
('Expression', ('Tuple', (1, 0), [], ('Load',))),
('Expression', ('Call', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',)), 'd', ('Load',)), [('Subscript', (1, 8), ('Attribute', (1, 8), ('Name', (1, 8), 'a', ('Load',)), 'b', ('Load',)), ('Slice', ('Constant', (1, 12), 1, None), ('Constant', (1, 14), 2, None), None), ('Load',))], [])),
('Expression', ('Constant', (1, 0, 1, 4), None, None)),
('Expression', ('BoolOp', (1, 0, 1, 7), ('And',), [('Name', (1, 0, 1, 1), 'a', ('Load',)), ('Name', (1, 6, 1, 7), 'b', ('Load',))])),
('Expression', ('BinOp', (1, 0, 1, 5), ('Name', (1, 0, 1, 1), 'a', ('Load',)), ('Add',), ('Name', (1, 4, 1, 5), 'b', ('Load',)))),
('Expression', ('UnaryOp', (1, 0, 1, 5), ('Not',), ('Name', (1, 4, 1, 5), 'v', ('Load',)))),
('Expression', ('Lambda', (1, 0, 1, 11), ('arguments', [], [], None, [], [], None, []), ('Constant', (1, 7, 1, 11), None, None))),
('Expression', ('Dict', (1, 0, 1, 7), [('Constant', (1, 2, 1, 3), 1, None)], [('Constant', (1, 4, 1, 5), 2, None)])),
('Expression', ('Dict', (1, 0, 1, 2), [], [])),
('Expression', ('Set', (1, 0, 1, 7), [('Constant', (1, 1, 1, 5), None, None)])),
('Expression', ('Dict', (1, 0, 5, 6), [('Constant', (2, 6, 2, 7), 1, None)], [('Constant', (4, 10, 4, 11), 2, None)])),
('Expression', ('ListComp', (1, 0, 1, 19), ('Name', (1, 1, 1, 2), 'a', ('Load',)), [('comprehension', ('Name', (1, 7, 1, 8), 'b', ('Store',)), ('Name', (1, 12, 1, 13), 'c', ('Load',)), [('Name', (1, 17, 1, 18), 'd', ('Load',))], 0)])),
('Expression', ('GeneratorExp', (1, 0, 1, 19), ('Name', (1, 1, 1, 2), 'a', ('Load',)), [('comprehension', ('Name', (1, 7, 1, 8), 'b', ('Store',)), ('Name', (1, 12, 1, 13), 'c', ('Load',)), [('Name', (1, 17, 1, 18), 'd', ('Load',))], 0)])),
('Expression', ('ListComp', (1, 0, 1, 20), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'a', ('Store',)), ('Name', (1, 13, 1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'c', ('Load',)), [], 0)])),
('Expression', ('ListComp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])),
('Expression', ('ListComp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('List', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])),
('Expression', ('SetComp', (1, 0, 1, 20), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'a', ('Store',)), ('Name', (1, 13, 1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'c', ('Load',)), [], 0)])),
('Expression', ('SetComp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])),
('Expression', ('SetComp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('List', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])),
('Expression', ('GeneratorExp', (1, 0, 1, 20), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'a', ('Store',)), ('Name', (1, 13, 1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'c', ('Load',)), [], 0)])),
('Expression', ('GeneratorExp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])),
('Expression', ('GeneratorExp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('List', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])),
('Expression', ('Compare', (1, 0, 1, 9), ('Constant', (1, 0, 1, 1), 1, None), [('Lt',), ('Lt',)], [('Constant', (1, 4, 1, 5), 2, None), ('Constant', (1, 8, 1, 9), 3, None)])),
('Expression', ('Call', (1, 0, 1, 17), ('Name', (1, 0, 1, 1), 'f', ('Load',)), [('Constant', (1, 2, 1, 3), 1, None), ('Constant', (1, 4, 1, 5), 2, None), ('Starred', (1, 10, 1, 12), ('Name', (1, 11, 1, 12), 'd', ('Load',)), ('Load',))], [('keyword', (1, 6, 1, 9), 'c', ('Constant', (1, 8, 1, 9), 3, None)), ('keyword', (1, 13, 1, 16), None, ('Name', (1, 15, 1, 16), 'e', ('Load',)))])),
('Expression', ('Call', (1, 0, 1, 10), ('Name', (1, 0, 1, 1), 'f', ('Load',)), [('Starred', (1, 2, 1, 9), ('List', (1, 3, 1, 9), [('Constant', (1, 4, 1, 5), 0, None), ('Constant', (1, 7, 1, 8), 1, None)], ('Load',)), ('Load',))], [])),
('Expression', ('Call', (1, 0, 1, 15), ('Name', (1, 0, 1, 1), 'f', ('Load',)), [('GeneratorExp', (1, 1, 1, 15), ('Name', (1, 2, 1, 3), 'a', ('Load',)), [('comprehension', ('Name', (1, 8, 1, 9), 'a', ('Store',)), ('Name', (1, 13, 1, 14), 'b', ('Load',)), [], 0)])], [])),
('Expression', ('Constant', (1, 0, 1, 2), 10, None)),
('Expression', ('Constant', (1, 0, 1, 8), 'string', None)),
('Expression', ('Attribute', (1, 0, 1, 3), ('Name', (1, 0, 1, 1), 'a', ('Load',)), 'b', ('Load',))),
('Expression', ('Subscript', (1, 0, 1, 6), ('Name', (1, 0, 1, 1), 'a', ('Load',)), ('Slice', (1, 2, 1, 5), ('Name', (1, 2, 1, 3), 'b', ('Load',)), ('Name', (1, 4, 1, 5), 'c', ('Load',)), None), ('Load',))),
('Expression', ('Name', (1, 0, 1, 1), 'v', ('Load',))),
('Expression', ('List', (1, 0, 1, 7), [('Constant', (1, 1, 1, 2), 1, None), ('Constant', (1, 3, 1, 4), 2, None), ('Constant', (1, 5, 1, 6), 3, None)], ('Load',))),
('Expression', ('List', (1, 0, 1, 2), [], ('Load',))),
('Expression', ('Tuple', (1, 0, 1, 5), [('Constant', (1, 0, 1, 1), 1, None), ('Constant', (1, 2, 1, 3), 2, None), ('Constant', (1, 4, 1, 5), 3, None)], ('Load',))),
('Expression', ('Tuple', (1, 0, 1, 7), [('Constant', (1, 1, 1, 2), 1, None), ('Constant', (1, 3, 1, 4), 2, None), ('Constant', (1, 5, 1, 6), 3, None)], ('Load',))),
('Expression', ('Tuple', (1, 0, 1, 2), [], ('Load',))),
('Expression', ('Call', (1, 0, 1, 17), ('Attribute', (1, 0, 1, 7), ('Attribute', (1, 0, 1, 5), ('Attribute', (1, 0, 1, 3), ('Name', (1, 0, 1, 1), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',)), 'd', ('Load',)), [('Subscript', (1, 8, 1, 16), ('Attribute', (1, 8, 1, 11), ('Name', (1, 8, 1, 9), 'a', ('Load',)), 'b', ('Load',)), ('Slice', (1, 12, 1, 15), ('Constant', (1, 12, 1, 13), 1, None), ('Constant', (1, 14, 1, 15), 2, None), None), ('Load',))], [])),
]
main()

View File

@@ -38,53 +38,62 @@ class FutureTest(unittest.TestCase):
with import_helper.CleanImport('test_future3'):
from test import test_future3
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_badfuture3(self):
with self.assertRaises(SyntaxError) as cm:
from test import badsyntax_future3
self.check_syntax_error(cm.exception, "badsyntax_future3", 3)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_badfuture4(self):
with self.assertRaises(SyntaxError) as cm:
from test import badsyntax_future4
self.check_syntax_error(cm.exception, "badsyntax_future4", 3)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_badfuture5(self):
with self.assertRaises(SyntaxError) as cm:
from test import badsyntax_future5
self.check_syntax_error(cm.exception, "badsyntax_future5", 4)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_badfuture6(self):
with self.assertRaises(SyntaxError) as cm:
from test import badsyntax_future6
self.check_syntax_error(cm.exception, "badsyntax_future6", 3)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_badfuture7(self):
with self.assertRaises(SyntaxError) as cm:
from test import badsyntax_future7
self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 53)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_badfuture8(self):
with self.assertRaises(SyntaxError) as cm:
from test import badsyntax_future8
self.check_syntax_error(cm.exception, "badsyntax_future8", 3)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_badfuture9(self):
with self.assertRaises(SyntaxError) as cm:
from test import badsyntax_future9
self.check_syntax_error(cm.exception, "badsyntax_future9", 3)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_badfuture10(self):
with self.assertRaises(SyntaxError) as cm:
from test import badsyntax_future10
self.check_syntax_error(cm.exception, "badsyntax_future10", 3)
k, v = None, None # 'dictionary changed size during iteration'
for k, v in locals().items():
if k.startswith("test_badfuture"):
# XXX RUSTPYTHON TODO: fix SyntaxError
locals()[k] = unittest.expectedFailure(v)
del k, v
def test_ensure_flags_dont_clash(self):
# bpo-39562: test that future flags and compiler flags doesn't clash
@@ -141,8 +150,12 @@ class AnnotationsFutureTestCase(unittest.TestCase):
...
async def g2(arg: {ann}) -> None:
...
class H:
var: {ann}
object.attr: {ann}
var: {ann}
var2: {ann} = None
object.attr: {ann}
"""
)
@@ -174,6 +187,14 @@ class AnnotationsFutureTestCase(unittest.TestCase):
self.assertEqual(actual, expected)
def _exec_future(self, code):
scope = {}
exec(
"from __future__ import annotations\n"
+ code, {}, scope
)
return scope
def test_annotations(self):
eq = self.assertAnnotationEqual
eq('...')
@@ -313,10 +334,6 @@ class AnnotationsFutureTestCase(unittest.TestCase):
eq("f'{x}'")
eq("f'{x!r}'")
eq("f'{x!a}'")
eq('(yield from outside_of_generator)')
eq('(yield)')
eq('(yield a + b)')
eq('await some.complicated[0].call(with_args=True or 1 is not 1)')
eq('[x for x in (a if b else c)]')
eq('[x for x in a if (b if c else d)]')
eq('f(x for x in a)')
@@ -324,13 +341,11 @@ class AnnotationsFutureTestCase(unittest.TestCase):
eq('f((x for x in a), 2)')
eq('(((a)))', 'a')
eq('(((a, b)))', '(a, b)')
eq("(x := 10)")
eq("f'{(x := 10):=10}'")
eq("1 + 2 + 3")
def test_fstring_debug_annotations(self):
# f-strings with '=' don't round trip very well, so set the expected
# result explicitely.
# result explicitly.
self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'")
self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'")
@@ -350,6 +365,66 @@ class AnnotationsFutureTestCase(unittest.TestCase):
self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})")
self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))")
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_annotation_with_complex_target(self):
with self.assertRaises(SyntaxError):
exec(
"from __future__ import annotations\n"
"object.__debug__: int"
)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_annotations_symbol_table_pass(self):
namespace = self._exec_future(dedent("""
from __future__ import annotations
def foo():
outer = 1
def bar():
inner: outer = 1
return bar
"""))
foo = namespace.pop("foo")
self.assertIsNone(foo().__closure__)
self.assertEqual(foo.__code__.co_cellvars, ())
self.assertEqual(foo().__code__.co_freevars, ())
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_annotations_forbidden(self):
with self.assertRaises(SyntaxError):
self._exec_future("test: (yield)")
with self.assertRaises(SyntaxError):
self._exec_future("test.test: (yield a + b)")
with self.assertRaises(SyntaxError):
self._exec_future("test[something]: (yield from x)")
with self.assertRaises(SyntaxError):
self._exec_future("def func(test: (yield from outside_of_generator)): pass")
with self.assertRaises(SyntaxError):
self._exec_future("def test() -> (await y): pass")
with self.assertRaises(SyntaxError):
self._exec_future("async def test() -> something((a := b)): pass")
with self.assertRaises(SyntaxError):
self._exec_future("test: await some.complicated[0].call(with_args=True or 1 is not 1)")
with self.assertRaises(SyntaxError):
self._exec_future("test: f'{(x := 10):=10}'")
with self.assertRaises(SyntaxError):
self._exec_future(dedent("""\
def foo():
def bar(arg: (yield)): pass
"""))
if __name__ == "__main__":
unittest.main()

View File

@@ -13,3 +13,4 @@ unparse = ["rustpython-common"]
[dependencies]
num-bigint = "0.4.3"
rustpython-common = { path = "../common", optional = true }
rustpython-bytecode = { path = "../bytecode"}

View File

@@ -26,7 +26,7 @@ module Python
| Assign(expr* targets, expr value, string? type_comment)
| AugAssign(expr target, operator op, expr value)
-- 'simple' indicates that we annotate simple name without parens
| AnnAssign(expr target, expr annotation, expr? value, bool simple)
| AnnAssign(expr target, expr annotation, expr? value, int simple)
-- use 'orelse' because else is a keyword in target languages
| For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
@@ -36,12 +36,14 @@ module Python
| With(withitem* items, stmt* body, string? type_comment)
| AsyncWith(withitem* items, stmt* body, string? type_comment)
| Match(expr subject, match_case* cases)
| Raise(expr? exc, expr? cause)
| Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
| Assert(expr test, expr? msg)
| Import(alias* names)
| ImportFrom(identifier? module, alias* names, int level)
| ImportFrom(identifier? module, alias* names, int? level)
| Global(identifier* names)
| Nonlocal(identifier* names)
@@ -58,7 +60,7 @@ module Python
| UnaryOp(unaryop op, expr operand)
| Lambda(arguments args, expr body)
| IfExp(expr test, expr body, expr orelse)
| Dict(expr?* keys, expr* values)
| Dict(expr* keys, expr* values)
| Set(expr* elts)
| ListComp(expr elt, comprehension* generators)
| SetComp(expr elt, comprehension* generators)
@@ -72,7 +74,7 @@ module Python
-- x < 4 < 3 and (x < 4) < 3
| Compare(expr left, cmpop* ops, expr* comparators)
| Call(expr func, expr* args, keyword* keywords)
| FormattedValue(expr value, conversion_flag? conversion, expr? format_spec)
| FormattedValue(expr value, int conversion, expr? format_spec)
| JoinedStr(expr* values)
| Constant(constant value, string? kind)
@@ -101,13 +103,13 @@ module Python
cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
comprehension = (expr target, expr iter, expr* ifs, bool is_async)
comprehension = (expr target, expr iter, expr* ifs, int is_async)
excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,
expr?* kw_defaults, arg? kwarg, expr* defaults)
expr* kw_defaults, arg? kwarg, expr* defaults)
arg = (identifier arg, expr? annotation, string? type_comment)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
@@ -118,8 +120,25 @@ module Python
-- import name with optional 'as' alias.
alias = (identifier name, identifier? asname)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
withitem = (expr context_expr, expr? optional_vars)
match_case = (pattern pattern, expr? guard, stmt* body)
pattern = MatchValue(expr value)
| MatchSingleton(constant value)
| MatchSequence(pattern* patterns)
| MatchMapping(expr* keys, pattern* patterns, identifier? rest)
| MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)
| MatchStar(identifier? name)
-- The optional "rest" MatchMapping parameter handles capturing extra mapping keys
| MatchAs(pattern? pattern, identifier? name)
| MatchOr(pattern* patterns)
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
type_ignore = TypeIgnore(int lineno, string tag)
}

View File

@@ -33,7 +33,7 @@ __all__ = [
# See the EBNF at the top of the file to understand the logical connection
# between the various node types.
builtin_types = {'identifier', 'string', 'int', 'constant', 'bool', 'conversion_flag'}
builtin_types = {'identifier', 'string', 'int', 'constant'}
class AST:
def __repr__(self):
@@ -204,7 +204,7 @@ def check(mod):
def parse(filename):
"""Parse ASDL from the given file and return a Module node describing it."""
with open(filename) as f:
with open(filename, encoding="utf-8") as f:
parser = ASDLParser()
return parser.parse(f.read())
@@ -340,12 +340,12 @@ class ASDLParser:
def _parse_optional_field_quantifier(self):
is_seq, is_opt = False, False
if self.cur_token.kind == TokenKind.Question:
is_opt = True
self._advance()
if self.cur_token.kind == TokenKind.Asterisk:
is_seq = True
self._advance()
elif self.cur_token.kind == TokenKind.Question:
is_opt = True
self._advance()
return is_seq, is_opt
def _advance(self):

View File

@@ -14,12 +14,10 @@ TABSIZE = 4
AUTOGEN_MESSAGE = "// File automatically generated by {}.\n"
builtin_type_mapping = {
'identifier': 'Ident',
'string': 'String',
'int': 'usize',
'constant': 'Constant',
'bool': 'bool',
'conversion_flag': 'ConversionFlag',
"identifier": "Ident",
"string": "String",
"int": "usize",
"constant": "Constant",
}
assert builtin_type_mapping.keys() == asdl.builtin_types
@@ -31,8 +29,10 @@ def get_rust_type(name):
"""
if name in asdl.builtin_types:
return builtin_type_mapping[name]
else:
elif name.islower():
return "".join(part.capitalize() for part in name.split("_"))
else:
return name
def is_simple(sum):
@@ -252,13 +252,23 @@ class StructVisitor(TypeInfoEmitVisitor):
if product.attributes:
dataname = rustname + "Data"
self.emit_attrs(depth)
self.emit(f"pub struct {dataname}{generics} {{", depth)
has_expr = any(f.type != "identifier" for f in product.fields)
if has_expr:
datadef = f"{dataname}{generics}"
else:
datadef = dataname
self.emit(f"pub struct {datadef} {{", depth)
for f in product.fields:
self.visit(f, typeinfo, "pub ", depth + 1)
self.emit("}", depth)
if product.attributes:
# attributes should just be location info
self.emit(f"pub type {rustname}<U = ()> = Located<{dataname}{generics_applied}, U>;", depth);
if not has_expr:
generics_applied = ""
self.emit(
f"pub type {rustname}<U = ()> = Located<{dataname}{generics_applied}, U>;",
depth,
)
self.emit("", depth)
@@ -422,8 +432,11 @@ class ClassDefVisitor(EmitVisitor):
self.gen_classdef(name, product.fields, product.attributes, depth)
def gen_classdef(self, name, fields, attrs, depth, base="AstNode"):
structname = "Node" + name
self.emit(f'#[pyclass(module = "_ast", name = {json.dumps(name)}, base = {json.dumps(base)})]', depth)
structname = "Node" + get_rust_type(name)
self.emit(
f'#[pyclass(module = "_ast", name = {json.dumps(name)}, base = {json.dumps(base)})]',
depth,
)
self.emit(f"struct {structname};", depth)
self.emit("#[pyclass(flags(HAS_DICT, BASETYPE))]", depth)
self.emit(f"impl {structname} {{", depth)
@@ -467,7 +480,10 @@ class ExtendModuleVisitor(EmitVisitor):
self.visit(type.value, type.name, depth)
def visitSum(self, sum, name, depth):
self.emit(f"{json.dumps(name)} => NodeKind{get_rust_type(name)}::make_class(&vm.ctx),", depth)
rust_name = get_rust_type(name)
self.emit(
f"{json.dumps(name)} => NodeKind{rust_name}::make_class(&vm.ctx),", depth
)
for cons in sum.types:
self.visit(cons, depth)
@@ -478,7 +494,8 @@ class ExtendModuleVisitor(EmitVisitor):
self.gen_extension(name, depth)
def gen_extension(self, name, depth):
self.emit(f"{json.dumps(name)} => Node{name}::make_class(&vm.ctx),", depth)
rust_name = get_rust_type(name)
self.emit(f"{json.dumps(name)} => Node{rust_name}::make_class(&vm.ctx),", depth)
class TraitImplVisitor(EmitVisitor):
@@ -494,7 +511,6 @@ class TraitImplVisitor(EmitVisitor):
if sum.attributes:
enumname += "Kind"
self.emit(f"impl NamedNode for ast::{enumname} {{", depth)
self.emit(f"const NAME: &'static str = {json.dumps(name)};", depth + 1)
self.emit("}", depth)
@@ -546,8 +562,11 @@ class TraitImplVisitor(EmitVisitor):
self.emit("}", depth)
def make_node(self, variant, fields, depth):
lines = []
self.emit(f"let _node = AstNode.into_ref_with_type(_vm, Node{variant}::static_type().to_owned()).unwrap();", depth)
rust_variant = get_rust_type(variant)
self.emit(
f"let _node = AstNode.into_ref_with_type(_vm, Node{rust_variant}::static_type().to_owned()).unwrap();",
depth,
)
if fields:
self.emit("let _dict = _node.as_object().dict().unwrap();", depth)
for f in fields:

180
ast/src/ast_gen.rs generated
View File

@@ -87,7 +87,7 @@ pub enum StmtKind<U = ()> {
target: Box<Expr<U>>,
annotation: Box<Expr<U>>,
value: Option<Box<Expr<U>>>,
simple: bool,
simple: usize,
},
For {
target: Box<Expr<U>>,
@@ -123,6 +123,10 @@ pub enum StmtKind<U = ()> {
body: Vec<Stmt<U>>,
type_comment: Option<String>,
},
Match {
subject: Box<Expr<U>>,
cases: Vec<MatchCase<U>>,
},
Raise {
exc: Option<Box<Expr<U>>>,
cause: Option<Box<Expr<U>>>,
@@ -138,12 +142,12 @@ pub enum StmtKind<U = ()> {
msg: Option<Box<Expr<U>>>,
},
Import {
names: Vec<Alias>,
names: Vec<Alias<U>>,
},
ImportFrom {
module: Option<Ident>,
names: Vec<Alias>,
level: usize,
names: Vec<Alias<U>>,
level: Option<usize>,
},
Global {
names: Vec<Ident>,
@@ -189,7 +193,7 @@ pub enum ExprKind<U = ()> {
orelse: Box<Expr<U>>,
},
Dict {
keys: Vec<Option<Box<Expr<U>>>>,
keys: Vec<Expr<U>>,
values: Vec<Expr<U>>,
},
Set {
@@ -233,7 +237,7 @@ pub enum ExprKind<U = ()> {
},
FormattedValue {
value: Box<Expr<U>>,
conversion: Option<ConversionFlag>,
conversion: usize,
format_spec: Option<Box<Expr<U>>>,
},
JoinedStr {
@@ -334,7 +338,7 @@ pub struct Comprehension<U = ()> {
pub target: Box<Expr<U>>,
pub iter: Box<Expr<U>>,
pub ifs: Vec<Expr<U>>,
pub is_async: bool,
pub is_async: usize,
}
#[derive(Debug, PartialEq)]
@@ -353,7 +357,7 @@ pub struct Arguments<U = ()> {
pub args: Vec<Arg<U>>,
pub vararg: Option<Box<Arg<U>>>,
pub kwonlyargs: Vec<Arg<U>>,
pub kw_defaults: Vec<Option<Box<Expr<U>>>>,
pub kw_defaults: Vec<Expr<U>>,
pub kwarg: Option<Box<Arg<U>>>,
pub defaults: Vec<Expr<U>>,
}
@@ -374,10 +378,11 @@ pub struct KeywordData<U = ()> {
pub type Keyword<U = ()> = Located<KeywordData<U>, U>;
#[derive(Debug, PartialEq)]
pub struct Alias {
pub struct AliasData {
pub name: Ident,
pub asname: Option<Ident>,
}
pub type Alias<U = ()> = Located<AliasData, U>;
#[derive(Debug, PartialEq)]
pub struct Withitem<U = ()> {
@@ -385,6 +390,48 @@ pub struct Withitem<U = ()> {
pub optional_vars: Option<Box<Expr<U>>>,
}
#[derive(Debug, PartialEq)]
pub struct MatchCase<U = ()> {
pub pattern: Box<Pattern<U>>,
pub guard: Option<Box<Expr<U>>>,
pub body: Vec<Stmt<U>>,
}
#[derive(Debug, PartialEq)]
pub enum PatternKind<U = ()> {
MatchValue {
value: Box<Expr<U>>,
},
MatchSingleton {
value: Constant,
},
MatchSequence {
patterns: Vec<Pattern<U>>,
},
MatchMapping {
keys: Vec<Expr<U>>,
patterns: Vec<Pattern<U>>,
rest: Option<Ident>,
},
MatchClass {
cls: Box<Expr<U>>,
patterns: Vec<Pattern<U>>,
kwd_attrs: Vec<Ident>,
kwd_patterns: Vec<Pattern<U>>,
},
MatchStar {
name: Option<Ident>,
},
MatchAs {
pattern: Option<Box<Pattern<U>>>,
name: Option<Ident>,
},
MatchOr {
patterns: Vec<Pattern<U>>,
},
}
pub type Pattern<U = ()> = Located<PatternKind<U>, U>;
#[derive(Debug, PartialEq)]
pub enum TypeIgnore {
TypeIgnore { lineno: usize, tag: String },
@@ -449,7 +496,7 @@ pub mod fold {
) -> Result<Keyword<Self::TargetU>, Self::Error> {
fold_keyword(self, node)
}
fn fold_alias(&mut self, node: Alias) -> Result<Alias, Self::Error> {
fn fold_alias(&mut self, node: Alias<U>) -> Result<Alias<Self::TargetU>, Self::Error> {
fold_alias(self, node)
}
fn fold_withitem(
@@ -458,6 +505,18 @@ pub mod fold {
) -> Result<Withitem<Self::TargetU>, Self::Error> {
fold_withitem(self, node)
}
fn fold_match_case(
&mut self,
node: MatchCase<U>,
) -> Result<MatchCase<Self::TargetU>, Self::Error> {
fold_match_case(self, node)
}
fn fold_pattern(
&mut self,
node: Pattern<U>,
) -> Result<Pattern<Self::TargetU>, Self::Error> {
fold_pattern(self, node)
}
fn fold_type_ignore(&mut self, node: TypeIgnore) -> Result<TypeIgnore, Self::Error> {
fold_type_ignore(self, node)
}
@@ -645,6 +704,10 @@ pub mod fold {
body: Foldable::fold(body, folder)?,
type_comment: Foldable::fold(type_comment, folder)?,
}),
StmtKind::Match { subject, cases } => Ok(StmtKind::Match {
subject: Foldable::fold(subject, folder)?,
cases: Foldable::fold(cases, folder)?,
}),
StmtKind::Raise { exc, cause } => Ok(StmtKind::Raise {
exc: Foldable::fold(exc, folder)?,
cause: Foldable::fold(cause, folder)?,
@@ -1074,8 +1137,8 @@ pub mod fold {
})
})
}
impl<T, U> Foldable<T, U> for Alias {
type Mapped = Alias;
impl<T, U> Foldable<T, U> for Alias<T> {
type Mapped = Alias<U>;
fn fold<F: Fold<T, TargetU = U> + ?Sized>(
self,
folder: &mut F,
@@ -1085,12 +1148,14 @@ pub mod fold {
}
pub fn fold_alias<U, F: Fold<U> + ?Sized>(
#[allow(unused)] folder: &mut F,
node: Alias,
) -> Result<Alias, F::Error> {
let Alias { name, asname } = node;
Ok(Alias {
name: Foldable::fold(name, folder)?,
asname: Foldable::fold(asname, folder)?,
node: Alias<U>,
) -> Result<Alias<F::TargetU>, F::Error> {
fold_located(folder, node, |folder, node| {
let AliasData { name, asname } = node;
Ok(AliasData {
name: Foldable::fold(name, folder)?,
asname: Foldable::fold(asname, folder)?,
})
})
}
impl<T, U> Foldable<T, U> for Withitem<T> {
@@ -1115,6 +1180,85 @@ pub mod fold {
optional_vars: Foldable::fold(optional_vars, folder)?,
})
}
impl<T, U> Foldable<T, U> for MatchCase<T> {
type Mapped = MatchCase<U>;
fn fold<F: Fold<T, TargetU = U> + ?Sized>(
self,
folder: &mut F,
) -> Result<Self::Mapped, F::Error> {
folder.fold_match_case(self)
}
}
pub fn fold_match_case<U, F: Fold<U> + ?Sized>(
#[allow(unused)] folder: &mut F,
node: MatchCase<U>,
) -> Result<MatchCase<F::TargetU>, F::Error> {
let MatchCase {
pattern,
guard,
body,
} = node;
Ok(MatchCase {
pattern: Foldable::fold(pattern, folder)?,
guard: Foldable::fold(guard, folder)?,
body: Foldable::fold(body, folder)?,
})
}
impl<T, U> Foldable<T, U> for Pattern<T> {
type Mapped = Pattern<U>;
fn fold<F: Fold<T, TargetU = U> + ?Sized>(
self,
folder: &mut F,
) -> Result<Self::Mapped, F::Error> {
folder.fold_pattern(self)
}
}
pub fn fold_pattern<U, F: Fold<U> + ?Sized>(
#[allow(unused)] folder: &mut F,
node: Pattern<U>,
) -> Result<Pattern<F::TargetU>, F::Error> {
fold_located(folder, node, |folder, node| match node {
PatternKind::MatchValue { value } => Ok(PatternKind::MatchValue {
value: Foldable::fold(value, folder)?,
}),
PatternKind::MatchSingleton { value } => Ok(PatternKind::MatchSingleton {
value: Foldable::fold(value, folder)?,
}),
PatternKind::MatchSequence { patterns } => Ok(PatternKind::MatchSequence {
patterns: Foldable::fold(patterns, folder)?,
}),
PatternKind::MatchMapping {
keys,
patterns,
rest,
} => Ok(PatternKind::MatchMapping {
keys: Foldable::fold(keys, folder)?,
patterns: Foldable::fold(patterns, folder)?,
rest: Foldable::fold(rest, folder)?,
}),
PatternKind::MatchClass {
cls,
patterns,
kwd_attrs,
kwd_patterns,
} => Ok(PatternKind::MatchClass {
cls: Foldable::fold(cls, folder)?,
patterns: Foldable::fold(patterns, folder)?,
kwd_attrs: Foldable::fold(kwd_attrs, folder)?,
kwd_patterns: Foldable::fold(kwd_patterns, folder)?,
}),
PatternKind::MatchStar { name } => Ok(PatternKind::MatchStar {
name: Foldable::fold(name, folder)?,
}),
PatternKind::MatchAs { pattern, name } => Ok(PatternKind::MatchAs {
pattern: Foldable::fold(pattern, folder)?,
name: Foldable::fold(name, folder)?,
}),
PatternKind::MatchOr { patterns } => Ok(PatternKind::MatchOr {
patterns: Foldable::fold(patterns, folder)?,
}),
})
}
impl<T, U> Foldable<T, U> for TypeIgnore {
type Mapped = TypeIgnore;
fn fold<F: Fold<T, TargetU = U> + ?Sized>(

View File

@@ -1,4 +1,5 @@
use num_bigint::BigInt;
pub use rustpython_bytecode::ConversionFlag;
#[derive(Debug, PartialEq)]
pub enum Constant {
@@ -70,29 +71,6 @@ impl std::fmt::Display for Constant {
}
}
/// Transforms a value prior to formatting it.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum ConversionFlag {
/// Converts by calling `str(<value>)`.
Str = b's',
/// Converts by calling `ascii(<value>)`.
Ascii = b'a',
/// Converts by calling `repr(<value>)`.
Repr = b'r',
}
impl ConversionFlag {
pub fn try_from_byte(b: u8) -> Option<Self> {
match b {
b's' => Some(Self::Str),
b'a' => Some(Self::Ascii),
b'r' => Some(Self::Repr),
_ => None,
}
}
}
#[cfg(feature = "constant-optimization")]
#[non_exhaustive]
#[derive(Default)]

View File

@@ -63,10 +63,4 @@ macro_rules! simple_fold {
};
}
simple_fold!(
usize,
String,
bool,
constant::Constant,
constant::ConversionFlag
);
simple_fold!(usize, String, bool, constant::Constant);

View File

@@ -149,13 +149,14 @@ impl<'a> Unparser<'a> {
ExprKind::Dict { keys, values } => {
self.p("{")?;
let mut first = true;
for (k, v) in keys.iter().zip(values) {
let (packed, unpacked) = values.split_at(keys.len());
for (k, v) in keys.iter().zip(packed) {
self.p_delim(&mut first, ", ")?;
if let Some(k) = k {
write!(self, "{}: {}", **k, *v)?;
} else {
write!(self, "**{}", *v)?;
}
write!(self, "{}: {}", *k, *v)?;
}
for d in unpacked {
self.p_delim(&mut first, ", ")?;
write!(self, "**{}", *d)?;
}
self.p("}")?;
}
@@ -397,7 +398,7 @@ impl<'a> Unparser<'a> {
self.unparse_arg(kwarg)?;
if let Some(default) = i
.checked_sub(defaults_start)
.and_then(|i| args.kw_defaults[i].as_deref())
.and_then(|i| args.kw_defaults.get(i))
{
write!(self, "={}", default)?;
}
@@ -419,7 +420,7 @@ impl<'a> Unparser<'a> {
fn unparse_comp<U>(&mut self, generators: &[Comprehension<U>]) -> fmt::Result {
for comp in generators {
self.p(if comp.is_async {
self.p(if comp.is_async > 0 {
" async for "
} else {
" for "
@@ -445,7 +446,7 @@ impl<'a> Unparser<'a> {
fn unparse_formatted<U>(
&mut self,
val: &Expr<U>,
conversion: Option<ConversionFlag>,
conversion: usize,
spec: Option<&Expr<U>>,
) -> fmt::Result {
let buffered = to_string_fmt(|f| Unparser::new(f).unparse_expr(val, precedence::TEST + 1));
@@ -459,13 +460,11 @@ impl<'a> Unparser<'a> {
self.p(&buffered)?;
drop(buffered);
if let Some(conv) = conversion {
let flag = match conv {
ConversionFlag::Str => "!s",
ConversionFlag::Ascii => "!a",
ConversionFlag::Repr => "!r",
};
self.p(flag)?;
if conversion != ConversionFlag::None as usize {
self.p("!")?;
let buf = &[conversion as u8];
let c = std::str::from_utf8(buf).unwrap();
self.p(c)?;
}
if let Some(spec) = spec {

View File

@@ -159,15 +159,30 @@ impl fmt::Display for Label {
/// Transforms a value prior to formatting it.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[repr(u8)]
pub enum ConversionFlag {
/// No conversion
None,
None = 0,
/// Converts by calling `str(<value>)`.
Str,
Str = b's',
/// Converts by calling `ascii(<value>)`.
Ascii,
Ascii = b'a',
/// Converts by calling `repr(<value>)`.
Repr,
Repr = b'r',
}
impl TryFrom<usize> for ConversionFlag {
type Error = usize;
fn try_from(b: usize) -> Result<Self, Self::Error> {
let b = b.try_into().map_err(|_| b)?;
match b {
0 => Ok(Self::None),
b's' => Ok(Self::Str),
b'a' => Ok(Self::Ascii),
b'r' => Ok(Self::Repr),
b => Err(b as usize),
}
}
}
/// The kind of Raise that occurred.
@@ -357,6 +372,7 @@ pub enum Instruction {
for_call: bool,
size: u32,
},
DictUpdate,
BuildSlice {
/// whether build a slice with a third step argument
step: bool,
@@ -1040,6 +1056,7 @@ impl Instruction {
let nargs = if *unpack { *size } else { *size * 2 };
-(nargs as i32) + 1
}
DictUpdate => -1,
BuildSlice { step } => -2 - (*step as i32) + 1,
ListAppend { .. } | SetAdd { .. } => -1,
MapAdd { .. } => -2,
@@ -1202,6 +1219,7 @@ impl Instruction {
unpack,
for_call,
} => w!(BuildMap, size, unpack, for_call),
DictUpdate => w!(DictUpdate),
BuildSlice { step } => w!(BuildSlice, step),
ListAppend { i } => w!(ListAppend, i),
SetAdd { i } => w!(SetAdd, i),

View File

@@ -552,6 +552,7 @@ impl Compiler {
Import { names } => {
// import a, b, c as d
for name in names {
let name = &name.node;
self.emit_constant(ConstantData::Integer {
value: num_traits::Zero::zero(),
});
@@ -574,7 +575,7 @@ impl Compiler {
module,
names,
} => {
let import_star = names.iter().any(|n| n.name == "*");
let import_star = names.iter().any(|n| n.node.name == "*");
let from_list = if import_star {
if self.ctx.in_func() {
@@ -588,7 +589,7 @@ impl Compiler {
names
.iter()
.map(|n| ConstantData::Str {
value: n.name.to_owned(),
value: n.node.name.to_owned(),
})
.collect()
};
@@ -597,7 +598,7 @@ impl Compiler {
// from .... import (*fromlist)
self.emit_constant(ConstantData::Integer {
value: (*level).into(),
value: (*level).unwrap_or(0).into(),
});
self.emit_constant(ConstantData::Tuple {
elements: from_list,
@@ -615,6 +616,7 @@ impl Compiler {
// from mod import a, b as c
for name in names {
let name = &name.node;
let idx = self.name(&name.name);
// import symbol from module:
self.emit(Instruction::ImportFrom { idx });
@@ -678,6 +680,7 @@ impl Compiler {
orelse,
..
} => self.compile_for(target, iter, body, orelse, true)?,
Match { subject, cases } => self.compile_match(subject, cases)?,
Raise { exc, cause } => {
let kind = match exc {
Some(value) => {
@@ -879,19 +882,19 @@ impl Compiler {
});
}
let mut num_kw_only_defaults = 0;
for (kw, default) in args.kwonlyargs.iter().zip(&args.kw_defaults) {
if let Some(default) = default {
if !args.kw_defaults.is_empty() {
let required_kw_count = args.kwonlyargs.len().saturating_sub(args.kw_defaults.len());
for (kw, default) in args.kwonlyargs[required_kw_count..]
.iter()
.zip(&args.kw_defaults)
{
self.emit_constant(ConstantData::Str {
value: kw.node.arg.clone(),
});
self.compile_expression(default)?;
num_kw_only_defaults += 1;
}
}
if num_kw_only_defaults > 0 {
self.emit(Instruction::BuildMap {
size: num_kw_only_defaults,
size: args.kw_defaults.len() as u32,
unpack: false,
for_call: false,
});
@@ -901,7 +904,7 @@ impl Compiler {
if have_defaults {
funcflags |= bytecode::MakeFunctionFlags::DEFAULTS;
}
if num_kw_only_defaults > 0 {
if !args.kw_defaults.is_empty() {
funcflags |= bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS;
}
@@ -1519,6 +1522,16 @@ impl Compiler {
Ok(())
}
fn compile_match(
&mut self,
subject: &ast::Expr,
cases: &[ast::MatchCase],
) -> CompileResult<()> {
eprintln!("match subject: {subject:?}");
eprintln!("match cases: {cases:?}");
Err(self.error(CompileErrorType::NotImplementedYet))
}
fn compile_chained_comparison(
&mut self,
left: &ast::Expr,
@@ -1928,51 +1941,26 @@ impl Compiler {
Ok(())
}
fn compile_dict(
&mut self,
keys: &[Option<Box<ast::Expr>>],
values: &[ast::Expr],
) -> CompileResult<()> {
fn compile_dict(&mut self, keys: &[ast::Expr], values: &[ast::Expr]) -> CompileResult<()> {
let mut size = 0;
let mut has_unpacking = false;
for (is_unpacking, subpairs) in &keys.iter().zip(values).group_by(|e| e.0.is_none()) {
if is_unpacking {
for (_, value) in subpairs {
self.compile_expression(value)?;
size += 1;
}
has_unpacking = true;
} else {
let mut subsize = 0;
for (key, value) in subpairs {
if let Some(key) = key {
self.compile_expression(key)?;
self.compile_expression(value)?;
subsize += 1;
}
}
self.emit(Instruction::BuildMap {
size: subsize,
unpack: false,
for_call: false,
});
size += 1;
}
let (packed_values, unpacked_values) = values.split_at(keys.len());
for (key, value) in keys.iter().zip(packed_values) {
self.compile_expression(key)?;
self.compile_expression(value)?;
size += 1;
}
if size == 0 {
self.emit(Instruction::BuildMap {
size,
unpack: false,
for_call: false,
});
}
if size > 1 || has_unpacking {
self.emit(Instruction::BuildMap {
size,
unpack: true,
for_call: false,
});
self.emit(Instruction::BuildMap {
size,
unpack: false,
for_call: false,
});
for value in unpacked_values {
self.compile_expression(value)?;
self.emit(Instruction::DictUpdate);
}
Ok(())
}
@@ -2120,7 +2108,7 @@ impl Compiler {
};
self.compile_expression(value)?;
self.emit(Instruction::FormatValue {
conversion: compile_conversion_flag(*conversion),
conversion: (*conversion).try_into().expect("invalid conversion flag"),
});
}
Name { id, .. } => self.load_name(id)?,
@@ -2475,7 +2463,7 @@ impl Compiler {
let mut loop_labels = vec![];
for generator in generators {
if generator.is_async {
if generator.is_async > 0 {
unimplemented!("async for comprehensions");
}
@@ -2564,7 +2552,7 @@ impl Compiler {
return Err(self.error(CompileErrorType::InvalidFuturePlacement));
}
for feature in features {
match &*feature.name {
match &*feature.node.name {
// Python 3 features; we've already implemented them by default
"nested_scopes" | "generators" | "division" | "absolute_import"
| "with_statement" | "print_function" | "unicode_literals" => {}
@@ -2688,17 +2676,6 @@ fn compile_location(location: &ast::Location) -> bytecode::Location {
bytecode::Location::new(location.row(), location.column())
}
fn compile_conversion_flag(
conversion_flag: Option<ast::ConversionFlag>,
) -> bytecode::ConversionFlag {
match conversion_flag {
None => bytecode::ConversionFlag::None,
Some(ast::ConversionFlag::Ascii) => bytecode::ConversionFlag::Ascii,
Some(ast::ConversionFlag::Repr) => bytecode::ConversionFlag::Repr,
Some(ast::ConversionFlag::Str) => bytecode::ConversionFlag::Str,
}
}
fn compile_constant(value: &ast::Constant) -> ConstantData {
match value {
ast::Constant::None => ConstantData::None,

View File

@@ -37,6 +37,7 @@ pub enum CompileErrorType {
TooManyStarUnpack,
EmptyWithItems,
EmptyWithBody,
NotImplementedYet, // RustPython marker for unimplemented features
}
impl fmt::Display for CompileErrorType {
@@ -78,6 +79,9 @@ impl fmt::Display for CompileErrorType {
CompileErrorType::EmptyWithBody => {
write!(f, "empty body on With")
}
CompileErrorType::NotImplementedYet => {
write!(f, "RustPython does not implement this feature yet")
}
}
}
}

View File

@@ -639,7 +639,7 @@ impl SymbolTableBuilder {
if let ImportFrom { module, names, .. } = &statement.node {
if module.as_deref() == Some("__future__") {
for feature in names {
if feature.name == "annotations" {
if feature.node.name == "annotations" {
self.future_annotations = true;
}
}
@@ -739,13 +739,13 @@ impl SymbolTableBuilder {
}
Import { names } | ImportFrom { names, .. } => {
for name in names {
if let Some(alias) = &name.asname {
if let Some(alias) = &name.node.asname {
// `import mymodule as myalias`
self.register_name(alias, SymbolUsage::Imported, location)?;
} else {
// `import module`
self.register_name(
name.name.split('.').next().unwrap(),
name.node.name.split('.').next().unwrap(),
SymbolUsage::Imported,
location,
)?;
@@ -782,7 +782,7 @@ impl SymbolTableBuilder {
} => {
// https://github.com/python/cpython/blob/main/Python/symtable.c#L1233
match &target.node {
ast::ExprKind::Name { id, .. } if *simple => {
ast::ExprKind::Name { id, .. } if *simple > 0 => {
self.register_name(id, SymbolUsage::AnnotationAssigned, location)?;
}
_ => {
@@ -823,6 +823,15 @@ impl SymbolTableBuilder {
self.scan_statements(orelse)?;
self.scan_statements(finalbody)?;
}
Match {
subject: _,
cases: _,
} => {
return Err(SymbolTableError {
error: "match expression is not implemented yet".to_owned(),
location: Location::default(),
});
}
Raise { exc, cause } => {
if let Some(expression) = exc {
self.scan_expression(expression, ExpressionContext::Load)?;
@@ -875,12 +884,13 @@ impl SymbolTableBuilder {
self.scan_expression(value, ExpressionContext::Load)?;
}
Dict { keys, values } => {
for (key, value) in keys.iter().zip(values) {
if let Some(key) = key {
self.scan_expression(key, context)?;
} else {
// dict unpacking marker
}
let (packed, unpacked) = values.split_at(keys.len());
for (key, value) in keys.iter().zip(packed) {
self.scan_expression(key, context)?;
self.scan_expression(value, context)?;
}
for value in unpacked {
// dict unpacking marker
self.scan_expression(value, context)?;
}
}
@@ -1094,7 +1104,7 @@ impl SymbolTableBuilder {
) -> SymbolTableResult {
// Evaluate eventual default parameters:
self.scan_expressions(&args.defaults, ExpressionContext::Load)?;
for expression in args.kw_defaults.iter().flatten() {
for expression in args.kw_defaults.iter() {
self.scan_expression(expression, ExpressionContext::Load)?;
}

View File

@@ -285,7 +285,7 @@ y = {'b': 2, 'c': 2, 'd': 2}
z = {'c': 3, 'd': 3, 'e': 3}
w = {1: 1, **x, 2: 2, **y, 3: 3, **z, 4: 4}
assert w == {1: 1, 'a': 1, 'b': 2, 'c': 3, 2: 2, 'd': 3, 3: 3, 'e': 3, 4: 4}
assert w == {1: 1, 'a': 1, 'b': 2, 'c': 3, 2: 2, 'd': 3, 3: 3, 'e': 3, 4: 4} # not in cpython test suite
assert str({True: True, 1.0: 1.0}) == str({True: 1.0})

View File

@@ -131,7 +131,7 @@ ExpressionStatement: ast::Stmt = {
target: Box::new(target),
annotation: Box::new(annotation),
value: rhs.map(Box::new),
simple,
simple: if simple { 1 } else { 0 },
},
}
},
@@ -253,12 +253,12 @@ ImportStatement: ast::Stmt = {
},
};
ImportFromLocation: (usize, Option<String>) = {
ImportFromLocation: (Option<usize>, Option<String>) = {
<dots: ImportDots*> <name:DottedName> => {
(dots.iter().sum(), Some(name))
(Some(dots.iter().sum()), Some(name))
},
<dots: ImportDots+> => {
(dots.iter().sum(), None)
(Some(dots.iter().sum()), None)
},
};
@@ -268,19 +268,19 @@ ImportDots: usize = {
};
ImportAsNames: Vec<ast::Alias> = {
<i:OneOrMore<ImportAsAlias<Identifier>>> => i,
"(" <i:OneOrMore<ImportAsAlias<Identifier>>> ","? ")" => i,
"*" => {
<location:@L> <i:OneOrMore<ImportAsAlias<Identifier>>> => i,
<location:@L> "(" <i:OneOrMore<ImportAsAlias<Identifier>>> ","? ")" => i,
<location:@L> "*" => {
// Star import all
vec![ast::Alias { name: "*".to_string(), asname: None }]
vec![ast::Alias::new(location, ast::AliasData { name: "*".to_string(), asname: None })]
},
};
#[inline]
ImportAsAlias<I>: ast::Alias = {
<name:I> <a: ("as" Identifier)?> => ast::Alias { name, asname: a.map(|a| a.1) },
};
<location:@L> <name:I> <a: ("as" Identifier)?> => ast::Alias::new(location, ast::AliasData { name, asname: a.map(|a| a.1) }),
}
// A name like abc or abc.def.ghi
DottedName: String = {
@@ -590,20 +590,26 @@ TypedParameter: ast::Arg = {
// Use inline here to make sure the "," is not creating an ambiguity.
// TODO: figure out another grammar that makes this inline no longer required.
#[inline]
ParameterListStarArgs<ArgType>: (Option<Box<ast::Arg>>, Vec<ast::Arg>, Vec<Option<Box<ast::Expr>>>, Option<Box<ast::Arg>>) = {
ParameterListStarArgs<ArgType>: (Option<Box<ast::Arg>>, Vec<ast::Arg>, Vec<ast::Expr>, Option<Box<ast::Arg>>) = {
"*" <va:ArgType?> <kw:("," ParameterDef<ArgType>)*> <kwarg:("," KwargParameter<ArgType>)?> => {
// Extract keyword arguments:
let mut kwonlyargs = vec![];
let mut kw_defaults = vec![];
let mut kwonlyargs = Vec::new();
let mut kw_defaults = Vec::new();
let mut kwargs = Vec::new();
for (name, value) in kw.into_iter().map(|x| x.1) {
kwonlyargs.push(name);
kw_defaults.push(value.map(Box::new));
if let Some(value) = value {
kwonlyargs.push(name);
kw_defaults.push(value);
} else {
kwargs.push(name);
}
}
kwargs.extend(kwonlyargs.into_iter());
let kwarg = kwarg.map(|n| n.1).flatten();
let va = va.map(Box::new);
(va, kwonlyargs, kw_defaults, kwarg)
(va, kwargs, kw_defaults, kwarg)
}
};
@@ -1039,7 +1045,42 @@ Atom: ast::Expr = {
}.into())
},
<location:@L> "{" <e:DictLiteralValues?> "}" => {
let (keys, values) = e.unwrap_or_default();
let pairs = e.unwrap_or_default();
let (keys, values) = match pairs.iter().position(|(k,_)| k.is_none()) {
Some(unpack_idx) => {
let mut pairs = pairs;
let (keys, mut values): (_, Vec<_>) = pairs.drain(..unpack_idx).map(|(k, v)| (*k.unwrap(), v)).unzip();
fn build_map(items: &mut Vec<(ast::Expr, ast::Expr)>) -> ast::Expr {
let location = items[0].0.location;
let (keys, values) = items.drain(..).unzip();
ast::Expr {
location,
custom: (),
node: ast::ExprKind::Dict { keys, values }
}
}
let mut items = Vec::new();
for (key, value) in pairs.into_iter() {
if let Some(key) = key {
items.push((*key, value));
continue;
}
if !items.is_empty() {
values.push(build_map(&mut items));
}
values.push(value);
}
if !items.is_empty() {
values.push(build_map(&mut items));
}
(keys, values)
},
None => pairs.into_iter().map(|(k, v)| (*k.unwrap(), v)).unzip()
};
ast::Expr {
location,
custom: (),
@@ -1079,8 +1120,8 @@ ListLiteralValues: Vec<ast::Expr> = {
<e:OneOrMore<TestOrStarNamedExpr>> ","? => e,
};
DictLiteralValues: (Vec<Option<Box<ast::Expr>>>, Vec<ast::Expr>) = {
<elements:OneOrMore<DictElement>> ","? => elements.into_iter().unzip(),
DictLiteralValues: Vec<(Option<Box<ast::Expr>>, ast::Expr)> = {
<elements:OneOrMore<DictElement>> ","? => elements,
};
DictEntry: (ast::Expr, ast::Expr) = {
@@ -1151,7 +1192,7 @@ SingleForComprehension: ast::Comprehension = {
target: Box::new(target),
iter: Box::new(iter),
ifs,
is_async
is_async: if is_async { 1 } else { 0 },
}
}
};

View File

@@ -160,11 +160,7 @@ impl From<LalrpopError<Location, Tok, LexicalError>> for ParseError {
LalrpopError::UnrecognizedToken { token, expected } => {
// Hacky, but it's how CPython does it. See PyParser_AddToken,
// in particular "Only one possible expected token" comment.
let expected = if expected.len() == 1 {
Some(expected[0].clone())
} else {
None
};
let expected = (expected.len() == 1).then(|| expected[0].clone());
ParseError {
error: ParseErrorType::UnrecognizedToken(token.1, expected),
location: token.0,

View File

@@ -30,7 +30,7 @@ impl<'a> FStringParser<'a> {
let mut expression = String::new();
let mut spec = None;
let mut delims = Vec::new();
let mut conversion = None;
let mut conversion = ConversionFlag::None;
let mut pred_expression_text = String::new();
let mut trailing_seq = String::new();
@@ -63,7 +63,7 @@ impl<'a> FStringParser<'a> {
return Err(EmptyExpression);
}
conversion = Some(match self.chars.next() {
conversion = match self.chars.next() {
Some('s') => ConversionFlag::Str,
Some('a') => ConversionFlag::Ascii,
Some('r') => ConversionFlag::Repr,
@@ -73,7 +73,7 @@ impl<'a> FStringParser<'a> {
None => {
return Err(ExpectedRbrace);
}
});
};
if let Some(&peek) = self.chars.peek() {
if peek != '}' && peek != ':' {
@@ -115,7 +115,7 @@ impl<'a> FStringParser<'a> {
)
.parse()?,
),
conversion: None,
conversion: ConversionFlag::None as _,
format_spec: None,
}),
);
@@ -187,7 +187,7 @@ impl<'a> FStringParser<'a> {
parse_fstring_expr(&expression)
.map_err(|e| InvalidExpression(Box::new(e.error)))?,
),
conversion,
conversion: conversion as _,
format_spec: spec,
})]
} else {
@@ -205,7 +205,7 @@ impl<'a> FStringParser<'a> {
parse_fstring_expr(&expression)
.map_err(|e| InvalidExpression(Box::new(e.error)))?,
),
conversion,
conversion: conversion as _,
format_spec: spec,
}),
]

View File

@@ -54,7 +54,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},

View File

@@ -67,7 +67,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},
@@ -128,7 +128,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},

View File

@@ -1,7 +1,6 @@
---
source: parser/src/fstring.rs
expression: parse_ast
---
Located {
location: Location {
@@ -55,7 +54,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: Some(
Located {
location: Location {

View File

@@ -28,7 +28,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},
@@ -50,7 +50,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},

View File

@@ -1,7 +1,6 @@
---
source: parser/src/fstring.rs
expression: parse_ast
---
Located {
location: Location {
@@ -58,7 +57,7 @@ Located {
],
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},

View File

@@ -1,7 +1,6 @@
---
source: parser/src/fstring.rs
expression: parse_ast
---
Located {
location: Location {
@@ -29,7 +28,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: Some(
Located {
location: Location {
@@ -85,14 +84,14 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},
],
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},

View File

@@ -1,7 +1,6 @@
---
source: parser/src/fstring.rs
expression: parse_ast
---
Located {
location: Location {
@@ -58,7 +57,7 @@ Located {
],
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},

View File

@@ -1,7 +1,6 @@
---
source: parser/src/fstring.rs
expression: parse_ast
---
Located {
location: Location {
@@ -29,7 +28,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: Some(
Located {
location: Location {

View File

@@ -54,7 +54,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},

View File

@@ -54,7 +54,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},

View File

@@ -1,7 +1,6 @@
---
source: parser/src/fstring.rs
expression: parse_ast
---
Located {
location: Location {
@@ -28,7 +27,7 @@ Located {
value: None,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},

View File

@@ -56,7 +56,7 @@ Located {
},
},
ifs: [],
is_async: false,
is_async: 0,
},
],
},

View File

@@ -1,7 +1,6 @@
---
source: parser/src/parser.rs
expression: parse_ast
---
Located {
location: Location {
@@ -69,7 +68,7 @@ Located {
},
},
ifs: [],
is_async: false,
is_async: 0,
},
Comprehension {
target: Located {
@@ -172,7 +171,7 @@ Located {
},
},
],
is_async: false,
is_async: 0,
},
],
},

View File

@@ -45,7 +45,7 @@ Located {
},
},
ifs: [],
is_async: false,
is_async: 0,
},
],
},

View File

@@ -71,15 +71,12 @@ impl PyDict {
}
// Used in update and ior.
fn merge_object(
dict: &DictContentType,
other: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()> {
pub(crate) fn merge_object(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
let other = match other.downcast_exact(vm) {
Ok(dict_other) => return Self::merge_dict(dict, dict_other, vm),
Ok(dict_other) => return self.merge_dict(dict_other, vm),
Err(other) => other,
};
let dict = &self.entries;
if let Some(keys) = vm.get_method(other.clone(), vm.ctx.intern_str("keys")) {
let keys = vm.invoke(&keys?, ())?.get_iter(vm)?;
while let PyIterReturn::Return(key) = keys.next(vm)? {
@@ -108,11 +105,8 @@ impl PyDict {
Ok(())
}
fn merge_dict(
dict: &DictContentType,
dict_other: PyDictRef,
vm: &VirtualMachine,
) -> PyResult<()> {
fn merge_dict(&self, dict_other: PyDictRef, vm: &VirtualMachine) -> PyResult<()> {
let dict = &self.entries;
let dict_size = &dict_other.size();
for (key, value) in &dict_other {
dict.insert(vm, &*key, value)?;
@@ -363,7 +357,7 @@ impl PyDict {
vm: &VirtualMachine,
) -> PyResult<()> {
if let OptionalArg::Present(dict_obj) = dict_obj {
Self::merge_object(&self.entries, dict_obj, vm)?;
self.merge_object(dict_obj, vm)?;
}
for (key, value) in kwargs.into_iter() {
self.entries.insert(vm, &key, value)?;
@@ -373,7 +367,7 @@ impl PyDict {
#[pymethod(magic)]
fn ior(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
PyDict::merge_object(&zelf.entries, other, vm)?;
zelf.merge_object(other, vm)?;
Ok(zelf)
}
@@ -382,7 +376,7 @@ impl PyDict {
let dicted: Result<PyDictRef, _> = other.downcast();
if let Ok(other) = dicted {
let other_cp = other.copy();
PyDict::merge_dict(&other_cp.entries, zelf, vm)?;
other_cp.merge_dict(zelf, vm)?;
return Ok(other_cp.into_pyobject(vm));
}
Ok(vm.ctx.not_implemented())
@@ -393,7 +387,7 @@ impl PyDict {
let dicted: Result<PyDictRef, _> = other.downcast();
if let Ok(other) = dicted {
let self_cp = self.copy();
PyDict::merge_dict(&self_cp.entries, other, vm)?;
self_cp.merge_dict(other, vm)?;
return Ok(self_cp.into_pyobject(vm));
}
Ok(vm.ctx.not_implemented())

View File

@@ -677,6 +677,15 @@ impl ExecutingFrame<'_> {
unpack,
for_call,
} => self.execute_build_map(vm, *size, *unpack, *for_call),
bytecode::Instruction::DictUpdate => {
let other = self.pop_value();
let dict = self
.last_value_ref()
.downcast_ref::<PyDict>()
.expect("exact dict expected");
dict.merge_object(other, vm)?;
Ok(None)
}
bytecode::Instruction::BuildSlice { step } => self.execute_build_slice(vm, *step),
bytecode::Instruction::ListAppend { i } => {
let item = self.pop_value();

View File

@@ -239,7 +239,11 @@ impl Node for ast::Constant {
}
builtins::singletons::PyNone => ast::Constant::None,
builtins::slice::PyEllipsis => ast::Constant::Ellipsis,
_ => return Err(vm.new_type_error("unsupported type for constant".to_owned())),
obj =>
return Err(vm.new_type_error(format!(
"invalid type in Constant: type '{}'",
obj.class().name()
))),
});
Ok(constant)
}
@@ -252,8 +256,8 @@ impl Node for ast::ConversionFlag {
fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult<Self> {
i32::try_from_object(vm, object)?
.to_u8()
.and_then(ast::ConversionFlag::try_from_byte)
.to_usize()
.and_then(|f| f.try_into().ok())
.ok_or_else(|| vm.new_value_error("invalid conversion flag".to_owned()))
}
}

596
vm/src/stdlib/ast/gen.rs generated
View File

@@ -458,6 +458,32 @@ impl NodeAsyncWith {
);
}
}
#[pyclass(module = "_ast", name = "Match", base = "NodeKindStmt")]
struct NodeMatch;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl NodeMatch {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
identifier!(ctx, _fields),
ctx.new_list(vec![
ctx.new_str(ascii!("subject")).into(),
ctx.new_str(ascii!("cases")).into(),
])
.into(),
);
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_list(vec![
ctx.new_str(ascii!("lineno")).into(),
ctx.new_str(ascii!("col_offset")).into(),
ctx.new_str(ascii!("end_lineno")).into(),
ctx.new_str(ascii!("end_col_offset")).into(),
])
.into(),
);
}
}
#[pyclass(module = "_ast", name = "Raise", base = "NodeKindStmt")]
struct NodeRaise;
#[pyclass(flags(HAS_DICT, BASETYPE))]
@@ -1755,9 +1781,9 @@ impl NodeNotIn {
}
}
#[pyclass(module = "_ast", name = "comprehension", base = "AstNode")]
struct Nodecomprehension;
struct NodeComprehension;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl Nodecomprehension {
impl NodeComprehension {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
@@ -1809,9 +1835,9 @@ impl NodeExceptHandler {
}
}
#[pyclass(module = "_ast", name = "arguments", base = "AstNode")]
struct Nodearguments;
struct NodeArguments;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl Nodearguments {
impl NodeArguments {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
@@ -1831,9 +1857,9 @@ impl Nodearguments {
}
}
#[pyclass(module = "_ast", name = "arg", base = "AstNode")]
struct Nodearg;
struct NodeArg;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl Nodearg {
impl NodeArg {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
@@ -1858,9 +1884,9 @@ impl Nodearg {
}
}
#[pyclass(module = "_ast", name = "keyword", base = "AstNode")]
struct Nodekeyword;
struct NodeKeyword;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl Nodekeyword {
impl NodeKeyword {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
@@ -1884,9 +1910,9 @@ impl Nodekeyword {
}
}
#[pyclass(module = "_ast", name = "alias", base = "AstNode")]
struct Nodealias;
struct NodeAlias;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl Nodealias {
impl NodeAlias {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
@@ -1897,13 +1923,22 @@ impl Nodealias {
])
.into(),
);
class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into());
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_list(vec![
ctx.new_str(ascii!("lineno")).into(),
ctx.new_str(ascii!("col_offset")).into(),
ctx.new_str(ascii!("end_lineno")).into(),
ctx.new_str(ascii!("end_col_offset")).into(),
])
.into(),
);
}
}
#[pyclass(module = "_ast", name = "withitem", base = "AstNode")]
struct Nodewithitem;
struct NodeWithitem;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl Nodewithitem {
impl NodeWithitem {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
@@ -1917,6 +1952,224 @@ impl Nodewithitem {
class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into());
}
}
#[pyclass(module = "_ast", name = "match_case", base = "AstNode")]
struct NodeMatchCase;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl NodeMatchCase {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
identifier!(ctx, _fields),
ctx.new_list(vec![
ctx.new_str(ascii!("pattern")).into(),
ctx.new_str(ascii!("guard")).into(),
ctx.new_str(ascii!("body")).into(),
])
.into(),
);
class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into());
}
}
#[pyclass(module = "_ast", name = "pattern", base = "AstNode")]
struct NodeKindPattern;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl NodeKindPattern {}
#[pyclass(module = "_ast", name = "MatchValue", base = "NodeKindPattern")]
struct NodeMatchValue;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl NodeMatchValue {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
identifier!(ctx, _fields),
ctx.new_list(vec![ctx.new_str(ascii!("value")).into()])
.into(),
);
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_list(vec![
ctx.new_str(ascii!("lineno")).into(),
ctx.new_str(ascii!("col_offset")).into(),
ctx.new_str(ascii!("end_lineno")).into(),
ctx.new_str(ascii!("end_col_offset")).into(),
])
.into(),
);
}
}
#[pyclass(module = "_ast", name = "MatchSingleton", base = "NodeKindPattern")]
struct NodeMatchSingleton;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl NodeMatchSingleton {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
identifier!(ctx, _fields),
ctx.new_list(vec![ctx.new_str(ascii!("value")).into()])
.into(),
);
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_list(vec![
ctx.new_str(ascii!("lineno")).into(),
ctx.new_str(ascii!("col_offset")).into(),
ctx.new_str(ascii!("end_lineno")).into(),
ctx.new_str(ascii!("end_col_offset")).into(),
])
.into(),
);
}
}
#[pyclass(module = "_ast", name = "MatchSequence", base = "NodeKindPattern")]
struct NodeMatchSequence;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl NodeMatchSequence {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
identifier!(ctx, _fields),
ctx.new_list(vec![ctx.new_str(ascii!("patterns")).into()])
.into(),
);
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_list(vec![
ctx.new_str(ascii!("lineno")).into(),
ctx.new_str(ascii!("col_offset")).into(),
ctx.new_str(ascii!("end_lineno")).into(),
ctx.new_str(ascii!("end_col_offset")).into(),
])
.into(),
);
}
}
#[pyclass(module = "_ast", name = "MatchMapping", base = "NodeKindPattern")]
struct NodeMatchMapping;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl NodeMatchMapping {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
identifier!(ctx, _fields),
ctx.new_list(vec![
ctx.new_str(ascii!("keys")).into(),
ctx.new_str(ascii!("patterns")).into(),
ctx.new_str(ascii!("rest")).into(),
])
.into(),
);
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_list(vec![
ctx.new_str(ascii!("lineno")).into(),
ctx.new_str(ascii!("col_offset")).into(),
ctx.new_str(ascii!("end_lineno")).into(),
ctx.new_str(ascii!("end_col_offset")).into(),
])
.into(),
);
}
}
#[pyclass(module = "_ast", name = "MatchClass", base = "NodeKindPattern")]
struct NodeMatchClass;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl NodeMatchClass {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
identifier!(ctx, _fields),
ctx.new_list(vec![
ctx.new_str(ascii!("cls")).into(),
ctx.new_str(ascii!("patterns")).into(),
ctx.new_str(ascii!("kwd_attrs")).into(),
ctx.new_str(ascii!("kwd_patterns")).into(),
])
.into(),
);
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_list(vec![
ctx.new_str(ascii!("lineno")).into(),
ctx.new_str(ascii!("col_offset")).into(),
ctx.new_str(ascii!("end_lineno")).into(),
ctx.new_str(ascii!("end_col_offset")).into(),
])
.into(),
);
}
}
#[pyclass(module = "_ast", name = "MatchStar", base = "NodeKindPattern")]
struct NodeMatchStar;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl NodeMatchStar {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
identifier!(ctx, _fields),
ctx.new_list(vec![ctx.new_str(ascii!("name")).into()])
.into(),
);
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_list(vec![
ctx.new_str(ascii!("lineno")).into(),
ctx.new_str(ascii!("col_offset")).into(),
ctx.new_str(ascii!("end_lineno")).into(),
ctx.new_str(ascii!("end_col_offset")).into(),
])
.into(),
);
}
}
#[pyclass(module = "_ast", name = "MatchAs", base = "NodeKindPattern")]
struct NodeMatchAs;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl NodeMatchAs {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
identifier!(ctx, _fields),
ctx.new_list(vec![
ctx.new_str(ascii!("pattern")).into(),
ctx.new_str(ascii!("name")).into(),
])
.into(),
);
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_list(vec![
ctx.new_str(ascii!("lineno")).into(),
ctx.new_str(ascii!("col_offset")).into(),
ctx.new_str(ascii!("end_lineno")).into(),
ctx.new_str(ascii!("end_col_offset")).into(),
])
.into(),
);
}
}
#[pyclass(module = "_ast", name = "MatchOr", base = "NodeKindPattern")]
struct NodeMatchOr;
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl NodeMatchOr {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
class.set_attr(
identifier!(ctx, _fields),
ctx.new_list(vec![ctx.new_str(ascii!("patterns")).into()])
.into(),
);
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_list(vec![
ctx.new_str(ascii!("lineno")).into(),
ctx.new_str(ascii!("col_offset")).into(),
ctx.new_str(ascii!("end_lineno")).into(),
ctx.new_str(ascii!("end_col_offset")).into(),
])
.into(),
);
}
}
#[pyclass(module = "_ast", name = "type_ignore", base = "AstNode")]
struct NodeKindTypeIgnore;
#[pyclass(flags(HAS_DICT, BASETYPE))]
@@ -2334,6 +2587,19 @@ impl Node for ast::StmtKind {
.unwrap();
_node.into()
}
ast::StmtKind::Match { subject, cases } => {
let _node = AstNode
.into_ref_with_type(_vm, NodeMatch::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
.set_item("subject", subject.ast_to_object(_vm), _vm)
.unwrap();
_dict
.set_item("cases", cases.ast_to_object(_vm), _vm)
.unwrap();
_node.into()
}
ast::StmtKind::Raise { exc, cause } => {
let _node = AstNode
.into_ref_with_type(_vm, NodeRaise::static_type().to_owned())
@@ -2629,6 +2895,14 @@ impl Node for ast::StmtKind {
.map(|obj| Node::ast_from_object(_vm, obj))
.transpose()?,
}
} else if _cls.is(NodeMatch::static_type()) {
ast::StmtKind::Match {
subject: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "subject", "stmt")?,
)?,
cases: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "cases", "stmt")?)?,
}
} else if _cls.is(NodeRaise::static_type()) {
ast::StmtKind::Raise {
exc: get_node_field_opt(_vm, &_object, "exc")?
@@ -2671,7 +2945,9 @@ impl Node for ast::StmtKind {
.map(|obj| Node::ast_from_object(_vm, obj))
.transpose()?,
names: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "names", "stmt")?)?,
level: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "level", "stmt")?)?,
level: get_node_field_opt(_vm, &_object, "level")?
.map(|obj| Node::ast_from_object(_vm, obj))
.transpose()?,
}
} else if _cls.is(NodeGlobal::static_type()) {
ast::StmtKind::Global {
@@ -3186,9 +3462,10 @@ impl Node for ast::ExprKind {
} else if _cls.is(NodeFormattedValue::static_type()) {
ast::ExprKind::FormattedValue {
value: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "value", "expr")?)?,
conversion: get_node_field_opt(_vm, &_object, "conversion")?
.map(|obj| Node::ast_from_object(_vm, obj))
.transpose()?,
conversion: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "conversion", "expr")?,
)?,
format_spec: get_node_field_opt(_vm, &_object, "format_spec")?
.map(|obj| Node::ast_from_object(_vm, obj))
.transpose()?,
@@ -3617,7 +3894,7 @@ impl Node for ast::Comprehension {
is_async,
} = self;
let _node = AstNode
.into_ref_with_type(_vm, Nodecomprehension::static_type().to_owned())
.into_ref_with_type(_vm, NodeComprehension::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
@@ -3725,7 +4002,7 @@ impl Node for ast::Arguments {
defaults,
} = self;
let _node = AstNode
.into_ref_with_type(_vm, Nodearguments::static_type().to_owned())
.into_ref_with_type(_vm, NodeArguments::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
@@ -3790,7 +4067,7 @@ impl Node for ast::ArgData {
type_comment,
} = self;
let _node = AstNode
.into_ref_with_type(_vm, Nodearg::static_type().to_owned())
.into_ref_with_type(_vm, NodeArg::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict.set_item("arg", arg.ast_to_object(_vm), _vm).unwrap();
@@ -3825,7 +4102,7 @@ impl Node for ast::KeywordData {
fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef {
let ast::KeywordData { arg, value } = self;
let _node = AstNode
.into_ref_with_type(_vm, Nodekeyword::static_type().to_owned())
.into_ref_with_type(_vm, NodeKeyword::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict.set_item("arg", arg.ast_to_object(_vm), _vm).unwrap();
@@ -3847,14 +4124,14 @@ impl Node for ast::KeywordData {
})
}
}
impl NamedNode for ast::Alias {
impl NamedNode for ast::AliasData {
const NAME: &'static str = "alias";
}
impl Node for ast::Alias {
impl Node for ast::AliasData {
fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef {
let ast::Alias { name, asname } = self;
let ast::AliasData { name, asname } = self;
let _node = AstNode
.into_ref_with_type(_vm, Nodealias::static_type().to_owned())
.into_ref_with_type(_vm, NodeAlias::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
@@ -3866,7 +4143,11 @@ impl Node for ast::Alias {
_node.into()
}
fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult<Self> {
Ok(ast::Alias {
let _location = ast::Location::new(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "lineno", "alias")?)?,
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "col_offset", "alias")?)?,
);
Ok(ast::AliasData {
name: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "name", "alias")?)?,
asname: get_node_field_opt(_vm, &_object, "asname")?
.map(|obj| Node::ast_from_object(_vm, obj))
@@ -3884,7 +4165,7 @@ impl Node for ast::Withitem {
optional_vars,
} = self;
let _node = AstNode
.into_ref_with_type(_vm, Nodewithitem::static_type().to_owned())
.into_ref_with_type(_vm, NodeWithitem::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
@@ -3907,6 +4188,244 @@ impl Node for ast::Withitem {
})
}
}
impl NamedNode for ast::MatchCase {
const NAME: &'static str = "match_case";
}
impl Node for ast::MatchCase {
fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef {
let ast::MatchCase {
pattern,
guard,
body,
} = self;
let _node = AstNode
.into_ref_with_type(_vm, NodeMatchCase::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
.set_item("pattern", pattern.ast_to_object(_vm), _vm)
.unwrap();
_dict
.set_item("guard", guard.ast_to_object(_vm), _vm)
.unwrap();
_dict
.set_item("body", body.ast_to_object(_vm), _vm)
.unwrap();
_node.into()
}
fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult<Self> {
Ok(ast::MatchCase {
pattern: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "pattern", "match_case")?,
)?,
guard: get_node_field_opt(_vm, &_object, "guard")?
.map(|obj| Node::ast_from_object(_vm, obj))
.transpose()?,
body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "match_case")?)?,
})
}
}
impl NamedNode for ast::PatternKind {
const NAME: &'static str = "pattern";
}
impl Node for ast::PatternKind {
fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef {
match self {
ast::PatternKind::MatchValue { value } => {
let _node = AstNode
.into_ref_with_type(_vm, NodeMatchValue::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
.set_item("value", value.ast_to_object(_vm), _vm)
.unwrap();
_node.into()
}
ast::PatternKind::MatchSingleton { value } => {
let _node = AstNode
.into_ref_with_type(_vm, NodeMatchSingleton::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
.set_item("value", value.ast_to_object(_vm), _vm)
.unwrap();
_node.into()
}
ast::PatternKind::MatchSequence { patterns } => {
let _node = AstNode
.into_ref_with_type(_vm, NodeMatchSequence::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
.set_item("patterns", patterns.ast_to_object(_vm), _vm)
.unwrap();
_node.into()
}
ast::PatternKind::MatchMapping {
keys,
patterns,
rest,
} => {
let _node = AstNode
.into_ref_with_type(_vm, NodeMatchMapping::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
.set_item("keys", keys.ast_to_object(_vm), _vm)
.unwrap();
_dict
.set_item("patterns", patterns.ast_to_object(_vm), _vm)
.unwrap();
_dict
.set_item("rest", rest.ast_to_object(_vm), _vm)
.unwrap();
_node.into()
}
ast::PatternKind::MatchClass {
cls,
patterns,
kwd_attrs,
kwd_patterns,
} => {
let _node = AstNode
.into_ref_with_type(_vm, NodeMatchClass::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict.set_item("cls", cls.ast_to_object(_vm), _vm).unwrap();
_dict
.set_item("patterns", patterns.ast_to_object(_vm), _vm)
.unwrap();
_dict
.set_item("kwd_attrs", kwd_attrs.ast_to_object(_vm), _vm)
.unwrap();
_dict
.set_item("kwd_patterns", kwd_patterns.ast_to_object(_vm), _vm)
.unwrap();
_node.into()
}
ast::PatternKind::MatchStar { name } => {
let _node = AstNode
.into_ref_with_type(_vm, NodeMatchStar::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
.set_item("name", name.ast_to_object(_vm), _vm)
.unwrap();
_node.into()
}
ast::PatternKind::MatchAs { pattern, name } => {
let _node = AstNode
.into_ref_with_type(_vm, NodeMatchAs::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
.set_item("pattern", pattern.ast_to_object(_vm), _vm)
.unwrap();
_dict
.set_item("name", name.ast_to_object(_vm), _vm)
.unwrap();
_node.into()
}
ast::PatternKind::MatchOr { patterns } => {
let _node = AstNode
.into_ref_with_type(_vm, NodeMatchOr::static_type().to_owned())
.unwrap();
let _dict = _node.as_object().dict().unwrap();
_dict
.set_item("patterns", patterns.ast_to_object(_vm), _vm)
.unwrap();
_node.into()
}
}
}
fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult<Self> {
let _location = ast::Location::new(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "lineno", "pattern")?)?,
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "col_offset", "pattern")?)?,
);
let _cls = _object.class();
Ok(if _cls.is(NodeMatchValue::static_type()) {
ast::PatternKind::MatchValue {
value: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "value", "pattern")?,
)?,
}
} else if _cls.is(NodeMatchSingleton::static_type()) {
ast::PatternKind::MatchSingleton {
value: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "value", "pattern")?,
)?,
}
} else if _cls.is(NodeMatchSequence::static_type()) {
ast::PatternKind::MatchSequence {
patterns: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "patterns", "pattern")?,
)?,
}
} else if _cls.is(NodeMatchMapping::static_type()) {
ast::PatternKind::MatchMapping {
keys: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "keys", "pattern")?,
)?,
patterns: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "patterns", "pattern")?,
)?,
rest: get_node_field_opt(_vm, &_object, "rest")?
.map(|obj| Node::ast_from_object(_vm, obj))
.transpose()?,
}
} else if _cls.is(NodeMatchClass::static_type()) {
ast::PatternKind::MatchClass {
cls: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "cls", "pattern")?)?,
patterns: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "patterns", "pattern")?,
)?,
kwd_attrs: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "kwd_attrs", "pattern")?,
)?,
kwd_patterns: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "kwd_patterns", "pattern")?,
)?,
}
} else if _cls.is(NodeMatchStar::static_type()) {
ast::PatternKind::MatchStar {
name: get_node_field_opt(_vm, &_object, "name")?
.map(|obj| Node::ast_from_object(_vm, obj))
.transpose()?,
}
} else if _cls.is(NodeMatchAs::static_type()) {
ast::PatternKind::MatchAs {
pattern: get_node_field_opt(_vm, &_object, "pattern")?
.map(|obj| Node::ast_from_object(_vm, obj))
.transpose()?,
name: get_node_field_opt(_vm, &_object, "name")?
.map(|obj| Node::ast_from_object(_vm, obj))
.transpose()?,
}
} else if _cls.is(NodeMatchOr::static_type()) {
ast::PatternKind::MatchOr {
patterns: Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "patterns", "pattern")?,
)?,
}
} else {
return Err(_vm.new_type_error(format!(
"expected some sort of pattern, but got {}",
_object.repr(_vm)?
)));
})
}
}
impl NamedNode for ast::TypeIgnore {
const NAME: &'static str = "type_ignore";
}
@@ -3970,6 +4489,7 @@ pub fn extend_module_nodes(vm: &VirtualMachine, module: &PyObject) {
"If" => NodeIf::make_class(&vm.ctx),
"With" => NodeWith::make_class(&vm.ctx),
"AsyncWith" => NodeAsyncWith::make_class(&vm.ctx),
"Match" => NodeMatch::make_class(&vm.ctx),
"Raise" => NodeRaise::make_class(&vm.ctx),
"Try" => NodeTry::make_class(&vm.ctx),
"Assert" => NodeAssert::make_class(&vm.ctx),
@@ -4046,14 +4566,24 @@ pub fn extend_module_nodes(vm: &VirtualMachine, module: &PyObject) {
"IsNot" => NodeIsNot::make_class(&vm.ctx),
"In" => NodeIn::make_class(&vm.ctx),
"NotIn" => NodeNotIn::make_class(&vm.ctx),
"comprehension" => Nodecomprehension::make_class(&vm.ctx),
"comprehension" => NodeComprehension::make_class(&vm.ctx),
"excepthandler" => NodeKindExcepthandler::make_class(&vm.ctx),
"ExceptHandler" => NodeExceptHandler::make_class(&vm.ctx),
"arguments" => Nodearguments::make_class(&vm.ctx),
"arg" => Nodearg::make_class(&vm.ctx),
"keyword" => Nodekeyword::make_class(&vm.ctx),
"alias" => Nodealias::make_class(&vm.ctx),
"withitem" => Nodewithitem::make_class(&vm.ctx),
"arguments" => NodeArguments::make_class(&vm.ctx),
"arg" => NodeArg::make_class(&vm.ctx),
"keyword" => NodeKeyword::make_class(&vm.ctx),
"alias" => NodeAlias::make_class(&vm.ctx),
"withitem" => NodeWithitem::make_class(&vm.ctx),
"match_case" => NodeMatchCase::make_class(&vm.ctx),
"pattern" => NodeKindPattern::make_class(&vm.ctx),
"MatchValue" => NodeMatchValue::make_class(&vm.ctx),
"MatchSingleton" => NodeMatchSingleton::make_class(&vm.ctx),
"MatchSequence" => NodeMatchSequence::make_class(&vm.ctx),
"MatchMapping" => NodeMatchMapping::make_class(&vm.ctx),
"MatchClass" => NodeMatchClass::make_class(&vm.ctx),
"MatchStar" => NodeMatchStar::make_class(&vm.ctx),
"MatchAs" => NodeMatchAs::make_class(&vm.ctx),
"MatchOr" => NodeMatchOr::make_class(&vm.ctx),
"type_ignore" => NodeKindTypeIgnore::make_class(&vm.ctx),
"TypeIgnore" => NodeTypeIgnore::make_class(&vm.ctx),
})

View File

@@ -109,6 +109,8 @@ mod builtins {
dont_inherit: OptionalArg<bool>,
#[pyarg(any, optional)]
optimize: OptionalArg<PyIntRef>,
#[pyarg(any, optional)]
_feature_version: OptionalArg<i32>,
}
#[cfg(feature = "rustpython-compiler")]
@@ -122,6 +124,10 @@ mod builtins {
{
use crate::{class::PyClassImpl, stdlib::ast};
if args._feature_version.is_present() {
eprintln!("TODO: compile() got `_feature_version` but ignored");
}
let mode_str = args.mode.as_str();
if args