Skip to content

Commit 06a7fef

Browse files
authored
Merge pull request #6616 from blueyed/merge-master-into-features
Merge master into features
2 parents 3ccf2a5 + 55e5817 commit 06a7fef

File tree

9 files changed

+85
-19
lines changed

9 files changed

+85
-19
lines changed

.github/workflows/main.yml

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ jobs:
5454
python: "3.5"
5555
os: windows-latest
5656
tox_env: "py35-xdist"
57+
use_coverage: true
5758
- name: "windows-py36"
5859
python: "3.6"
5960
os: windows-latest
@@ -70,6 +71,7 @@ jobs:
7071
python: "3.8"
7172
os: windows-latest
7273
tox_env: "py38"
74+
use_coverage: true
7375

7476
- name: "ubuntu-py35"
7577
python: "3.5"
@@ -83,6 +85,7 @@ jobs:
8385
python: "3.7"
8486
os: ubuntu-latest
8587
tox_env: "py37-lsof-numpy-oldattrs-pexpect-twisted"
88+
use_coverage: true
8689
- name: "ubuntu-py37-pluggy"
8790
python: "3.7"
8891
os: ubuntu-latest
@@ -91,8 +94,6 @@ jobs:
9194
python: "3.7"
9295
os: ubuntu-latest
9396
tox_env: "py37-freeze"
94-
# coverage does not apply for freeze test, skip it
95-
skip_coverage: true
9697
- name: "ubuntu-py38"
9798
python: "3.8"
9899
os: ubuntu-latest
@@ -101,8 +102,6 @@ jobs:
101102
python: "pypy3"
102103
os: ubuntu-latest
103104
tox_env: "pypy3-xdist"
104-
# coverage too slow with pypy3, skip it
105-
skip_coverage: true
106105

107106
- name: "macos-py37"
108107
python: "3.7"
@@ -112,21 +111,21 @@ jobs:
112111
python: "3.8"
113112
os: macos-latest
114113
tox_env: "py38-xdist"
114+
use_coverage: true
115115

116116
- name: "linting"
117117
python: "3.7"
118118
os: ubuntu-latest
119119
tox_env: "linting"
120-
skip_coverage: true
121120
- name: "docs"
122121
python: "3.7"
123122
os: ubuntu-latest
124123
tox_env: "docs"
125-
skip_coverage: true
126124
- name: "doctesting"
127125
python: "3.7"
128126
os: ubuntu-latest
129127
tox_env: "doctesting"
128+
use_coverage: true
130129

131130
steps:
132131
- uses: actions/checkout@v1
@@ -140,24 +139,24 @@ jobs:
140139
pip install tox coverage
141140
142141
- name: Test without coverage
143-
if: "matrix.skip_coverage"
142+
if: "! matrix.use_coverage"
144143
run: "tox -e ${{ matrix.tox_env }}"
145144

146145
- name: Test with coverage
147-
if: "! matrix.skip_coverage"
146+
if: "matrix.use_coverage"
148147
env:
149148
_PYTEST_TOX_COVERAGE_RUN: "coverage run -m"
150149
COVERAGE_PROCESS_START: ".coveragerc"
151150
_PYTEST_TOX_EXTRA_DEP: "coverage-enable-subprocess"
152151
run: "tox -e ${{ matrix.tox_env }}"
153152

154153
- name: Prepare coverage token
155-
if: (!matrix.skip_coverage && ( github.repository == 'pytest-dev/pytest' || github.event_name == 'pull_request' ))
154+
if: (matrix.use_coverage && ( github.repository == 'pytest-dev/pytest' || github.event_name == 'pull_request' ))
156155
run: |
157156
python scripts/append_codecov_token.py
158157
159158
- name: Report coverage
160-
if: (!matrix.skip_coverage)
159+
if: (matrix.use_coverage)
161160
env:
162161
CODECOV_NAME: ${{ matrix.name }}
163162
run: bash scripts/report-coverage.sh -F GHA,${{ runner.os }}

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ Guido Wesdorp
114114
Guoqiang Zhang
115115
Harald Armin Massa
116116
Henk-Jaap Wagenaar
117+
Holger Kohr
117118
Hugo van Kemenade
118119
Hui Wang (coldnight)
119120
Ian Bicking

changelog/6497.bugfix.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix bug in the comparison of request key with cached key in fixture.
2+
3+
A construct ``if key == cached_key:`` can fail either because ``==`` is explicitly disallowed, or for, e.g., NumPy arrays, where the result of ``a == b`` cannot generally be converted to `bool`.
4+
The implemented fix replaces `==` with ``is``.

src/_pytest/_code/code.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,11 @@ def path(self) -> Union[py.path.local, str]:
7777
# maybe don't try this checking
7878
if not p.check():
7979
raise OSError("py.path check failed.")
80+
return p
8081
except OSError:
8182
# XXX maybe try harder like the weird logic
8283
# in the standard lib [linecache.updatecache] does?
83-
p = self.raw.co_filename
84-
85-
return p
84+
return self.raw.co_filename
8685

8786
@property
8887
def fullsource(self) -> Optional["Source"]:

