Skip to content

Commit

Permalink
Avoid ast deprecation warnings on Python 3.12
Browse files Browse the repository at this point in the history
Fix #10977.
  • Loading branch information
bluetech committed May 23, 2023
1 parent 9e491f4 commit b1ba5ff
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 20 deletions.
44 changes: 25 additions & 19 deletions src/_pytest/assertion/rewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@

if sys.version_info >= (3, 8):
namedExpr = ast.NamedExpr
astNameConstant = ast.Constant
astStr = ast.Constant
astNum = ast.Constant
else:
namedExpr = ast.Expr
astNameConstant = ast.NameConstant
astStr = ast.Str
astNum = ast.Num


assertstate_key = StashKey["AssertionState"]()
Expand Down Expand Up @@ -680,7 +686,7 @@ def run(self, mod: ast.Module) -> None:
if (
expect_docstring
and isinstance(item, ast.Expr)
and isinstance(item.value, ast.Str)
and isinstance(item.value, astStr)
):
doc = item.value.s
if self.is_rewrite_disabled(doc):
Expand Down Expand Up @@ -814,7 +820,7 @@ def pop_format_context(self, expl_expr: ast.expr) -> ast.Name:
current = self.stack.pop()
if self.stack:
self.explanation_specifiers = self.stack[-1]
keys = [ast.Str(key) for key in current.keys()]
keys = [astStr(key) for key in current.keys()]
format_dict = ast.Dict(keys, list(current.values()))
form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
name = "@py_format" + str(next(self.variable_counter))
Expand Down Expand Up @@ -868,16 +874,16 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]:
negation = ast.UnaryOp(ast.Not(), top_condition)

if self.enable_assertion_pass_hook: # Experimental pytest_assertion_pass hook
msg = self.pop_format_context(ast.Str(explanation))
msg = self.pop_format_context(astStr(explanation))

# Failed
if assert_.msg:
assertmsg = self.helper("_format_assertmsg", assert_.msg)
gluestr = "\n>assert "
else:
assertmsg = ast.Str("")
assertmsg = astStr("")
gluestr = "assert "
err_explanation = ast.BinOp(ast.Str(gluestr), ast.Add(), msg)
err_explanation = ast.BinOp(astStr(gluestr), ast.Add(), msg)
err_msg = ast.BinOp(assertmsg, ast.Add(), err_explanation)
err_name = ast.Name("AssertionError", ast.Load())
fmt = self.helper("_format_explanation", err_msg)
Expand All @@ -893,8 +899,8 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]:
hook_call_pass = ast.Expr(
self.helper(
"_call_assertion_pass",
ast.Num(assert_.lineno),
ast.Str(orig),
astNum(assert_.lineno),
astStr(orig),
fmt_pass,
)
)
Expand All @@ -913,7 +919,7 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]:
variables = [
ast.Name(name, ast.Store()) for name in self.format_variables
]
clear_format = ast.Assign(variables, ast.NameConstant(None))
clear_format = ast.Assign(variables, astNameConstant(None))
self.statements.append(clear_format)

else: # Original assertion rewriting
Expand All @@ -924,9 +930,9 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]:
assertmsg = self.helper("_format_assertmsg", assert_.msg)
explanation = "\n>assert " + explanation
else:
assertmsg = ast.Str("")
assertmsg = astStr("")
explanation = "assert " + explanation
template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation))
template = ast.BinOp(assertmsg, ast.Add(), astStr(explanation))
msg = self.pop_format_context(template)
fmt = self.helper("_format_explanation", msg)
err_name = ast.Name("AssertionError", ast.Load())
Expand All @@ -938,7 +944,7 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]:
# Clear temporary variables by setting them to None.
if self.variables:
variables = [ast.Name(name, ast.Store()) for name in self.variables]
clear = ast.Assign(variables, ast.NameConstant(None))
clear = ast.Assign(variables, astNameConstant(None))
self.statements.append(clear)
# Fix locations (line numbers/column offsets).
for stmt in self.statements:
Expand All @@ -952,20 +958,20 @@ def visit_NamedExpr(self, name: namedExpr) -> Tuple[namedExpr, str]:
# thinks it's acceptable.
locs = ast.Call(self.builtin("locals"), [], [])
target_id = name.target.id # type: ignore[attr-defined]
inlocs = ast.Compare(ast.Str(target_id), [ast.In()], [locs])
inlocs = ast.Compare(astStr(target_id), [ast.In()], [locs])
dorepr = self.helper("_should_repr_global_name", name)
test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
expr = ast.IfExp(test, self.display(name), ast.Str(target_id))
expr = ast.IfExp(test, self.display(name), astStr(target_id))
return name, self.explanation_param(expr)

def visit_Name(self, name: ast.Name) -> Tuple[ast.Name, str]:
# Display the repr of the name if it's a local variable or
# _should_repr_global_name() thinks it's acceptable.
locs = ast.Call(self.builtin("locals"), [], [])
inlocs = ast.Compare(ast.Str(name.id), [ast.In()], [locs])
inlocs = ast.Compare(astStr(name.id), [ast.In()], [locs])
dorepr = self.helper("_should_repr_global_name", name)
test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
expr = ast.IfExp(test, self.display(name), ast.Str(name.id))
expr = ast.IfExp(test, self.display(name), astStr(name.id))
return name, self.explanation_param(expr)

def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]:
Expand Down Expand Up @@ -1001,7 +1007,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]:
self.push_format_context()
res, expl = self.visit(v)
body.append(ast.Assign([ast.Name(res_var, ast.Store())], res))
expl_format = self.pop_format_context(ast.Str(expl))
expl_format = self.pop_format_context(astStr(expl))
call = ast.Call(app, [expl_format], [])
self.expl_stmts.append(ast.Expr(call))
if i < levels:
Expand All @@ -1013,7 +1019,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]:
self.statements = body = inner
self.statements = save
self.expl_stmts = fail_save
expl_template = self.helper("_format_boolop", expl_list, ast.Num(is_or))
expl_template = self.helper("_format_boolop", expl_list, astNum(is_or))
expl = self.pop_format_context(expl_template)
return ast.Name(res_var, ast.Load()), self.explanation_param(expl)

Expand Down Expand Up @@ -1099,9 +1105,9 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]:
next_expl = f"({next_expl})"
results.append(next_res)
sym = BINOP_MAP[op.__class__]
syms.append(ast.Str(sym))
syms.append(astStr(sym))
expl = f"{left_expl} {sym} {next_expl}"
expls.append(ast.Str(expl))
expls.append(astStr(expl))
res_expr = ast.Compare(left_res, [op], [next_res])
self.statements.append(ast.Assign([store_names[i]], res_expr))
left_res, left_expl = next_res, next_expl
Expand Down
8 changes: 7 additions & 1 deletion src/_pytest/mark/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import dataclasses
import enum
import re
import sys
import types
from typing import Callable
from typing import Iterator
Expand All @@ -26,6 +27,11 @@
from typing import Optional
from typing import Sequence

if sys.version_info >= (3, 8):
astNameConstant = ast.Constant
else:
astNameConstant = ast.NameConstant


__all__ = [
"Expression",
Expand Down Expand Up @@ -132,7 +138,7 @@ def reject(self, expected: Sequence[TokenType]) -> NoReturn:

def expression(s: Scanner) -> ast.Expression:
if s.accept(TokenType.EOF):
ret: ast.expr = ast.NameConstant(False)
ret: ast.expr = astNameConstant(False)
else:
ret = expr(s)
s.accept(TokenType.EOF, reject=True)
Expand Down

0 comments on commit b1ba5ff

Please sign in to comment.