Skip to content

Commit

Permalink
Merge master into features (#6458)
Browse files Browse the repository at this point in the history
Merge master into features
  • Loading branch information
nicoddemus authored Jan 14, 2020
2 parents 2d488f7 + b9c136b commit f2659f7
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 34 deletions.
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

0 comments on commit f2659f7

Please sign in to comment.