Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
180f93158e | ||
|
|
f1d7aa60b1 | ||
|
|
ded772b288 | ||
|
|
3d470555e8 | ||
|
|
2a5ca51fe8 | ||
|
|
a6029ff2b7 | ||
|
|
020831d868 | ||
|
|
c5831ac98f | ||
|
|
f606fef19d | ||
|
|
24898e0640 | ||
|
|
b39b867967 |
191
.github/workflows/main.yml
vendored
Normal file
191
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
name: main
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 4.6.x
|
||||||
|
tags:
|
||||||
|
- "*"
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- 4.6.x
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
name: [
|
||||||
|
"windows-py27",
|
||||||
|
"windows-py35",
|
||||||
|
"windows-py36",
|
||||||
|
"windows-py37",
|
||||||
|
"windows-py37-pluggy",
|
||||||
|
"windows-py38",
|
||||||
|
|
||||||
|
"ubuntu-py27-pluggy",
|
||||||
|
"ubuntu-py27-nobyte",
|
||||||
|
"ubuntu-py37",
|
||||||
|
"ubuntu-py37-pluggy",
|
||||||
|
"ubuntu-py37-pexpect-py37-twisted",
|
||||||
|
"ubuntu-py37-freeze",
|
||||||
|
"ubuntu-pypy",
|
||||||
|
"ubuntu-pypy3",
|
||||||
|
|
||||||
|
"macos-py27",
|
||||||
|
"macos-py38",
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
include:
|
||||||
|
# Windows jobs
|
||||||
|
- name: "windows-py27"
|
||||||
|
python: "2.7"
|
||||||
|
os: windows-latest
|
||||||
|
tox_env: "py27-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "windows-py35"
|
||||||
|
python: "3.5"
|
||||||
|
os: windows-latest
|
||||||
|
tox_env: "py35-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "windows-py36"
|
||||||
|
python: "3.6"
|
||||||
|
os: windows-latest
|
||||||
|
tox_env: "py36-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "windows-py37"
|
||||||
|
python: "3.7"
|
||||||
|
os: windows-latest
|
||||||
|
tox_env: "py37-twisted-numpy"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "windows-py37-pluggy"
|
||||||
|
python: "3.7"
|
||||||
|
os: windows-latest
|
||||||
|
tox_env: "py37-pluggymaster-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "windows-py38"
|
||||||
|
python: "3.8"
|
||||||
|
os: windows-latest
|
||||||
|
tox_env: "py38-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
|
||||||
|
# Ubuntu jobs – find the rest of them in .travis.yml
|
||||||
|
- name: "ubuntu-py27-pluggy"
|
||||||
|
python: "2.7"
|
||||||
|
os: ubuntu-latest
|
||||||
|
tox_env: "py27-pluggymaster-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "ubuntu-py27-nobyte"
|
||||||
|
python: "2.7"
|
||||||
|
os: ubuntu-latest
|
||||||
|
tox_env: "py27-nobyte-numpy-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "ubuntu-py37"
|
||||||
|
python: "3.7"
|
||||||
|
os: ubuntu-latest
|
||||||
|
tox_env: "py37-lsof-numpy-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "ubuntu-py37-pluggy"
|
||||||
|
python: "3.7"
|
||||||
|
os: ubuntu-latest
|
||||||
|
tox_env: "py37-pluggymaster-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "ubuntu-py37-pexpect-py37-twisted"
|
||||||
|
python: "3.7"
|
||||||
|
os: ubuntu-latest
|
||||||
|
tox_env: "py37-pexpect,py37-twisted"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "ubuntu-py37-freeze"
|
||||||
|
python: "3.7"
|
||||||
|
os: ubuntu-latest
|
||||||
|
tox_env: "py37-freeze"
|
||||||
|
- name: "ubuntu-pypy"
|
||||||
|
python: "pypy2"
|
||||||
|
os: ubuntu-latest
|
||||||
|
tox_env: "pypy-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "ubuntu-pypy3"
|
||||||
|
python: "pypy3"
|
||||||
|
os: ubuntu-latest
|
||||||
|
tox_env: "pypy3-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
|
||||||
|
# MacOS jobs
|
||||||
|
- name: "macos-py27"
|
||||||
|
python: "2.7"
|
||||||
|
os: macos-latest
|
||||||
|
tox_env: "py27-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
- name: "macos-py38"
|
||||||
|
python: "3.8"
|
||||||
|
os: macos-latest
|
||||||
|
tox_env: "py38-xdist"
|
||||||
|
use_coverage: true
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Set up Python ${{ matrix.python }} on ${{ matrix.os }}
|
||||||
|
uses: actions/setup-python@v1
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install tox coverage
|
||||||
|
- name: Test without coverage
|
||||||
|
if: "! matrix.use_coverage"
|
||||||
|
run: "tox -e ${{ matrix.tox_env }}"
|
||||||
|
|
||||||
|
- name: Test with coverage
|
||||||
|
if: "matrix.use_coverage"
|
||||||
|
env:
|
||||||
|
_PYTEST_TOX_COVERAGE_RUN: "coverage run -m"
|
||||||
|
COVERAGE_PROCESS_START: ".coveragerc"
|
||||||
|
_PYTEST_TOX_EXTRA_DEP: "coverage-enable-subprocess"
|
||||||
|
run: "tox -vv -e ${{ matrix.tox_env }}"
|
||||||
|
|
||||||
|
- name: Prepare coverage token
|
||||||
|
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.use_coverage)
|
||||||
|
env:
|
||||||
|
CODECOV_NAME: ${{ matrix.name }}
|
||||||
|
run: bash scripts/report-coverage.sh -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: [build]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v1
|
||||||
|
with:
|
||||||
|
python-version: "3.7"
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install --upgrade wheel setuptools tox
|
||||||
|
- 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
|
||||||
162
.travis.yml
162
.travis.yml
@@ -1,17 +1,12 @@
|
|||||||
language: python
|
language: python
|
||||||
dist: xenial
|
dist: xenial
|
||||||
stages:
|
python: '3.7.4'
|
||||||
- baseline
|
|
||||||
- name: test
|
|
||||||
if: repo = pytest-dev/pytest AND tag IS NOT present
|
|
||||||
- name: deploy
|
|
||||||
if: repo = pytest-dev/pytest AND tag IS present
|
|
||||||
python: '3.7'
|
|
||||||
cache: false
|
cache: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- PYTEST_ADDOPTS=-vv
|
- PYTEST_ADDOPTS="-vv --showlocals --durations=100 --exitfirst"
|
||||||
|
- PYTEST_COVERAGE=1
|
||||||
|
|
||||||
# setuptools-scm needs all tags in order to obtain a proper version
|
# setuptools-scm needs all tags in order to obtain a proper version
|
||||||
git:
|
git:
|
||||||
@@ -22,113 +17,44 @@ install:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
# OSX tests - first (in test stage), since they are the slower ones.
|
|
||||||
- &test-macos
|
|
||||||
os: osx
|
|
||||||
osx_image: xcode10.1
|
|
||||||
language: generic
|
|
||||||
# Coverage for:
|
|
||||||
# - py2 with symlink in test_cmdline_python_package_symlink.
|
|
||||||
env: TOXENV=py27-xdist PYTEST_COVERAGE=1
|
|
||||||
before_install:
|
|
||||||
- python -V
|
|
||||||
- test $(python -c 'import sys; print("%d%d" % sys.version_info[0:2])') = 27
|
|
||||||
- <<: *test-macos
|
|
||||||
env: TOXENV=py37-pexpect,py37-xdist PYTEST_COVERAGE=1
|
|
||||||
before_install:
|
|
||||||
- which python3
|
|
||||||
- python3 -V
|
|
||||||
- ln -sfn "$(which python3)" /usr/local/bin/python
|
|
||||||
- python -V
|
|
||||||
- test $(python -c 'import sys; print("%d%d" % sys.version_info[0:2])') = 37
|
|
||||||
|
|
||||||
# Full run of latest (major) supported versions, without xdist.
|
|
||||||
- env: TOXENV=py27
|
|
||||||
python: '2.7'
|
|
||||||
- env: TOXENV=py37
|
|
||||||
python: '3.7'
|
|
||||||
|
|
||||||
# Coverage tracking is slow with pypy, skip it.
|
|
||||||
- env: TOXENV=pypy-xdist
|
|
||||||
python: 'pypy'
|
|
||||||
- env: TOXENV=pypy3-xdist
|
|
||||||
python: 'pypy3'
|
|
||||||
|
|
||||||
- env: TOXENV=py34-xdist
|
|
||||||
python: '3.4'
|
|
||||||
- env: TOXENV=py35-xdist
|
|
||||||
python: '3.5'
|
|
||||||
|
|
||||||
# Coverage for:
|
# Coverage for:
|
||||||
# - pytester's LsofFdLeakChecker
|
|
||||||
# - TestArgComplete (linux only)
|
# - TestArgComplete (linux only)
|
||||||
# - numpy
|
# - numpy
|
||||||
# Empty PYTEST_ADDOPTS to run this non-verbose.
|
# - verbose=0
|
||||||
- env: TOXENV=py37-lsof-numpy-xdist PYTEST_COVERAGE=1 PYTEST_ADDOPTS=
|
|
||||||
|
|
||||||
# Specialized factors for py27.
|
|
||||||
- env: TOXENV=py27-nobyte-numpy-xdist
|
|
||||||
python: '2.7'
|
|
||||||
- env: TOXENV=py27-pluggymaster-xdist
|
|
||||||
python: '2.7'
|
|
||||||
|
|
||||||
# Specialized factors for py37.
|
|
||||||
# Coverage for:
|
|
||||||
# - test_sys_breakpoint_interception (via pexpect).
|
|
||||||
- env: TOXENV=py37-pexpect,py37-twisted PYTEST_COVERAGE=1
|
|
||||||
- env: TOXENV=py37-pluggymaster-xdist
|
|
||||||
- env: TOXENV=py37-freeze
|
|
||||||
|
|
||||||
# Jobs only run via Travis cron jobs (currently daily).
|
|
||||||
- env: TOXENV=py38-xdist
|
|
||||||
python: '3.8-dev'
|
|
||||||
if: type = cron
|
|
||||||
|
|
||||||
- stage: baseline
|
- stage: baseline
|
||||||
# Coverage for:
|
env: TOXENV=py27-xdist
|
||||||
# - _pytest.unittest._handle_skip (via pexpect).
|
|
||||||
env: TOXENV=py27-pexpect,py27-twisted PYTEST_COVERAGE=1
|
|
||||||
python: '2.7'
|
python: '2.7'
|
||||||
# Use py36 here for faster baseline.
|
|
||||||
- env: TOXENV=py36-xdist
|
- env: TOXENV=py38-xdist
|
||||||
python: '3.6'
|
python: '3.8'
|
||||||
- env: TOXENV=linting,docs,doctesting PYTEST_COVERAGE=1
|
|
||||||
|
- stage: tests
|
||||||
|
# - _pytest.unittest._handle_skip (via pexpect).
|
||||||
|
env: TOXENV=py27-pexpect,py27-twisted
|
||||||
|
python: '2.7'
|
||||||
|
|
||||||
|
- env: TOXENV=py35-xdist
|
||||||
|
python: '3.5.9'
|
||||||
|
|
||||||
|
- env: TOXENV=py36-xdist PYTEST_REORDER_TESTS=0
|
||||||
|
python: '3.6.9'
|
||||||
|
|
||||||
|
- env: TOXENV=py37-numpy-pexpect-twisted
|
||||||
|
python: '3.7.4'
|
||||||
|
|
||||||
|
# - test_sys_breakpoint_interception (via pexpect).
|
||||||
|
- env: TOXENV=py37-pexpect,py37-twisted
|
||||||
|
python: '3.7.4'
|
||||||
|
|
||||||
|
# Run also non-verbosely, to gain coverage
|
||||||
|
- env: TOXENV=py38-xdist PYTEST_ADDOPTS=""
|
||||||
|
python: '3.8'
|
||||||
|
|
||||||
|
- env: TOXENV=linting,docs,doctesting
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- $HOME/.cache/pre-commit
|
- $HOME/.cache/pre-commit
|
||||||
|
|
||||||
- stage: deploy
|
|
||||||
python: '3.6'
|
|
||||||
install: pip install -U setuptools setuptools_scm tox
|
|
||||||
script: skip
|
|
||||||
# token to upload github release notes: GH_RELEASE_NOTES_TOKEN
|
|
||||||
env:
|
|
||||||
- secure: "OjOeL7/0JUDkV00SsTs732e8vQjHynpbG9FKTNtZZJ+1Zn4Cib+hAlwmlBnvVukML0X60YpcfjnC4quDOIGLPsh5zeXnvJmYtAIIUNQXjWz8NhcGYrhyzuP1rqV22U68RTCdmOq3lMYU/W2acwHP7T49PwJtOiUM5kF120UAQ0Zi5EmkqkIvH8oM5mO9Dlver+/U7Htpz9rhKrHBXQNCMZI6yj2aUyukqB2PN2fjAlDbCF//+FmvYw9NjT4GeFOSkTCf4ER9yfqs7yglRfwiLtOCZ2qKQhWZNsSJDB89rxIRXWavJUjJKeY2EW2/NkomYJDpqJLIF4JeFRw/HhA47CYPeo6BJqyyNV+0CovL1frpWfi9UQw2cMbgFUkUIUk3F6DD59PHNIOX2R/HX56dQsw7WKl3QuHlCOkICXYg8F7Ta684IoKjeTX03/6QNOkURfDBwfGszY0FpbxrjCSWKom6RyZdyidnESaxv9RzjcIRZVh1rp8KMrwS1OrwRSdG0zjlsPr49hWMenN/8fKgcHTV4/r1Tj6mip0dorSRCrgUNIeRBKgmui6FS8642ab5JNKOxMteVPVR2sFuhjOQ0Jy+PmvceYY9ZMWc3+/B/KVh0dZ3hwvLGZep/vxDS2PwCA5/xw31714vT5LxidKo8yECjBynMU/wUTTS695D3NY="
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
# required by publish_gh_release_notes
|
|
||||||
- pandoc
|
|
||||||
after_deploy: tox -e publish_gh_release_notes
|
|
||||||
deploy:
|
|
||||||
provider: pypi
|
|
||||||
user: nicoddemus
|
|
||||||
distributions: sdist bdist_wheel
|
|
||||||
skip_upload_docs: true
|
|
||||||
password:
|
|
||||||
secure: xanTgTUu6XDQVqB/0bwJQXoDMnU5tkwZc5koz6mBkkqZhKdNOi2CLoC1XhiSZ+ah24l4V1E0GAqY5kBBcy9d7NVe4WNg4tD095LsHw+CRU6/HCVIFfyk2IZ+FPAlguesCcUiJSXOrlBF+Wj68wEvLoK7EoRFbJeiZ/f91Ww1sbtDlqXABWGHrmhPJL5Wva7o7+wG7JwJowqdZg1pbQExsCc7b53w4v2RBu3D6TJaTAzHiVsW+nUSI67vKI/uf+cR/OixsTfy37wlHgSwihYmrYLFls3V0bSpahCim3bCgMaFZx8S8xrdgJ++PzBCof2HeflFKvW+VCkoYzGEG4NrTWJoNz6ni4red9GdvfjGH3YCjAKS56h9x58zp2E5rpsb/kVq5/45xzV+dq6JRuhQ1nJWjBC6fSKAc/bfwnuFK3EBxNLkvBssLHvsNjj5XG++cB8DdS9wVGUqjpoK4puaXUWFqy4q3S9F86HEsKNgExtieA9qNx+pCIZVs6JCXZNjr0I5eVNzqJIyggNgJG6RyravsU35t9Zd9doL5g4Y7UKmAGTn1Sz24HQ4sMQgXdm2SyD8gEK5je4tlhUvfGtDvMSlstq71kIn9nRpFnqB6MFlbYSEAZmo8dGbCquoUc++6Rum208wcVbrzzVtGlXB/Ow9AbFMYeAGA0+N/K1e59c=
|
|
||||||
on:
|
|
||||||
tags: true
|
|
||||||
repo: pytest-dev/pytest
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- python: '3.8-dev'
|
|
||||||
env: TOXENV=py38-xdist
|
|
||||||
# Temporary (https://github.com/pytest-dev/pytest/pull/5334).
|
|
||||||
- env: TOXENV=pypy3-xdist
|
|
||||||
python: 'pypy3'
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- |
|
- |
|
||||||
# Do not (re-)upload coverage with cron runs.
|
# Do not (re-)upload coverage with cron runs.
|
||||||
@@ -142,27 +68,13 @@ before_script:
|
|||||||
export _PYTEST_TOX_COVERAGE_RUN="coverage run -m"
|
export _PYTEST_TOX_COVERAGE_RUN="coverage run -m"
|
||||||
export _PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess
|
export _PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess
|
||||||
fi
|
fi
|
||||||
|
script: env COLUMNS=120 python -m tox
|
||||||
script: tox
|
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- |
|
- |
|
||||||
if [[ "$PYTEST_COVERAGE" = 1 ]]; then
|
if [[ "$PYTEST_COVERAGE" = 1 ]]; then
|
||||||
set -e
|
env CODECOV_NAME="$TOXENV-$TRAVIS_OS_NAME" scripts/report-coverage.sh
|
||||||
# Add last TOXENV to $PATH.
|
|
||||||
PATH="$PWD/.tox/${TOXENV##*,}/bin:$PATH"
|
|
||||||
coverage combine
|
|
||||||
coverage xml
|
|
||||||
coverage report -m
|
|
||||||
bash <(curl -s https://codecov.io/bash) -Z -X gcov -X coveragepy -X search -X xcode -X gcovout -X fix -f coverage.xml -n $TOXENV-$TRAVIS_OS_NAME
|
|
||||||
fi
|
fi
|
||||||
|
branches:
|
||||||
notifications:
|
only:
|
||||||
irc:
|
- 4.6.x
|
||||||
channels:
|
|
||||||
- "chat.freenode.net#pytest"
|
|
||||||
on_success: change
|
|
||||||
on_failure: change
|
|
||||||
skip_join: true
|
|
||||||
email:
|
|
||||||
- pytest-commit@python.org
|
|
||||||
|
|||||||
1
AUTHORS
1
AUTHORS
@@ -92,6 +92,7 @@ Evan Kepner
|
|||||||
Fabien Zarifian
|
Fabien Zarifian
|
||||||
Fabio Zadrozny
|
Fabio Zadrozny
|
||||||
Feng Ma
|
Feng Ma
|
||||||
|
Fernando Mezzabotta Rey
|
||||||
Florian Bruhin
|
Florian Bruhin
|
||||||
Floris Bruynooghe
|
Floris Bruynooghe
|
||||||
Gabriel Reis
|
Gabriel Reis
|
||||||
|
|||||||
@@ -18,6 +18,22 @@ with advance notice in the **Deprecations** section of releases.
|
|||||||
|
|
||||||
.. towncrier release notes start
|
.. towncrier release notes start
|
||||||
|
|
||||||
|
pytest 4.6.10 (2020-05-08)
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
- `#6870 <https://github.com/pytest-dev/pytest/issues/6870>`_: New ``Config.invocation_args`` attribute containing the unchanged arguments passed to ``pytest.main()``.
|
||||||
|
|
||||||
|
Remark: while this is technically a new feature and according to our `policy <https://docs.pytest.org/en/latest/py27-py34-deprecation.html#what-goes-into-4-6-x-releases>`_ it should not have been backported, we have opened an exception in this particular case because it fixes a serious interaction with ``pytest-xdist``, so it can also be considered a bugfix.
|
||||||
|
|
||||||
|
Trivial/Internal Changes
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
- `#6404 <https://github.com/pytest-dev/pytest/issues/6404>`_: Remove usage of ``parser`` module, deprecated in Python 3.9.
|
||||||
|
|
||||||
|
|
||||||
pytest 4.6.9 (2020-01-04)
|
pytest 4.6.9 (2020-01-04)
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Release announcements
|
|||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
|
||||||
|
release-4.6.10
|
||||||
release-4.6.9
|
release-4.6.9
|
||||||
release-4.6.8
|
release-4.6.8
|
||||||
release-4.6.7
|
release-4.6.7
|
||||||
|
|||||||
20
doc/en/announce/release-4.6.10.rst
Normal file
20
doc/en/announce/release-4.6.10.rst
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
pytest-4.6.10
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
pytest 4.6.10 has just been released to PyPI.
|
||||||
|
|
||||||
|
This is a bug-fix release, being a drop-in replacement. To upgrade::
|
||||||
|
|
||||||
|
pip install --upgrade pytest
|
||||||
|
|
||||||
|
The full changelog is available at https://docs.pytest.org/en/latest/changelog.html.
|
||||||
|
|
||||||
|
Thanks to all who contributed to this release, among them:
|
||||||
|
|
||||||
|
* Anthony Sottile
|
||||||
|
* Bruno Oliveira
|
||||||
|
* Fernando Mez
|
||||||
|
|
||||||
|
|
||||||
|
Happy testing,
|
||||||
|
The pytest Development Team
|
||||||
@@ -434,10 +434,11 @@ Running it results in some skips if we don't have all the python interpreters in
|
|||||||
.. code-block:: pytest
|
.. code-block:: pytest
|
||||||
|
|
||||||
. $ pytest -rs -q multipython.py
|
. $ pytest -rs -q multipython.py
|
||||||
......sss......ssssssssssss [100%]
|
...ssssssssssssssssssssssss [100%]
|
||||||
========================= short test summary info ==========================
|
========================= short test summary info ==========================
|
||||||
SKIPPED [15] $REGENDOC_TMPDIR/CWD/multipython.py:31: 'python3.5' not found
|
SKIPPED [12] $REGENDOC_TMPDIR/CWD/multipython.py:31: 'python3.4' not found
|
||||||
12 passed, 15 skipped in 0.12 seconds
|
SKIPPED [12] $REGENDOC_TMPDIR/CWD/multipython.py:31: 'python3.5' not found
|
||||||
|
3 passed, 24 skipped in 0.12 seconds
|
||||||
|
|
||||||
Indirect parametrization of optional implementations/imports
|
Indirect parametrization of optional implementations/imports
|
||||||
--------------------------------------------------------------------
|
--------------------------------------------------------------------
|
||||||
|
|||||||
@@ -436,7 +436,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
|||||||
items = [1, 2, 3]
|
items = [1, 2, 3]
|
||||||
print("items is %r" % items)
|
print("items is %r" % items)
|
||||||
> a, b = items.pop()
|
> a, b = items.pop()
|
||||||
E TypeError: 'int' object is not iterable
|
E TypeError: cannot unpack non-iterable int object
|
||||||
|
|
||||||
failure_demo.py:182: TypeError
|
failure_demo.py:182: TypeError
|
||||||
--------------------------- Captured stdout call ---------------------------
|
--------------------------- Captured stdout call ---------------------------
|
||||||
@@ -515,7 +515,7 @@ Here is a nice run of several failures and how ``pytest`` presents things:
|
|||||||
def test_z2_type_error(self):
|
def test_z2_type_error(self):
|
||||||
items = 3
|
items = 3
|
||||||
> a, b = items
|
> a, b = items
|
||||||
E TypeError: 'int' object is not iterable
|
E TypeError: cannot unpack non-iterable int object
|
||||||
|
|
||||||
failure_demo.py:222: TypeError
|
failure_demo.py:222: TypeError
|
||||||
______________________ TestMoreErrors.test_startswith ______________________
|
______________________ TestMoreErrors.test_startswith ______________________
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Install ``pytest``
|
|||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ pytest --version
|
$ pytest --version
|
||||||
This is pytest version 4.x.y, imported from $PYTHON_PREFIX/lib/python3.6/site-packages/pytest.py
|
This is pytest version 4.x.y, imported from $PYTHON_PREFIX/lib/python3.7/site-packages/pytest.py
|
||||||
|
|
||||||
.. _`simpletest`:
|
.. _`simpletest`:
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ are available on PyPI.
|
|||||||
|
|
||||||
While pytest ``5.0`` will be the new mainstream and development version, until **January 2020**
|
While pytest ``5.0`` will be the new mainstream and development version, until **January 2020**
|
||||||
the pytest core team plans to make bug-fix releases of the pytest ``4.6`` series by
|
the pytest core team plans to make bug-fix releases of the pytest ``4.6`` series by
|
||||||
back-porting patches to the ``4.6-maintenance`` branch that affect Python 2 users.
|
back-porting patches to the ``4.6.x`` branch that affect Python 2 users.
|
||||||
|
|
||||||
**After 2020**, the core team will no longer actively backport patches, but the ``4.6-maintenance``
|
**After 2020**, the core team will no longer actively backport patches, but the ``4.6.x``
|
||||||
branch will continue to exist so the community itself can contribute patches. The core team will
|
branch will continue to exist so the community itself can contribute patches. The core team will
|
||||||
be happy to accept those patches and make new ``4.6`` releases **until mid-2020**.
|
be happy to accept those patches and make new ``4.6`` releases **until mid-2020**.
|
||||||
|
|
||||||
|
|||||||
35
scripts/append_codecov_token.py
Normal file
35
scripts/append_codecov_token.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
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()
|
||||||
18
scripts/report-coverage.sh
Executable file
18
scripts/report-coverage.sh
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
if [ -z "$TOXENV" ]; then
|
||||||
|
python -m pip install coverage
|
||||||
|
else
|
||||||
|
# Add last TOXENV to $PATH.
|
||||||
|
PATH="$PWD/.tox/${TOXENV##*,}/bin:$PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
python -m coverage combine
|
||||||
|
python -m coverage xml
|
||||||
|
python -m coverage report -m
|
||||||
|
# Set --connect-timeout to work around https://github.com/curl/curl/issues/4461
|
||||||
|
curl -S -L --connect-timeout 5 --retry 6 -s https://codecov.io/bash -o codecov-upload.sh
|
||||||
|
bash codecov-upload.sh -Z -X fix -f coverage.xml "$@"
|
||||||
@@ -30,6 +30,8 @@ classifiers =
|
|||||||
Programming Language :: Python :: 3.5
|
Programming Language :: Python :: 3.5
|
||||||
Programming Language :: Python :: 3.6
|
Programming Language :: Python :: 3.6
|
||||||
Programming Language :: Python :: 3.7
|
Programming Language :: Python :: 3.7
|
||||||
|
Programming Language :: Python :: 3.8
|
||||||
|
Programming Language :: Python :: 3.9
|
||||||
platforms = unix, linux, osx, cygwin, win32
|
platforms = unix, linux, osx, cygwin, win32
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
|
|||||||
@@ -123,18 +123,13 @@ class Source(object):
|
|||||||
""" return True if source is parseable, heuristically
|
""" return True if source is parseable, heuristically
|
||||||
deindenting it by default.
|
deindenting it by default.
|
||||||
"""
|
"""
|
||||||
from parser import suite as syntax_checker
|
|
||||||
|
|
||||||
if deindent:
|
if deindent:
|
||||||
source = str(self.deindent())
|
source = str(self.deindent())
|
||||||
else:
|
else:
|
||||||
source = str(self)
|
source = str(self)
|
||||||
try:
|
try:
|
||||||
# compile(source+'\n', "x", "exec")
|
ast.parse(source)
|
||||||
syntax_checker(source + "\n")
|
except (SyntaxError, ValueError, TypeError):
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import sys
|
|||||||
import types
|
import types
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
import attr
|
||||||
import py
|
import py
|
||||||
import six
|
import six
|
||||||
from packaging.version import Version
|
from packaging.version import Version
|
||||||
@@ -35,6 +36,7 @@ from _pytest.compat import lru_cache
|
|||||||
from _pytest.compat import safe_str
|
from _pytest.compat import safe_str
|
||||||
from _pytest.outcomes import fail
|
from _pytest.outcomes import fail
|
||||||
from _pytest.outcomes import Skipped
|
from _pytest.outcomes import Skipped
|
||||||
|
from _pytest.pathlib import Path
|
||||||
from _pytest.warning_types import PytestConfigWarning
|
from _pytest.warning_types import PytestConfigWarning
|
||||||
|
|
||||||
hookimpl = HookimplMarker("pytest")
|
hookimpl = HookimplMarker("pytest")
|
||||||
@@ -154,10 +156,15 @@ builtin_plugins = set(default_plugins)
|
|||||||
builtin_plugins.add("pytester")
|
builtin_plugins.add("pytester")
|
||||||
|
|
||||||
|
|
||||||
def get_config(args=None):
|
def get_config(args=None, plugins=None):
|
||||||
# subsequent calls to main will create a fresh instance
|
# subsequent calls to main will create a fresh instance
|
||||||
pluginmanager = PytestPluginManager()
|
pluginmanager = PytestPluginManager()
|
||||||
config = Config(pluginmanager)
|
config = Config(
|
||||||
|
pluginmanager,
|
||||||
|
invocation_params=Config.InvocationParams(
|
||||||
|
args=args, plugins=plugins, dir=Path().resolve()
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
if args is not None:
|
if args is not None:
|
||||||
# Handle any "-p no:plugin" args.
|
# Handle any "-p no:plugin" args.
|
||||||
@@ -190,7 +197,7 @@ def _prepareconfig(args=None, plugins=None):
|
|||||||
msg = "`args` parameter expected to be a list or tuple of strings, got: {!r} (type: {})"
|
msg = "`args` parameter expected to be a list or tuple of strings, got: {!r} (type: {})"
|
||||||
raise TypeError(msg.format(args, type(args)))
|
raise TypeError(msg.format(args, type(args)))
|
||||||
|
|
||||||
config = get_config(args)
|
config = get_config(args, plugins)
|
||||||
pluginmanager = config.pluginmanager
|
pluginmanager = config.pluginmanager
|
||||||
try:
|
try:
|
||||||
if plugins:
|
if plugins:
|
||||||
@@ -686,13 +693,52 @@ def _iter_rewritable_modules(package_files):
|
|||||||
|
|
||||||
|
|
||||||
class Config(object):
|
class Config(object):
|
||||||
""" access to configuration values, pluginmanager and plugin hooks. """
|
"""
|
||||||
|
Access to configuration values, pluginmanager and plugin hooks.
|
||||||
|
|
||||||
|
:ivar PytestPluginManager pluginmanager: the plugin manager handles plugin registration and hook invocation.
|
||||||
|
|
||||||
|
:ivar argparse.Namespace option: access to command line option as attributes.
|
||||||
|
|
||||||
|
:ivar InvocationParams invocation_params:
|
||||||
|
|
||||||
|
Object containing the parameters regarding the ``pytest.main``
|
||||||
|
invocation.
|
||||||
|
Contains the followinig read-only attributes:
|
||||||
|
* ``args``: list of command-line arguments as passed to ``pytest.main()``.
|
||||||
|
* ``plugins``: list of extra plugins, might be None
|
||||||
|
* ``dir``: directory where ``pytest.main()`` was invoked from.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@attr.s(frozen=True)
|
||||||
|
class InvocationParams(object):
|
||||||
|
"""Holds parameters passed during ``pytest.main()``
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Currently the environment variable PYTEST_ADDOPTS is also handled by
|
||||||
|
pytest implicitly, not being part of the invocation.
|
||||||
|
|
||||||
|
Plugins accessing ``InvocationParams`` must be aware of that.
|
||||||
|
"""
|
||||||
|
|
||||||
|
args = attr.ib()
|
||||||
|
plugins = attr.ib()
|
||||||
|
dir = attr.ib()
|
||||||
|
|
||||||
|
def __init__(self, pluginmanager, invocation_params=None, *args):
|
||||||
|
from .argparsing import Parser, FILE_OR_DIR
|
||||||
|
|
||||||
|
if invocation_params is None:
|
||||||
|
invocation_params = self.InvocationParams(
|
||||||
|
args=(), plugins=None, dir=Path().resolve()
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, pluginmanager):
|
|
||||||
#: access to command line option as attributes.
|
#: access to command line option as attributes.
|
||||||
#: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
|
#: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
|
||||||
self.option = argparse.Namespace()
|
self.option = argparse.Namespace()
|
||||||
from .argparsing import Parser, FILE_OR_DIR
|
|
||||||
|
self.invocation_params = invocation_params
|
||||||
|
|
||||||
_a = FILE_OR_DIR
|
_a = FILE_OR_DIR
|
||||||
self._parser = Parser(
|
self._parser = Parser(
|
||||||
@@ -709,9 +755,13 @@ class Config(object):
|
|||||||
self._cleanup = []
|
self._cleanup = []
|
||||||
self.pluginmanager.register(self, "pytestconfig")
|
self.pluginmanager.register(self, "pytestconfig")
|
||||||
self._configured = False
|
self._configured = False
|
||||||
self.invocation_dir = py.path.local()
|
|
||||||
self.hook.pytest_addoption.call_historic(kwargs=dict(parser=self._parser))
|
self.hook.pytest_addoption.call_historic(kwargs=dict(parser=self._parser))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def invocation_dir(self):
|
||||||
|
"""Backward compatibility"""
|
||||||
|
return py.path.local(str(self.invocation_params.dir))
|
||||||
|
|
||||||
def add_cleanup(self, func):
|
def add_cleanup(self, func):
|
||||||
""" Add a function to be called when the config object gets out of
|
""" Add a function to be called when the config object gets out of
|
||||||
use (usually coninciding with pytest_unconfigure)."""
|
use (usually coninciding with pytest_unconfigure)."""
|
||||||
|
|||||||
@@ -501,7 +501,7 @@ def test_getfslineno():
|
|||||||
class B(object):
|
class B(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
B.__name__ = "B2"
|
B.__name__ = B.__qualname__ = "B2"
|
||||||
assert getfslineno(B)[1] == -1
|
assert getfslineno(B)[1] == -1
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ from _pytest.main import EXIT_NOTESTSCOLLECTED
|
|||||||
from _pytest.main import EXIT_OK
|
from _pytest.main import EXIT_OK
|
||||||
from _pytest.main import EXIT_TESTSFAILED
|
from _pytest.main import EXIT_TESTSFAILED
|
||||||
from _pytest.main import EXIT_USAGEERROR
|
from _pytest.main import EXIT_USAGEERROR
|
||||||
|
from _pytest.pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
class TestParseIni(object):
|
class TestParseIni(object):
|
||||||
@@ -1222,6 +1223,29 @@ def test_config_does_not_load_blocked_plugin_from_args(testdir):
|
|||||||
assert result.ret == EXIT_USAGEERROR
|
assert result.ret == EXIT_USAGEERROR
|
||||||
|
|
||||||
|
|
||||||
|
def test_invocation_args(testdir):
|
||||||
|
"""Ensure that Config.invocation_* arguments are correctly defined"""
|
||||||
|
|
||||||
|
class DummyPlugin(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
p = testdir.makepyfile("def test(): pass")
|
||||||
|
plugin = DummyPlugin()
|
||||||
|
rec = testdir.inline_run(p, "-v", plugins=[plugin])
|
||||||
|
calls = rec.getcalls("pytest_runtest_protocol")
|
||||||
|
assert len(calls) == 1
|
||||||
|
call = calls[0]
|
||||||
|
config = call.item.config
|
||||||
|
|
||||||
|
assert config.invocation_params.args == [p, "-v"]
|
||||||
|
assert config.invocation_params.dir == Path(str(testdir.tmpdir))
|
||||||
|
|
||||||
|
plugins = config.invocation_params.plugins
|
||||||
|
assert len(plugins) == 2
|
||||||
|
assert plugins[0] is plugin
|
||||||
|
assert type(plugins[1]).__name__ == "Collect" # installed by testdir.inline_run()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"plugin",
|
"plugin",
|
||||||
[
|
[
|
||||||
|
|||||||
2
tox.ini
2
tox.ini
@@ -11,6 +11,7 @@ envlist =
|
|||||||
py36
|
py36
|
||||||
py37
|
py37
|
||||||
py38
|
py38
|
||||||
|
py39
|
||||||
pypy
|
pypy
|
||||||
pypy3
|
pypy3
|
||||||
{py27,py37}-{pexpect,xdist,twisted,numpy,pluggymaster}
|
{py27,py37}-{pexpect,xdist,twisted,numpy,pluggymaster}
|
||||||
@@ -119,6 +120,7 @@ changedir = testing/freeze
|
|||||||
# Disable PEP 517 with pip, which does not work with PyInstaller currently.
|
# Disable PEP 517 with pip, which does not work with PyInstaller currently.
|
||||||
deps =
|
deps =
|
||||||
pyinstaller
|
pyinstaller
|
||||||
|
setuptools < 45.0.0
|
||||||
commands =
|
commands =
|
||||||
{envpython} create_executable.py
|
{envpython} create_executable.py
|
||||||
{envpython} tox_run.py
|
{envpython} tox_run.py
|
||||||
|
|||||||
Reference in New Issue
Block a user