From 0b913873b9db8c157a8dd581e8771242bcb8864b Mon Sep 17 00:00:00 2001 From: Frank Hoffmann <15r10nk-git@polarbit.de> Date: Fri, 16 Aug 2024 22:51:32 +0200 Subject: [PATCH 1/4] fix: backward compatibility fix for changed source positions in 3.12.5 (#82) --- executing/_position_node_finder.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) Index: executing-2.0.1/executing/_position_node_finder.py =================================================================== --- executing-2.0.1.orig/executing/_position_node_finder.py +++ executing-2.0.1/executing/_position_node_finder.py @@ -156,6 +156,8 @@ class PositionNodeFinder(object): typ=typ, ) + self.result = self.fix_result(self.result, self.instruction(lasti)) + self.known_issues(self.result, self.instruction(lasti)) self.test_for_decorator(self.result, lasti) @@ -213,6 +215,32 @@ class PositionNodeFinder(object): if sys.version_info < (3, 12): index += 4 + def fix_result( + self, node: EnhancedAST, instruction: dis.Instruction + ) -> EnhancedAST: + if ( + sys.version_info >= (3, 12, 5) + and instruction.opname in ("GET_ITER", "FOR_ITER") + and isinstance(node.parent, ast.For) + and node is node.parent.iter + ): + # node positions have changed in 3.12.5 + # https://github.com/python/cpython/issues/93691 + # `for` calls __iter__ and __next__ during execution, the calling + # expression of these calls was the ast.For node since cpython 3.11 (see test_iter). + # cpython 3.12.5 changed this to the `iter` node of the loop, to make tracebacks easier to read. + # This keeps backward compatibility with older executing versions. + + # there are also cases like: + # + # for a in iter(l): pass + # + # where `iter(l)` would be otherwise the resulting node for the `iter()` call and the __iter__ call of the for implementation. + # keeping the old behaviour makes it possible to distinguish both cases. + + return node.parent + return node + def known_issues(self, node: EnhancedAST, instruction: dis.Instruction) -> None: if instruction.opname in ("COMPARE_OP", "IS_OP", "CONTAINS_OP") and isinstance( node, types_cmp_issue Index: executing-2.0.1/.github/workflows/test.yml =================================================================== --- executing-2.0.1.orig/.github/workflows/test.yml +++ executing-2.0.1/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8, 3.9, '3.10', 3.11, 3.12-dev, pypy-3.6] + python-version: [3.8, 3.9, '3.10', 3.11, 3.12-dev] steps: - uses: actions/checkout@v2 Index: executing-2.0.1/setup.cfg =================================================================== --- executing-2.0.1.orig/setup.cfg +++ executing-2.0.1/setup.cfg @@ -25,7 +25,7 @@ packages = executing zip_safe = False include_package_data = True setup_requires = setuptools; setuptools_scm[toml] -python_requires = >=3.5 +python_requires = >=3.8 [options.extras_require] tests = Index: executing-2.0.1/tox.ini =================================================================== --- executing-2.0.1.orig/tox.ini +++ executing-2.0.1/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py35,py36,py37,py38,py39,py310,py311,py312,pypy35,pypy36 +envlist = py38,py39,py310,py311,py312,pypy35,pypy36 [testenv] commands = @@ -10,7 +10,7 @@ passenv = ADD_EXECUTING_TESTS EXECUTING_SLOW_TESTS -[testenv:generate_small_sample-py{35,36,37,38,39,310,311}] +[testenv:generate_small_sample-py{38,39,310,311,312}] extras = tests deps = pysource-minimize commands = Index: executing-2.0.1/tests/test_main.py =================================================================== --- executing-2.0.1.orig/tests/test_main.py +++ executing-2.0.1/tests/test_main.py @@ -802,6 +802,9 @@ class TestFiles: or 'pyparsing.py' in filename or 'enum' in filename ) + or sys.version_info < (3,11) and ( + 'python.py' in filename + ) ): continue