Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 41 additions & 6 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# evaluating GitHub actions for CI, disconsider failures when evaluating PRs
# evaluating GitHub actions for CI, disregard failures when evaluating PRs
#
# this is still missing:
# - deploy
# - coverage
# - upload github notes
#
name: main
Expand All @@ -11,13 +10,14 @@ on:
push:
branches:
- master
- features
pull_request:
branches:
- master
- features

jobs:
build:

runs-on: ${{ matrix.os }}

strategy:
Expand Down Expand Up @@ -86,6 +86,8 @@ 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
Expand All @@ -94,6 +96,8 @@ 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"
Expand All @@ -118,6 +122,37 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Test
run: tox -e ${{ matrix.tox_env }}
pip install tox coverage

- name: Test without coverage
if: "matrix.skip_coverage"
run: "tox -e ${{ matrix.tox_env }}"

- name: Test with coverage
if: "! matrix.skip_coverage"
env:
_PYTEST_TOX_COVERAGE_RUN: "coverage run -m"
COVERAGE_PROCESS_START: ".coveragerc"
_PYTEST_TOX_EXTRA_DEP: "coverage-enable-subprocess"
run: "tox -e ${{ matrix.tox_env }}"

- name: Prepare coverage token
if: success() && !matrix.skip_coverage && ( github.repository == 'pytest-dev/pytest' || github.event_name == 'pull_request' )
run: |
python scripts/append_codecov_token.py

- name: Combine coverage
if: success() && !matrix.skip_coverage
run: |
python -m coverage combine
python -m coverage xml

- name: Codecov upload
if: success() && !matrix.skip_coverage
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.codecov }}
file: ./coverage.xml
flags: ${{ runner.os }}
fail_ci_if_error: false
name: ${{ matrix.name }}
6 changes: 4 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ jobs:
- env: TOXENV=pypy3-xdist
python: 'pypy3'

- env: TOXENV=py35-xdist
python: '3.5'
# Coverage for Python 3.5.{0,1} specific code, mostly typing related.
- env: TOXENV=py35 PYTEST_COVERAGE=1 PYTEST_ADDOPTS="-k test_raises_cyclic_reference"
python: '3.5.1'
dist: trusty

# Specialized factors for py37.
- env: TOXENV=py37-pluggymaster-xdist
Expand Down
36 changes: 36 additions & 0 deletions scripts/append_codecov_token.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""
Appends the codecov token to the 'codecov.yml' file at the root of the repository.

This is done by CI during PRs and builds on the pytest-dev repository so we can upload coverage, at least
until codecov grows some native integration like it has with Travis and AppVeyor.

