diff --git a/.ci/report-coverage.sh b/.ci/report-coverage.sh new file mode 100755 index 00000000000..4e6ec06b257 --- /dev/null +++ b/.ci/report-coverage.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +set -ex + +# Set --connect-timeout to work around https://github.com/curl/curl/issues/4461 +curl -S -L --connect-timeout 5 --retry 6 -s -o /tmp/codecov.sh https://codecov.io/bash + +for _ in 1 2 3 4 5; do + bash /tmp/codecov.sh -Z -X fix -f coverage.xml "$@" && break +done diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000000..4ae0877cd67 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,202 @@ +name: main + +on: + push: + branches: + - my-4.6-maintenance + - "[0-9]+.[0-9]+.x" + tags: + - "*" + pull_request: + +jobs: + tests: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + name: [ + "ubuntu-py39", + "ubuntu-py38", + "ubuntu-py38 (pexpect, integration)", + "ubuntu-pypy3", + + "macos-py36", + + "windows-py37 (1)", + "windows-py37 (2)", + + "xdist", + + "linting", + "docs", + "doctesting", + "mypy", + ] + + include: + - name: "ubuntu-py39" + python: "3.9" + os: ubuntu-latest + tox_env: "py39-coverage" + - name: "ubuntu-py38" + python: "3.8" + os: ubuntu-latest + tox_env: "py38-numpy-oldattrs-twisted-coverage" + - name: "ubuntu-pypy3" + python: "pypy3" + os: ubuntu-latest + tox_env: "pypy3-coverage" + pytest_addopts: "-m 'pypy_specific or acceptance_tests'" + - name: "ubuntu-py38 (pexpect, integration)" + python: "3.8" + os: ubuntu-latest + # NOTE: the lsof factor is not really useful currently, with its + # warnings being ignored. This uses it here only to cover the + # LsofFdLeakChecker itself. + # (https://github.com/blueyed/pytest/issues/195) + tox_env: "py38-lsof-pexpect-coverage" + pytest_addopts: "-m 'uses_pexpect or integration'" + script_prefix: "env -u COLUMNS" + + # Coverage for: + # - osx + # - pygments + # - verbosity=1 + - name: "macos-py36" + python: "3.6" + os: macos-latest + tox_env: "py36-pygments-coverage" + pytest_addopts: "--verbosity=1" + + - name: "windows-py37 (1)" + python: "3.7" + os: windows-latest + tox_env: "py37-coverage-grouped" + # Coverage for: + # - verbosity=2 + pytest_addopts: "--verbosity=2 --test-group-count 2 --test-group=1" + - name: "windows-py37 (2)" + python: "3.7" + os: windows-latest + tox_env: "py37-coverage-grouped" + # Coverage for: + # - verbosity=2 + pytest_addopts: "--verbosity=2 --test-group-count 2 --test-group=2" + + - name: "xdist" + python: "3.8" + os: ubuntu-latest + tox_env: "py38-xdist-coverage" + pytest_addopts: "-m 'xdist_specific or acceptance_tests' -n 0" + + - name: "linting" + python: "3.8" + os: ubuntu-latest + tox_env: "linting_ci" + - name: "docs" + python: "3.8" + os: ubuntu-latest + tox_env: "docs" + - name: "doctesting" + python: "3.8" + os: ubuntu-latest + tox_env: "doctesting-coverage" + - name: "mypy" + python: "3.8" + os: ubuntu-latest + tox_env: "mypy_ci" + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 2000 + - run: git fetch --tags origin + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python }} + + # Caching. + - name: set PY_CACHE_KEY + run: echo "PY_CACHE_KEY=$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')" >> $GITHUB_ENV + - name: Cache .tox + if: (matrix.tox_env != 'docs') + uses: actions/cache@v1 + with: + path: ${{ github.workspace }}/.tox/${{ matrix.tox_env }} + key: "tox|${{ matrix.tox_env }}|${{ env.PY_CACHE_KEY }}|${{ hashFiles('tox.ini', 'setup.*') }}" + - name: Cache .tox (docs) + if: (matrix.tox_env == 'docs') + uses: actions/cache@v1 + with: + path: ${{ github.workspace }}/.tox/${{ matrix.tox_env }} + # Work around tox not rebuilding on changed requirements file (https://github.com/tox-dev/tox/issues/149). + key: "tox|${{ matrix.tox_env }}|${{ env.PY_CACHE_KEY }}|${{ hashFiles('tox.ini', 'setup.*', 'doc/en/requirements.txt') }}" + - name: Cache .pre-commit + if: (matrix.tox_env == 'linting_ci') + uses: actions/cache@v1 + with: + path: ~/.cache/pre-commit + key: pre-commit|${{ env.PY_CACHE_KEY }}|${{ hashFiles('.pre-commit-config.yaml') }} + + - name: Install tox / version information + env: + PIP_DISABLE_PIP_VERSION_CHECK: "1" + run: | + python -m pip --version + python -m pip install git+https://github.com/blueyed/tox@master + python -m pip list + + - name: Setup tox environment + id: setup_tox + run: python -m tox --notest -v --durations -e ${{ matrix.tox_env }} + + - name: Test + env: + PYTEST_ADDOPTS: "-ra --durations=50 ${{ matrix.pytest_addopts }}" + COLUMNS: "120" + # UTF-8 mode for Windows (https://docs.python.org/3/using/windows.html#utf-8-mode). + PYTHONUTF8: "1" + TOX_TESTENV_PASSENV: "PYTHONUTF8" + run: "${{ matrix.script_prefix }} tox -e ${{ matrix.tox_env }}" + + - name: Report coverage + if: always() && (contains(matrix.tox_env, '-coverage') && (steps.setup_tox.outcome == 'success')) + env: + CODECOV_TOKEN: d79f3a85-e675-4d75-8f55-3d0e4a99ebe8 + run: "bash .ci/report-coverage.sh -n '${{ matrix.name }}' -F 'GHA,${{ runner.os }}'" + + deploy: + if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') && github.repository == 'pytest-dev/pytest' + runs-on: ubuntu-latest + needs: [tests] + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 2000 + - run: git fetch --tags origin + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: "3.7" + - name: Install dependencies + run: | + python -m pip --version + python -m pip install wheel setuptools git+https://github.com/blueyed/tox@master + - name: Build package + run: | + python setup.py sdist bdist_wheel + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.pypi_token }} + - name: Publish GitHub release notes + env: + GH_RELEASE_NOTES_TOKEN: ${{ secrets.release_notes }} + run: | + sudo apt-get install pandoc + tox -e publish-gh-release-notes + diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b8d73a5e020..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,80 +0,0 @@ -language: python -dist: xenial -python: '3.7.4' -cache: false - -env: - global: - - PYTEST_ADDOPTS="-vv --showlocals --durations=100 --exitfirst" - - PYTEST_COVERAGE=1 - - TOX=git+https://github.com/blueyed/tox@master - - TOX_EXTRA_ARGS=--durations - -# setuptools-scm needs all tags in order to obtain a proper version -git: - depth: false - -install: - - python -m pip install $TOX - -jobs: - include: - # Coverage for: - # - TestArgComplete (linux only) - # - numpy - # - verbose=0 - # - test_sys_breakpoint_interception (via pexpect). - - stage: baseline - env: TOXENV=py38-xdist - python: '3.8' - - - env: TOXENV=py27-xdist - python: '2.7' - - - stage: tests - env: TOXENV=py37-numpy-pexpect-twisted - python: '3.7.4' - - - env: TOXENV=py36-xdist PYTEST_REORDER_TESTS=0 - python: '3.6.9' - - - env: TOXENV=py35-xdist - python: '3.5.9' - - - env: - - TOXENV=py34-xdist - - TOX='tox==3.14.0' # tox 3.14.1 dropped support for py34. - - TOX_EXTRA_ARGS= # no --durations. - python: '3.4' - - - env: TOXENV=linting,docs,doctesting - cache: - directories: - - $HOME/.cache/pre-commit - -before_script: - - | - # Do not (re-)upload coverage with cron runs. - if [[ "$TRAVIS_EVENT_TYPE" = cron ]]; then - PYTEST_COVERAGE=0 - fi - - | - if [[ "$PYTEST_COVERAGE" = 1 ]]; then - export COVERAGE_FILE="$PWD/.coverage" - export COVERAGE_PROCESS_START="$PWD/.coveragerc" - export _PYTEST_TOX_COVERAGE_RUN="coverage run -m" - export _PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess - fi - - python -m tox --notest -v $TOX_EXTRA_ARGS - -script: env COLUMNS=120 python -m tox -v $TOX_EXTRA_ARGS - -after_success: - - | - if [[ "$PYTEST_COVERAGE" = 1 ]]; then - env CODECOV_NAME="$TOXENV-$TRAVIS_OS_NAME" scripts/report-coverage.sh - fi - -branches: - only: - - my-4.6-maintenance diff --git a/tox.ini b/tox.ini index 1c838ff5b02..0ff94f9c99d 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,6 @@ isolated_build = True minversion = 3.5.3 distshare = {homedir}/.tox/distshare -# make sure to update environment list in travis.yml and appveyor.yml envlist = linting py27 @@ -11,6 +10,7 @@ envlist = py36 py37 py38 + py39 pypy pypy3 {py27,py37}-{pexpect,xdist,twisted,numpy,pluggymaster} @@ -22,39 +22,43 @@ envlist = [testenv] commands = {env:_PYTEST_TOX_COVERAGE_RUN:} pytest {posargs:{env:_PYTEST_TOX_DEFAULT_POSARGS:}} + doctesting: {env:_PYTEST_TOX_COVERAGE_RUN:} pytest --doctest-modules --pyargs _pytest coverage: coverage combine - coverage: coverage report -passenv = USER USERNAME COVERAGE_* TRAVIS PYTEST_ADDOPTS + coverage: coverage report -m + coverage: coverage xml +ignore_errors = true +passenv = USER USERNAME COVERAGE_* PYTEST_ADDOPTS PYTEST_REORDER_TESTS TERM COLUMNS + coverage: CODECOV_* CI CI_* GITHUB_* TRAVIS TRAVIS_* setenv = - _PYTEST_TOX_DEFAULT_POSARGS={env:_PYTEST_TOX_POSARGS_LSOF:} {env:_PYTEST_TOX_POSARGS_PEXPECT:} {env:_PYTEST_TOX_POSARGS_TWISTED:} {env:_PYTEST_TOX_POSARGS_XDIST:} + _PYTEST_TOX_DEFAULT_POSARGS={env:_PYTEST_TOX_POSARGS_DOCTESTING:} {env:_PYTEST_TOX_POSARGS_LSOF:} - # 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 coverage: COVERAGE_FILE={toxinidir}/.coverage coverage: COVERAGE_PROCESS_START={toxinidir}/.coveragerc + doctesting: _PYTEST_TOX_POSARGS_DOCTESTING=doc/en + grouped: PYTEST_REORDER_TESTS={env:PYTEST_REORDER_TESTS:0} nobyte: PYTHONDONTWRITEBYTECODE=1 - lsof: _PYTEST_TOX_POSARGS_LSOF=--lsof - - pexpect: _PYTEST_TOX_PLATFORM=linux|darwin - pexpect: _PYTEST_TOX_POSARGS_PEXPECT=-m uses_pexpect - - twisted: _PYTEST_TOX_POSARGS_TWISTED=testing/test_unittest.py - - xdist: _PYTEST_TOX_POSARGS_XDIST=-n auto + oldattrs: _PYTEST_TOX_TWISTED=twisted<20.3.0 + xdist: PYTEST_ADDOPTS=-n auto {env:PYTEST_ADDOPTS:} extras = testing deps = + doctesting: PyYAML + grouped: pytest-test-groups + oldattrs: attrs==17.4.0 numpy: numpy pexpect: pexpect pluggymaster: git+https://github.com/pytest-dev/pluggy.git@master - twisted: twisted - twisted: unittest2 - xdist: pytest-xdist>=1.13,<2 + pygments: pygments + twisted: {env:_PYTEST_TOX_TWISTED:twisted} + xdist: pytest-xdist>=1.13 {env:_PYTEST_TOX_EXTRA_DEP:} -platform = {env:_PYTEST_TOX_PLATFORM:.*} + # Pin pylib for Windows (pending investigation of test failures). + py>=1.5.0,!=1.8.2,<1.9.0 ; sys_platform == 'win32' [testenv:py27-subprocess] deps = @@ -69,7 +73,37 @@ commands = 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:} + +# Special env to massage pre-commit config for CI: +# - removes mypy config from there, which gets run (more precise) via +# separate mypy env. +# - removes black config: fine if you want to use it via pre-commit/manually, +# but does not need to be enforced (slow, issues). +[testenv:linting_ci] +skip_install = True +basepython = python3 +deps = {[testenv:linting]deps} +whitelist_externals = sh +ignore_errors = false +commands = + sh -c "sed -e '/^- repo: .*mirrors-mypy/,/^ \+args:/ d' -e '/^- repo: .*black$/,/^ \+args:/ d' .pre-commit-config.yaml > {envtmpdir}/pc.yaml" + pre-commit run --all-files --show-diff-on-failure --config {envtmpdir}/pc.yaml {posargs:} + +[testenv:mypy] +deps = +extras = checkqa-mypy, testing +commands = mypy {posargs:src testing} + +# Checks default (configured) python_version, and the minimal one. +[testenv:mypy_ci] +deps = {[testenv:mypy]deps} +extras = {[testenv:mypy]extras} +whitelist_externals = sh +commands = + mypy {posargs:src testing} + mypy --python-version 3.5 --warn-unused-ignores {posargs:src testing} + sh scripts/check-mypy-pyi.sh [testenv:docs] basepython = python3 @@ -116,9 +150,9 @@ commands = [testenv:py37-freeze] changedir = testing/freeze -# Disable PEP 517 with pip, which does not work with PyInstaller currently. deps = pyinstaller +ignore_errors = false commands = {envpython} create_executable.py {envpython} tox_run.py