Merge master into features
This commit is contained in:
commit
55e5817570
|
@ -54,6 +54,7 @@ jobs:
|
|||
python: "3.5"
|
||||
os: windows-latest
|
||||
tox_env: "py35-xdist"
|
||||
use_coverage: true
|
||||
- name: "windows-py36"
|
||||
python: "3.6"
|
||||
os: windows-latest
|
||||
|
@ -70,6 +71,7 @@ jobs:
|
|||
python: "3.8"
|
||||
os: windows-latest
|
||||
tox_env: "py38"
|
||||
use_coverage: true
|
||||
|
||||
- name: "ubuntu-py35"
|
||||
python: "3.5"
|
||||
|
@ -83,6 +85,7 @@ jobs:
|
|||
python: "3.7"
|
||||
os: ubuntu-latest
|
||||
tox_env: "py37-lsof-numpy-oldattrs-pexpect-twisted"
|
||||
use_coverage: true
|
||||
- name: "ubuntu-py37-pluggy"
|
||||
python: "3.7"
|
||||
os: ubuntu-latest
|
||||
|
@ -91,8 +94,6 @@ jobs:
|
|||
python: "3.7"
|
||||
os: ubuntu-latest
|
||||
tox_env: "py37-freeze"
|
||||
# coverage does not apply for freeze test, skip it
|
||||
skip_coverage: true
|
||||
- name: "ubuntu-py38"
|
||||
python: "3.8"
|
||||
os: ubuntu-latest
|
||||
|
@ -101,8 +102,6 @@ jobs:
|
|||
python: "pypy3"
|
||||
os: ubuntu-latest
|
||||
tox_env: "pypy3-xdist"
|
||||
# coverage too slow with pypy3, skip it
|
||||
skip_coverage: true
|
||||
|
||||
- name: "macos-py37"
|
||||
python: "3.7"
|
||||
|
@ -112,21 +111,21 @@ jobs:
|
|||
python: "3.8"
|
||||
os: macos-latest
|
||||
tox_env: "py38-xdist"
|
||||
use_coverage: true
|
||||
|
||||
- name: "linting"
|
||||
python: "3.7"
|
||||
os: ubuntu-latest
|
||||
tox_env: "linting"
|
||||
skip_coverage: true
|
||||
- name: "docs"
|
||||
python: "3.7"
|
||||
os: ubuntu-latest
|
||||
tox_env: "docs"
|
||||
skip_coverage: true
|
||||
- name: "doctesting"
|
||||
python: "3.7"
|
||||
os: ubuntu-latest
|
||||
tox_env: "doctesting"
|
||||
use_coverage: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
@ -140,11 +139,11 @@ jobs:
|
|||
pip install tox coverage
|
||||
|
||||
- name: Test without coverage
|
||||
if: "matrix.skip_coverage"
|
||||
if: "! matrix.use_coverage"
|
||||
run: "tox -e ${{ matrix.tox_env }}"
|
||||
|
||||
- name: Test with coverage
|
||||
if: "! matrix.skip_coverage"
|
||||
if: "matrix.use_coverage"
|
||||
env:
|
||||
_PYTEST_TOX_COVERAGE_RUN: "coverage run -m"
|
||||
COVERAGE_PROCESS_START: ".coveragerc"
|
||||
|
@ -152,12 +151,12 @@ jobs:
|
|||
run: "tox -e ${{ matrix.tox_env }}"
|
||||
|
||||
- name: Prepare coverage token
|
||||
if: (!matrix.skip_coverage && ( github.repository == 'pytest-dev/pytest' || github.event_name == 'pull_request' ))
|
||||
if: (matrix.use_coverage && ( github.repository == 'pytest-dev/pytest' || github.event_name == 'pull_request' ))
|
||||
run: |
|
||||
python scripts/append_codecov_token.py
|
||||
|
||||
- name: Report coverage
|
||||
if: (!matrix.skip_coverage)
|
||||
if: (matrix.use_coverage)
|
||||
env:
|
||||
CODECOV_NAME: ${{ matrix.name }}
|
||||
run: bash scripts/report-coverage.sh -F GHA,${{ runner.os }}
|
||||
|
|
1
AUTHORS
1
AUTHORS
|
@ -114,6 +114,7 @@ Guido Wesdorp
|
|||
Guoqiang Zhang
|
||||
Harald Armin Massa
|
||||
Henk-Jaap Wagenaar
|
||||
Holger Kohr
|
||||
Hugo van Kemenade
|
||||
Hui Wang (coldnight)
|
||||
Ian Bicking
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Fix bug in the comparison of request key with cached key in fixture.
|
||||
|
||||
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`.
|
||||
The implemented fix replaces `==` with ``is``.
|
|
@ -77,12 +77,11 @@ class Code:
|
|||
# maybe don't try this checking
|
||||
if not p.check():
|
||||
raise OSError("py.path check failed.")
|
||||
return p
|
||||
except OSError:
|
||||
# XXX maybe try harder like the weird logic
|
||||
# in the standard lib [linecache.updatecache] does?
|
||||
p = self.raw.co_filename
|
||||
|
||||
return p
|
||||
return self.raw.co_filename
|
||||
|
||||
@property
|
||||
def fullsource(self) -> Optional["Source"]:
|
||||
|
|
|
@ -548,8 +548,9 @@ class FixtureRequest:
|
|||
frameinfo = inspect.getframeinfo(frame[0])
|
||||
source_path = py.path.local(frameinfo.filename)
|
||||
source_lineno = frameinfo.lineno
|
||||
if source_path.relto(funcitem.config.rootdir):
|
||||
source_path_str = source_path.relto(funcitem.config.rootdir)
|
||||
rel_source_path = source_path.relto(funcitem.config.rootdir)
|
||||
if rel_source_path:
|
||||
source_path_str = rel_source_path
|
||||
else:
|
||||
source_path_str = str(source_path)
|
||||
msg = (
|
||||
|
@ -896,7 +897,9 @@ class FixtureDef:
|
|||
cached_result = getattr(self, "cached_result", None)
|
||||
if cached_result is not None:
|
||||
result, cache_key, err = cached_result
|
||||
if my_cache_key == cache_key:
|
||||
# note: comparison with `==` can fail (or be expensive) for e.g.
|
||||
# numpy arrays (#6497)
|
||||
if my_cache_key is cache_key:
|
||||
if err is not None:
|
||||
_, val, tb = err
|
||||
raise val.with_traceback(tb)
|
||||
|
|
|
@ -4,6 +4,7 @@ import re
|
|||
import sys
|
||||
import warnings
|
||||
from contextlib import contextmanager
|
||||
from typing import Generator
|
||||
|
||||
import pytest
|
||||
from _pytest.fixtures import fixture
|
||||
|
@ -108,7 +109,7 @@ class MonkeyPatch:
|
|||
self._savesyspath = None
|
||||
|
||||
@contextmanager
|
||||
def context(self):
|
||||
def context(self) -> Generator["MonkeyPatch", None, None]:
|
||||
"""
|
||||
Context manager that returns a new :class:`MonkeyPatch` object which
|
||||
undoes any patching done inside the ``with`` block upon exit:
|
||||
|
|
|
@ -685,7 +685,7 @@ def raises( # noqa: F811
|
|||
"""
|
||||
__tracebackhide__ = True
|
||||
for exc in filterfalse(
|
||||
inspect.isclass, always_iterable(expected_exception, BASE_TYPE)
|
||||
inspect.isclass, always_iterable(expected_exception, BASE_TYPE) # type: ignore[arg-type] # noqa: F821
|
||||
):
|
||||
msg = "exceptions must be derived from BaseException, not %s"
|
||||
raise TypeError(msg % type(exc))
|
||||
|
|
|
@ -1102,6 +1102,38 @@ class TestFixtureUsages:
|
|||
"*Fixture 'badscope' from test_invalid_scope.py got an unexpected scope value 'functions'"
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize("scope", ["function", "session"])
|
||||
def test_parameters_without_eq_semantics(self, scope, testdir):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
class NoEq1: # fails on `a == b` statement
|
||||
def __eq__(self, _):
|
||||
raise RuntimeError
|
||||
|
||||
class NoEq2: # fails on `if a == b:` statement
|
||||
def __eq__(self, _):
|
||||
class NoBool:
|
||||
def __bool__(self):
|
||||
raise RuntimeError
|
||||
return NoBool()
|
||||
|
||||
import pytest
|
||||
@pytest.fixture(params=[NoEq1(), NoEq2()], scope={scope!r})
|
||||
def no_eq(request):
|
||||
return request.param
|
||||
|
||||
def test1(no_eq):
|
||||
pass
|
||||
|
||||
def test2(no_eq):
|
||||
pass
|
||||
""".format(
|
||||
scope=scope
|
||||
)
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(["*4 passed*"])
|
||||
|
||||
def test_funcarg_parametrized_and_used_twice(self, testdir):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
|
@ -3662,13 +3694,30 @@ class TestParameterizedSubRequest:
|
|||
" test_foos.py::test_foo",
|
||||
"",
|
||||
"Requested fixture 'fix_with_param' defined in:",
|
||||
"*fix.py:4",
|
||||
"{}:4".format(fixfile),
|
||||
"Requested here:",
|
||||
"test_foos.py:4",
|
||||
"*1 failed*",
|
||||
]
|
||||
)
|
||||
|
||||
# With non-overlapping rootdir, passing tests_dir.
|
||||
rootdir = testdir.mkdir("rootdir")
|
||||
rootdir.chdir()
|
||||
result = testdir.runpytest("--rootdir", rootdir, tests_dir)
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"The requested fixture has no parameter defined for test:",
|
||||
" test_foos.py::test_foo",
|
||||
"",
|
||||
"Requested fixture 'fix_with_param' defined in:",
|
||||
"{}:4".format(fixfile),
|
||||
"Requested here:",
|
||||
"{}:4".format(testfile),
|
||||
"*1 failed*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_pytest_fixture_setup_and_post_finalizer_hook(testdir):
|
||||
testdir.makeconftest(
|
||||
|
|
|
@ -704,3 +704,13 @@ def test_testdir_outcomes_with_multiple_errors(testdir):
|
|||
result.assert_outcomes(error=2)
|
||||
|
||||
assert result.parseoutcomes() == {"error": 2}
|
||||
|
||||
|
||||
def test_makefile_joins_absolute_path(testdir: Testdir) -> None:
|
||||
absfile = testdir.tmpdir / "absfile"
|
||||
if sys.platform == "win32":
|
||||
with pytest.raises(OSError):
|
||||
testdir.makepyfile(**{str(absfile): ""})
|
||||
else:
|
||||
p1 = testdir.makepyfile(**{str(absfile): ""})
|
||||
assert str(p1) == (testdir.tmpdir / absfile) + ".py"
|
||||
|
|
Loading…
Reference in New Issue