See discussion in https://github.com/pytest-dev/pytest/pull/6441 for more information.
"""
import os.path
from textwrap import dedent


def main():
this_dir = os.path.dirname(__file__)
cov_file = os.path.join(this_dir, "..", "codecov.yml")

assert os.path.isfile(cov_file), "{cov_file} does not exist".format(
cov_file=cov_file
)

with open(cov_file, "a") as f:
# token from: https://codecov.io/gh/pytest-dev/pytest/settings
# use same URL to regenerate it if needed
text = dedent(
"""
codecov:
token: "1eca3b1f-31a2-4fb8-a8c3-138b441b50a7"
"""
)
f.write(text)

print("Token updated:", cov_file)


if __name__ == "__main__":
main()
2 changes: 1 addition & 1 deletion src/_pytest/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ def write(self, s) -> int:
return self._other.write(s)


if sys.version_info < (3, 5, 2): # pragma: no cover
if sys.version_info < (3, 5, 2):

def overload(f): # noqa: F811
return f
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/config/findpaths.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def get_dir_from_path(path):


def determine_setup(
inifile: str,
inifile: Optional[str],
args: List[str],
rootdir_cmd_arg: Optional[str] = None,
config: Optional["Config"] = None,
Expand Down
2 changes: 1 addition & 1 deletion testing/python/raises.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def __call__(self):
# Early versions of Python 3.5 have some bug causing the
# __call__ frame to still refer to t even after everything
# is done. This makes the test pass for them.
if sys.version_info < (3, 5, 2): # pragma: no cover
if sys.version_info < (3, 5, 2):
del self
raise ValueError

Expand Down
18 changes: 9 additions & 9 deletions testing/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ def test_simple_noini(self, tmpdir):
assert get_common_ancestor([no_path.join("a")]) == tmpdir

@pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
def test_with_ini(self, tmpdir, name):
def test_with_ini(self, tmpdir, name) -> None:
inifile = tmpdir.join(name)
inifile.write("[pytest]\n" if name != "setup.cfg" else "[tool:pytest]\n")

Expand All @@ -874,15 +874,15 @@ def test_with_ini(self, tmpdir, name):
assert inifile == inifile

@pytest.mark.parametrize("name", "setup.cfg tox.ini".split())
def test_pytestini_overrides_empty_other(self, tmpdir, name):
def test_pytestini_overrides_empty_other(self, tmpdir, name) -> None:
inifile = tmpdir.ensure("pytest.ini")
a = tmpdir.mkdir("a")
a.ensure(name)
rootdir, inifile, inicfg = determine_setup(None, [a])
assert rootdir == tmpdir
assert inifile == inifile

def test_setuppy_fallback(self, tmpdir):
def test_setuppy_fallback(self, tmpdir) -> None:
a = tmpdir.mkdir("a")
a.ensure("setup.cfg")
tmpdir.ensure("setup.py")
Expand All @@ -891,14 +891,14 @@ def test_setuppy_fallback(self, tmpdir):
assert inifile is None
assert inicfg == {}

def test_nothing(self, tmpdir, monkeypatch):
def test_nothing(self, tmpdir, monkeypatch) -> None:
monkeypatch.chdir(str(tmpdir))
rootdir, inifile, inicfg = determine_setup(None, [tmpdir])
assert rootdir == tmpdir
assert inifile is None
assert inicfg == {}

def test_with_specific_inifile(self, tmpdir):
def test_with_specific_inifile(self, tmpdir) -> None:
inifile = tmpdir.ensure("pytest.ini")
rootdir, inifile, inicfg = determine_setup(inifile, [tmpdir])
assert rootdir == tmpdir
Expand Down Expand Up @@ -1039,15 +1039,15 @@ def test():
result = testdir.runpytest("--override-ini", "python_files=unittest_*.py")
result.stdout.fnmatch_lines(["*1 passed in*"])

def test_with_arg_outside_cwd_without_inifile(self, tmpdir, monkeypatch):
def test_with_arg_outside_cwd_without_inifile(self, tmpdir, monkeypatch) -> None:
monkeypatch.chdir(str(tmpdir))
a = tmpdir.mkdir("a")
b = tmpdir.mkdir("b")
rootdir, inifile, inicfg = determine_setup(None, [a, b])
assert rootdir == tmpdir
assert inifile is None

def test_with_arg_outside_cwd_with_inifile(self, tmpdir):
def test_with_arg_outside_cwd_with_inifile(self, tmpdir) -> None:
a = tmpdir.mkdir("a")
b = tmpdir.mkdir("b")
inifile = a.ensure("pytest.ini")
Expand All @@ -1056,13 +1056,13 @@ def test_with_arg_outside_cwd_with_inifile(self, tmpdir):
assert inifile == parsed_inifile

@pytest.mark.parametrize("dirs", ([], ["does-not-exist"], ["a/does-not-exist"]))
def test_with_non_dir_arg(self, dirs, tmpdir):
def test_with_non_dir_arg(self, dirs, tmpdir) -> None:
with tmpdir.ensure(dir=True).as_cwd():
rootdir, inifile, inicfg = determine_setup(None, dirs)
assert rootdir == tmpdir
assert inifile is None

def test_with_existing_file_in_subdir(self, tmpdir):
def test_with_existing_file_in_subdir(self, tmpdir) -> None:
a = tmpdir.mkdir("a")
a.ensure("exist")
with tmpdir.as_cwd():
Expand Down
51 changes: 39 additions & 12 deletions testing/test_reports.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import sys

import pytest
from _pytest._code.code import ExceptionChainRepr
from _pytest.pathlib import Path
Expand Down Expand Up @@ -314,27 +316,52 @@ def check_longrepr(longrepr):
# elsewhere and we do check the contents of the longrepr object after loading it.
loaded_report.longrepr.toterminal(tw_mock)

def test_chained_exceptions_no_reprcrash(
self, testdir, tw_mock,
):
def test_chained_exceptions_no_reprcrash(self, testdir, tw_mock):
"""Regression test for tracebacks without a reprcrash (#5971)

This happens notably on exceptions raised by multiprocess.pool: the exception transfer
from subprocess to main process creates an artificial exception, which ExceptionInfo
can't obtain the ReprFileLocation from.
"""
testdir.makepyfile(
# somehow in Python 3.5 on Windows this test fails with:
# File "c:\...\3.5.4\x64\Lib\multiprocessing\connection.py", line 302, in _recv_bytes
# overlapped=True)
# OSError: [WinError 6] The handle is invalid
#
# so in this platform we opted to use a mock traceback which is identical to the
# one produced by the multiprocessing module
if sys.version_info[:2] <= (3, 5) and sys.platform.startswith("win"):
testdir.makepyfile(
"""
# equivalent of multiprocessing.pool.RemoteTraceback
class RemoteTraceback(Exception):
def __init__(self, tb):
self.tb = tb
def __str__(self):
return self.tb
def test_a():
try:
raise ValueError('value error')
except ValueError as e:
# equivalent to how multiprocessing.pool.rebuild_exc does it
e.__cause__ = RemoteTraceback('runtime error')
raise e
"""
from concurrent.futures import ProcessPoolExecutor
)
else:
testdir.makepyfile(
"""
from concurrent.futures import ProcessPoolExecutor

def func():
raise ValueError('value error')
def func():
raise ValueError('value error')

def test_a():
with ProcessPoolExecutor() as p:
p.submit(func).result()
"""
)

def test_a():
with ProcessPoolExecutor() as p:
p.submit(func).result()
"""
)
reprec = testdir.inline_run()

reports = reprec.getreports("pytest_runtest_logreport")
Expand Down
4 changes: 2 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ passenv = USER USERNAME COVERAGE_* TRAVIS PYTEST_ADDOPTS TERM
setenv =
_PYTEST_TOX_DEFAULT_POSARGS={env:_PYTEST_TOX_POSARGS_LSOF:} {env:_PYTEST_TOX_POSARGS_XDIST:}

# Configuration to run with coverage similar to Travis/Appveyor, e.g.
# Configuration to run with coverage similar to CI, e.g.
# "tox -e py37-coverage".
coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m
coverage: _PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess
Expand All @@ -53,7 +53,7 @@ deps =
skip_install = True
basepython = python3
deps = pre-commit>=1.11.0
commands = pre-commit run --all-files --show-diff-on-failure
commands = pre-commit run --all-files --show-diff-on-failure {posargs:}

[testenv:docs]
basepython = python3
Expand Down