Fedora Account System
Red Hat Associate
Red Hat Customer
python-executing fails to build with Python 3.15.0b2. 16 tests failed: _________________________ TestFiles.test_module_files __________________________ self = <tests.test_main.TestFiles object at 0x7fa12c007d10> def test_module_files(self): self.start_time = time.time() modules = list(sys.modules.values()) shuffle(modules) for module in modules: try: filename = inspect.getsourcefile(module) except TypeError: continue except AttributeError as error: if str(error)== "'_SixMetaPathImporter' object has no attribute '_path'": # work around for https://github.com/benjaminp/six/issues/376 continue raise if not filename: continue filename = os.path.abspath(filename) if ( # The sentinel actually appearing in code messes things up 'executing' in filename # because of: {t[0] for t in lines2} - {t[0] for t in lines1} or 'pytester.py' in filename # A file that's particularly slow or 'errorcodes.py' in filename # Contains unreachable code which pypy removes or PYPY and ( 'sysconfig.py' in filename or 'pyparsing.py' in filename or 'enum' in filename ) or sys.version_info < (3,11) and ( 'python.py' in filename ) ): continue with open(filename) as source: source_text = source.read() if PYPY and "__debug__" in source_text: continue try: > self.check_filename(filename, check_names=False) tests/test_main.py:823: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_main.py:885: in check_filename result = list(self.check_code(code, nodes, decorators, check_names=check_names)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_main.py:1462: in check_code for x in self.check_code(inst.argval, nodes, decorators, check_names=check_names): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_main.py:1462: in check_code for x in self.check_code(inst.argval, nodes, decorators, check_names=check_names): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_main.py:1241: in check_code ex = Source.executing(frame) ^^^^^^^^^^^^^^^^^^^^^^^ executing/executing.py:233: in executing node_finder = NodeFinder(frame, stmts, tree, lasti, source) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ executing/_position_node_finder.py:128: in __init__ self.verify(self.result, instruction) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <executing._position_node_finder.PositionNodeFinder object at 0x7fa126722190> node = Name(id='self', ctx=Load()) instruction = Instruction(opname='CALL', opcode=50, arg=3, argval=3, argrepr='', offset=378, start_offset=378, starts_line=False, li... col_offset=17, end_col_offset=21), cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]) 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","LOAD_FAST_BORROW")) and node_match( (ast.ListComp, ast.GeneratorExp, ast.SetComp, ast.DictComp) ): # call to the generator function return if ( sys.version_info >= (3, 12) and inst_match(("LOAD_FAST_AND_CLEAR", "STORE_FAST")) and node_match((ast.ListComp, ast.SetComp, ast.DictComp)) ): 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("LOAD_ATTR", argval="join") # 3.12 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 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"): arg=instruction.argrepr.removesuffix("=") if arg!="[]" and node_match( ast.AugAssign, op=op_type_map[arg]): # 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", "POP_JUMP_IF_TRUE", "POP_JUMP_IF_FALSE", ) ) 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) or ( node_match(ast.Name, ctx=ast.Store) and isinstance(node.parent, ast.AugAssign) ) ) and inst_match( ( "LOAD_NAME", "LOAD_FAST", "LOAD_FAST_CHECK", "LOAD_FAST_BORROW", "LOAD_GLOBAL", "LOAD_DEREF", "LOAD_FROM_DICT_OR_DEREF", "LOAD_FAST_BORROW_LOAD_FAST_BORROW", ), ) and ( mangled_name(node) in instruction.argval if isinstance(instruction.argval,tuple) else instruction.argval == mangled_name(node) ): return if node_match(ast.Name, ctx=ast.Del) and inst_match( ("DELETE_NAME", "DELETE_GLOBAL", "DELETE_DEREF"), argval=mangled_name(node) ): return if node_match(ast.Constant) and inst_match( ("LOAD_CONST","LOAD_SMALL_INT"), argval=cast(ast.Constant, node).value ): return if node_match( (ast.ListComp, ast.SetComp, ast.DictComp, ast.GeneratorExp, ast.For) ) and inst_match(("GET_ITER", "FOR_ITER")): return if sys.version_info >= (3, 12): if node_match(ast.UnaryOp, op=ast.UAdd) and inst_match( "CALL_INTRINSIC_1", argrepr="INTRINSIC_UNARY_POSITIVE" ): return if node_match(ast.Subscript) and inst_match("BINARY_SLICE"): return if node_match(ast.ImportFrom) and inst_match( "CALL_INTRINSIC_1", argrepr="INTRINSIC_IMPORT_STAR" ): return if ( node_match(ast.Yield) or isinstance(node.parent, ast.GeneratorExp) ) and inst_match("CALL_INTRINSIC_1", argrepr="INTRINSIC_ASYNC_GEN_WRAP"): return if node_match(ast.Name) and inst_match("LOAD_DEREF",argval="__classdict__"): return if node_match(ast.TypeVar) and ( inst_match("CALL_INTRINSIC_1", argrepr="INTRINSIC_TYPEVAR") or inst_match( "CALL_INTRINSIC_2", argrepr="INTRINSIC_TYPEVAR_WITH_BOUND" ) or inst_match( "CALL_INTRINSIC_2", argrepr="INTRINSIC_TYPEVAR_WITH_CONSTRAINTS" ) or inst_match(("STORE_FAST", "STORE_DEREF"), argrepr=mangled_name(node)) ): return if node_match(ast.TypeVarTuple) and ( inst_match("CALL_INTRINSIC_1", argrepr="INTRINSIC_TYPEVARTUPLE") or inst_match(("STORE_FAST", "STORE_DEREF"), argrepr=node.name) ): return if node_match(ast.ParamSpec) and ( inst_match("CALL_INTRINSIC_1", argrepr="INTRINSIC_PARAMSPEC") or inst_match(("STORE_FAST", "STORE_DEREF"), argrepr=node.name)): return if node_match(ast.TypeAlias): if( inst_match("CALL_INTRINSIC_1", argrepr="INTRINSIC_TYPEALIAS") or inst_match( ("STORE_NAME", "STORE_FAST", "STORE_DEREF","STORE_GLOBAL"), argrepr=node.name.id ) or inst_match("CALL") ): return if node_match(ast.ClassDef) and node.type_params: if inst_match( ("STORE_DEREF", "LOAD_DEREF", "LOAD_FROM_DICT_OR_DEREF"), argrepr=".type_params", ): return if inst_match(("STORE_FAST", "LOAD_FAST"), argrepr=".generic_base"): return if inst_match( "CALL_INTRINSIC_1", argrepr="INTRINSIC_SUBSCRIPT_GENERIC" ): return if inst_match("LOAD_DEREF",argval="__classdict__"): return if node_match((ast.FunctionDef,ast.AsyncFunctionDef)) and node.type_params: if inst_match("CALL"): return if inst_match( "CALL_INTRINSIC_2", argrepr="INTRINSIC_SET_FUNCTION_TYPE_PARAMS" ): return if inst_match("LOAD_FAST",argval=".defaults"): return if inst_match("LOAD_FAST",argval=".kwdefaults"): return if sys.version_info >= (3, 14): if inst_match("LOAD_FAST_BORROW_LOAD_FAST_BORROW",argval=(".defaults",".kwdefaults")): return if inst_match("STORE_NAME", argval="__classdictcell__"): # this is a general thing return # f-strings if node_match(ast.JoinedStr) and ( inst_match("LOAD_ATTR", argval="join") or inst_match(("LIST_APPEND", "CALL")) ): return if node_match(ast.FormattedValue) and inst_match("FORMAT_VALUE"): return if sys.version_info >= (3, 13): if inst_match("NOP"): return if inst_match("TO_BOOL") and node_match(ast.BoolOp): return if inst_match("CALL_KW") and node_match((ast.Call, ast.ClassDef)): return if inst_match("LOAD_FAST", argval=".type_params"): return if inst_match("LOAD_FAST", argval="__classdict__"): return if inst_match(("LOAD_FAST","LOAD_FAST_BORROW")) and node_match( ( ast.FunctionDef, ast.ClassDef, ast.TypeAlias, ast.TypeVar, ast.Lambda, ast.AsyncFunctionDef, ) ): # These are loads for closure variables. # It is difficult to check that this is actually closure variable, see: # https://github.com/alexmojaki/executing/pull/80#discussion_r1716027317 return if ( inst_match("LOAD_FAST") and node_match(ast.TypeAlias) and node.name.id == instruction.argval ): return if inst_match("STORE_NAME",argval="__static_attributes__"): # the node is the first node in the body return if inst_match(("LOAD_FAST","LOAD_FAST_BORROW")) and isinstance(node.parent,ast.TypeVar): return if inst_match("CALL_INTRINSIC_2",argrepr="INTRINSIC_SET_TYPEPARAM_DEFAULT") and node_match((ast.TypeVar,ast.ParamSpec,ast.TypeVarTuple)): return if sys.version_info >= (3, 14): if inst_match("BINARY_OP",argrepr="[]") and node_match(ast.Subscript): return if inst_match("LOAD_FAST_BORROW", argval="__classdict__"): return if inst_match(("STORE_NAME","LOAD_NAME"), argval="__conditional_annotations__"): return if inst_match("LOAD_FAST_BORROW_LOAD_FAST_BORROW") and node_match(ast.Name) and node.id in instruction.argval: return if sys.version_info >= (3, 15): if ( inst_match(("LOAD_FAST", "LOAD_FAST_BORROW"), argval=".0") and isinstance(node.parent, ast.comprehension) and node is node.parent.iter ): # In Python 3.15, the LOAD_FAST/LOAD_FAST_BORROW .0 instruction # (which loads the hidden iterator parameter in comprehensions/generator # expressions) has source positions that match the iterator expression 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","LOAD_SUPER_ATTR"): 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:1003: VerifierFailure ----------------------------- Captured stdout call ----------------------------- check /usr/lib64/python3.15/json/__init__.py check /usr/lib64/python3.15/abc.py check /usr/lib64/python3.15/asyncio/timeouts.py check /usr/lib64/python3.15/annotationlib.py check /usr/lib64/python3.15/re/__init__.py check /usr/lib64/python3.15/keyword.py check /usr/lib/python3.15/site-packages/_pytest/_py/error.py check /usr/lib64/python3.15/xml/__init__.py check /usr/lib64/python3.15/bz2.py check /usr/lib64/python3.15/asyncio/sslproto.py check /usr/lib64/python3.15/posixpath.py check /usr/lib64/python3.15/re/_casefix.py check /usr/lib64/python3.15/__future__.py check /usr/lib64/python3.15/importlib/resources/abc.py check /usr/lib/python3.15/site-packages/_pytest/_py/error.py check /usr/lib64/python3.15/argparse.py check /usr/lib64/python3.15/unittest/case.py VerifierFailure: ast.Name is not created from CALL instruction: CALL 3 node: Name(id='self', lineno=244, col_offset=17, end_lineno=244, end_col_offset=21) parent node: withitem source code: 240: try: 241: self.obj_name = callable_obj.__name__ 242: except AttributeError: 243: self.obj_name = str(callable_obj) 244: with self: 245: callable_obj(*args, **kwargs) 246: finally: 247: # bpo-23890: manually break a reference cycle 248: self = None 249: None bytecode: https://docs.python.org/3.15/whatsnew/3.15.html For our attempts to build python-executing with Python 3.15, see: https://koji.fedoraproject.org/koji/search?terms=python-executing&type=package&match=exact Let us know here if you have any questions. Python 3.15 is planned to be included in Fedora 45. To make that update smoother, we're building Fedora packages with all pre-releases of Python 3.15. 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.
https://src.fedoraproject.org/rpms/python-executing/pull-request/21
https://koji.fedoraproject.org/koji/taskinfo?taskID=146583373