https://bugzilla.redhat.com/show_bug.cgi?id=2207642
Bug ID: 2207642 Summary: python-executing fails to build with Python 3.12: executing._exceptions.VerifierFailure: ast.UnaryOp is not created from CALL_INTRINSIC_1 Product: Fedora Version: rawhide Status: NEW Component: python-executing Assignee: rominf@aiven.io Reporter: thrnciar@redhat.com CC: epel-packagers-sig@lists.fedoraproject.org, lbalhar@redhat.com, mhroncok@redhat.com, paul.wouters@aiven.io, rominf@aiven.io, thrnciar@redhat.com Blocks: 2135404 (PYTHON3.12) Target Milestone: --- Classification: Fedora
python-executing fails to build with Python 3.12.0a7.
=================================== FAILURES =================================== ___________________________ TestStuff.test_decorator ___________________________
self = <tests.test_main.TestStuff testMethod=test_decorator>
def test_decorator(self): @empty_decorator # 0 @decorator_with_args(tester('123'), x=int()) # 1 @tester(list(tuple([1, 2]))) # 2! @tester( # 3! list( tuple( [3, 4])), ) @empty_decorator # 4 @decorator_with_args( # 5 str(), x=int()) @tester(list(tuple([5, 6]))) # 6!
@tester(list(tuple([7, 8]))) # 7!
tests/test_main.py:83: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/utils.py:63: in __call__ self.check(call.args[0], arg) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <tests.utils.Tester object at 0x7f702c74c050> node = <ast.Call object at 0x7f702c7f22d0> value = <function TestStuff.test_decorator.<locals>.foo at 0x7f702c62b740>
def check(self, node, value): frame = inspect.currentframe().f_back.f_back result = eval( compile(ast.Expression(node), frame.f_code.co_filename, 'eval'), frame.f_globals, frame.f_locals, )
assert result == value, (result, value)
E AssertionError: ([7, 8], <function TestStuff.test_decorator.<locals>.foo at 0x7f702c62b740>)
tests/utils.py:51: AssertionError __________________ TestStuff.test_decorator_cache_instruction __________________
self = <tests.test_main.TestStuff testMethod=test_decorator_cache_instruction>
def test_decorator_cache_instruction(self): frame = inspect.currentframe()
def deco(f): assert f.__name__ == "foo" ex = Source.executing(frame) assert isinstance(ex.node, ast.FunctionDef) assert isinstance(ex.decorator, ast.Name)
@deco
tests/test_main.py:587: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_main.py:583: in deco ex = Source.executing(frame) executing/executing.py:368: in executing node_finder = NodeFinder(frame, stmts, tree, lasti, source) executing/_position_node_finder.py:158: in __init__ self.verify(self.result, self.instruction(lasti)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <executing._position_node_finder.PositionNodeFinder object at 0x7f702c3f75c0> node = <ast.Name object at 0x7f702c5875d0> instruction = Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=62, starts_line=587, is_jump_target=False, positions=Positions(lineno=587, end_lineno=587, col_offset=9, end_col_offset=13))
def verify(self, node: EnhancedAST, instruction: dis.Instruction) -> None: """ checks if this node could gererate this instruction """
op_name = instruction.opname extra_filter: Callable[[EnhancedAST], bool] = lambda e: True ctx: Type = type(None)
def inst_match(opnames: Union[str, Sequence[str]], **kwargs: Any) -> bool: """ match instruction
Parameters: opnames: (str|Seq[str]): inst.opname has to be equal to or in `opname` **kwargs: every arg has to match inst.arg
Returns: True if all conditions match the instruction
"""
if isinstance(opnames, str): opnames = [opnames] return instruction.opname in opnames and kwargs == { k: getattr(instruction, k) for k in kwargs }
def node_match(node_type: Union[Type, Tuple[Type, ...]], **kwargs: Any) -> bool: """ match the ast-node
Parameters: node_type: type of the node **kwargs: every `arg` has to be equal `node.arg` or `node.arg` has to be an instance of `arg` if it is a type. """ return isinstance(node, node_type) and all( isinstance(getattr(node, k), v) if isinstance(v, type) else getattr(node, k) == v for k, v in kwargs.items() )
if op_name == "CACHE": return
if inst_match("CALL") and node_match((ast.With, ast.AsyncWith)): # call to context.__exit__ return
if inst_match(("CALL", "LOAD_FAST")) and node_match( (ast.ListComp, ast.GeneratorExp, ast.SetComp, ast.DictComp) ): # call to the generator function return
if inst_match(("CALL", "CALL_FUNCTION_EX")) and node_match( (ast.ClassDef, ast.Call) ): return
if inst_match(("COMPARE_OP", "IS_OP", "CONTAINS_OP")) and node_match( ast.Compare ): return
if inst_match("LOAD_NAME", argval="__annotations__") and node_match( ast.AnnAssign ): return
if ( ( inst_match("LOAD_METHOD", argval="join") or inst_match(("CALL", "BUILD_STRING")) ) and node_match(ast.BinOp, left=ast.Constant, op=ast.Mod) and isinstance(cast(ast.Constant, cast(ast.BinOp, node).left).value, str) ): # "..."%(...) uses "".join return
if inst_match("STORE_SUBSCR") and node_match(ast.AnnAssign): # data: int return
if self.is_except_cleanup(instruction, node): return
if inst_match(("DELETE_NAME", "DELETE_FAST")) and node_match( ast.Name, id=instruction.argval, ctx=ast.Del ): return
if inst_match("BUILD_STRING") and ( node_match(ast.JoinedStr) or node_match(ast.BinOp, op=ast.Mod) ): return
if inst_match(("BEFORE_WITH","WITH_EXCEPT_START")) and node_match(ast.With): return
if inst_match(("STORE_NAME", "STORE_GLOBAL"), argval="__doc__") and node_match( ast.Constant ): # store docstrings return
if ( inst_match(("STORE_NAME", "STORE_FAST", "STORE_GLOBAL", "STORE_DEREF")) and node_match(ast.ExceptHandler) and instruction.argval == mangled_name(node) ): # store exception in variable return
if ( inst_match(("STORE_NAME", "STORE_FAST", "STORE_DEREF", "STORE_GLOBAL")) and node_match((ast.Import, ast.ImportFrom)) and any(mangled_name(cast(EnhancedAST, alias)) == instruction.argval for alias in cast(ast.Import, node).names) ): # store imported module in variable return
if ( inst_match(("STORE_FAST", "STORE_DEREF", "STORE_NAME", "STORE_GLOBAL")) and ( node_match((ast.FunctionDef, ast.ClassDef, ast.AsyncFunctionDef)) or node_match( ast.Name, ctx=ast.Store, ) ) and instruction.argval == mangled_name(node) ): return
if False: # TODO: match expressions are not supported for now if inst_match(("STORE_FAST", "STORE_NAME")) and node_match( ast.MatchAs, name=instruction.argval ): return
if inst_match("COMPARE_OP", argval="==") and node_match(ast.MatchSequence): return
if inst_match("COMPARE_OP", argval="==") and node_match(ast.MatchValue): return
if inst_match("BINARY_OP") and node_match( ast.AugAssign, op=op_type_map[instruction.argrepr.removesuffix("=")] ): # a+=5 return
if node_match(ast.Attribute, ctx=ast.Del) and inst_match( "DELETE_ATTR", argval=mangled_name(node) ): return
if inst_match(("JUMP_IF_TRUE_OR_POP", "JUMP_IF_FALSE_OR_POP")) and node_match( ast.BoolOp ): # and/or short circuit return
if inst_match("DELETE_SUBSCR") and node_match(ast.Subscript, ctx=ast.Del): return
if node_match(ast.Name, ctx=ast.Load) and inst_match( ("LOAD_NAME", "LOAD_FAST", "LOAD_GLOBAL"), argval=mangled_name(node) ): return
if node_match(ast.Name, ctx=ast.Del) and inst_match( ("DELETE_NAME", "DELETE_GLOBAL"), argval=mangled_name(node) ): return
# old verifier
typ: Type = type(None) op_type: Type = type(None)
if op_name.startswith(("BINARY_SUBSCR", "SLICE+")): typ = ast.Subscript ctx = ast.Load elif op_name.startswith("BINARY_"): typ = ast.BinOp op_type = op_type_map[instruction.argrepr] extra_filter = lambda e: isinstance(cast(ast.BinOp, e).op, op_type) elif op_name.startswith("UNARY_"): typ = ast.UnaryOp op_type = dict( UNARY_POSITIVE=ast.UAdd, UNARY_NEGATIVE=ast.USub, UNARY_NOT=ast.Not, UNARY_INVERT=ast.Invert, )[op_name] extra_filter = lambda e: isinstance(cast(ast.UnaryOp, e).op, op_type) elif op_name in ("LOAD_ATTR", "LOAD_METHOD", "LOOKUP_METHOD"): typ = ast.Attribute ctx = ast.Load extra_filter = lambda e: mangled_name(e) == instruction.argval elif op_name in ( "LOAD_NAME", "LOAD_GLOBAL", "LOAD_FAST", "LOAD_DEREF", "LOAD_CLASSDEREF", ): typ = ast.Name ctx = ast.Load extra_filter = lambda e: cast(ast.Name, e).id == instruction.argval elif op_name in ("COMPARE_OP", "IS_OP", "CONTAINS_OP"): typ = ast.Compare extra_filter = lambda e: len(cast(ast.Compare, e).ops) == 1 elif op_name.startswith(("STORE_SLICE", "STORE_SUBSCR")): ctx = ast.Store typ = ast.Subscript elif op_name.startswith("STORE_ATTR"): ctx = ast.Store typ = ast.Attribute extra_filter = lambda e: mangled_name(e) == instruction.argval
node_ctx = getattr(node, "ctx", None)
ctx_match = ( ctx is not type(None) or not hasattr(node, "ctx") or isinstance(node_ctx, ctx) )
# check for old verifier if isinstance(node, typ) and ctx_match and extra_filter(node): return
# generate error
title = "ast.%s is not created from %s" % ( type(node).__name__, instruction.opname, )
raise VerifierFailure(title, node, instruction)
E executing._exceptions.VerifierFailure: ast.Name is not created from CALL
executing/_position_node_finder.py:545: VerifierFailure _____________________________ TestStuff.test_names _____________________________
self = <tests.test_main.TestStuff testMethod=test_names>
@contextlib.contextmanager def assert_name_error(self): try:
yield
tests/test_main.py:536: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <tests.test_main.TestStuff testMethod=test_names>
def test_names(self): with self.assert_name_error(): self, completely_nonexistent # noqa
with self.assert_name_error(): self, global_never_defined # noqa
with self.assert_name_error():
self, local_not_defined_yet # noqa
E UnboundLocalError: cannot access local variable 'local_not_defined_yet' where it is not associated with a value
tests/test_main.py:554: UnboundLocalError
During handling of the above exception, another exception occurred:
self = <tests.test_main.TestStuff testMethod=test_names>
def test_names(self): with self.assert_name_error(): self, completely_nonexistent # noqa
with self.assert_name_error(): self, global_never_defined # noqa
with self.assert_name_error():
tests/test_main.py:553: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib64/python3.12/contextlib.py:155: in __exit__ self.gen.throw(value) tests/test_main.py:539: in assert_name_error ex = Source.executing(tb.tb_next) executing/executing.py:368: in executing node_finder = NodeFinder(frame, stmts, tree, lasti, source) executing/_position_node_finder.py:158: in __init__ self.verify(self.result, self.instruction(lasti)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <executing._position_node_finder.PositionNodeFinder object at 0x7f7029434e30> node = <ast.Name object at 0x7f702c781450> instruction = Instruction(opname='LOAD_FAST_CHECK', opcode=127, arg=1, argval='local_not_defined_yet', argrepr='local_not_defined_ye...rts_line=None, is_jump_target=False, positions=Positions(lineno=554, end_lineno=554, col_offset=18, end_col_offset=39))
def verify(self, node: EnhancedAST, instruction: dis.Instruction) -> None: """ checks if this node could gererate this instruction """
op_name = instruction.opname extra_filter: Callable[[EnhancedAST], bool] = lambda e: True ctx: Type = type(None)
def inst_match(opnames: Union[str, Sequence[str]], **kwargs: Any) -> bool: """ match instruction
Parameters: opnames: (str|Seq[str]): inst.opname has to be equal to or in `opname` **kwargs: every arg has to match inst.arg
Returns: True if all conditions match the instruction
"""
if isinstance(opnames, str): opnames = [opnames] return instruction.opname in opnames and kwargs == { k: getattr(instruction, k) for k in kwargs }
def node_match(node_type: Union[Type, Tuple[Type, ...]], **kwargs: Any) -> bool: """ match the ast-node
Parameters: node_type: type of the node **kwargs: every `arg` has to be equal `node.arg` or `node.arg` has to be an instance of `arg` if it is a type. """ return isinstance(node, node_type) and all( isinstance(getattr(node, k), v) if isinstance(v, type) else getattr(node, k) == v for k, v in kwargs.items() )
if op_name == "CACHE": return
if inst_match("CALL") and node_match((ast.With, ast.AsyncWith)): # call to context.__exit__ return
if inst_match(("CALL", "LOAD_FAST")) and node_match( (ast.ListComp, ast.GeneratorExp, ast.SetComp, ast.DictComp) ): # call to the generator function return
if inst_match(("CALL", "CALL_FUNCTION_EX")) and node_match( (ast.ClassDef, ast.Call) ): return
if inst_match(("COMPARE_OP", "IS_OP", "CONTAINS_OP")) and node_match( ast.Compare ): return
if inst_match("LOAD_NAME", argval="__annotations__") and node_match( ast.AnnAssign ): return
if ( ( inst_match("LOAD_METHOD", argval="join") or inst_match(("CALL", "BUILD_STRING")) ) and node_match(ast.BinOp, left=ast.Constant, op=ast.Mod) and isinstance(cast(ast.Constant, cast(ast.BinOp, node).left).value, str) ): # "..."%(...) uses "".join return
if inst_match("STORE_SUBSCR") and node_match(ast.AnnAssign): # data: int return
if self.is_except_cleanup(instruction, node): return
if inst_match(("DELETE_NAME", "DELETE_FAST")) and node_match( ast.Name, id=instruction.argval, ctx=ast.Del ): return
if inst_match("BUILD_STRING") and ( node_match(ast.JoinedStr) or node_match(ast.BinOp, op=ast.Mod) ): return
if inst_match(("BEFORE_WITH","WITH_EXCEPT_START")) and node_match(ast.With): return
if inst_match(("STORE_NAME", "STORE_GLOBAL"), argval="__doc__") and node_match( ast.Constant ): # store docstrings return
if ( inst_match(("STORE_NAME", "STORE_FAST", "STORE_GLOBAL", "STORE_DEREF")) and node_match(ast.ExceptHandler) and instruction.argval == mangled_name(node) ): # store exception in variable return
if ( inst_match(("STORE_NAME", "STORE_FAST", "STORE_DEREF", "STORE_GLOBAL")) and node_match((ast.Import, ast.ImportFrom)) and any(mangled_name(cast(EnhancedAST, alias)) == instruction.argval for alias in cast(ast.Import, node).names) ): # store imported module in variable return
if ( inst_match(("STORE_FAST", "STORE_DEREF", "STORE_NAME", "STORE_GLOBAL")) and ( node_match((ast.FunctionDef, ast.ClassDef, ast.AsyncFunctionDef)) or node_match( ast.Name, ctx=ast.Store, ) ) and instruction.argval == mangled_name(node) ): return
if False: # TODO: match expressions are not supported for now if inst_match(("STORE_FAST", "STORE_NAME")) and node_match( ast.MatchAs, name=instruction.argval ): return
if inst_match("COMPARE_OP", argval="==") and node_match(ast.MatchSequence): return
if inst_match("COMPARE_OP", argval="==") and node_match(ast.MatchValue): return
if inst_match("BINARY_OP") and node_match( ast.AugAssign, op=op_type_map[instruction.argrepr.removesuffix("=")] ): # a+=5 return
if node_match(ast.Attribute, ctx=ast.Del) and inst_match( "DELETE_ATTR", argval=mangled_name(node) ): return
if inst_match(("JUMP_IF_TRUE_OR_POP", "JUMP_IF_FALSE_OR_POP")) and node_match( ast.BoolOp ): # and/or short circuit return
if inst_match("DELETE_SUBSCR") and node_match(ast.Subscript, ctx=ast.Del): return
if node_match(ast.Name, ctx=ast.Load) and inst_match( ("LOAD_NAME", "LOAD_FAST", "LOAD_GLOBAL"), argval=mangled_name(node) ): return
if node_match(ast.Name, ctx=ast.Del) and inst_match( ("DELETE_NAME", "DELETE_GLOBAL"), argval=mangled_name(node) ): return
# old verifier
typ: Type = type(None) op_type: Type = type(None)
if op_name.startswith(("BINARY_SUBSCR", "SLICE+")): typ = ast.Subscript ctx = ast.Load elif op_name.startswith("BINARY_"): typ = ast.BinOp op_type = op_type_map[instruction.argrepr] extra_filter = lambda e: isinstance(cast(ast.BinOp, e).op, op_type) elif op_name.startswith("UNARY_"): typ = ast.UnaryOp op_type = dict( UNARY_POSITIVE=ast.UAdd, UNARY_NEGATIVE=ast.USub, UNARY_NOT=ast.Not, UNARY_INVERT=ast.Invert, )[op_name] extra_filter = lambda e: isinstance(cast(ast.UnaryOp, e).op, op_type) elif op_name in ("LOAD_ATTR", "LOAD_METHOD", "LOOKUP_METHOD"): typ = ast.Attribute ctx = ast.Load extra_filter = lambda e: mangled_name(e) == instruction.argval elif op_name in ( "LOAD_NAME", "LOAD_GLOBAL", "LOAD_FAST", "LOAD_DEREF", "LOAD_CLASSDEREF", ): typ = ast.Name ctx = ast.Load extra_filter = lambda e: cast(ast.Name, e).id == instruction.argval elif op_name in ("COMPARE_OP", "IS_OP", "CONTAINS_OP"): typ = ast.Compare extra_filter = lambda e: len(cast(ast.Compare, e).ops) == 1 elif op_name.startswith(("STORE_SLICE", "STORE_SUBSCR")): ctx = ast.Store typ = ast.Subscript elif op_name.startswith("STORE_ATTR"): ctx = ast.Store typ = ast.Attribute extra_filter = lambda e: mangled_name(e) == instruction.argval
node_ctx = getattr(node, "ctx", None)
ctx_match = ( ctx is not type(None) or not hasattr(node, "ctx") or isinstance(node_ctx, ctx) )
# check for old verifier if isinstance(node, typ) and ctx_match and extra_filter(node): return
# generate error
title = "ast.%s is not created from %s" % ( type(node).__name__, instruction.opname, )
raise VerifierFailure(title, node, instruction)
E executing._exceptions.VerifierFailure: ast.Name is not created from LOAD_FAST_CHECK
executing/_position_node_finder.py:545: VerifierFailure ___________________________ test_global_tester_calls ___________________________
def test_global_tester_calls(): # tester calls should be tested at global scope
from . import global_tester_calls
tests/test_main.py:1397: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/global_tester_calls.py:13: in <module> assert -tester is +tester is ~tester is tester tests/utils.py:131: in __invert__ node = self.get_node(ast.UnaryOp) tests/utils.py:35: in get_node ex = self.get_executing(inspect.currentframe().f_back.f_back) tests/utils.py:42: in get_executing return Source.executing(frame) executing/executing.py:368: in executing node_finder = NodeFinder(frame, stmts, tree, lasti, source) executing/_position_node_finder.py:158: in __init__ self.verify(self.result, self.instruction(lasti)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <executing._position_node_finder.PositionNodeFinder object at 0x7f702c84ede0> node = <ast.UnaryOp object at 0x7f7029326590> instruction = Instruction(opname='CALL_INTRINSIC_1', opcode=173, arg=5, argval=5, argrepr='', offset=178, starts_line=None, is_jump_target=False, positions=Positions(lineno=13, end_lineno=13, col_offset=18, end_col_offset=25))
def verify(self, node: EnhancedAST, instruction: dis.Instruction) -> None: """ checks if this node could gererate this instruction """
op_name = instruction.opname extra_filter: Callable[[EnhancedAST], bool] = lambda e: True ctx: Type = type(None)
def inst_match(opnames: Union[str, Sequence[str]], **kwargs: Any) -> bool: """ match instruction
Parameters: opnames: (str|Seq[str]): inst.opname has to be equal to or in `opname` **kwargs: every arg has to match inst.arg
Returns: True if all conditions match the instruction
"""
if isinstance(opnames, str): opnames = [opnames] return instruction.opname in opnames and kwargs == { k: getattr(instruction, k) for k in kwargs }
def node_match(node_type: Union[Type, Tuple[Type, ...]], **kwargs: Any) -> bool: """ match the ast-node
Parameters: node_type: type of the node **kwargs: every `arg` has to be equal `node.arg` or `node.arg` has to be an instance of `arg` if it is a type. """ return isinstance(node, node_type) and all( isinstance(getattr(node, k), v) if isinstance(v, type) else getattr(node, k) == v for k, v in kwargs.items() )
if op_name == "CACHE": return
if inst_match("CALL") and node_match((ast.With, ast.AsyncWith)): # call to context.__exit__ return
if inst_match(("CALL", "LOAD_FAST")) and node_match( (ast.ListComp, ast.GeneratorExp, ast.SetComp, ast.DictComp) ): # call to the generator function return
if inst_match(("CALL", "CALL_FUNCTION_EX")) and node_match( (ast.ClassDef, ast.Call) ): return
if inst_match(("COMPARE_OP", "IS_OP", "CONTAINS_OP")) and node_match( ast.Compare ): return
if inst_match("LOAD_NAME", argval="__annotations__") and node_match( ast.AnnAssign ): return
if ( ( inst_match("LOAD_METHOD", argval="join") or inst_match(("CALL", "BUILD_STRING")) ) and node_match(ast.BinOp, left=ast.Constant, op=ast.Mod) and isinstance(cast(ast.Constant, cast(ast.BinOp, node).left).value, str) ): # "..."%(...) uses "".join return
if inst_match("STORE_SUBSCR") and node_match(ast.AnnAssign): # data: int return
if self.is_except_cleanup(instruction, node): return
if inst_match(("DELETE_NAME", "DELETE_FAST")) and node_match( ast.Name, id=instruction.argval, ctx=ast.Del ): return
if inst_match("BUILD_STRING") and ( node_match(ast.JoinedStr) or node_match(ast.BinOp, op=ast.Mod) ): return
if inst_match(("BEFORE_WITH","WITH_EXCEPT_START")) and node_match(ast.With): return
if inst_match(("STORE_NAME", "STORE_GLOBAL"), argval="__doc__") and node_match( ast.Constant ): # store docstrings return
if ( inst_match(("STORE_NAME", "STORE_FAST", "STORE_GLOBAL", "STORE_DEREF")) and node_match(ast.ExceptHandler) and instruction.argval == mangled_name(node) ): # store exception in variable return
if ( inst_match(("STORE_NAME", "STORE_FAST", "STORE_DEREF", "STORE_GLOBAL")) and node_match((ast.Import, ast.ImportFrom)) and any(mangled_name(cast(EnhancedAST, alias)) == instruction.argval for alias in cast(ast.Import, node).names) ): # store imported module in variable return
if ( inst_match(("STORE_FAST", "STORE_DEREF", "STORE_NAME", "STORE_GLOBAL")) and ( node_match((ast.FunctionDef, ast.ClassDef, ast.AsyncFunctionDef)) or node_match( ast.Name, ctx=ast.Store, ) ) and instruction.argval == mangled_name(node) ): return
if False: # TODO: match expressions are not supported for now if inst_match(("STORE_FAST", "STORE_NAME")) and node_match( ast.MatchAs, name=instruction.argval ): return
if inst_match("COMPARE_OP", argval="==") and node_match(ast.MatchSequence): return
if inst_match("COMPARE_OP", argval="==") and node_match(ast.MatchValue): return
if inst_match("BINARY_OP") and node_match( ast.AugAssign, op=op_type_map[instruction.argrepr.removesuffix("=")] ): # a+=5 return
if node_match(ast.Attribute, ctx=ast.Del) and inst_match( "DELETE_ATTR", argval=mangled_name(node) ): return
if inst_match(("JUMP_IF_TRUE_OR_POP", "JUMP_IF_FALSE_OR_POP")) and node_match( ast.BoolOp ): # and/or short circuit return
if inst_match("DELETE_SUBSCR") and node_match(ast.Subscript, ctx=ast.Del): return
if node_match(ast.Name, ctx=ast.Load) and inst_match( ("LOAD_NAME", "LOAD_FAST", "LOAD_GLOBAL"), argval=mangled_name(node) ): return
if node_match(ast.Name, ctx=ast.Del) and inst_match( ("DELETE_NAME", "DELETE_GLOBAL"), argval=mangled_name(node) ): return
# old verifier
typ: Type = type(None) op_type: Type = type(None)
if op_name.startswith(("BINARY_SUBSCR", "SLICE+")): typ = ast.Subscript ctx = ast.Load elif op_name.startswith("BINARY_"): typ = ast.BinOp op_type = op_type_map[instruction.argrepr] extra_filter = lambda e: isinstance(cast(ast.BinOp, e).op, op_type) elif op_name.startswith("UNARY_"): typ = ast.UnaryOp op_type = dict( UNARY_POSITIVE=ast.UAdd, UNARY_NEGATIVE=ast.USub, UNARY_NOT=ast.Not, UNARY_INVERT=ast.Invert, )[op_name] extra_filter = lambda e: isinstance(cast(ast.UnaryOp, e).op, op_type) elif op_name in ("LOAD_ATTR", "LOAD_METHOD", "LOOKUP_METHOD"): typ = ast.Attribute ctx = ast.Load extra_filter = lambda e: mangled_name(e) == instruction.argval elif op_name in ( "LOAD_NAME", "LOAD_GLOBAL", "LOAD_FAST", "LOAD_DEREF", "LOAD_CLASSDEREF", ): typ = ast.Name ctx = ast.Load extra_filter = lambda e: cast(ast.Name, e).id == instruction.argval elif op_name in ("COMPARE_OP", "IS_OP", "CONTAINS_OP"): typ = ast.Compare extra_filter = lambda e: len(cast(ast.Compare, e).ops) == 1 elif op_name.startswith(("STORE_SLICE", "STORE_SUBSCR")): ctx = ast.Store typ = ast.Subscript elif op_name.startswith("STORE_ATTR"): ctx = ast.Store typ = ast.Attribute extra_filter = lambda e: mangled_name(e) == instruction.argval
node_ctx = getattr(node, "ctx", None)
ctx_match = ( ctx is not type(None) or not hasattr(node, "ctx") or isinstance(node_ctx, ctx) )
# check for old verifier if isinstance(node, typ) and ctx_match and extra_filter(node): return
# generate error
title = "ast.%s is not created from %s" % ( type(node).__name__, instruction.opname, )
raise VerifierFailure(title, node, instruction)
E executing._exceptions.VerifierFailure: ast.UnaryOp is not created from CALL_INTRINSIC_1
executing/_position_node_finder.py:545: VerifierFailure =========================== short test summary info ============================ FAILED tests/test_main.py::TestStuff::test_decorator - AssertionError: ([7, 8... FAILED tests/test_main.py::TestStuff::test_decorator_cache_instruction - exec... FAILED tests/test_main.py::TestStuff::test_names - executing._exceptions.Veri... FAILED tests/test_main.py::test_global_tester_calls - executing._exceptions.V... =================== 4 failed, 41 passed, 15 skipped in 3.02s ===================
https://docs.python.org/3.12/whatsnew/3.12.html
For the build logs, see: https://copr-be.cloud.fedoraproject.org/results/@python/python3.12/fedora-ra...
For all our attempts to build python-executing with Python 3.12, see: https://copr.fedorainfracloud.org/coprs/g/python/python3.12/package/python-e...
Testing and mass rebuild of packages is happening in copr. You can follow these instructions to test locally in mock if your package builds with Python 3.12: https://copr.fedorainfracloud.org/coprs/g/python/python3.12/
Let us know here if you have any questions.
Python 3.12 is planned to be included in Fedora 39. To make that update smoother, we're building Fedora packages with all pre-releases of Python 3.12. A build failure prevents us from testing all dependent packages (transitive [Build]Requires), so if this package is required a lot, it's important for us to get it fixed soon. We'd appreciate help from the people who know this package best, but if you don't want to work on this now, let us know so we can try to work around it on our side.
Referenced Bugs:
https://bugzilla.redhat.com/show_bug.cgi?id=2135404 [Bug 2135404] Python 3.12
https://bugzilla.redhat.com/show_bug.cgi?id=2207642
Tomáš Hrnčiar thrnciar@redhat.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |POST
--- Comment #1 from Tomáš Hrnčiar thrnciar@redhat.com --- PR: https://src.fedoraproject.org/rpms/python-executing/pull-request/5
https://bugzilla.redhat.com/show_bug.cgi?id=2207642
Lumír Balhar lbalhar@redhat.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|POST |CLOSED Resolution|--- |RAWHIDE Last Closed| |2023-07-12 13:43:04
--- Comment #2 from Lumír Balhar lbalhar@redhat.com --- The PR is merged and the package has been built for Python 3.12.
epel-packagers-sig@lists.fedoraproject.org