mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Preserve existing coverage while following verified final behavior for script metadata, builtin signatures and loading, AST fixture construction, memoryview diagnostics, mmap search bounds, and struct format errors. The unchanged final comparator exposes the earlier expectations; focused native baseline failures establish the required implementation changes. Assisted-by: OpenAI Codex:model identifier unavailable
112 lines
2.8 KiB
Python
112 lines
2.8 KiB
Python
import ast
|
|
import copy
|
|
|
|
print(ast)
|
|
|
|
source = """
|
|
def foo():
|
|
print('bar')
|
|
pass
|
|
"""
|
|
n = ast.parse(source)
|
|
print(n)
|
|
print(n.body)
|
|
print(n.body[0].name)
|
|
assert n.body[0].name == "foo"
|
|
foo = n.body[0]
|
|
assert foo.lineno == 2
|
|
print(foo.body)
|
|
assert len(foo.body) == 2
|
|
print(foo.body[0])
|
|
print(foo.body[0].value.func.id)
|
|
assert foo.body[0].value.func.id == "print"
|
|
assert foo.body[0].lineno == 3
|
|
assert foo.body[1].lineno == 4
|
|
|
|
n = ast.parse("3 < 4 > 5\n")
|
|
assert n.body[0].value.left.value == 3
|
|
assert "Lt" in str(n.body[0].value.ops[0])
|
|
assert "Gt" in str(n.body[0].value.ops[1])
|
|
assert n.body[0].value.comparators[0].value == 4
|
|
assert n.body[0].value.comparators[1].value == 5
|
|
|
|
|
|
n = ast.parse("from ... import a\n")
|
|
print(n)
|
|
i = n.body[0]
|
|
assert i.level == 3
|
|
assert i.module is None
|
|
assert i.names[0].name == "a"
|
|
assert i.names[0].asname is None
|
|
|
|
|
|
# Regression: parsed AST identifier fields are interned, matching CPython.
|
|
name_literal = "x"
|
|
name = ast.parse("x").body[0].value
|
|
assert name.id is name_literal
|
|
|
|
name.extra = object()
|
|
replacement = copy.replace(name)
|
|
assert replacement.id is name.id
|
|
assert replacement.ctx is name.ctx
|
|
assert not hasattr(replacement, "extra")
|
|
|
|
function_name = "f"
|
|
function = ast.parse("def f(): pass").body[0]
|
|
assert function.name is function_name
|
|
|
|
async_function = ast.parse("async def f(): pass").body[0]
|
|
assert async_function.name is function_name
|
|
|
|
|
|
# Regression test for issue #4862:
|
|
# A cyclic AST fed to compile() used to overflow the Rust stack and SIGSEGV.
|
|
# After the fix, the recursion guard in ast_from_object raises RecursionError,
|
|
# matching CPython's behavior. Covers both Box<T> descents (UnaryOp, BinOp,
|
|
# Call, Attribute) and Vec<T> descents (List, Tuple).
|
|
import warnings
|
|
|
|
|
|
def _cyclic_cases():
|
|
# Box<Expr> descents
|
|
u = ast.UnaryOp(op=ast.Not(), operand=None, lineno=0, col_offset=0)
|
|
u.operand = u
|
|
yield "UnaryOp", u
|
|
|
|
b = ast.BinOp(
|
|
op=ast.Add(),
|
|
left=None,
|
|
right=ast.Constant(value=0, lineno=0, col_offset=0),
|
|
lineno=0,
|
|
col_offset=0,
|
|
)
|
|
b.left = b
|
|
yield "BinOp", b
|
|
|
|
c = ast.Call(func=None, args=[], keywords=[], lineno=0, col_offset=0)
|
|
c.func = c
|
|
yield "Call", c
|
|
|
|
a = ast.Attribute(value=None, attr="x", ctx=ast.Load(), lineno=0, col_offset=0)
|
|
a.value = a
|
|
yield "Attribute", a
|
|
|
|
# Vec<Expr> descents
|
|
lst = ast.List(ctx=ast.Load(), lineno=0, col_offset=0)
|
|
lst.elts = [lst]
|
|
yield "List", lst
|
|
|
|
tup = ast.Tuple(ctx=ast.Load(), lineno=0, col_offset=0)
|
|
tup.elts = [tup]
|
|
yield "Tuple", tup
|
|
|
|
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore")
|
|
for name, node in _cyclic_cases():
|
|
try:
|
|
compile(ast.Expression(node), "<cyclic>", "eval")
|
|
raise AssertionError(f"cyclic {name} should raise RecursionError")
|
|
except RecursionError:
|
|
pass # expected; matches CPython
|