From bf62c21ea0590f15872c15a26d3b33ad84a6c91c Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Tue, 27 Dec 2022 06:57:18 -0500 Subject: [PATCH] fix: adjust some PyPy behaviors. #1515 --- CHANGES.rst | 4 +++- coverage/env.py | 7 ++++++- tests/helpers.py | 7 +++---- tests/test_arcs.py | 8 ++------ tests/test_coverage.py | 4 ---- tests/test_parser.py | 7 +++---- 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index e92b3768b..ae3428cd6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -20,7 +20,9 @@ development at the same time, such as 4.5.x and 5.0. Unreleased ---------- -Nothing yet. +- Fix: adjusted how decorators are traced on PyPy 7.3.10, fixing `issue 1515`_. + +.. _issue 1515: https://github.com/nedbat/coveragepy/issues/1515 .. _changes_7-0-1: diff --git a/coverage/env.py b/coverage/env.py index f77f22ee5..96143dc71 100644 --- a/coverage/env.py +++ b/coverage/env.py @@ -67,11 +67,16 @@ class PYBEHAVIOR: # does the finally jump back to the break/continue/return (3.8) to do the # work? finally_jumps_back = ((3, 8) <= PYVERSION < (3, 10)) + if PYPY and PYPYVERSION < (7, 3, 7): + finally_jumps_back = False # When a function is decorated, does the trace function get called for the # @-line and also the def-line (new behavior in 3.8)? Or just the @-line # (old behavior)? - trace_decorated_def = (CPYTHON and PYVERSION >= (3, 8)) or (PYPY and PYVERSION >= (3, 9)) + trace_decorated_def = ( + (PYVERSION >= (3, 8)) and + (CPYTHON or (PYVERSION > (3, 8)) or (PYPYVERSION > (7, 3, 9))) + ) # Functions are no longer claimed to start at their earliest decorator even though # the decorators are traced? diff --git a/tests/helpers.py b/tests/helpers.py index fbdf13978..725bd3407 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -317,8 +317,7 @@ def swallow_warnings(message=r".", category=CoverageWarning): warnings.filterwarnings("ignore", category=category, message=message) yield - -xfail_pypy_3749 = pytest.mark.xfail( - env.PYVERSION[:2] == (3, 8) and env.PYPY and env.PYPYVERSION >= (7, 3, 10), - reason="Avoid a PyPy bug: https://foss.heptapod.net/pypy/pypy/-/issues/3749", +xfail_pypy38 = pytest.mark.xfail( + env.PYVERSION[:2] == (3, 8) and env.PYPY, + reason="Not sure why these few tests fail on PyPy 3.8 still", ) diff --git a/tests/test_arcs.py b/tests/test_arcs.py index df7d00014..58683f9d4 100644 --- a/tests/test_arcs.py +++ b/tests/test_arcs.py @@ -6,7 +6,7 @@ import pytest from tests.coveragetest import CoverageTest -from tests.helpers import assert_count_equal, xfail_pypy_3749 +from tests.helpers import assert_count_equal, xfail_pypy38 import coverage from coverage import env @@ -1645,7 +1645,6 @@ def f(a, b): class DecoratorArcTest(CoverageTest): """Tests of arcs with decorators.""" - @xfail_pypy_3749 def test_function_decorator(self): arcz = ( ".1 16 67 7A AE EF F. " # main line @@ -1674,7 +1673,7 @@ def my_function( arcz=arcz, ) - @xfail_pypy_3749 + @xfail_pypy_adhoc def test_class_decorator(self): arcz = ( ".1 16 67 6D 7A AE E. " # main line @@ -1702,7 +1701,6 @@ class MyObject( arcz=arcz, ) - @xfail_pypy_3749 def test_bug_466a(self): # A bad interaction between decorators and multi-line list assignments, # believe it or not...! @@ -1727,7 +1725,6 @@ def parse(cls): arcz=arcz, ) - @xfail_pypy_3749 def test_bug_466b(self): # A bad interaction between decorators and multi-line list assignments, # believe it or not...! @@ -1919,7 +1916,6 @@ async def go(): arcz_missing=arcz_missing, ) - @xfail_pypy_3749 def test_async_decorator(self): arcz = ".1 14 4. .2 2. -46 6-4 " if env.PYBEHAVIOR.trace_decorated_def: diff --git a/tests/test_coverage.py b/tests/test_coverage.py index b9e5d6ae1..17da4f5e5 100644 --- a/tests/test_coverage.py +++ b/tests/test_coverage.py @@ -10,7 +10,6 @@ from coverage.exceptions import NoDataError from tests.coveragetest import CoverageTest -from tests.helpers import xfail_pypy_3749 class TestCoverageTest(CoverageTest): @@ -1618,7 +1617,6 @@ def test_excluded_comprehension_branches(self): class Py24Test(CoverageTest): """Tests of new syntax in Python 2.4.""" - @xfail_pypy_3749 def test_function_decorators(self): lines = [1, 2, 3, 4, 6, 8, 10, 12] if env.PYBEHAVIOR.trace_decorated_def: @@ -1639,7 +1637,6 @@ def p1(arg): """, lines, "") - @xfail_pypy_3749 def test_function_decorators_with_args(self): lines = [1, 2, 3, 4, 5, 6, 8, 10, 12] if env.PYBEHAVIOR.trace_decorated_def: @@ -1660,7 +1657,6 @@ def boosted(arg): """, lines, "") - @xfail_pypy_3749 def test_double_function_decorators(self): lines = [1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 14, 15, 17, 19, 21, 22, 24, 26] if env.PYBEHAVIOR.trace_decorated_def: diff --git a/tests/test_parser.py b/tests/test_parser.py index b13c32fef..24f20f703 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -15,7 +15,7 @@ from coverage.parser import ast_dump, PythonParser from tests.coveragetest import CoverageTest, TESTS_DIR -from tests.helpers import arcz_to_arcs, re_lines, xfail_pypy_3749 +from tests.helpers import arcz_to_arcs, re_lines, xfail_pypy_38 class PythonParserTest(CoverageTest): @@ -140,7 +140,7 @@ def test_token_error(self): ''' """) - @xfail_pypy_3749 + @xfail_pypy_38 def test_decorator_pragmas(self): parser = self.parse_source("""\ # 1 @@ -176,7 +176,7 @@ def func(x=25): assert parser.raw_statements == raw_statements assert parser.statements == {8} - @xfail_pypy_3749 + @xfail_pypy_38 def test_decorator_pragmas_with_colons(self): # A colon in a decorator expression would confuse the parser, # ending the exclusion of the decorated function. @@ -211,7 +211,6 @@ def __init__(self): assert parser.raw_statements == {1, 2, 3, 5, 6, 7, 8} assert parser.statements == {1, 2, 3} - @xfail_pypy_3749 def test_empty_decorated_function(self): parser = self.parse_source("""\ def decorator(func):