src/_pytest/fixtures.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,9 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef") -> None:
548548
frameinfo = inspect.getframeinfo(frame[0])
549549
source_path = py.path.local(frameinfo.filename)
550550
source_lineno = frameinfo.lineno
551-
if source_path.relto(funcitem.config.rootdir):
552-
source_path_str = source_path.relto(funcitem.config.rootdir)
551+
rel_source_path = source_path.relto(funcitem.config.rootdir)
552+
if rel_source_path:
553+
source_path_str = rel_source_path
553554
else:
554555
source_path_str = str(source_path)
555556
msg = (
@@ -896,7 +897,9 @@ def execute(self, request):
896897
cached_result = getattr(self, "cached_result", None)
897898
if cached_result is not None:
898899
result, cache_key, err = cached_result
899-
if my_cache_key == cache_key:
900+
# note: comparison with `==` can fail (or be expensive) for e.g.
901+
# numpy arrays (#6497)
902+
if my_cache_key is cache_key:
900903
if err is not None:
901904
_, val, tb = err
902905
raise val.with_traceback(tb)

src/_pytest/monkeypatch.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import sys
55
import warnings
66
from contextlib import contextmanager
7+
from typing import Generator
78

89
import pytest
910
from _pytest.fixtures import fixture
@@ -108,7 +109,7 @@ def __init__(self):
108109
self._savesyspath = None
109110

110111
@contextmanager
111-
def context(self):
112+
def context(self) -> Generator["MonkeyPatch", None, None]:
112113
"""
113114
Context manager that returns a new :class:`MonkeyPatch` object which
114115
undoes any patching done inside the ``with`` block upon exit:

src/_pytest/python_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ def raises( # noqa: F811
685685
"""
686686
__tracebackhide__ = True
687687
for exc in filterfalse(
688-
inspect.isclass, always_iterable(expected_exception, BASE_TYPE)
688+
inspect.isclass, always_iterable(expected_exception, BASE_TYPE) # type: ignore[arg-type] # noqa: F821
689689
):
690690
msg = "exceptions must be derived from BaseException, not %s"
691691
raise TypeError(msg % type(exc))

testing/python/fixtures.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,38 @@ def test_nothing(badscope):
11021102
"*Fixture 'badscope' from test_invalid_scope.py got an unexpected scope value 'functions'"
11031103
)
11041104

1105+
@pytest.mark.parametrize("scope", ["function", "session"])
1106+
def test_parameters_without_eq_semantics(self, scope, testdir):
1107+
testdir.makepyfile(
1108+
"""
1109+
class NoEq1: # fails on `a == b` statement
1110+
def __eq__(self, _):
1111+
raise RuntimeError
1112+
1113+
class NoEq2: # fails on `if a == b:` statement
1114+
def __eq__(self, _):
1115+
class NoBool:
1116+
def __bool__(self):
1117+
raise RuntimeError
1118+
return NoBool()
1119+
1120+
import pytest
1121+
@pytest.fixture(params=[NoEq1(), NoEq2()], scope={scope!r})
1122+
def no_eq(request):
1123+
return request.param
1124+
1125+
def test1(no_eq):
1126+
pass
1127+
1128+
def test2(no_eq):
1129+
pass
1130+
""".format(
1131+
scope=scope
1132+
)
1133+
)
1134+
result = testdir.runpytest()
1135+
result.stdout.fnmatch_lines(["*4 passed*"])
1136+
11051137
def test_funcarg_parametrized_and_used_twice(self, testdir):
11061138
testdir.makepyfile(
11071139
"""
@@ -3662,13 +3694,30 @@ def test_foo(request):
36623694
" test_foos.py::test_foo",
36633695
"",
36643696
"Requested fixture 'fix_with_param' defined in:",
3665-
"*fix.py:4",
3697+
"{}:4".format(fixfile),
36663698
"Requested here:",
36673699
"test_foos.py:4",
36683700
"*1 failed*",
36693701
]
36703702
)
36713703

3704+
# With non-overlapping rootdir, passing tests_dir.
3705+
rootdir = testdir.mkdir("rootdir")
3706+
rootdir.chdir()
3707+
result = testdir.runpytest("--rootdir", rootdir, tests_dir)
3708+
result.stdout.fnmatch_lines(
3709+
[
3710+
"The requested fixture has no parameter defined for test:",
3711+
" test_foos.py::test_foo",
3712+
"",
3713+
"Requested fixture 'fix_with_param' defined in:",
3714+
"{}:4".format(fixfile),
3715+
"Requested here:",
3716+
"{}:4".format(testfile),
3717+
"*1 failed*",
3718+
]
3719+
)
3720+
36723721

36733722
def test_pytest_fixture_setup_and_post_finalizer_hook(testdir):
36743723
testdir.makeconftest(

testing/test_pytester.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,3 +704,13 @@ def test_error2(bad_fixture):
704704
result.assert_outcomes(error=2)
705705

706706
assert result.parseoutcomes() == {"error": 2}
707+
708+
709+
def test_makefile_joins_absolute_path(testdir: Testdir) -> None:
710+
absfile = testdir.tmpdir / "absfile"
711+
if sys.platform == "win32":
712+
with pytest.raises(OSError):
713+
testdir.makepyfile(**{str(absfile): ""})
714+
else:
715+
p1 = testdir.makepyfile(**{str(absfile): ""})
716+
assert str(p1) == (testdir.tmpdir / absfile) + ".py"

0 commit comments

Comments
 (0)