Merge pull request #3620 from RonnyPfannschmidt/merge-from-master
Merge from master
This commit is contained in:
commit
6b239263da
|
@ -1,19 +1,19 @@
|
||||||
exclude: doc/en/example/py2py3/test_py2.py
|
exclude: doc/en/example/py2py3/test_py2.py
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/ambv/black
|
- repo: https://github.com/ambv/black
|
||||||
rev: 18.4a4
|
rev: 18.6b4
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
args: [--safe, --quiet]
|
args: [--safe, --quiet]
|
||||||
language_version: python3.6
|
language_version: python3.6
|
||||||
- repo: https://github.com/asottile/blacken-docs
|
- repo: https://github.com/asottile/blacken-docs
|
||||||
rev: v0.1.1
|
rev: v0.2.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: blacken-docs
|
- id: blacken-docs
|
||||||
additional_dependencies: [black==18.5b1]
|
additional_dependencies: [black==18.6b4]
|
||||||
language_version: python3.6
|
language_version: python3.6
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v1.2.3
|
rev: v1.3.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
|
|
|
@ -37,8 +37,8 @@ jobs:
|
||||||
python: 'pypy-5.4'
|
python: 'pypy-5.4'
|
||||||
- env: TOXENV=py35
|
- env: TOXENV=py35
|
||||||
python: '3.5'
|
python: '3.5'
|
||||||
- env: TOXENV=py35-freeze
|
- env: TOXENV=py36-freeze
|
||||||
python: '3.5'
|
python: '3.6'
|
||||||
- env: TOXENV=py37
|
- env: TOXENV=py37
|
||||||
python: 'nightly'
|
python: 'nightly'
|
||||||
|
|
||||||
|
|
2
AUTHORS
2
AUTHORS
|
@ -126,6 +126,7 @@ Maik Figura
|
||||||
Mandeep Bhutani
|
Mandeep Bhutani
|
||||||
Manuel Krebber
|
Manuel Krebber
|
||||||
Marc Schlaich
|
Marc Schlaich
|
||||||
|
Marcelo Duarte Trevisani
|
||||||
Marcin Bachry
|
Marcin Bachry
|
||||||
Mark Abramowitz
|
Mark Abramowitz
|
||||||
Markus Unterwaditzer
|
Markus Unterwaditzer
|
||||||
|
@ -157,6 +158,7 @@ Oleg Sushchenko
|
||||||
Oliver Bestwalter
|
Oliver Bestwalter
|
||||||
Omar Kohl
|
Omar Kohl
|
||||||
Omer Hadari
|
Omer Hadari
|
||||||
|
Ondřej Súkup
|
||||||
Patrick Hayes
|
Patrick Hayes
|
||||||
Paweł Adamczak
|
Paweł Adamczak
|
||||||
Pedro Algarvio
|
Pedro Algarvio
|
||||||
|
|
|
@ -8,6 +8,52 @@
|
||||||
|
|
||||||
.. towncrier release notes start
|
.. towncrier release notes start
|
||||||
|
|
||||||
|
Pytest 3.6.2 (2018-06-20)
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- Fix regression in ``Node.add_marker`` by extracting the mark object of a
|
||||||
|
``MarkDecorator``. (`#3555
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/3555>`_)
|
||||||
|
|
||||||
|
- Warnings without ``location`` were reported as ``None``. This is corrected to
|
||||||
|
now report ``<undetermined location>``. (`#3563
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/3563>`_)
|
||||||
|
|
||||||
|
- Continue to call finalizers in the stack when a finalizer in a former scope
|
||||||
|
raises an exception. (`#3569
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/3569>`_)
|
||||||
|
|
||||||
|
- Fix encoding error with `print` statements in doctests (`#3583
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/3583>`_)
|
||||||
|
|
||||||
|
|
||||||
|
Improved Documentation
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
- Add documentation for the ``--strict`` flag. (`#3549
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/3549>`_)
|
||||||
|
|
||||||
|
|
||||||
|
Trivial/Internal Changes
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
- Update old quotation style to parens in fixture.rst documentation. (`#3525
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/3525>`_)
|
||||||
|
|
||||||
|
- Improve display of hint about ``--fulltrace`` with ``KeyboardInterrupt``.
|
||||||
|
(`#3545 <https://github.com/pytest-dev/pytest/issues/3545>`_)
|
||||||
|
|
||||||
|
- pytest's testsuite is no longer runnable through ``python setup.py test`` --
|
||||||
|
instead invoke ``pytest`` or ``tox`` directly. (`#3552
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/3552>`_)
|
||||||
|
|
||||||
|
- Fix typo in documentation (`#3567
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/3567>`_)
|
||||||
|
|
||||||
|
|
||||||
Pytest 3.6.1 (2018-06-05)
|
Pytest 3.6.1 (2018-06-05)
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ environment:
|
||||||
- TOXENV: "py36-pluggymaster"
|
- TOXENV: "py36-pluggymaster"
|
||||||
- TOXENV: "py27-nobyte"
|
- TOXENV: "py27-nobyte"
|
||||||
- TOXENV: "doctesting"
|
- TOXENV: "doctesting"
|
||||||
- TOXENV: "py35-freeze"
|
- TOXENV: "py36-freeze"
|
||||||
- TOXENV: "docs"
|
- TOXENV: "docs"
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix ``ImportWarning`` triggered by explicit relative imports in assertion-rewritten package modules.
|
|
@ -1 +0,0 @@
|
||||||
Improve display of hint about ``--fulltrace`` with ``KeyboardInterrupt``.
|
|
|
@ -1 +0,0 @@
|
||||||
Add documentation for the ``--strict`` flag.
|
|
|
@ -1 +0,0 @@
|
||||||
pytest's testsuite is no longer runnable through ``python setup.py test`` -- instead invoke ``pytest`` or ``tox`` directly.
|
|
|
@ -1 +0,0 @@
|
||||||
Fix regression in ``Node.add_marker`` by extracting the mark object of a ``MarkDecorator``.
|
|
|
@ -1 +0,0 @@
|
||||||
Warnings without ``location`` were reported as ``None``. This is corrected to now report ``<undetermined location>``.
|
|
|
@ -1 +0,0 @@
|
||||||
Fix typo in documentation
|
|
|
@ -1 +0,0 @@
|
||||||
Continue to call finalizers in the stack when a finalizer in a former scope raises an exception.
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
If the user pass as a expected value a numpy array created like
|
||||||
|
numpy.array(5); it will creates an array with one element without shape,
|
||||||
|
when used with approx it will raise an error for the `repr`
|
||||||
|
'TypeError: iteration over a 0-d array'. With this PR pytest will iterate
|
||||||
|
properly in the numpy array even with 0 dimension.
|
|
@ -0,0 +1 @@
|
||||||
|
Internal refactoring: removed unused ``CallSpec2tox ._globalid_args`` attribute and ``metafunc`` parameter from ``CallSpec2.copy()``.
|
|
@ -0,0 +1 @@
|
||||||
|
Silence usage of ``reduce`` warning in python 2
|
|
@ -0,0 +1 @@
|
||||||
|
The description above the example for ``@pytest.mark.skipif`` now better matches the code.
|
|
@ -6,6 +6,7 @@ Release announcements
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
|
||||||
|
release-3.6.2
|
||||||
release-3.6.1
|
release-3.6.1
|
||||||
release-3.6.0
|
release-3.6.0
|
||||||
release-3.5.1
|
release-3.5.1
|
||||||
|
|
|
@ -23,7 +23,7 @@ a full list of details. A few feature highlights:
|
||||||
called if the corresponding setup method succeeded.
|
called if the corresponding setup method succeeded.
|
||||||
|
|
||||||
- integrate tab-completion on command line options if you
|
- integrate tab-completion on command line options if you
|
||||||
have `argcomplete <http://pypi.python.org/pypi/argcomplete>`_
|
have `argcomplete <https://pypi.org/project/argcomplete/>`_
|
||||||
configured.
|
configured.
|
||||||
|
|
||||||
- allow boolean expression directly with skipif/xfail
|
- allow boolean expression directly with skipif/xfail
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
pytest-3.6.2
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
pytest 3.6.2 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 http://doc.pytest.org/en/latest/changelog.html.
|
||||||
|
|
||||||
|
Thanks to all who contributed to this release, among them:
|
||||||
|
|
||||||
|
* Alan Velasco
|
||||||
|
* Alex Barbato
|
||||||
|
* Anthony Sottile
|
||||||
|
* Bartosz Cierocki
|
||||||
|
* Bruno Oliveira
|
||||||
|
* Daniel Hahler
|
||||||
|
* Guoqiang Zhang
|
||||||
|
* Hynek Schlawack
|
||||||
|
* John T. Wodder II
|
||||||
|
* Michael Käufl
|
||||||
|
* Ronny Pfannschmidt
|
||||||
|
* Samuel Dion-Girardeau
|
||||||
|
|
||||||
|
|
||||||
|
Happy testing,
|
||||||
|
The pytest Development Team
|
|
@ -25,9 +25,7 @@ def pytest_generate_tests(metafunc):
|
||||||
|
|
||||||
|
|
||||||
class TestFailing(object):
|
class TestFailing(object):
|
||||||
|
|
||||||
def test_simple(self):
|
def test_simple(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
@ -40,7 +38,6 @@ class TestFailing(object):
|
||||||
otherfunc_multi(42, 6 * 9)
|
otherfunc_multi(42, 6 * 9)
|
||||||
|
|
||||||
def test_not(self):
|
def test_not(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
@ -48,7 +45,6 @@ class TestFailing(object):
|
||||||
|
|
||||||
|
|
||||||
class TestSpecialisedExplanations(object):
|
class TestSpecialisedExplanations(object):
|
||||||
|
|
||||||
def test_eq_text(self):
|
def test_eq_text(self):
|
||||||
assert "spam" == "eggs"
|
assert "spam" == "eggs"
|
||||||
|
|
||||||
|
@ -106,7 +102,6 @@ class TestSpecialisedExplanations(object):
|
||||||
|
|
||||||
|
|
||||||
def test_attribute():
|
def test_attribute():
|
||||||
|
|
||||||
class Foo(object):
|
class Foo(object):
|
||||||
b = 1
|
b = 1
|
||||||
|
|
||||||
|
@ -115,7 +110,6 @@ def test_attribute():
|
||||||
|
|
||||||
|
|
||||||
def test_attribute_instance():
|
def test_attribute_instance():
|
||||||
|
|
||||||
class Foo(object):
|
class Foo(object):
|
||||||
b = 1
|
b = 1
|
||||||
|
|
||||||
|
@ -123,9 +117,7 @@ def test_attribute_instance():
|
||||||
|
|
||||||
|
|
||||||
def test_attribute_failure():
|
def test_attribute_failure():
|
||||||
|
|
||||||
class Foo(object):
|
class Foo(object):
|
||||||
|
|
||||||
def _get_b(self):
|
def _get_b(self):
|
||||||
raise Exception("Failed to get attrib")
|
raise Exception("Failed to get attrib")
|
||||||
|
|
||||||
|
@ -136,7 +128,6 @@ def test_attribute_failure():
|
||||||
|
|
||||||
|
|
||||||
def test_attribute_multiple():
|
def test_attribute_multiple():
|
||||||
|
|
||||||
class Foo(object):
|
class Foo(object):
|
||||||
b = 1
|
b = 1
|
||||||
|
|
||||||
|
@ -151,7 +142,6 @@ def globf(x):
|
||||||
|
|
||||||
|
|
||||||
class TestRaises(object):
|
class TestRaises(object):
|
||||||
|
|
||||||
def test_raises(self):
|
def test_raises(self):
|
||||||
s = "qwe" # NOQA
|
s = "qwe" # NOQA
|
||||||
raises(TypeError, "int(s)")
|
raises(TypeError, "int(s)")
|
||||||
|
@ -193,9 +183,7 @@ def test_dynamic_compile_shows_nicely():
|
||||||
|
|
||||||
|
|
||||||
class TestMoreErrors(object):
|
class TestMoreErrors(object):
|
||||||
|
|
||||||
def test_complex_error(self):
|
def test_complex_error(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
return 44
|
return 44
|
||||||
|
|
||||||
|
@ -218,7 +206,6 @@ class TestMoreErrors(object):
|
||||||
assert s.startswith(g)
|
assert s.startswith(g)
|
||||||
|
|
||||||
def test_startswith_nested(self):
|
def test_startswith_nested(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
return "123"
|
return "123"
|
||||||
|
|
||||||
|
@ -246,9 +233,7 @@ class TestMoreErrors(object):
|
||||||
|
|
||||||
|
|
||||||
class TestCustomAssertMsg(object):
|
class TestCustomAssertMsg(object):
|
||||||
|
|
||||||
def test_single_line(self):
|
def test_single_line(self):
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
a = 1
|
a = 1
|
||||||
|
|
||||||
|
@ -256,7 +241,6 @@ class TestCustomAssertMsg(object):
|
||||||
assert A.a == b, "A.a appears not to be b"
|
assert A.a == b, "A.a appears not to be b"
|
||||||
|
|
||||||
def test_multiline(self):
|
def test_multiline(self):
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
a = 1
|
a = 1
|
||||||
|
|
||||||
|
@ -266,7 +250,6 @@ class TestCustomAssertMsg(object):
|
||||||
), "A.a appears not to be b\n" "or does not appear to be b\none of those"
|
), "A.a appears not to be b\n" "or does not appear to be b\none of those"
|
||||||
|
|
||||||
def test_custom_repr(self):
|
def test_custom_repr(self):
|
||||||
|
|
||||||
class JSON(object):
|
class JSON(object):
|
||||||
a = 1
|
a = 1
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import py
|
import py
|
||||||
|
|
||||||
failure_demo = py.path.local(__file__).dirpath("failure_demo.py")
|
failure_demo = py.path.local(__file__).dirpath("failure_demo.py")
|
||||||
pytest_plugins = "pytester",
|
pytest_plugins = ("pytester",)
|
||||||
|
|
||||||
|
|
||||||
def test_failure_demo_fails_properly(testdir):
|
def test_failure_demo_fails_properly(testdir):
|
||||||
|
|
|
@ -3,7 +3,6 @@ def setup_module(module):
|
||||||
|
|
||||||
|
|
||||||
class TestStateFullThing(object):
|
class TestStateFullThing(object):
|
||||||
|
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
cls.classcount += 1
|
cls.classcount += 1
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ def setup(request):
|
||||||
|
|
||||||
|
|
||||||
class CostlySetup(object):
|
class CostlySetup(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ def python2(request, python1):
|
||||||
|
|
||||||
|
|
||||||
class Python(object):
|
class Python(object):
|
||||||
|
|
||||||
def __init__(self, version, picklefile):
|
def __init__(self, version, picklefile):
|
||||||
self.pythonpath = py.path.local.sysfind(version)
|
self.pythonpath = py.path.local.sysfind(version)
|
||||||
if not self.pythonpath:
|
if not self.pythonpath:
|
||||||
|
|
|
@ -9,7 +9,6 @@ def pytest_collect_file(parent, path):
|
||||||
|
|
||||||
|
|
||||||
class YamlFile(pytest.File):
|
class YamlFile(pytest.File):
|
||||||
|
|
||||||
def collect(self):
|
def collect(self):
|
||||||
import yaml # we need a yaml parser, e.g. PyYAML
|
import yaml # we need a yaml parser, e.g. PyYAML
|
||||||
|
|
||||||
|
@ -19,7 +18,6 @@ class YamlFile(pytest.File):
|
||||||
|
|
||||||
|
|
||||||
class YamlItem(pytest.Item):
|
class YamlItem(pytest.Item):
|
||||||
|
|
||||||
def __init__(self, name, parent, spec):
|
def __init__(self, name, parent, spec):
|
||||||
super(YamlItem, self).__init__(name, parent)
|
super(YamlItem, self).__init__(name, parent)
|
||||||
self.spec = spec
|
self.spec = spec
|
||||||
|
|
|
@ -5,7 +5,6 @@ py3 = sys.version_info[0] >= 3
|
||||||
|
|
||||||
|
|
||||||
class DummyCollector(pytest.collect.File):
|
class DummyCollector(pytest.collect.File):
|
||||||
|
|
||||||
def collect(self):
|
def collect(self):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ def test_function():
|
||||||
|
|
||||||
|
|
||||||
class TestClass(object):
|
class TestClass(object):
|
||||||
|
|
||||||
def test_method(self):
|
def test_method(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -625,7 +625,7 @@ get on the terminal - we are working on that)::
|
||||||
|
|
||||||
failure_demo.py:278: AssertionError
|
failure_demo.py:278: AssertionError
|
||||||
============================= warnings summary =============================
|
============================= warnings summary =============================
|
||||||
None
|
<undetermined location>
|
||||||
Metafunc.addcall is deprecated and scheduled to be removed in pytest 4.0.
|
Metafunc.addcall is deprecated and scheduled to be removed in pytest 4.0.
|
||||||
Please use Metafunc.parametrize instead.
|
Please use Metafunc.parametrize instead.
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ This makes use of the automatic caching mechanisms of pytest.
|
||||||
Another good approach is by adding the data files in the ``tests`` folder.
|
Another good approach is by adding the data files in the ``tests`` folder.
|
||||||
There are also community plugins available to help managing this aspect of
|
There are also community plugins available to help managing this aspect of
|
||||||
testing, e.g. `pytest-datadir <https://github.com/gabrielcnr/pytest-datadir>`__
|
testing, e.g. `pytest-datadir <https://github.com/gabrielcnr/pytest-datadir>`__
|
||||||
and `pytest-datafiles <https://pypi.python.org/pypi/pytest-datafiles>`__.
|
and `pytest-datafiles <https://pypi.org/project/pytest-datafiles/>`__.
|
||||||
|
|
||||||
.. _smtpshared:
|
.. _smtpshared:
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ Scope: sharing a fixture instance across tests in a class, module or session
|
||||||
|
|
||||||
Fixtures requiring network access depend on connectivity and are
|
Fixtures requiring network access depend on connectivity and are
|
||||||
usually time-expensive to create. Extending the previous example, we
|
usually time-expensive to create. Extending the previous example, we
|
||||||
can add a ``scope='module'`` parameter to the
|
can add a ``scope="module"`` parameter to the
|
||||||
:py:func:`@pytest.fixture <_pytest.python.fixture>` invocation
|
:py:func:`@pytest.fixture <_pytest.python.fixture>` invocation
|
||||||
to cause the decorated ``smtp`` fixture function to only be invoked once
|
to cause the decorated ``smtp`` fixture function to only be invoked once
|
||||||
per test *module* (the default is to invoke once per test *function*).
|
per test *module* (the default is to invoke once per test *function*).
|
||||||
|
|
|
@ -733,7 +733,7 @@ Node
|
||||||
Parser
|
Parser
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
.. autoclass:: _pytest.config.Parser()
|
.. autoclass:: _pytest.config.argparsing.Parser()
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
PluginManager
|
PluginManager
|
||||||
|
|
|
@ -80,11 +80,11 @@ during import time.
|
||||||
|
|
||||||
If you wish to skip something conditionally then you can use ``skipif`` instead.
|
If you wish to skip something conditionally then you can use ``skipif`` instead.
|
||||||
Here is an example of marking a test function to be skipped
|
Here is an example of marking a test function to be skipped
|
||||||
when run on a Python3.6 interpreter::
|
when run on an interpreter earlier than Python3.6 ::
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@pytest.mark.skipif(sys.version_info < (3,6),
|
@pytest.mark.skipif(sys.version_info < (3,6),
|
||||||
reason="requires python3.6")
|
reason="requires python3.6 or higher")
|
||||||
def test_function():
|
def test_function():
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
[build-system]
|
||||||
|
requires = [
|
||||||
|
"setuptools",
|
||||||
|
"setuptools-scm",
|
||||||
|
"wheel",
|
||||||
|
]
|
||||||
|
|
||||||
[tool.towncrier]
|
[tool.towncrier]
|
||||||
package = "pytest"
|
package = "pytest"
|
||||||
package_dir = "src"
|
package_dir = "src"
|
||||||
|
|
8
setup.py
8
setup.py
|
@ -112,7 +112,13 @@ def main():
|
||||||
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
|
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
|
||||||
install_requires=install_requires,
|
install_requires=install_requires,
|
||||||
extras_require=extras_require,
|
extras_require=extras_require,
|
||||||
packages=["_pytest", "_pytest.assertion", "_pytest._code", "_pytest.mark"],
|
packages=[
|
||||||
|
"_pytest",
|
||||||
|
"_pytest.assertion",
|
||||||
|
"_pytest._code",
|
||||||
|
"_pytest.mark",
|
||||||
|
"_pytest.config",
|
||||||
|
],
|
||||||
py_modules=["pytest"],
|
py_modules=["pytest"],
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
)
|
)
|
||||||
|
|
|
@ -274,6 +274,7 @@ class Traceback(list):
|
||||||
""" Traceback objects encapsulate and offer higher level
|
""" Traceback objects encapsulate and offer higher level
|
||||||
access to Traceback entries.
|
access to Traceback entries.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Entry = TracebackEntry
|
Entry = TracebackEntry
|
||||||
|
|
||||||
def __init__(self, tb, excinfo=None):
|
def __init__(self, tb, excinfo=None):
|
||||||
|
@ -382,8 +383,11 @@ class ExceptionInfo(object):
|
||||||
""" wraps sys.exc_info() objects and offers
|
""" wraps sys.exc_info() objects and offers
|
||||||
help for navigating the traceback.
|
help for navigating the traceback.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_striptext = ""
|
_striptext = ""
|
||||||
_assert_start_repr = "AssertionError(u'assert " if _PY2 else "AssertionError('assert "
|
_assert_start_repr = (
|
||||||
|
"AssertionError(u'assert " if _PY2 else "AssertionError('assert "
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, tup=None, exprinfo=None):
|
def __init__(self, tup=None, exprinfo=None):
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
|
@ -497,6 +501,7 @@ class ExceptionInfo(object):
|
||||||
@attr.s
|
@attr.s
|
||||||
class FormattedExcinfo(object):
|
class FormattedExcinfo(object):
|
||||||
""" presenting information about failing Functions and Generators. """
|
""" presenting information about failing Functions and Generators. """
|
||||||
|
|
||||||
# for traceback entries
|
# for traceback entries
|
||||||
flow_marker = ">"
|
flow_marker = ">"
|
||||||
fail_marker = "E"
|
fail_marker = "E"
|
||||||
|
@ -722,15 +727,19 @@ class FormattedExcinfo(object):
|
||||||
repr_chain += [(reprtraceback, reprcrash, descr)]
|
repr_chain += [(reprtraceback, reprcrash, descr)]
|
||||||
if e.__cause__ is not None:
|
if e.__cause__ is not None:
|
||||||
e = e.__cause__
|
e = e.__cause__
|
||||||
excinfo = ExceptionInfo(
|
excinfo = (
|
||||||
(type(e), e, e.__traceback__)
|
ExceptionInfo((type(e), e, e.__traceback__))
|
||||||
) if e.__traceback__ else None
|
if e.__traceback__
|
||||||
|
else None
|
||||||
|
)
|
||||||
descr = "The above exception was the direct cause of the following exception:"
|
descr = "The above exception was the direct cause of the following exception:"
|
||||||
elif (e.__context__ is not None and not e.__suppress_context__):
|
elif e.__context__ is not None and not e.__suppress_context__:
|
||||||
e = e.__context__
|
e = e.__context__
|
||||||
excinfo = ExceptionInfo(
|
excinfo = (
|
||||||
(type(e), e, e.__traceback__)
|
ExceptionInfo((type(e), e, e.__traceback__))
|
||||||
) if e.__traceback__ else None
|
if e.__traceback__
|
||||||
|
else None
|
||||||
|
)
|
||||||
descr = "During handling of the above exception, another exception occurred:"
|
descr = "During handling of the above exception, another exception occurred:"
|
||||||
else:
|
else:
|
||||||
e = None
|
e = None
|
||||||
|
@ -739,7 +748,6 @@ class FormattedExcinfo(object):
|
||||||
|
|
||||||
|
|
||||||
class TerminalRepr(object):
|
class TerminalRepr(object):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = self.__unicode__()
|
s = self.__unicode__()
|
||||||
if _PY2:
|
if _PY2:
|
||||||
|
@ -759,7 +767,6 @@ class TerminalRepr(object):
|
||||||
|
|
||||||
|
|
||||||
class ExceptionRepr(TerminalRepr):
|
class ExceptionRepr(TerminalRepr):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.sections = []
|
self.sections = []
|
||||||
|
|
||||||
|
@ -773,7 +780,6 @@ class ExceptionRepr(TerminalRepr):
|
||||||
|
|
||||||
|
|
||||||
class ExceptionChainRepr(ExceptionRepr):
|
class ExceptionChainRepr(ExceptionRepr):
|
||||||
|
|
||||||
def __init__(self, chain):
|
def __init__(self, chain):
|
||||||
super(ExceptionChainRepr, self).__init__()
|
super(ExceptionChainRepr, self).__init__()
|
||||||
self.chain = chain
|
self.chain = chain
|
||||||
|
@ -792,7 +798,6 @@ class ExceptionChainRepr(ExceptionRepr):
|
||||||
|
|
||||||
|
|
||||||
class ReprExceptionInfo(ExceptionRepr):
|
class ReprExceptionInfo(ExceptionRepr):
|
||||||
|
|
||||||
def __init__(self, reprtraceback, reprcrash):
|
def __init__(self, reprtraceback, reprcrash):
|
||||||
super(ReprExceptionInfo, self).__init__()
|
super(ReprExceptionInfo, self).__init__()
|
||||||
self.reprtraceback = reprtraceback
|
self.reprtraceback = reprtraceback
|
||||||
|
@ -831,7 +836,6 @@ class ReprTraceback(TerminalRepr):
|
||||||
|
|
||||||
|
|
||||||
class ReprTracebackNative(ReprTraceback):
|
class ReprTracebackNative(ReprTraceback):
|
||||||
|
|
||||||
def __init__(self, tblines):
|
def __init__(self, tblines):
|
||||||
self.style = "native"
|
self.style = "native"
|
||||||
self.reprentries = [ReprEntryNative(tblines)]
|
self.reprentries = [ReprEntryNative(tblines)]
|
||||||
|
@ -885,7 +889,6 @@ class ReprEntry(TerminalRepr):
|
||||||
|
|
||||||
|
|
||||||
class ReprFileLocation(TerminalRepr):
|
class ReprFileLocation(TerminalRepr):
|
||||||
|
|
||||||
def __init__(self, path, lineno, message):
|
def __init__(self, path, lineno, message):
|
||||||
self.path = str(path)
|
self.path = str(path)
|
||||||
self.lineno = lineno
|
self.lineno = lineno
|
||||||
|
@ -903,7 +906,6 @@ class ReprFileLocation(TerminalRepr):
|
||||||
|
|
||||||
|
|
||||||
class ReprLocals(TerminalRepr):
|
class ReprLocals(TerminalRepr):
|
||||||
|
|
||||||
def __init__(self, lines):
|
def __init__(self, lines):
|
||||||
self.lines = lines
|
self.lines = lines
|
||||||
|
|
||||||
|
@ -913,7 +915,6 @@ class ReprLocals(TerminalRepr):
|
||||||
|
|
||||||
|
|
||||||
class ReprFuncArgs(TerminalRepr):
|
class ReprFuncArgs(TerminalRepr):
|
||||||
|
|
||||||
def __init__(self, args):
|
def __init__(self, args):
|
||||||
self.args = args
|
self.args = args
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ class Source(object):
|
||||||
""" an immutable object holding a source code fragment,
|
""" an immutable object holding a source code fragment,
|
||||||
possibly deindenting it.
|
possibly deindenting it.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_compilecounter = 0
|
_compilecounter = 0
|
||||||
|
|
||||||
def __init__(self, *parts, **kwargs):
|
def __init__(self, *parts, **kwargs):
|
||||||
|
|
|
@ -45,6 +45,14 @@ else:
|
||||||
return ast.Call(a, b, c, None, None)
|
return ast.Call(a, b, c, None, None)
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 4):
|
||||||
|
from importlib.util import spec_from_file_location
|
||||||
|
else:
|
||||||
|
|
||||||
|
def spec_from_file_location(*_, **__):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class AssertionRewritingHook(object):
|
class AssertionRewritingHook(object):
|
||||||
"""PEP302 Import hook which rewrites asserts."""
|
"""PEP302 Import hook which rewrites asserts."""
|
||||||
|
|
||||||
|
@ -213,6 +221,8 @@ class AssertionRewritingHook(object):
|
||||||
# Normally, this attribute is 3.2+.
|
# Normally, this attribute is 3.2+.
|
||||||
mod.__cached__ = pyc
|
mod.__cached__ = pyc
|
||||||
mod.__loader__ = self
|
mod.__loader__ = self
|
||||||
|
# Normally, this attribute is 3.4+
|
||||||
|
mod.__spec__ = spec_from_file_location(name, co.co_filename, loader=self)
|
||||||
py.builtin.exec_(co, mod.__dict__)
|
py.builtin.exec_(co, mod.__dict__)
|
||||||
except: # noqa
|
except: # noqa
|
||||||
if name in sys.modules:
|
if name in sys.modules:
|
||||||
|
|
|
@ -32,7 +32,6 @@ See [the docs](https://docs.pytest.org/en/latest/cache.html) for more informatio
|
||||||
|
|
||||||
@attr.s
|
@attr.s
|
||||||
class Cache(object):
|
class Cache(object):
|
||||||
|
|
||||||
_cachedir = attr.ib(repr=False)
|
_cachedir = attr.ib(repr=False)
|
||||||
_warn = attr.ib(repr=False)
|
_warn = attr.ib(repr=False)
|
||||||
|
|
||||||
|
@ -215,9 +214,7 @@ class NFPlugin(object):
|
||||||
|
|
||||||
items[:] = self._get_increasing_order(
|
items[:] = self._get_increasing_order(
|
||||||
six.itervalues(new_items)
|
six.itervalues(new_items)
|
||||||
) + self._get_increasing_order(
|
) + self._get_increasing_order(six.itervalues(other_items))
|
||||||
six.itervalues(other_items)
|
|
||||||
)
|
|
||||||
self.cached_nodeids = [x.nodeid for x in items if isinstance(x, pytest.Item)]
|
self.cached_nodeids = [x.nodeid for x in items if isinstance(x, pytest.Item)]
|
||||||
|
|
||||||
def _get_increasing_order(self, items):
|
def _get_increasing_order(self, items):
|
||||||
|
|
|
@ -531,7 +531,6 @@ class FDCapture(FDCaptureBinary):
|
||||||
|
|
||||||
|
|
||||||
class SysCapture(object):
|
class SysCapture(object):
|
||||||
|
|
||||||
def __init__(self, fd, tmpfile=None):
|
def __init__(self, fd, tmpfile=None):
|
||||||
name = patchsysdict[fd]
|
name = patchsysdict[fd]
|
||||||
self._old = getattr(sys, name)
|
self._old = getattr(sys, name)
|
||||||
|
@ -569,7 +568,6 @@ class SysCapture(object):
|
||||||
|
|
||||||
|
|
||||||
class SysCaptureBinary(SysCapture):
|
class SysCaptureBinary(SysCapture):
|
||||||
|
|
||||||
def snap(self):
|
def snap(self):
|
||||||
res = self.tmpfile.buffer.getvalue()
|
res = self.tmpfile.buffer.getvalue()
|
||||||
self.tmpfile.seek(0)
|
self.tmpfile.seek(0)
|
||||||
|
|
|
@ -78,12 +78,8 @@ def iscoroutinefunction(func):
|
||||||
Note: copied and modified from Python 3.5's builtin couroutines.py to avoid import asyncio directly,
|
Note: copied and modified from Python 3.5's builtin couroutines.py to avoid import asyncio directly,
|
||||||
which in turns also initializes the "logging" module as side-effect (see issue #8).
|
which in turns also initializes the "logging" module as side-effect (see issue #8).
|
||||||
"""
|
"""
|
||||||
return (
|
return getattr(func, "_is_coroutine", False) or (
|
||||||
getattr(func, "_is_coroutine", False)
|
hasattr(inspect, "iscoroutinefunction") and inspect.iscoroutinefunction(func)
|
||||||
or (
|
|
||||||
hasattr(inspect, "iscoroutinefunction")
|
|
||||||
and inspect.iscoroutinefunction(func)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,12 +140,8 @@ def getfuncargnames(function, is_method=False, cls=None):
|
||||||
# If this function should be treated as a bound method even though
|
# If this function should be treated as a bound method even though
|
||||||
# it's passed as an unbound method or function, remove the first
|
# it's passed as an unbound method or function, remove the first
|
||||||
# parameter name.
|
# parameter name.
|
||||||
if (
|
if is_method or (
|
||||||
is_method
|
cls and not isinstance(cls.__dict__.get(function.__name__, None), staticmethod)
|
||||||
or (
|
|
||||||
cls
|
|
||||||
and not isinstance(cls.__dict__.get(function.__name__, None), staticmethod)
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
arg_names = arg_names[1:]
|
arg_names = arg_names[1:]
|
||||||
# Remove any names that will be replaced with mocks.
|
# Remove any names that will be replaced with mocks.
|
||||||
|
@ -346,7 +338,6 @@ if _PY2:
|
||||||
from py.io import TextIO
|
from py.io import TextIO
|
||||||
|
|
||||||
class CaptureIO(TextIO):
|
class CaptureIO(TextIO):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def encoding(self):
|
def encoding(self):
|
||||||
return getattr(self, "_encoding", "UTF-8")
|
return getattr(self, "_encoding", "UTF-8")
|
||||||
|
@ -356,7 +347,6 @@ else:
|
||||||
import io
|
import io
|
||||||
|
|
||||||
class CaptureIO(io.TextIOWrapper):
|
class CaptureIO(io.TextIOWrapper):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(CaptureIO, self).__init__(
|
super(CaptureIO, self).__init__(
|
||||||
io.BytesIO(), encoding="UTF-8", newline="", write_through=True
|
io.BytesIO(), encoding="UTF-8", newline="", write_through=True
|
||||||
|
|
|
@ -19,6 +19,8 @@ import _pytest.hookspec # the extension point definitions
|
||||||
import _pytest.assertion
|
import _pytest.assertion
|
||||||
from pluggy import PluginManager, HookimplMarker, HookspecMarker
|
from pluggy import PluginManager, HookimplMarker, HookspecMarker
|
||||||
from _pytest.compat import safe_str
|
from _pytest.compat import safe_str
|
||||||
|
from .exceptions import UsageError, PrintHelp
|
||||||
|
from .findpaths import determine_setup, exists
|
||||||
|
|
||||||
hookimpl = HookimplMarker("pytest")
|
hookimpl = HookimplMarker("pytest")
|
||||||
hookspec = HookspecMarker("pytest")
|
hookspec = HookspecMarker("pytest")
|
||||||
|
@ -28,7 +30,6 @@ hookspec = HookspecMarker("pytest")
|
||||||
|
|
||||||
|
|
||||||
class ConftestImportFailure(Exception):
|
class ConftestImportFailure(Exception):
|
||||||
|
|
||||||
def __init__(self, path, excinfo):
|
def __init__(self, path, excinfo):
|
||||||
Exception.__init__(self, path, excinfo)
|
Exception.__init__(self, path, excinfo)
|
||||||
self.path = path
|
self.path = path
|
||||||
|
@ -74,16 +75,6 @@ class cmdline(object): # NOQA compatibility namespace
|
||||||
main = staticmethod(main)
|
main = staticmethod(main)
|
||||||
|
|
||||||
|
|
||||||
class UsageError(Exception):
|
|
||||||
""" error in pytest usage or invocation"""
|
|
||||||
|
|
||||||
|
|
||||||
class PrintHelp(Exception):
|
|
||||||
"""Raised when pytest should print it's help to skip the rest of the
|
|
||||||
argument parsing and validation."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def filename_arg(path, optname):
|
def filename_arg(path, optname):
|
||||||
""" Argparse type validator for filename arguments.
|
""" Argparse type validator for filename arguments.
|
||||||
|
|
||||||
|
@ -107,11 +98,33 @@ def directory_arg(path, optname):
|
||||||
|
|
||||||
|
|
||||||
default_plugins = (
|
default_plugins = (
|
||||||
"mark main terminal runner python fixtures debugging unittest capture skipping "
|
"mark",
|
||||||
"tmpdir monkeypatch recwarn pastebin helpconfig nose assertion "
|
"main",
|
||||||
"junitxml resultlog doctest cacheprovider freeze_support "
|
"terminal",
|
||||||
"setuponly setupplan warnings logging"
|
"runner",
|
||||||
).split()
|
"python",
|
||||||
|
"fixtures",
|
||||||
|
"debugging",
|
||||||
|
"unittest",
|
||||||
|
"capture",
|
||||||
|
"skipping",
|
||||||
|
"tmpdir",
|
||||||
|
"monkeypatch",
|
||||||
|
"recwarn",
|
||||||
|
"pastebin",
|
||||||
|
"helpconfig",
|
||||||
|
"nose",
|
||||||
|
"assertion",
|
||||||
|
"junitxml",
|
||||||
|
"resultlog",
|
||||||
|
"doctest",
|
||||||
|
"cacheprovider",
|
||||||
|
"freeze_support",
|
||||||
|
"setuponly",
|
||||||
|
"setupplan",
|
||||||
|
"warnings",
|
||||||
|
"logging",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
builtin_plugins = set(default_plugins)
|
builtin_plugins = set(default_plugins)
|
||||||
|
@ -304,9 +317,11 @@ class PytestPluginManager(PluginManager):
|
||||||
self._configured = True
|
self._configured = True
|
||||||
|
|
||||||
def _warn(self, message):
|
def _warn(self, message):
|
||||||
kwargs = message if isinstance(message, dict) else {
|
kwargs = (
|
||||||
"code": "I1", "message": message, "fslocation": None, "nodeid": None
|
message
|
||||||
}
|
if isinstance(message, dict)
|
||||||
|
else {"code": "I1", "message": message, "fslocation": None, "nodeid": None}
|
||||||
|
)
|
||||||
self.hook.pytest_logwarning.call_historic(kwargs=kwargs)
|
self.hook.pytest_logwarning.call_historic(kwargs=kwargs)
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -321,9 +336,11 @@ class PytestPluginManager(PluginManager):
|
||||||
here.
|
here.
|
||||||
"""
|
"""
|
||||||
current = py.path.local()
|
current = py.path.local()
|
||||||
self._confcutdir = current.join(
|
self._confcutdir = (
|
||||||
namespace.confcutdir, abs=True
|
current.join(namespace.confcutdir, abs=True)
|
||||||
) if namespace.confcutdir else None
|
if namespace.confcutdir
|
||||||
|
else None
|
||||||
|
)
|
||||||
self._noconftest = namespace.noconftest
|
self._noconftest = namespace.noconftest
|
||||||
testpaths = namespace.file_or_dir
|
testpaths = namespace.file_or_dir
|
||||||
foundanchor = False
|
foundanchor = False
|
||||||
|
@ -391,7 +408,9 @@ class PytestPluginManager(PluginManager):
|
||||||
try:
|
try:
|
||||||
mod = conftestpath.pyimport()
|
mod = conftestpath.pyimport()
|
||||||
if hasattr(mod, "pytest_plugins") and self._configured:
|
if hasattr(mod, "pytest_plugins") and self._configured:
|
||||||
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
|
from _pytest.deprecated import (
|
||||||
|
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
|
||||||
|
)
|
||||||
|
|
||||||
warnings.warn(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST)
|
warnings.warn(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -463,7 +482,8 @@ class PytestPluginManager(PluginManager):
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
new_exc_type = ImportError
|
new_exc_type = ImportError
|
||||||
new_exc_message = 'Error importing plugin "%s": %s' % (
|
new_exc_message = 'Error importing plugin "%s": %s' % (
|
||||||
modname, safe_str(e.args[0])
|
modname,
|
||||||
|
safe_str(e.args[0]),
|
||||||
)
|
)
|
||||||
new_exc = new_exc_type(new_exc_message)
|
new_exc = new_exc_type(new_exc_message)
|
||||||
|
|
||||||
|
@ -496,395 +516,6 @@ def _get_plugin_specs_as_list(specs):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
class Parser(object):
|
|
||||||
""" Parser for command line arguments and ini-file values.
|
|
||||||
|
|
||||||
:ivar extra_info: dict of generic param -> value to display in case
|
|
||||||
there's an error processing the command line arguments.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, usage=None, processopt=None):
|
|
||||||
self._anonymous = OptionGroup("custom options", parser=self)
|
|
||||||
self._groups = []
|
|
||||||
self._processopt = processopt
|
|
||||||
self._usage = usage
|
|
||||||
self._inidict = {}
|
|
||||||
self._ininames = []
|
|
||||||
self.extra_info = {}
|
|
||||||
|
|
||||||
def processoption(self, option):
|
|
||||||
if self._processopt:
|
|
||||||
if option.dest:
|
|
||||||
self._processopt(option)
|
|
||||||
|
|
||||||
def getgroup(self, name, description="", after=None):
|
|
||||||
""" get (or create) a named option Group.
|
|
||||||
|
|
||||||
:name: name of the option group.
|
|
||||||
:description: long description for --help output.
|
|
||||||
:after: name of other group, used for ordering --help output.
|
|
||||||
|
|
||||||
The returned group object has an ``addoption`` method with the same
|
|
||||||
signature as :py:func:`parser.addoption
|
|
||||||
<_pytest.config.Parser.addoption>` but will be shown in the
|
|
||||||
respective group in the output of ``pytest. --help``.
|
|
||||||
"""
|
|
||||||
for group in self._groups:
|
|
||||||
if group.name == name:
|
|
||||||
return group
|
|
||||||
group = OptionGroup(name, description, parser=self)
|
|
||||||
i = 0
|
|
||||||
for i, grp in enumerate(self._groups):
|
|
||||||
if grp.name == after:
|
|
||||||
break
|
|
||||||
self._groups.insert(i + 1, group)
|
|
||||||
return group
|
|
||||||
|
|
||||||
def addoption(self, *opts, **attrs):
|
|
||||||
""" register a command line option.
|
|
||||||
|
|
||||||
:opts: option names, can be short or long options.
|
|
||||||
:attrs: same attributes which the ``add_option()`` function of the
|
|
||||||
`argparse library
|
|
||||||
<http://docs.python.org/2/library/argparse.html>`_
|
|
||||||
accepts.
|
|
||||||
|
|
||||||
After command line parsing options are available on the pytest config
|
|
||||||
object via ``config.option.NAME`` where ``NAME`` is usually set
|
|
||||||
by passing a ``dest`` attribute, for example
|
|
||||||
``addoption("--long", dest="NAME", ...)``.
|
|
||||||
"""
|
|
||||||
self._anonymous.addoption(*opts, **attrs)
|
|
||||||
|
|
||||||
def parse(self, args, namespace=None):
|
|
||||||
from _pytest._argcomplete import try_argcomplete
|
|
||||||
|
|
||||||
self.optparser = self._getparser()
|
|
||||||
try_argcomplete(self.optparser)
|
|
||||||
return self.optparser.parse_args([str(x) for x in args], namespace=namespace)
|
|
||||||
|
|
||||||
def _getparser(self):
|
|
||||||
from _pytest._argcomplete import filescompleter
|
|
||||||
|
|
||||||
optparser = MyOptionParser(self, self.extra_info)
|
|
||||||
groups = self._groups + [self._anonymous]
|
|
||||||
for group in groups:
|
|
||||||
if group.options:
|
|
||||||
desc = group.description or group.name
|
|
||||||
arggroup = optparser.add_argument_group(desc)
|
|
||||||
for option in group.options:
|
|
||||||
n = option.names()
|
|
||||||
a = option.attrs()
|
|
||||||
arggroup.add_argument(*n, **a)
|
|
||||||
# bash like autocompletion for dirs (appending '/')
|
|
||||||
optparser.add_argument(FILE_OR_DIR, nargs="*").completer = filescompleter
|
|
||||||
return optparser
|
|
||||||
|
|
||||||
def parse_setoption(self, args, option, namespace=None):
|
|
||||||
parsedoption = self.parse(args, namespace=namespace)
|
|
||||||
for name, value in parsedoption.__dict__.items():
|
|
||||||
setattr(option, name, value)
|
|
||||||
return getattr(parsedoption, FILE_OR_DIR)
|
|
||||||
|
|
||||||
def parse_known_args(self, args, namespace=None):
|
|
||||||
"""parses and returns a namespace object with known arguments at this
|
|
||||||
point.
|
|
||||||
"""
|
|
||||||
return self.parse_known_and_unknown_args(args, namespace=namespace)[0]
|
|
||||||
|
|
||||||
def parse_known_and_unknown_args(self, args, namespace=None):
|
|
||||||
"""parses and returns a namespace object with known arguments, and
|
|
||||||
the remaining arguments unknown at this point.
|
|
||||||
"""
|
|
||||||
optparser = self._getparser()
|
|
||||||
args = [str(x) for x in args]
|
|
||||||
return optparser.parse_known_args(args, namespace=namespace)
|
|
||||||
|
|
||||||
def addini(self, name, help, type=None, default=None):
|
|
||||||
""" register an ini-file option.
|
|
||||||
|
|
||||||
:name: name of the ini-variable
|
|
||||||
:type: type of the variable, can be ``pathlist``, ``args``, ``linelist``
|
|
||||||
or ``bool``.
|
|
||||||
:default: default value if no ini-file option exists but is queried.
|
|
||||||
|
|
||||||
The value of ini-variables can be retrieved via a call to
|
|
||||||
:py:func:`config.getini(name) <_pytest.config.Config.getini>`.
|
|
||||||
"""
|
|
||||||
assert type in (None, "pathlist", "args", "linelist", "bool")
|
|
||||||
self._inidict[name] = (help, type, default)
|
|
||||||
self._ininames.append(name)
|
|
||||||
|
|
||||||
|
|
||||||
class ArgumentError(Exception):
|
|
||||||
"""
|
|
||||||
Raised if an Argument instance is created with invalid or
|
|
||||||
inconsistent arguments.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, msg, option):
|
|
||||||
self.msg = msg
|
|
||||||
self.option_id = str(option)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.option_id:
|
|
||||||
return "option %s: %s" % (self.option_id, self.msg)
|
|
||||||
else:
|
|
||||||
return self.msg
|
|
||||||
|
|
||||||
|
|
||||||
class Argument(object):
|
|
||||||
"""class that mimics the necessary behaviour of optparse.Option
|
|
||||||
|
|
||||||
its currently a least effort implementation
|
|
||||||
and ignoring choices and integer prefixes
|
|
||||||
https://docs.python.org/3/library/optparse.html#optparse-standard-option-types
|
|
||||||
"""
|
|
||||||
_typ_map = {"int": int, "string": str, "float": float, "complex": complex}
|
|
||||||
|
|
||||||
def __init__(self, *names, **attrs):
|
|
||||||
"""store parms in private vars for use in add_argument"""
|
|
||||||
self._attrs = attrs
|
|
||||||
self._short_opts = []
|
|
||||||
self._long_opts = []
|
|
||||||
self.dest = attrs.get("dest")
|
|
||||||
if "%default" in (attrs.get("help") or ""):
|
|
||||||
warnings.warn(
|
|
||||||
'pytest now uses argparse. "%default" should be'
|
|
||||||
' changed to "%(default)s" ',
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=3,
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
typ = attrs["type"]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
# this might raise a keyerror as well, don't want to catch that
|
|
||||||
if isinstance(typ, six.string_types):
|
|
||||||
if typ == "choice":
|
|
||||||
warnings.warn(
|
|
||||||
"type argument to addoption() is a string %r."
|
|
||||||
" For parsearg this is optional and when supplied"
|
|
||||||
" should be a type."
|
|
||||||
" (options: %s)" % (typ, names),
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=3,
|
|
||||||
)
|
|
||||||
# argparse expects a type here take it from
|
|
||||||
# the type of the first element
|
|
||||||
attrs["type"] = type(attrs["choices"][0])
|
|
||||||
else:
|
|
||||||
warnings.warn(
|
|
||||||
"type argument to addoption() is a string %r."
|
|
||||||
" For parsearg this should be a type."
|
|
||||||
" (options: %s)" % (typ, names),
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=3,
|
|
||||||
)
|
|
||||||
attrs["type"] = Argument._typ_map[typ]
|
|
||||||
# used in test_parseopt -> test_parse_defaultgetter
|
|
||||||
self.type = attrs["type"]
|
|
||||||
else:
|
|
||||||
self.type = typ
|
|
||||||
try:
|
|
||||||
# attribute existence is tested in Config._processopt
|
|
||||||
self.default = attrs["default"]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
self._set_opt_strings(names)
|
|
||||||
if not self.dest:
|
|
||||||
if self._long_opts:
|
|
||||||
self.dest = self._long_opts[0][2:].replace("-", "_")
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
self.dest = self._short_opts[0][1:]
|
|
||||||
except IndexError:
|
|
||||||
raise ArgumentError("need a long or short option", self)
|
|
||||||
|
|
||||||
def names(self):
|
|
||||||
return self._short_opts + self._long_opts
|
|
||||||
|
|
||||||
def attrs(self):
|
|
||||||
# update any attributes set by processopt
|
|
||||||
attrs = "default dest help".split()
|
|
||||||
if self.dest:
|
|
||||||
attrs.append(self.dest)
|
|
||||||
for attr in attrs:
|
|
||||||
try:
|
|
||||||
self._attrs[attr] = getattr(self, attr)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
if self._attrs.get("help"):
|
|
||||||
a = self._attrs["help"]
|
|
||||||
a = a.replace("%default", "%(default)s")
|
|
||||||
# a = a.replace('%prog', '%(prog)s')
|
|
||||||
self._attrs["help"] = a
|
|
||||||
return self._attrs
|
|
||||||
|
|
||||||
def _set_opt_strings(self, opts):
|
|
||||||
"""directly from optparse
|
|
||||||
|
|
||||||
might not be necessary as this is passed to argparse later on"""
|
|
||||||
for opt in opts:
|
|
||||||
if len(opt) < 2:
|
|
||||||
raise ArgumentError(
|
|
||||||
"invalid option string %r: "
|
|
||||||
"must be at least two characters long" % opt,
|
|
||||||
self,
|
|
||||||
)
|
|
||||||
elif len(opt) == 2:
|
|
||||||
if not (opt[0] == "-" and opt[1] != "-"):
|
|
||||||
raise ArgumentError(
|
|
||||||
"invalid short option string %r: "
|
|
||||||
"must be of the form -x, (x any non-dash char)" % opt,
|
|
||||||
self,
|
|
||||||
)
|
|
||||||
self._short_opts.append(opt)
|
|
||||||
else:
|
|
||||||
if not (opt[0:2] == "--" and opt[2] != "-"):
|
|
||||||
raise ArgumentError(
|
|
||||||
"invalid long option string %r: "
|
|
||||||
"must start with --, followed by non-dash" % opt,
|
|
||||||
self,
|
|
||||||
)
|
|
||||||
self._long_opts.append(opt)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
args = []
|
|
||||||
if self._short_opts:
|
|
||||||
args += ["_short_opts: " + repr(self._short_opts)]
|
|
||||||
if self._long_opts:
|
|
||||||
args += ["_long_opts: " + repr(self._long_opts)]
|
|
||||||
args += ["dest: " + repr(self.dest)]
|
|
||||||
if hasattr(self, "type"):
|
|
||||||
args += ["type: " + repr(self.type)]
|
|
||||||
if hasattr(self, "default"):
|
|
||||||
args += ["default: " + repr(self.default)]
|
|
||||||
return "Argument({})".format(", ".join(args))
|
|
||||||
|
|
||||||
|
|
||||||
class OptionGroup(object):
|
|
||||||
|
|
||||||
def __init__(self, name, description="", parser=None):
|
|
||||||
self.name = name
|
|
||||||
self.description = description
|
|
||||||
self.options = []
|
|
||||||
self.parser = parser
|
|
||||||
|
|
||||||
def addoption(self, *optnames, **attrs):
|
|
||||||
""" add an option to this group.
|
|
||||||
|
|
||||||
if a shortened version of a long option is specified it will
|
|
||||||
be suppressed in the help. addoption('--twowords', '--two-words')
|
|
||||||
results in help showing '--two-words' only, but --twowords gets
|
|
||||||
accepted **and** the automatic destination is in args.twowords
|
|
||||||
"""
|
|
||||||
conflict = set(optnames).intersection(
|
|
||||||
name for opt in self.options for name in opt.names()
|
|
||||||
)
|
|
||||||
if conflict:
|
|
||||||
raise ValueError("option names %s already added" % conflict)
|
|
||||||
option = Argument(*optnames, **attrs)
|
|
||||||
self._addoption_instance(option, shortupper=False)
|
|
||||||
|
|
||||||
def _addoption(self, *optnames, **attrs):
|
|
||||||
option = Argument(*optnames, **attrs)
|
|
||||||
self._addoption_instance(option, shortupper=True)
|
|
||||||
|
|
||||||
def _addoption_instance(self, option, shortupper=False):
|
|
||||||
if not shortupper:
|
|
||||||
for opt in option._short_opts:
|
|
||||||
if opt[0] == "-" and opt[1].islower():
|
|
||||||
raise ValueError("lowercase shortoptions reserved")
|
|
||||||
if self.parser:
|
|
||||||
self.parser.processoption(option)
|
|
||||||
self.options.append(option)
|
|
||||||
|
|
||||||
|
|
||||||
class MyOptionParser(argparse.ArgumentParser):
|
|
||||||
|
|
||||||
def __init__(self, parser, extra_info=None):
|
|
||||||
if not extra_info:
|
|
||||||
extra_info = {}
|
|
||||||
self._parser = parser
|
|
||||||
argparse.ArgumentParser.__init__(
|
|
||||||
self,
|
|
||||||
usage=parser._usage,
|
|
||||||
add_help=False,
|
|
||||||
formatter_class=DropShorterLongHelpFormatter,
|
|
||||||
)
|
|
||||||
# extra_info is a dict of (param -> value) to display if there's
|
|
||||||
# an usage error to provide more contextual information to the user
|
|
||||||
self.extra_info = extra_info
|
|
||||||
|
|
||||||
def parse_args(self, args=None, namespace=None):
|
|
||||||
"""allow splitting of positional arguments"""
|
|
||||||
args, argv = self.parse_known_args(args, namespace)
|
|
||||||
if argv:
|
|
||||||
for arg in argv:
|
|
||||||
if arg and arg[0] == "-":
|
|
||||||
lines = ["unrecognized arguments: %s" % (" ".join(argv))]
|
|
||||||
for k, v in sorted(self.extra_info.items()):
|
|
||||||
lines.append(" %s: %s" % (k, v))
|
|
||||||
self.error("\n".join(lines))
|
|
||||||
getattr(args, FILE_OR_DIR).extend(argv)
|
|
||||||
return args
|
|
||||||
|
|
||||||
|
|
||||||
class DropShorterLongHelpFormatter(argparse.HelpFormatter):
|
|
||||||
"""shorten help for long options that differ only in extra hyphens
|
|
||||||
|
|
||||||
- collapse **long** options that are the same except for extra hyphens
|
|
||||||
- special action attribute map_long_option allows surpressing additional
|
|
||||||
long options
|
|
||||||
- shortcut if there are only two options and one of them is a short one
|
|
||||||
- cache result on action object as this is called at least 2 times
|
|
||||||
"""
|
|
||||||
|
|
||||||
def _format_action_invocation(self, action):
|
|
||||||
orgstr = argparse.HelpFormatter._format_action_invocation(self, action)
|
|
||||||
if orgstr and orgstr[0] != "-": # only optional arguments
|
|
||||||
return orgstr
|
|
||||||
res = getattr(action, "_formatted_action_invocation", None)
|
|
||||||
if res:
|
|
||||||
return res
|
|
||||||
options = orgstr.split(", ")
|
|
||||||
if len(options) == 2 and (len(options[0]) == 2 or len(options[1]) == 2):
|
|
||||||
# a shortcut for '-h, --help' or '--abc', '-a'
|
|
||||||
action._formatted_action_invocation = orgstr
|
|
||||||
return orgstr
|
|
||||||
return_list = []
|
|
||||||
option_map = getattr(action, "map_long_option", {})
|
|
||||||
if option_map is None:
|
|
||||||
option_map = {}
|
|
||||||
short_long = {}
|
|
||||||
for option in options:
|
|
||||||
if len(option) == 2 or option[2] == " ":
|
|
||||||
continue
|
|
||||||
if not option.startswith("--"):
|
|
||||||
raise ArgumentError(
|
|
||||||
'long optional argument without "--": [%s]' % (option), self
|
|
||||||
)
|
|
||||||
xxoption = option[2:]
|
|
||||||
if xxoption.split()[0] not in option_map:
|
|
||||||
shortened = xxoption.replace("-", "")
|
|
||||||
if (
|
|
||||||
shortened not in short_long
|
|
||||||
or len(short_long[shortened]) < len(xxoption)
|
|
||||||
):
|
|
||||||
short_long[shortened] = xxoption
|
|
||||||
# now short_long has been filled out to the longest with dashes
|
|
||||||
# **and** we keep the right option ordering from add_argument
|
|
||||||
for option in options:
|
|
||||||
if len(option) == 2 or option[2] == " ":
|
|
||||||
return_list.append(option)
|
|
||||||
if option[2:] == short_long.get(option.replace("-", "")):
|
|
||||||
return_list.append(option.replace(" ", "=", 1))
|
|
||||||
action._formatted_action_invocation = ", ".join(return_list)
|
|
||||||
return action._formatted_action_invocation
|
|
||||||
|
|
||||||
|
|
||||||
def _ensure_removed_sysmodule(modname):
|
def _ensure_removed_sysmodule(modname):
|
||||||
try:
|
try:
|
||||||
del sys.modules[modname]
|
del sys.modules[modname]
|
||||||
|
@ -893,13 +524,11 @@ def _ensure_removed_sysmodule(modname):
|
||||||
|
|
||||||
|
|
||||||
class Notset(object):
|
class Notset(object):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<NOTSET>"
|
return "<NOTSET>"
|
||||||
|
|
||||||
|
|
||||||
notset = Notset()
|
notset = Notset()
|
||||||
FILE_OR_DIR = "file_or_dir"
|
|
||||||
|
|
||||||
|
|
||||||
def _iter_rewritable_modules(package_files):
|
def _iter_rewritable_modules(package_files):
|
||||||
|
@ -921,6 +550,8 @@ class Config(object):
|
||||||
#: 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
|
||||||
|
|
||||||
_a = FILE_OR_DIR
|
_a = FILE_OR_DIR
|
||||||
self._parser = Parser(
|
self._parser = Parser(
|
||||||
usage="%%(prog)s [options] [%s] [%s] [...]" % (_a, _a),
|
usage="%%(prog)s [options] [%s] [%s] [...]" % (_a, _a),
|
||||||
|
@ -1300,143 +931,6 @@ def _warn_about_missing_assertion(mode):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def exists(path, ignore=EnvironmentError):
|
|
||||||
try:
|
|
||||||
return path.check()
|
|
||||||
except ignore:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def getcfg(args, warnfunc=None):
|
|
||||||
"""
|
|
||||||
Search the list of arguments for a valid ini-file for pytest,
|
|
||||||
and return a tuple of (rootdir, inifile, cfg-dict).
|
|
||||||
|
|
||||||
note: warnfunc is an optional function used to warn
|
|
||||||
about ini-files that use deprecated features.
|
|
||||||
This parameter should be removed when pytest
|
|
||||||
adopts standard deprecation warnings (#1804).
|
|
||||||
"""
|
|
||||||
from _pytest.deprecated import CFG_PYTEST_SECTION
|
|
||||||
|
|
||||||
inibasenames = ["pytest.ini", "tox.ini", "setup.cfg"]
|
|
||||||
args = [x for x in args if not str(x).startswith("-")]
|
|
||||||
if not args:
|
|
||||||
args = [py.path.local()]
|
|
||||||
for arg in args:
|
|
||||||
arg = py.path.local(arg)
|
|
||||||
for base in arg.parts(reverse=True):
|
|
||||||
for inibasename in inibasenames:
|
|
||||||
p = base.join(inibasename)
|
|
||||||
if exists(p):
|
|
||||||
iniconfig = py.iniconfig.IniConfig(p)
|
|
||||||
if "pytest" in iniconfig.sections:
|
|
||||||
if inibasename == "setup.cfg" and warnfunc:
|
|
||||||
warnfunc(
|
|
||||||
"C1", CFG_PYTEST_SECTION.format(filename=inibasename)
|
|
||||||
)
|
|
||||||
return base, p, iniconfig["pytest"]
|
|
||||||
if (
|
|
||||||
inibasename == "setup.cfg"
|
|
||||||
and "tool:pytest" in iniconfig.sections
|
|
||||||
):
|
|
||||||
return base, p, iniconfig["tool:pytest"]
|
|
||||||
elif inibasename == "pytest.ini":
|
|
||||||
# allowed to be empty
|
|
||||||
return base, p, {}
|
|
||||||
return None, None, None
|
|
||||||
|
|
||||||
|
|
||||||
def get_common_ancestor(paths):
|
|
||||||
common_ancestor = None
|
|
||||||
for path in paths:
|
|
||||||
if not path.exists():
|
|
||||||
continue
|
|
||||||
if common_ancestor is None:
|
|
||||||
common_ancestor = path
|
|
||||||
else:
|
|
||||||
if path.relto(common_ancestor) or path == common_ancestor:
|
|
||||||
continue
|
|
||||||
elif common_ancestor.relto(path):
|
|
||||||
common_ancestor = path
|
|
||||||
else:
|
|
||||||
shared = path.common(common_ancestor)
|
|
||||||
if shared is not None:
|
|
||||||
common_ancestor = shared
|
|
||||||
if common_ancestor is None:
|
|
||||||
common_ancestor = py.path.local()
|
|
||||||
elif common_ancestor.isfile():
|
|
||||||
common_ancestor = common_ancestor.dirpath()
|
|
||||||
return common_ancestor
|
|
||||||
|
|
||||||
|
|
||||||
def get_dirs_from_args(args):
|
|
||||||
|
|
||||||
def is_option(x):
|
|
||||||
return str(x).startswith("-")
|
|
||||||
|
|
||||||
def get_file_part_from_node_id(x):
|
|
||||||
return str(x).split("::")[0]
|
|
||||||
|
|
||||||
def get_dir_from_path(path):
|
|
||||||
if path.isdir():
|
|
||||||
return path
|
|
||||||
return py.path.local(path.dirname)
|
|
||||||
|
|
||||||
# These look like paths but may not exist
|
|
||||||
possible_paths = (
|
|
||||||
py.path.local(get_file_part_from_node_id(arg))
|
|
||||||
for arg in args
|
|
||||||
if not is_option(arg)
|
|
||||||
)
|
|
||||||
|
|
||||||
return [get_dir_from_path(path) for path in possible_paths if path.exists()]
|
|
||||||
|
|
||||||
|
|
||||||
def determine_setup(inifile, args, warnfunc=None, rootdir_cmd_arg=None):
|
|
||||||
dirs = get_dirs_from_args(args)
|
|
||||||
if inifile:
|
|
||||||
iniconfig = py.iniconfig.IniConfig(inifile)
|
|
||||||
is_cfg_file = str(inifile).endswith(".cfg")
|
|
||||||
# TODO: [pytest] section in *.cfg files is depricated. Need refactoring.
|
|
||||||
sections = ["tool:pytest", "pytest"] if is_cfg_file else ["pytest"]
|
|
||||||
for section in sections:
|
|
||||||
try:
|
|
||||||
inicfg = iniconfig[section]
|
|
||||||
if is_cfg_file and section == "pytest" and warnfunc:
|
|
||||||
from _pytest.deprecated import CFG_PYTEST_SECTION
|
|
||||||
|
|
||||||
warnfunc("C1", CFG_PYTEST_SECTION.format(filename=str(inifile)))
|
|
||||||
break
|
|
||||||
except KeyError:
|
|
||||||
inicfg = None
|
|
||||||
rootdir = get_common_ancestor(dirs)
|
|
||||||
else:
|
|
||||||
ancestor = get_common_ancestor(dirs)
|
|
||||||
rootdir, inifile, inicfg = getcfg([ancestor], warnfunc=warnfunc)
|
|
||||||
if rootdir is None:
|
|
||||||
for rootdir in ancestor.parts(reverse=True):
|
|
||||||
if rootdir.join("setup.py").exists():
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
rootdir, inifile, inicfg = getcfg(dirs, warnfunc=warnfunc)
|
|
||||||
if rootdir is None:
|
|
||||||
rootdir = get_common_ancestor([py.path.local(), ancestor])
|
|
||||||
is_fs_root = os.path.splitdrive(str(rootdir))[1] == "/"
|
|
||||||
if is_fs_root:
|
|
||||||
rootdir = ancestor
|
|
||||||
if rootdir_cmd_arg:
|
|
||||||
rootdir_abs_path = py.path.local(os.path.expandvars(rootdir_cmd_arg))
|
|
||||||
if not os.path.isdir(str(rootdir_abs_path)):
|
|
||||||
raise UsageError(
|
|
||||||
"Directory '{}' not found. Check your '--rootdir' option.".format(
|
|
||||||
rootdir_abs_path
|
|
||||||
)
|
|
||||||
)
|
|
||||||
rootdir = rootdir_abs_path
|
|
||||||
return rootdir, inifile, inicfg or {}
|
|
||||||
|
|
||||||
|
|
||||||
def setns(obj, dic):
|
def setns(obj, dic):
|
||||||
import pytest
|
import pytest
|
||||||
|
|
|
@ -0,0 +1,392 @@
|
||||||
|
import six
|
||||||
|
import warnings
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
FILE_OR_DIR = "file_or_dir"
|
||||||
|
|
||||||
|
|
||||||
|
class Parser(object):
|
||||||
|
""" Parser for command line arguments and ini-file values.
|
||||||
|
|
||||||
|
:ivar extra_info: dict of generic param -> value to display in case
|
||||||
|
there's an error processing the command line arguments.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, usage=None, processopt=None):
|
||||||
|
self._anonymous = OptionGroup("custom options", parser=self)
|
||||||
|
self._groups = []
|
||||||
|
self._processopt = processopt
|
||||||
|
self._usage = usage
|
||||||
|
self._inidict = {}
|
||||||
|
self._ininames = []
|
||||||
|
self.extra_info = {}
|
||||||
|
|
||||||
|
def processoption(self, option):
|
||||||
|
if self._processopt:
|
||||||
|
if option.dest:
|
||||||
|
self._processopt(option)
|
||||||
|
|
||||||
|
def getgroup(self, name, description="", after=None):
|
||||||
|
""" get (or create) a named option Group.
|
||||||
|
|
||||||
|
:name: name of the option group.
|
||||||
|
:description: long description for --help output.
|
||||||
|
:after: name of other group, used for ordering --help output.
|
||||||
|
|
||||||
|
The returned group object has an ``addoption`` method with the same
|
||||||
|
signature as :py:func:`parser.addoption
|
||||||
|
<_pytest.config.Parser.addoption>` but will be shown in the
|
||||||
|
respective group in the output of ``pytest. --help``.
|
||||||
|
"""
|
||||||
|
for group in self._groups:
|
||||||
|
if group.name == name:
|
||||||
|
return group
|
||||||
|
group = OptionGroup(name, description, parser=self)
|
||||||
|
i = 0
|
||||||
|
for i, grp in enumerate(self._groups):
|
||||||
|
if grp.name == after:
|
||||||
|
break
|
||||||
|
self._groups.insert(i + 1, group)
|
||||||
|
return group
|
||||||
|
|
||||||
|
def addoption(self, *opts, **attrs):
|
||||||
|
""" register a command line option.
|
||||||
|
|
||||||
|
:opts: option names, can be short or long options.
|
||||||
|
:attrs: same attributes which the ``add_option()`` function of the
|
||||||
|
`argparse library
|
||||||
|
<http://docs.python.org/2/library/argparse.html>`_
|
||||||
|
accepts.
|
||||||
|
|
||||||
|
After command line parsing options are available on the pytest config
|
||||||
|
object via ``config.option.NAME`` where ``NAME`` is usually set
|
||||||
|
by passing a ``dest`` attribute, for example
|
||||||
|
``addoption("--long", dest="NAME", ...)``.
|
||||||
|
"""
|
||||||
|
self._anonymous.addoption(*opts, **attrs)
|
||||||
|
|
||||||
|
def parse(self, args, namespace=None):
|
||||||
|
from _pytest._argcomplete import try_argcomplete
|
||||||
|
|
||||||
|
self.optparser = self._getparser()
|
||||||
|
try_argcomplete(self.optparser)
|
||||||
|
return self.optparser.parse_args([str(x) for x in args], namespace=namespace)
|
||||||
|
|
||||||
|
def _getparser(self):
|
||||||
|
from _pytest._argcomplete import filescompleter
|
||||||
|
|
||||||
|
optparser = MyOptionParser(self, self.extra_info)
|
||||||
|
groups = self._groups + [self._anonymous]
|
||||||
|
for group in groups:
|
||||||
|
if group.options:
|
||||||
|
desc = group.description or group.name
|
||||||
|
arggroup = optparser.add_argument_group(desc)
|
||||||
|
for option in group.options:
|
||||||
|
n = option.names()
|
||||||
|
a = option.attrs()
|
||||||
|
arggroup.add_argument(*n, **a)
|
||||||
|
# bash like autocompletion for dirs (appending '/')
|
||||||
|
optparser.add_argument(FILE_OR_DIR, nargs="*").completer = filescompleter
|
||||||
|
return optparser
|
||||||
|
|
||||||
|
def parse_setoption(self, args, option, namespace=None):
|
||||||
|
parsedoption = self.parse(args, namespace=namespace)
|
||||||
|
for name, value in parsedoption.__dict__.items():
|
||||||
|
setattr(option, name, value)
|
||||||
|
return getattr(parsedoption, FILE_OR_DIR)
|
||||||
|
|
||||||
|
def parse_known_args(self, args, namespace=None):
|
||||||
|
"""parses and returns a namespace object with known arguments at this
|
||||||
|
point.
|
||||||
|
"""
|
||||||
|
return self.parse_known_and_unknown_args(args, namespace=namespace)[0]
|
||||||
|
|
||||||
|
def parse_known_and_unknown_args(self, args, namespace=None):
|
||||||
|
"""parses and returns a namespace object with known arguments, and
|
||||||
|
the remaining arguments unknown at this point.
|
||||||
|
"""
|
||||||
|
optparser = self._getparser()
|
||||||
|
args = [str(x) for x in args]
|
||||||
|
return optparser.parse_known_args(args, namespace=namespace)
|
||||||
|
|
||||||
|
def addini(self, name, help, type=None, default=None):
|
||||||
|
""" register an ini-file option.
|
||||||
|
|
||||||
|
:name: name of the ini-variable
|
||||||
|
:type: type of the variable, can be ``pathlist``, ``args``, ``linelist``
|
||||||
|
or ``bool``.
|
||||||
|
:default: default value if no ini-file option exists but is queried.
|
||||||
|
|
||||||
|
The value of ini-variables can be retrieved via a call to
|
||||||
|
:py:func:`config.getini(name) <_pytest.config.Config.getini>`.
|
||||||
|
"""
|
||||||
|
assert type in (None, "pathlist", "args", "linelist", "bool")
|
||||||
|
self._inidict[name] = (help, type, default)
|
||||||
|
self._ininames.append(name)
|
||||||
|
|
||||||
|
|
||||||
|
class ArgumentError(Exception):
|
||||||
|
"""
|
||||||
|
Raised if an Argument instance is created with invalid or
|
||||||
|
inconsistent arguments.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, msg, option):
|
||||||
|
self.msg = msg
|
||||||
|
self.option_id = str(option)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.option_id:
|
||||||
|
return "option %s: %s" % (self.option_id, self.msg)
|
||||||
|
else:
|
||||||
|
return self.msg
|
||||||
|
|
||||||
|
|
||||||
|
class Argument(object):
|
||||||
|
"""class that mimics the necessary behaviour of optparse.Option
|
||||||
|
|
||||||
|
its currently a least effort implementation
|
||||||
|
and ignoring choices and integer prefixes
|
||||||
|
https://docs.python.org/3/library/optparse.html#optparse-standard-option-types
|
||||||
|
"""
|
||||||
|
|
||||||
|
_typ_map = {"int": int, "string": str, "float": float, "complex": complex}
|
||||||
|
|
||||||
|
def __init__(self, *names, **attrs):
|
||||||
|
"""store parms in private vars for use in add_argument"""
|
||||||
|
self._attrs = attrs
|
||||||
|
self._short_opts = []
|
||||||
|
self._long_opts = []
|
||||||
|
self.dest = attrs.get("dest")
|
||||||
|
if "%default" in (attrs.get("help") or ""):
|
||||||
|
warnings.warn(
|
||||||
|
'pytest now uses argparse. "%default" should be'
|
||||||
|
' changed to "%(default)s" ',
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=3,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
typ = attrs["type"]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# this might raise a keyerror as well, don't want to catch that
|
||||||
|
if isinstance(typ, six.string_types):
|
||||||
|
if typ == "choice":
|
||||||
|
warnings.warn(
|
||||||
|
"type argument to addoption() is a string %r."
|
||||||
|
" For parsearg this is optional and when supplied"
|
||||||
|
" should be a type."
|
||||||
|
" (options: %s)" % (typ, names),
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=3,
|
||||||
|
)
|
||||||
|
# argparse expects a type here take it from
|
||||||
|
# the type of the first element
|
||||||
|
attrs["type"] = type(attrs["choices"][0])
|
||||||
|
else:
|
||||||
|
warnings.warn(
|
||||||
|
"type argument to addoption() is a string %r."
|
||||||
|
" For parsearg this should be a type."
|
||||||
|
" (options: %s)" % (typ, names),
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=3,
|
||||||
|
)
|
||||||
|
attrs["type"] = Argument._typ_map[typ]
|
||||||
|
# used in test_parseopt -> test_parse_defaultgetter
|
||||||
|
self.type = attrs["type"]
|
||||||
|
else:
|
||||||
|
self.type = typ
|
||||||
|
try:
|
||||||
|
# attribute existence is tested in Config._processopt
|
||||||
|
self.default = attrs["default"]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
self._set_opt_strings(names)
|
||||||
|
if not self.dest:
|
||||||
|
if self._long_opts:
|
||||||
|
self.dest = self._long_opts[0][2:].replace("-", "_")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self.dest = self._short_opts[0][1:]
|
||||||
|
except IndexError:
|
||||||
|
raise ArgumentError("need a long or short option", self)
|
||||||
|
|
||||||
|
def names(self):
|
||||||
|
return self._short_opts + self._long_opts
|
||||||
|
|
||||||
|
def attrs(self):
|
||||||
|
# update any attributes set by processopt
|
||||||
|
attrs = "default dest help".split()
|
||||||
|
if self.dest:
|
||||||
|
attrs.append(self.dest)
|
||||||
|
for attr in attrs:
|
||||||
|
try:
|
||||||
|
self._attrs[attr] = getattr(self, attr)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if self._attrs.get("help"):
|
||||||
|
a = self._attrs["help"]
|
||||||
|
a = a.replace("%default", "%(default)s")
|
||||||
|
# a = a.replace('%prog', '%(prog)s')
|
||||||
|
self._attrs["help"] = a
|
||||||
|
return self._attrs
|
||||||
|
|
||||||
|
def _set_opt_strings(self, opts):
|
||||||
|
"""directly from optparse
|
||||||
|
|
||||||
|
might not be necessary as this is passed to argparse later on"""
|
||||||
|
for opt in opts:
|
||||||
|
if len(opt) < 2:
|
||||||
|
raise ArgumentError(
|
||||||
|
"invalid option string %r: "
|
||||||
|
"must be at least two characters long" % opt,
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
elif len(opt) == 2:
|
||||||
|
if not (opt[0] == "-" and opt[1] != "-"):
|
||||||
|
raise ArgumentError(
|
||||||
|
"invalid short option string %r: "
|
||||||
|
"must be of the form -x, (x any non-dash char)" % opt,
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
self._short_opts.append(opt)
|
||||||
|
else:
|
||||||
|
if not (opt[0:2] == "--" and opt[2] != "-"):
|
||||||
|
raise ArgumentError(
|
||||||
|
"invalid long option string %r: "
|
||||||
|
"must start with --, followed by non-dash" % opt,
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
self._long_opts.append(opt)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
args = []
|
||||||
|
if self._short_opts:
|
||||||
|
args += ["_short_opts: " + repr(self._short_opts)]
|
||||||
|
if self._long_opts:
|
||||||
|
args += ["_long_opts: " + repr(self._long_opts)]
|
||||||
|
args += ["dest: " + repr(self.dest)]
|
||||||
|
if hasattr(self, "type"):
|
||||||
|
args += ["type: " + repr(self.type)]
|
||||||
|
if hasattr(self, "default"):
|
||||||
|
args += ["default: " + repr(self.default)]
|
||||||
|
return "Argument({})".format(", ".join(args))
|
||||||
|
|
||||||
|
|
||||||
|
class OptionGroup(object):
|
||||||
|
def __init__(self, name, description="", parser=None):
|
||||||
|
self.name = name
|
||||||
|
self.description = description
|
||||||
|
self.options = []
|
||||||
|
self.parser = parser
|
||||||
|
|
||||||
|
def addoption(self, *optnames, **attrs):
|
||||||
|
""" add an option to this group.
|
||||||
|
|
||||||
|
if a shortened version of a long option is specified it will
|
||||||
|
be suppressed in the help. addoption('--twowords', '--two-words')
|
||||||
|
results in help showing '--two-words' only, but --twowords gets
|
||||||
|
accepted **and** the automatic destination is in args.twowords
|
||||||
|
"""
|
||||||
|
conflict = set(optnames).intersection(
|
||||||
|
name for opt in self.options for name in opt.names()
|
||||||
|
)
|
||||||
|
if conflict:
|
||||||
|
raise ValueError("option names %s already added" % conflict)
|
||||||
|
option = Argument(*optnames, **attrs)
|
||||||
|
self._addoption_instance(option, shortupper=False)
|
||||||
|
|
||||||
|
def _addoption(self, *optnames, **attrs):
|
||||||
|
option = Argument(*optnames, **attrs)
|
||||||
|
self._addoption_instance(option, shortupper=True)
|
||||||
|
|
||||||
|
def _addoption_instance(self, option, shortupper=False):
|
||||||
|
if not shortupper:
|
||||||
|
for opt in option._short_opts:
|
||||||
|
if opt[0] == "-" and opt[1].islower():
|
||||||
|
raise ValueError("lowercase shortoptions reserved")
|
||||||
|
if self.parser:
|
||||||
|
self.parser.processoption(option)
|
||||||
|
self.options.append(option)
|
||||||
|
|
||||||
|
|
||||||
|
class MyOptionParser(argparse.ArgumentParser):
|
||||||
|
def __init__(self, parser, extra_info=None):
|
||||||
|
if not extra_info:
|
||||||
|
extra_info = {}
|
||||||
|
self._parser = parser
|
||||||
|
argparse.ArgumentParser.__init__(
|
||||||
|
self,
|
||||||
|
usage=parser._usage,
|
||||||
|
add_help=False,
|
||||||
|
formatter_class=DropShorterLongHelpFormatter,
|
||||||
|
)
|
||||||
|
# extra_info is a dict of (param -> value) to display if there's
|
||||||
|
# an usage error to provide more contextual information to the user
|
||||||
|
self.extra_info = extra_info
|
||||||
|
|
||||||
|
def parse_args(self, args=None, namespace=None):
|
||||||
|
"""allow splitting of positional arguments"""
|
||||||
|
args, argv = self.parse_known_args(args, namespace)
|
||||||
|
if argv:
|
||||||
|
for arg in argv:
|
||||||
|
if arg and arg[0] == "-":
|
||||||
|
lines = ["unrecognized arguments: %s" % (" ".join(argv))]
|
||||||
|
for k, v in sorted(self.extra_info.items()):
|
||||||
|
lines.append(" %s: %s" % (k, v))
|
||||||
|
self.error("\n".join(lines))
|
||||||
|
getattr(args, FILE_OR_DIR).extend(argv)
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
class DropShorterLongHelpFormatter(argparse.HelpFormatter):
|
||||||
|
"""shorten help for long options that differ only in extra hyphens
|
||||||
|
|
||||||
|
- collapse **long** options that are the same except for extra hyphens
|
||||||
|
- special action attribute map_long_option allows surpressing additional
|
||||||
|
long options
|
||||||
|
- shortcut if there are only two options and one of them is a short one
|
||||||
|
- cache result on action object as this is called at least 2 times
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _format_action_invocation(self, action):
|
||||||
|
orgstr = argparse.HelpFormatter._format_action_invocation(self, action)
|
||||||
|
if orgstr and orgstr[0] != "-": # only optional arguments
|
||||||
|
return orgstr
|
||||||
|
res = getattr(action, "_formatted_action_invocation", None)
|
||||||
|
if res:
|
||||||
|
return res
|
||||||
|
options = orgstr.split(", ")
|
||||||
|
if len(options) == 2 and (len(options[0]) == 2 or len(options[1]) == 2):
|
||||||
|
# a shortcut for '-h, --help' or '--abc', '-a'
|
||||||
|
action._formatted_action_invocation = orgstr
|
||||||
|
return orgstr
|
||||||
|
return_list = []
|
||||||
|
option_map = getattr(action, "map_long_option", {})
|
||||||
|
if option_map is None:
|
||||||
|
option_map = {}
|
||||||
|
short_long = {}
|
||||||
|
for option in options:
|
||||||
|
if len(option) == 2 or option[2] == " ":
|
||||||
|
continue
|
||||||
|
if not option.startswith("--"):
|
||||||
|
raise ArgumentError(
|
||||||
|
'long optional argument without "--": [%s]' % (option), self
|
||||||
|
)
|
||||||
|
xxoption = option[2:]
|
||||||
|
if xxoption.split()[0] not in option_map:
|
||||||
|
shortened = xxoption.replace("-", "")
|
||||||
|
if shortened not in short_long or len(short_long[shortened]) < len(
|
||||||
|
xxoption
|
||||||
|
):
|
||||||
|
short_long[shortened] = xxoption
|
||||||
|
# now short_long has been filled out to the longest with dashes
|
||||||
|
# **and** we keep the right option ordering from add_argument
|
||||||
|
for option in options:
|
||||||
|
if len(option) == 2 or option[2] == " ":
|
||||||
|
return_list.append(option)
|
||||||
|
if option[2:] == short_long.get(option.replace("-", "")):
|
||||||
|
return_list.append(option.replace(" ", "=", 1))
|
||||||
|
action._formatted_action_invocation = ", ".join(return_list)
|
||||||
|
return action._formatted_action_invocation
|
|
@ -0,0 +1,9 @@
|
||||||
|
class UsageError(Exception):
|
||||||
|
""" error in pytest usage or invocation"""
|
||||||
|
|
||||||
|
|
||||||
|
class PrintHelp(Exception):
|
||||||
|
"""Raised when pytest should print it's help to skip the rest of the
|
||||||
|
argument parsing and validation."""
|
||||||
|
|
||||||
|
pass
|
|
@ -0,0 +1,139 @@
|
||||||
|
import py
|
||||||
|
import os
|
||||||
|
from .exceptions import UsageError
|
||||||
|
|
||||||
|
|
||||||
|
def exists(path, ignore=EnvironmentError):
|
||||||
|
try:
|
||||||
|
return path.check()
|
||||||
|
except ignore:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def getcfg(args, warnfunc=None):
|
||||||
|
"""
|
||||||
|
Search the list of arguments for a valid ini-file for pytest,
|
||||||
|
and return a tuple of (rootdir, inifile, cfg-dict).
|
||||||
|
|
||||||
|
note: warnfunc is an optional function used to warn
|
||||||
|
about ini-files that use deprecated features.
|
||||||
|
This parameter should be removed when pytest
|
||||||
|
adopts standard deprecation warnings (#1804).
|
||||||
|
"""
|
||||||
|
from _pytest.deprecated import CFG_PYTEST_SECTION
|
||||||
|
|
||||||
|
inibasenames = ["pytest.ini", "tox.ini", "setup.cfg"]
|
||||||
|
args = [x for x in args if not str(x).startswith("-")]
|
||||||
|
if not args:
|
||||||
|
args = [py.path.local()]
|
||||||
|
for arg in args:
|
||||||
|
arg = py.path.local(arg)
|
||||||
|
for base in arg.parts(reverse=True):
|
||||||
|
for inibasename in inibasenames:
|
||||||
|
p = base.join(inibasename)
|
||||||
|
if exists(p):
|
||||||
|
iniconfig = py.iniconfig.IniConfig(p)
|
||||||
|
if "pytest" in iniconfig.sections:
|
||||||
|
if inibasename == "setup.cfg" and warnfunc:
|
||||||
|
warnfunc(
|
||||||
|
"C1", CFG_PYTEST_SECTION.format(filename=inibasename)
|
||||||
|
)
|
||||||
|
return base, p, iniconfig["pytest"]
|
||||||
|
if (
|
||||||
|
inibasename == "setup.cfg"
|
||||||
|
and "tool:pytest" in iniconfig.sections
|
||||||
|
):
|
||||||
|
return base, p, iniconfig["tool:pytest"]
|
||||||
|
elif inibasename == "pytest.ini":
|
||||||
|
# allowed to be empty
|
||||||
|
return base, p, {}
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
|
||||||
|
def get_common_ancestor(paths):
|
||||||
|
common_ancestor = None
|
||||||
|
for path in paths:
|
||||||
|
if not path.exists():
|
||||||
|
continue
|
||||||
|
if common_ancestor is None:
|
||||||
|
common_ancestor = path
|
||||||
|
else:
|
||||||
|
if path.relto(common_ancestor) or path == common_ancestor:
|
||||||
|
continue
|
||||||
|
elif common_ancestor.relto(path):
|
||||||
|
common_ancestor = path
|
||||||
|
else:
|
||||||
|
shared = path.common(common_ancestor)
|
||||||
|
if shared is not None:
|
||||||
|
common_ancestor = shared
|
||||||
|
if common_ancestor is None:
|
||||||
|
common_ancestor = py.path.local()
|
||||||
|
elif common_ancestor.isfile():
|
||||||
|
common_ancestor = common_ancestor.dirpath()
|
||||||
|
return common_ancestor
|
||||||
|
|
||||||
|
|
||||||
|
def get_dirs_from_args(args):
|
||||||
|
def is_option(x):
|
||||||
|
return str(x).startswith("-")
|
||||||
|
|
||||||
|
def get_file_part_from_node_id(x):
|
||||||
|
return str(x).split("::")[0]
|
||||||
|
|
||||||
|
def get_dir_from_path(path):
|
||||||
|
if path.isdir():
|
||||||
|
return path
|
||||||
|
return py.path.local(path.dirname)
|
||||||
|
|
||||||
|
# These look like paths but may not exist
|
||||||
|
possible_paths = (
|
||||||
|
py.path.local(get_file_part_from_node_id(arg))
|
||||||
|
for arg in args
|
||||||
|
if not is_option(arg)
|
||||||
|
)
|
||||||
|
|
||||||
|
return [get_dir_from_path(path) for path in possible_paths if path.exists()]
|
||||||
|
|
||||||
|
|
||||||
|
def determine_setup(inifile, args, warnfunc=None, rootdir_cmd_arg=None):
|
||||||
|
dirs = get_dirs_from_args(args)
|
||||||
|
if inifile:
|
||||||
|
iniconfig = py.iniconfig.IniConfig(inifile)
|
||||||
|
is_cfg_file = str(inifile).endswith(".cfg")
|
||||||
|
# TODO: [pytest] section in *.cfg files is depricated. Need refactoring.
|
||||||
|
sections = ["tool:pytest", "pytest"] if is_cfg_file else ["pytest"]
|
||||||
|
for section in sections:
|
||||||
|
try:
|
||||||
|
inicfg = iniconfig[section]
|
||||||
|
if is_cfg_file and section == "pytest" and warnfunc:
|
||||||
|
from _pytest.deprecated import CFG_PYTEST_SECTION
|
||||||
|
|
||||||
|
warnfunc("C1", CFG_PYTEST_SECTION.format(filename=str(inifile)))
|
||||||
|
break
|
||||||
|
except KeyError:
|
||||||
|
inicfg = None
|
||||||
|
rootdir = get_common_ancestor(dirs)
|
||||||
|
else:
|
||||||
|
ancestor = get_common_ancestor(dirs)
|
||||||
|
rootdir, inifile, inicfg = getcfg([ancestor], warnfunc=warnfunc)
|
||||||
|
if rootdir is None:
|
||||||
|
for rootdir in ancestor.parts(reverse=True):
|
||||||
|
if rootdir.join("setup.py").exists():
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
rootdir, inifile, inicfg = getcfg(dirs, warnfunc=warnfunc)
|
||||||
|
if rootdir is None:
|
||||||
|
rootdir = get_common_ancestor([py.path.local(), ancestor])
|
||||||
|
is_fs_root = os.path.splitdrive(str(rootdir))[1] == "/"
|
||||||
|
if is_fs_root:
|
||||||
|
rootdir = ancestor
|
||||||
|
if rootdir_cmd_arg:
|
||||||
|
rootdir_abs_path = py.path.local(os.path.expandvars(rootdir_cmd_arg))
|
||||||
|
if not os.path.isdir(str(rootdir_abs_path)):
|
||||||
|
raise UsageError(
|
||||||
|
"Directory '{}' not found. Check your '--rootdir' option.".format(
|
||||||
|
rootdir_abs_path
|
||||||
|
)
|
||||||
|
)
|
||||||
|
rootdir = rootdir_abs_path
|
||||||
|
return rootdir, inifile, inicfg or {}
|
|
@ -65,6 +65,7 @@ def pytest_configure(config):
|
||||||
|
|
||||||
class pytestPDB(object):
|
class pytestPDB(object):
|
||||||
""" Pseudo PDB that defers to the real pdb. """
|
""" Pseudo PDB that defers to the real pdb. """
|
||||||
|
|
||||||
_pluginmanager = None
|
_pluginmanager = None
|
||||||
_config = None
|
_config = None
|
||||||
_pdb_cls = pdb.Pdb
|
_pdb_cls = pdb.Pdb
|
||||||
|
@ -87,7 +88,6 @@ class pytestPDB(object):
|
||||||
|
|
||||||
|
|
||||||
class PdbInvoke(object):
|
class PdbInvoke(object):
|
||||||
|
|
||||||
def pytest_exception_interact(self, node, call, report):
|
def pytest_exception_interact(self, node, call, report):
|
||||||
capman = node.config.pluginmanager.getplugin("capturemanager")
|
capman = node.config.pluginmanager.getplugin("capturemanager")
|
||||||
if capman:
|
if capman:
|
||||||
|
@ -114,7 +114,9 @@ def _enter_pdb(node, excinfo, rep):
|
||||||
showcapture = node.config.option.showcapture
|
showcapture = node.config.option.showcapture
|
||||||
|
|
||||||
for sectionname, content in (
|
for sectionname, content in (
|
||||||
("stdout", rep.capstdout), ("stderr", rep.capstderr), ("log", rep.caplog)
|
("stdout", rep.capstdout),
|
||||||
|
("stderr", rep.capstderr),
|
||||||
|
("log", rep.caplog),
|
||||||
):
|
):
|
||||||
if showcapture in (sectionname, "all") and content:
|
if showcapture in (sectionname, "all") and content:
|
||||||
tw.sep(">", "captured " + sectionname)
|
tw.sep(">", "captured " + sectionname)
|
||||||
|
@ -148,9 +150,7 @@ def _find_last_non_hidden_frame(stack):
|
||||||
|
|
||||||
|
|
||||||
def post_mortem(t):
|
def post_mortem(t):
|
||||||
|
|
||||||
class Pdb(pytestPDB._pdb_cls):
|
class Pdb(pytestPDB._pdb_cls):
|
||||||
|
|
||||||
def get_stack(self, f, t):
|
def get_stack(self, f, t):
|
||||||
stack, i = pdb.Pdb.get_stack(self, f, t)
|
stack, i = pdb.Pdb.get_stack(self, f, t)
|
||||||
if f is None:
|
if f is None:
|
||||||
|
|
|
@ -22,7 +22,9 @@ FUNCARG_PREFIX = (
|
||||||
"Please remove the prefix and use the @pytest.fixture decorator instead."
|
"Please remove the prefix and use the @pytest.fixture decorator instead."
|
||||||
)
|
)
|
||||||
|
|
||||||
CFG_PYTEST_SECTION = "[pytest] section in {filename} files is deprecated, use [tool:pytest] instead."
|
CFG_PYTEST_SECTION = (
|
||||||
|
"[pytest] section in {filename} files is deprecated, use [tool:pytest] instead."
|
||||||
|
)
|
||||||
|
|
||||||
GETFUNCARGVALUE = "use of getfuncargvalue is deprecated, use getfixturevalue"
|
GETFUNCARGVALUE = "use of getfuncargvalue is deprecated, use getfixturevalue"
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,6 @@ def _is_doctest(config, path, parent):
|
||||||
|
|
||||||
|
|
||||||
class ReprFailDoctest(TerminalRepr):
|
class ReprFailDoctest(TerminalRepr):
|
||||||
|
|
||||||
def __init__(self, reprlocation_lines):
|
def __init__(self, reprlocation_lines):
|
||||||
# List of (reprlocation, lines) tuples
|
# List of (reprlocation, lines) tuples
|
||||||
self.reprlocation_lines = reprlocation_lines
|
self.reprlocation_lines = reprlocation_lines
|
||||||
|
@ -118,7 +117,6 @@ class ReprFailDoctest(TerminalRepr):
|
||||||
|
|
||||||
|
|
||||||
class MultipleDoctestFailures(Exception):
|
class MultipleDoctestFailures(Exception):
|
||||||
|
|
||||||
def __init__(self, failures):
|
def __init__(self, failures):
|
||||||
super(MultipleDoctestFailures, self).__init__()
|
super(MultipleDoctestFailures, self).__init__()
|
||||||
self.failures = failures
|
self.failures = failures
|
||||||
|
@ -172,7 +170,6 @@ def _get_runner(checker=None, verbose=None, optionflags=0, continue_on_failure=T
|
||||||
|
|
||||||
|
|
||||||
class DoctestItem(pytest.Item):
|
class DoctestItem(pytest.Item):
|
||||||
|
|
||||||
def __init__(self, name, parent, runner=None, dtest=None):
|
def __init__(self, name, parent, runner=None, dtest=None):
|
||||||
super(DoctestItem, self).__init__(name, parent)
|
super(DoctestItem, self).__init__(name, parent)
|
||||||
self.runner = runner
|
self.runner = runner
|
||||||
|
@ -255,9 +252,7 @@ class DoctestItem(pytest.Item):
|
||||||
if isinstance(failure, doctest.DocTestFailure):
|
if isinstance(failure, doctest.DocTestFailure):
|
||||||
lines += checker.output_difference(
|
lines += checker.output_difference(
|
||||||
example, failure.got, report_choice
|
example, failure.got, report_choice
|
||||||
).split(
|
).split("\n")
|
||||||
"\n"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
inner_excinfo = ExceptionInfo(failure.exc_info)
|
inner_excinfo = ExceptionInfo(failure.exc_info)
|
||||||
lines += ["UNEXPECTED EXCEPTION: %s" % repr(inner_excinfo.value)]
|
lines += ["UNEXPECTED EXCEPTION: %s" % repr(inner_excinfo.value)]
|
||||||
|
@ -347,7 +342,6 @@ def _check_all_skipped(test):
|
||||||
|
|
||||||
|
|
||||||
class DoctestModule(pytest.Module):
|
class DoctestModule(pytest.Module):
|
||||||
|
|
||||||
def collect(self):
|
def collect(self):
|
||||||
import doctest
|
import doctest
|
||||||
|
|
||||||
|
@ -480,9 +474,7 @@ def _get_report_choice(key):
|
||||||
DOCTEST_REPORT_CHOICE_NDIFF: doctest.REPORT_NDIFF,
|
DOCTEST_REPORT_CHOICE_NDIFF: doctest.REPORT_NDIFF,
|
||||||
DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE: doctest.REPORT_ONLY_FIRST_FAILURE,
|
DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE: doctest.REPORT_ONLY_FIRST_FAILURE,
|
||||||
DOCTEST_REPORT_CHOICE_NONE: 0,
|
DOCTEST_REPORT_CHOICE_NONE: 0,
|
||||||
}[
|
}[key]
|
||||||
key
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def _fix_spoof_python2(runner, encoding):
|
def _fix_spoof_python2(runner, encoding):
|
||||||
|
@ -502,10 +494,9 @@ def _fix_spoof_python2(runner, encoding):
|
||||||
from doctest import _SpoofOut
|
from doctest import _SpoofOut
|
||||||
|
|
||||||
class UnicodeSpoof(_SpoofOut):
|
class UnicodeSpoof(_SpoofOut):
|
||||||
|
|
||||||
def getvalue(self):
|
def getvalue(self):
|
||||||
result = _SpoofOut.getvalue(self)
|
result = _SpoofOut.getvalue(self)
|
||||||
if encoding:
|
if encoding and isinstance(result, bytes):
|
||||||
result = result.decode(encoding)
|
result = result.decode(encoding)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,6 @@ scope2props["function"] = scope2props["instance"] + ("function", "keywords")
|
||||||
|
|
||||||
|
|
||||||
def scopeproperty(name=None, doc=None):
|
def scopeproperty(name=None, doc=None):
|
||||||
|
|
||||||
def decoratescope(func):
|
def decoratescope(func):
|
||||||
scopename = name or func.__name__
|
scopename = name or func.__name__
|
||||||
|
|
||||||
|
@ -276,7 +275,6 @@ def get_direct_param_fixture_func(request):
|
||||||
|
|
||||||
|
|
||||||
class FuncFixtureInfo(object):
|
class FuncFixtureInfo(object):
|
||||||
|
|
||||||
def __init__(self, argnames, names_closure, name2fixturedefs):
|
def __init__(self, argnames, names_closure, name2fixturedefs):
|
||||||
self.argnames = argnames
|
self.argnames = argnames
|
||||||
self.names_closure = names_closure
|
self.names_closure = names_closure
|
||||||
|
@ -698,7 +696,6 @@ class FixtureLookupError(LookupError):
|
||||||
|
|
||||||
|
|
||||||
class FixtureLookupErrorRepr(TerminalRepr):
|
class FixtureLookupErrorRepr(TerminalRepr):
|
||||||
|
|
||||||
def __init__(self, filename, firstlineno, tblines, errorstring, argname):
|
def __init__(self, filename, firstlineno, tblines, errorstring, argname):
|
||||||
self.tblines = tblines
|
self.tblines = tblines
|
||||||
self.errorstring = errorstring
|
self.errorstring = errorstring
|
||||||
|
@ -837,9 +834,10 @@ class FixtureDef(object):
|
||||||
return hook.pytest_fixture_setup(fixturedef=self, request=request)
|
return hook.pytest_fixture_setup(fixturedef=self, request=request)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return (
|
return "<FixtureDef name=%r scope=%r baseid=%r >" % (
|
||||||
"<FixtureDef name=%r scope=%r baseid=%r >"
|
self.argname,
|
||||||
% (self.argname, self.scope, self.baseid)
|
self.scope,
|
||||||
|
self.baseid,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,6 @@ _py_ext_re = re.compile(r"\.py$")
|
||||||
|
|
||||||
|
|
||||||
def bin_xml_escape(arg):
|
def bin_xml_escape(arg):
|
||||||
|
|
||||||
def repl(matchobj):
|
def repl(matchobj):
|
||||||
i = ord(matchobj.group())
|
i = ord(matchobj.group())
|
||||||
if i <= 0xFF:
|
if i <= 0xFF:
|
||||||
|
@ -67,7 +66,6 @@ def bin_xml_escape(arg):
|
||||||
|
|
||||||
|
|
||||||
class _NodeReporter(object):
|
class _NodeReporter(object):
|
||||||
|
|
||||||
def __init__(self, nodeid, xml):
|
def __init__(self, nodeid, xml):
|
||||||
|
|
||||||
self.id = nodeid
|
self.id = nodeid
|
||||||
|
@ -358,7 +356,6 @@ def mangle_test_address(address):
|
||||||
|
|
||||||
|
|
||||||
class LogXML(object):
|
class LogXML(object):
|
||||||
|
|
||||||
def __init__(self, logfile, prefix, suite_name="pytest", logging="no"):
|
def __init__(self, logfile, prefix, suite_name="pytest", logging="no"):
|
||||||
logfile = os.path.expanduser(os.path.expandvars(logfile))
|
logfile = os.path.expanduser(os.path.expandvars(logfile))
|
||||||
self.logfile = os.path.normpath(os.path.abspath(logfile))
|
self.logfile = os.path.normpath(os.path.abspath(logfile))
|
||||||
|
@ -544,9 +541,7 @@ class LogXML(object):
|
||||||
skips=self.stats["skipped"],
|
skips=self.stats["skipped"],
|
||||||
tests=numtests,
|
tests=numtests,
|
||||||
time="%.3f" % suite_time_delta,
|
time="%.3f" % suite_time_delta,
|
||||||
).unicode(
|
).unicode(indent=0)
|
||||||
indent=0
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
logfile.close()
|
logfile.close()
|
||||||
|
|
||||||
|
|
|
@ -425,9 +425,7 @@ class LoggingPlugin(object):
|
||||||
"""
|
"""
|
||||||
return self._config.getoption(
|
return self._config.getoption(
|
||||||
"--log-cli-level"
|
"--log-cli-level"
|
||||||
) is not None or self._config.getini(
|
) is not None or self._config.getini("log_cli")
|
||||||
"log_cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _runtest_for(self, item, when):
|
def _runtest_for(self, item, when):
|
||||||
|
|
|
@ -343,7 +343,6 @@ def _patched_find_module():
|
||||||
|
|
||||||
|
|
||||||
class FSHookProxy(object):
|
class FSHookProxy(object):
|
||||||
|
|
||||||
def __init__(self, fspath, pm, remove_mods):
|
def __init__(self, fspath, pm, remove_mods):
|
||||||
self.fspath = fspath
|
self.fspath = fspath
|
||||||
self.pm = pm
|
self.pm = pm
|
||||||
|
@ -361,6 +360,7 @@ class NoMatch(Exception):
|
||||||
|
|
||||||
class Interrupted(KeyboardInterrupt):
|
class Interrupted(KeyboardInterrupt):
|
||||||
""" signals an interrupted test run. """
|
""" signals an interrupted test run. """
|
||||||
|
|
||||||
__module__ = "builtins" # for py3
|
__module__ = "builtins" # for py3
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ def cached_eval(config, expr, d):
|
||||||
|
|
||||||
|
|
||||||
class MarkEvaluator(object):
|
class MarkEvaluator(object):
|
||||||
|
|
||||||
def __init__(self, item, name):
|
def __init__(self, item, name):
|
||||||
self.item = item
|
self.item = item
|
||||||
self._marks = None
|
self._marks = None
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import inspect
|
import inspect
|
||||||
import warnings
|
import warnings
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
from functools import reduce
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
|
||||||
from ..deprecated import MARK_PARAMETERSET_UNPACKING, MARK_INFO_ATTRIBUTE
|
from ..deprecated import MARK_PARAMETERSET_UNPACKING, MARK_INFO_ATTRIBUTE
|
||||||
from ..compat import NOTSET, getfslineno, MappingMixin
|
from ..compat import NOTSET, getfslineno, MappingMixin
|
||||||
from six.moves import map, reduce
|
from six.moves import map
|
||||||
|
|
||||||
|
|
||||||
EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark"
|
EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark"
|
||||||
|
@ -24,9 +25,10 @@ def alias(name, warning=None):
|
||||||
|
|
||||||
|
|
||||||
def istestfunc(func):
|
def istestfunc(func):
|
||||||
return hasattr(func, "__call__") and getattr(
|
return (
|
||||||
func, "__name__", "<lambda>"
|
hasattr(func, "__call__")
|
||||||
) != "<lambda>"
|
and getattr(func, "__name__", "<lambda>") != "<lambda>"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_empty_parameterset_mark(config, argnames, func):
|
def get_empty_parameterset_mark(config, argnames, func):
|
||||||
|
@ -39,18 +41,20 @@ def get_empty_parameterset_mark(config, argnames, func):
|
||||||
raise LookupError(requested_mark)
|
raise LookupError(requested_mark)
|
||||||
fs, lineno = getfslineno(func)
|
fs, lineno = getfslineno(func)
|
||||||
reason = "got empty parameter set %r, function %s at %s:%d" % (
|
reason = "got empty parameter set %r, function %s at %s:%d" % (
|
||||||
argnames, func.__name__, fs, lineno
|
argnames,
|
||||||
|
func.__name__,
|
||||||
|
fs,
|
||||||
|
lineno,
|
||||||
)
|
)
|
||||||
return mark(reason=reason)
|
return mark(reason=reason)
|
||||||
|
|
||||||
|
|
||||||
class ParameterSet(namedtuple("ParameterSet", "values, marks, id")):
|
class ParameterSet(namedtuple("ParameterSet", "values, marks, id")):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def param(cls, *values, **kw):
|
def param(cls, *values, **kw):
|
||||||
marks = kw.pop("marks", ())
|
marks = kw.pop("marks", ())
|
||||||
if isinstance(marks, MarkDecorator):
|
if isinstance(marks, MarkDecorator):
|
||||||
marks = marks,
|
marks = (marks,)
|
||||||
else:
|
else:
|
||||||
assert isinstance(marks, (tuple, list, set))
|
assert isinstance(marks, (tuple, list, set))
|
||||||
|
|
||||||
|
@ -87,7 +91,7 @@ class ParameterSet(namedtuple("ParameterSet", "values, marks, id")):
|
||||||
argval = argval.args[-1]
|
argval = argval.args[-1]
|
||||||
assert not isinstance(argval, ParameterSet)
|
assert not isinstance(argval, ParameterSet)
|
||||||
if legacy_force_tuple:
|
if legacy_force_tuple:
|
||||||
argval = argval,
|
argval = (argval,)
|
||||||
|
|
||||||
if newmarks:
|
if newmarks:
|
||||||
warnings.warn(MARK_PARAMETERSET_UNPACKING)
|
warnings.warn(MARK_PARAMETERSET_UNPACKING)
|
||||||
|
@ -332,6 +336,7 @@ class MarkGenerator(object):
|
||||||
|
|
||||||
will set a 'slowtest' :class:`MarkInfo` object
|
will set a 'slowtest' :class:`MarkInfo` object
|
||||||
on the ``test_function`` object. """
|
on the ``test_function`` object. """
|
||||||
|
|
||||||
_config = None
|
_config = None
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
|
@ -361,7 +366,6 @@ MARK_GEN = MarkGenerator()
|
||||||
|
|
||||||
|
|
||||||
class NodeKeywords(MappingMixin):
|
class NodeKeywords(MappingMixin):
|
||||||
|
|
||||||
def __init__(self, node):
|
def __init__(self, node):
|
||||||
self.node = node
|
self.node = node
|
||||||
self.parent = node.parent
|
self.parent = node.parent
|
||||||
|
@ -408,6 +412,7 @@ class NodeMarkers(object):
|
||||||
unstable api
|
unstable api
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
own_markers = attr.ib(default=attr.Factory(list))
|
own_markers = attr.ib(default=attr.Factory(list))
|
||||||
|
|
||||||
def update(self, add_markers):
|
def update(self, add_markers):
|
||||||
|
|
|
@ -86,7 +86,6 @@ def derive_importpath(import_path, raising):
|
||||||
|
|
||||||
|
|
||||||
class Notset(object):
|
class Notset(object):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<notset>"
|
return "<notset>"
|
||||||
|
|
||||||
|
|
|
@ -341,7 +341,6 @@ def _check_initialpaths_for_relpath(session, fspath):
|
||||||
|
|
||||||
|
|
||||||
class FSCollector(Collector):
|
class FSCollector(Collector):
|
||||||
|
|
||||||
def __init__(self, fspath, parent=None, config=None, session=None, nodeid=None):
|
def __init__(self, fspath, parent=None, config=None, session=None, nodeid=None):
|
||||||
fspath = py.path.local(fspath) # xxx only for test_resultlog.py?
|
fspath = py.path.local(fspath) # xxx only for test_resultlog.py?
|
||||||
name = fspath.basename
|
name = fspath.basename
|
||||||
|
@ -375,6 +374,7 @@ class Item(Node):
|
||||||
""" a basic test invocation item. Note that for a single function
|
""" a basic test invocation item. Note that for a single function
|
||||||
there might be multiple test invocation items.
|
there might be multiple test invocation items.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
nextitem = None
|
nextitem = None
|
||||||
|
|
||||||
def __init__(self, name, parent=None, config=None, session=None, nodeid=None):
|
def __init__(self, name, parent=None, config=None, session=None, nodeid=None):
|
||||||
|
|
|
@ -43,6 +43,7 @@ class Skipped(OutcomeException):
|
||||||
|
|
||||||
class Failed(OutcomeException):
|
class Failed(OutcomeException):
|
||||||
""" raised from an explicit call to pytest.fail() """
|
""" raised from an explicit call to pytest.fail() """
|
||||||
|
|
||||||
__module__ = "builtins"
|
__module__ = "builtins"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,6 @@ def pytest_configure(config):
|
||||||
|
|
||||||
|
|
||||||
class LsofFdLeakChecker(object):
|
class LsofFdLeakChecker(object):
|
||||||
|
|
||||||
def get_open_files(self):
|
def get_open_files(self):
|
||||||
out = self._exec_lsof()
|
out = self._exec_lsof()
|
||||||
open_files = self._parse_lsof_output(out)
|
open_files = self._parse_lsof_output(out)
|
||||||
|
@ -73,7 +72,6 @@ class LsofFdLeakChecker(object):
|
||||||
return py.process.cmdexec("lsof -Ffn0 -p %d" % pid)
|
return py.process.cmdexec("lsof -Ffn0 -p %d" % pid)
|
||||||
|
|
||||||
def _parse_lsof_output(self, out):
|
def _parse_lsof_output(self, out):
|
||||||
|
|
||||||
def isopen(line):
|
def isopen(line):
|
||||||
return line.startswith("f") and (
|
return line.startswith("f") and (
|
||||||
"deleted" not in line
|
"deleted" not in line
|
||||||
|
@ -195,7 +193,6 @@ def _pytest(request):
|
||||||
|
|
||||||
|
|
||||||
class PytestArg(object):
|
class PytestArg(object):
|
||||||
|
|
||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
self.request = request
|
self.request = request
|
||||||
|
|
||||||
|
@ -211,7 +208,6 @@ def get_public_names(values):
|
||||||
|
|
||||||
|
|
||||||
class ParsedCall(object):
|
class ParsedCall(object):
|
||||||
|
|
||||||
def __init__(self, name, kwargs):
|
def __init__(self, name, kwargs):
|
||||||
self.__dict__.update(kwargs)
|
self.__dict__.update(kwargs)
|
||||||
self._name = name
|
self._name = name
|
||||||
|
@ -423,13 +419,12 @@ class RunResult(object):
|
||||||
"failed": d.get("failed", 0),
|
"failed": d.get("failed", 0),
|
||||||
"error": d.get("error", 0),
|
"error": d.get("error", 0),
|
||||||
}
|
}
|
||||||
assert (
|
assert obtained == dict(
|
||||||
obtained == dict(passed=passed, skipped=skipped, failed=failed, error=error)
|
passed=passed, skipped=skipped, failed=failed, error=error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CwdSnapshot(object):
|
class CwdSnapshot(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__saved = os.getcwd()
|
self.__saved = os.getcwd()
|
||||||
|
|
||||||
|
@ -438,7 +433,6 @@ class CwdSnapshot(object):
|
||||||
|
|
||||||
|
|
||||||
class SysModulesSnapshot(object):
|
class SysModulesSnapshot(object):
|
||||||
|
|
||||||
def __init__(self, preserve=None):
|
def __init__(self, preserve=None):
|
||||||
self.__preserve = preserve
|
self.__preserve = preserve
|
||||||
self.__saved = dict(sys.modules)
|
self.__saved = dict(sys.modules)
|
||||||
|
@ -453,7 +447,6 @@ class SysModulesSnapshot(object):
|
||||||
|
|
||||||
|
|
||||||
class SysPathsSnapshot(object):
|
class SysPathsSnapshot(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__saved = list(sys.path), list(sys.meta_path)
|
self.__saved = list(sys.path), list(sys.meta_path)
|
||||||
|
|
||||||
|
@ -778,7 +771,6 @@ class Testdir(object):
|
||||||
rec = []
|
rec = []
|
||||||
|
|
||||||
class Collect(object):
|
class Collect(object):
|
||||||
|
|
||||||
def pytest_configure(x, config):
|
def pytest_configure(x, config):
|
||||||
rec.append(self.make_hook_recorder(config.pluginmanager))
|
rec.append(self.make_hook_recorder(config.pluginmanager))
|
||||||
|
|
||||||
|
@ -910,8 +902,10 @@ class Testdir(object):
|
||||||
for item in items:
|
for item in items:
|
||||||
if item.name == funcname:
|
if item.name == funcname:
|
||||||
return item
|
return item
|
||||||
assert 0, (
|
assert 0, "%r item not found in module:\n%s\nitems: %s" % (
|
||||||
"%r item not found in module:\n%s\nitems: %s" % (funcname, source, items)
|
funcname,
|
||||||
|
source,
|
||||||
|
items,
|
||||||
)
|
)
|
||||||
|
|
||||||
def getitems(self, source):
|
def getitems(self, source):
|
||||||
|
@ -1115,7 +1109,6 @@ def getdecoded(out):
|
||||||
|
|
||||||
|
|
||||||
class LineComp(object):
|
class LineComp(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.stringio = py.io.TextIO()
|
self.stringio = py.io.TextIO()
|
||||||
|
|
||||||
|
|
|
@ -69,13 +69,12 @@ def filter_traceback(entry):
|
||||||
# entry.path might point to a non-existing file, in which case it will
|
# entry.path might point to a non-existing file, in which case it will
|
||||||
# also return a str object. see #1133
|
# also return a str object. see #1133
|
||||||
p = py.path.local(entry.path)
|
p = py.path.local(entry.path)
|
||||||
return not p.relto(_pluggy_dir) and not p.relto(_pytest_dir) and not p.relto(
|
return (
|
||||||
_py_dir
|
not p.relto(_pluggy_dir) and not p.relto(_pytest_dir) and not p.relto(_py_dir)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def pyobj_property(name):
|
def pyobj_property(name):
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
node = self.getparent(getattr(__import__("pytest"), name))
|
node = self.getparent(getattr(__import__("pytest"), name))
|
||||||
if node is not None:
|
if node is not None:
|
||||||
|
@ -258,7 +257,6 @@ class PyobjMixin(PyobjContext):
|
||||||
super(PyobjMixin, self).__init__(*k, **kw)
|
super(PyobjMixin, self).__init__(*k, **kw)
|
||||||
|
|
||||||
def obj():
|
def obj():
|
||||||
|
|
||||||
def fget(self):
|
def fget(self):
|
||||||
obj = getattr(self, "_obj", None)
|
obj = getattr(self, "_obj", None)
|
||||||
if obj is None:
|
if obj is None:
|
||||||
|
@ -320,7 +318,6 @@ class PyobjMixin(PyobjContext):
|
||||||
|
|
||||||
|
|
||||||
class PyCollector(PyobjMixin, nodes.Collector):
|
class PyCollector(PyobjMixin, nodes.Collector):
|
||||||
|
|
||||||
def funcnamefilter(self, name):
|
def funcnamefilter(self, name):
|
||||||
return self._matches_prefix_or_glob_option("python_functions", name)
|
return self._matches_prefix_or_glob_option("python_functions", name)
|
||||||
|
|
||||||
|
@ -487,9 +484,11 @@ class Module(nodes.File, PyCollector):
|
||||||
exc_info = ExceptionInfo()
|
exc_info = ExceptionInfo()
|
||||||
if self.config.getoption("verbose") < 2:
|
if self.config.getoption("verbose") < 2:
|
||||||
exc_info.traceback = exc_info.traceback.filter(filter_traceback)
|
exc_info.traceback = exc_info.traceback.filter(filter_traceback)
|
||||||
exc_repr = exc_info.getrepr(
|
exc_repr = (
|
||||||
style="short"
|
exc_info.getrepr(style="short")
|
||||||
) if exc_info.traceback else exc_info.exconly()
|
if exc_info.traceback
|
||||||
|
else exc_info.exconly()
|
||||||
|
)
|
||||||
formatted_tb = safe_str(exc_repr)
|
formatted_tb = safe_str(exc_repr)
|
||||||
raise self.CollectError(
|
raise self.CollectError(
|
||||||
"ImportError while importing test module '{fspath}'.\n"
|
"ImportError while importing test module '{fspath}'.\n"
|
||||||
|
@ -673,7 +672,6 @@ class FunctionMixin(PyobjMixin):
|
||||||
|
|
||||||
|
|
||||||
class Generator(FunctionMixin, PyCollector):
|
class Generator(FunctionMixin, PyCollector):
|
||||||
|
|
||||||
def collect(self):
|
def collect(self):
|
||||||
# test generators are seen as collectors but they also
|
# test generators are seen as collectors but they also
|
||||||
# invoke setup/teardown on popular request
|
# invoke setup/teardown on popular request
|
||||||
|
@ -728,20 +726,18 @@ def hasnew(obj):
|
||||||
|
|
||||||
|
|
||||||
class CallSpec2(object):
|
class CallSpec2(object):
|
||||||
|
|
||||||
def __init__(self, metafunc):
|
def __init__(self, metafunc):
|
||||||
self.metafunc = metafunc
|
self.metafunc = metafunc
|
||||||
self.funcargs = {}
|
self.funcargs = {}
|
||||||
self._idlist = []
|
self._idlist = []
|
||||||
self.params = {}
|
self.params = {}
|
||||||
self._globalid = NOTSET
|
self._globalid = NOTSET
|
||||||
self._globalid_args = set()
|
|
||||||
self._globalparam = NOTSET
|
self._globalparam = NOTSET
|
||||||
self._arg2scopenum = {} # used for sorting parametrized resources
|
self._arg2scopenum = {} # used for sorting parametrized resources
|
||||||
self.marks = []
|
self.marks = []
|
||||||
self.indices = {}
|
self.indices = {}
|
||||||
|
|
||||||
def copy(self, metafunc):
|
def copy(self):
|
||||||
cs = CallSpec2(self.metafunc)
|
cs = CallSpec2(self.metafunc)
|
||||||
cs.funcargs.update(self.funcargs)
|
cs.funcargs.update(self.funcargs)
|
||||||
cs.params.update(self.params)
|
cs.params.update(self.params)
|
||||||
|
@ -750,7 +746,6 @@ class CallSpec2(object):
|
||||||
cs._arg2scopenum.update(self._arg2scopenum)
|
cs._arg2scopenum.update(self._arg2scopenum)
|
||||||
cs._idlist = list(self._idlist)
|
cs._idlist = list(self._idlist)
|
||||||
cs._globalid = self._globalid
|
cs._globalid = self._globalid
|
||||||
cs._globalid_args = self._globalid_args
|
|
||||||
cs._globalparam = self._globalparam
|
cs._globalparam = self._globalparam
|
||||||
return cs
|
return cs
|
||||||
|
|
||||||
|
@ -933,7 +928,7 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
|
||||||
param.values, argnames
|
param.values, argnames
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
newcallspec = callspec.copy(self)
|
newcallspec = callspec.copy()
|
||||||
newcallspec.setmulti2(
|
newcallspec.setmulti2(
|
||||||
valtypes,
|
valtypes,
|
||||||
argnames,
|
argnames,
|
||||||
|
@ -1004,9 +999,9 @@ def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):
|
||||||
from _pytest.fixtures import scopes
|
from _pytest.fixtures import scopes
|
||||||
|
|
||||||
indirect_as_list = isinstance(indirect, (list, tuple))
|
indirect_as_list = isinstance(indirect, (list, tuple))
|
||||||
all_arguments_are_fixtures = indirect is True or indirect_as_list and len(
|
all_arguments_are_fixtures = (
|
||||||
indirect
|
indirect is True or indirect_as_list and len(indirect) == argnames
|
||||||
) == argnames
|
)
|
||||||
if all_arguments_are_fixtures:
|
if all_arguments_are_fixtures:
|
||||||
fixturedefs = arg2fixturedefs or {}
|
fixturedefs = arg2fixturedefs or {}
|
||||||
used_scopes = [fixturedef[0].scope for name, fixturedef in fixturedefs.items()]
|
used_scopes = [fixturedef[0].scope for name, fixturedef in fixturedefs.items()]
|
||||||
|
@ -1028,8 +1023,9 @@ def _idval(val, argname, idx, idfn, config=None):
|
||||||
# See issue https://github.com/pytest-dev/pytest/issues/2169
|
# See issue https://github.com/pytest-dev/pytest/issues/2169
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
msg = "Raised while trying to determine id of parameter %s at position %d." % (
|
msg = (
|
||||||
argname, idx
|
"Raised while trying to determine id of parameter %s at position %d."
|
||||||
|
% (argname, idx)
|
||||||
)
|
)
|
||||||
msg += "\nUpdate your code as this will raise an error in pytest-4.0."
|
msg += "\nUpdate your code as this will raise an error in pytest-4.0."
|
||||||
warnings.warn(msg, DeprecationWarning)
|
warnings.warn(msg, DeprecationWarning)
|
||||||
|
@ -1224,6 +1220,7 @@ class Function(FunctionMixin, nodes.Item, fixtures.FuncargnamesCompatAttr):
|
||||||
""" a Function Item is responsible for setting up and executing a
|
""" a Function Item is responsible for setting up and executing a
|
||||||
Python test function.
|
Python test function.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_genid = None
|
_genid = None
|
||||||
# disable since functions handle it themselfes
|
# disable since functions handle it themselfes
|
||||||
_ALLOW_MARKERS = False
|
_ALLOW_MARKERS = False
|
||||||
|
|
|
@ -86,9 +86,11 @@ class ApproxNumpy(ApproxBase):
|
||||||
# shape of the array...
|
# shape of the array...
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
return "approx({!r})".format(
|
list_scalars = []
|
||||||
list(self._approx_scalar(x) for x in np.asarray(self.expected))
|
for x in np.ndindex(self.expected.shape):
|
||||||
)
|
list_scalars.append(self._approx_scalar(np.asscalar(self.expected[x])))
|
||||||
|
|
||||||
|
return "approx({!r})".format(list_scalars)
|
||||||
|
|
||||||
if sys.version_info[0] == 2:
|
if sys.version_info[0] == 2:
|
||||||
__cmp__ = _cmp_raises_type_error
|
__cmp__ = _cmp_raises_type_error
|
||||||
|
@ -172,6 +174,7 @@ class ApproxScalar(ApproxBase):
|
||||||
"""
|
"""
|
||||||
Perform approximate comparisons for single numbers only.
|
Perform approximate comparisons for single numbers only.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DEFAULT_ABSOLUTE_TOLERANCE = 1e-12
|
DEFAULT_ABSOLUTE_TOLERANCE = 1e-12
|
||||||
DEFAULT_RELATIVE_TOLERANCE = 1e-6
|
DEFAULT_RELATIVE_TOLERANCE = 1e-6
|
||||||
|
|
||||||
|
@ -269,9 +272,7 @@ class ApproxScalar(ApproxBase):
|
||||||
# we aren't even going to use it.
|
# we aren't even going to use it.
|
||||||
relative_tolerance = set_default(
|
relative_tolerance = set_default(
|
||||||
self.rel, self.DEFAULT_RELATIVE_TOLERANCE
|
self.rel, self.DEFAULT_RELATIVE_TOLERANCE
|
||||||
) * abs(
|
) * abs(self.expected)
|
||||||
self.expected
|
|
||||||
)
|
|
||||||
|
|
||||||
if relative_tolerance < 0:
|
if relative_tolerance < 0:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -497,7 +498,7 @@ def _is_numpy_array(obj):
|
||||||
|
|
||||||
|
|
||||||
def raises(expected_exception, *args, **kwargs):
|
def raises(expected_exception, *args, **kwargs):
|
||||||
"""
|
r"""
|
||||||
Assert that a code block/function call raises ``expected_exception``
|
Assert that a code block/function call raises ``expected_exception``
|
||||||
and raise a failure exception otherwise.
|
and raise a failure exception otherwise.
|
||||||
|
|
||||||
|
@ -650,7 +651,6 @@ raises.Exception = fail.Exception
|
||||||
|
|
||||||
|
|
||||||
class RaisesContext(object):
|
class RaisesContext(object):
|
||||||
|
|
||||||
def __init__(self, expected_exception, message, match_expr):
|
def __init__(self, expected_exception, message, match_expr):
|
||||||
self.expected_exception = expected_exception
|
self.expected_exception = expected_exception
|
||||||
self.message = message
|
self.message = message
|
||||||
|
|
|
@ -85,7 +85,7 @@ class _DeprecatedCallContext(object):
|
||||||
|
|
||||||
|
|
||||||
def warns(expected_warning, *args, **kwargs):
|
def warns(expected_warning, *args, **kwargs):
|
||||||
"""Assert that code raises a particular class of warning.
|
r"""Assert that code raises a particular class of warning.
|
||||||
|
|
||||||
Specifically, the parameter ``expected_warning`` can be a warning class or
|
Specifically, the parameter ``expected_warning`` can be a warning class or
|
||||||
sequence of warning classes, and the inside the ``with`` block must issue a warning of that class or
|
sequence of warning classes, and the inside the ``with`` block must issue a warning of that class or
|
||||||
|
@ -193,13 +193,10 @@ class WarningsRecorder(warnings.catch_warnings):
|
||||||
|
|
||||||
|
|
||||||
class WarningsChecker(WarningsRecorder):
|
class WarningsChecker(WarningsRecorder):
|
||||||
|
|
||||||
def __init__(self, expected_warning=None, match_expr=None):
|
def __init__(self, expected_warning=None, match_expr=None):
|
||||||
super(WarningsChecker, self).__init__()
|
super(WarningsChecker, self).__init__()
|
||||||
|
|
||||||
msg = (
|
msg = "exceptions must be old-style classes or " "derived from Warning, not %s"
|
||||||
"exceptions must be old-style classes or " "derived from Warning, not %s"
|
|
||||||
)
|
|
||||||
if isinstance(expected_warning, tuple):
|
if isinstance(expected_warning, tuple):
|
||||||
for exc in expected_warning:
|
for exc in expected_warning:
|
||||||
if not inspect.isclass(exc):
|
if not inspect.isclass(exc):
|
||||||
|
|
|
@ -68,7 +68,6 @@ def generic_path(item):
|
||||||
|
|
||||||
|
|
||||||
class ResultLog(object):
|
class ResultLog(object):
|
||||||
|
|
||||||
def __init__(self, config, logfile):
|
def __init__(self, config, logfile):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.logfile = logfile # preferably line buffered
|
self.logfile = logfile # preferably line buffered
|
||||||
|
|
|
@ -186,6 +186,7 @@ def call_runtest_hook(item, when, **kwds):
|
||||||
|
|
||||||
class CallInfo(object):
|
class CallInfo(object):
|
||||||
""" Result/Exception info a function invocation. """
|
""" Result/Exception info a function invocation. """
|
||||||
|
|
||||||
#: None or ExceptionInfo object.
|
#: None or ExceptionInfo object.
|
||||||
excinfo = None
|
excinfo = None
|
||||||
|
|
||||||
|
@ -221,13 +222,15 @@ def getslaveinfoline(node):
|
||||||
d = node.slaveinfo
|
d = node.slaveinfo
|
||||||
ver = "%s.%s.%s" % d["version_info"][:3]
|
ver = "%s.%s.%s" % d["version_info"][:3]
|
||||||
node._slaveinfocache = s = "[%s] %s -- Python %s %s" % (
|
node._slaveinfocache = s = "[%s] %s -- Python %s %s" % (
|
||||||
d["id"], d["sysplatform"], ver, d["executable"]
|
d["id"],
|
||||||
|
d["sysplatform"],
|
||||||
|
ver,
|
||||||
|
d["executable"],
|
||||||
)
|
)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
class BaseReport(object):
|
class BaseReport(object):
|
||||||
|
|
||||||
def __init__(self, **kw):
|
def __init__(self, **kw):
|
||||||
self.__dict__.update(kw)
|
self.__dict__.update(kw)
|
||||||
|
|
||||||
|
@ -401,7 +404,9 @@ class TestReport(BaseReport):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<TestReport %r when=%r outcome=%r>" % (
|
return "<TestReport %r when=%r outcome=%r>" % (
|
||||||
self.nodeid, self.when, self.outcome
|
self.nodeid,
|
||||||
|
self.when,
|
||||||
|
self.outcome,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -442,7 +447,6 @@ def pytest_make_collect_report(collector):
|
||||||
|
|
||||||
|
|
||||||
class CollectReport(BaseReport):
|
class CollectReport(BaseReport):
|
||||||
|
|
||||||
def __init__(self, nodeid, outcome, longrepr, result, sections=(), **extra):
|
def __init__(self, nodeid, outcome, longrepr, result, sections=(), **extra):
|
||||||
self.nodeid = nodeid
|
self.nodeid = nodeid
|
||||||
self.outcome = outcome
|
self.outcome = outcome
|
||||||
|
@ -457,12 +461,13 @@ class CollectReport(BaseReport):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<CollectReport %r lenresult=%s outcome=%r>" % (
|
return "<CollectReport %r lenresult=%s outcome=%r>" % (
|
||||||
self.nodeid, len(self.result), self.outcome
|
self.nodeid,
|
||||||
|
len(self.result),
|
||||||
|
self.outcome,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CollectErrorRepr(TerminalRepr):
|
class CollectErrorRepr(TerminalRepr):
|
||||||
|
|
||||||
def __init__(self, msg):
|
def __init__(self, msg):
|
||||||
self.longrepr = msg
|
self.longrepr = msg
|
||||||
|
|
||||||
|
|
|
@ -157,9 +157,11 @@ def pytest_runtest_makereport(item, call):
|
||||||
else:
|
else:
|
||||||
rep.outcome = "passed"
|
rep.outcome = "passed"
|
||||||
rep.wasxfail = explanation
|
rep.wasxfail = explanation
|
||||||
elif getattr(item, "_skipped_by_mark", False) and rep.skipped and type(
|
elif (
|
||||||
rep.longrepr
|
getattr(item, "_skipped_by_mark", False)
|
||||||
) is tuple:
|
and rep.skipped
|
||||||
|
and type(rep.longrepr) is tuple
|
||||||
|
):
|
||||||
# skipped by mark.skipif; change the location of the failure
|
# skipped by mark.skipif; change the location of the failure
|
||||||
# to point to the item definition, otherwise it will display
|
# to point to the item definition, otherwise it will display
|
||||||
# the location of where the skip exception was raised within pytest
|
# the location of where the skip exception was raised within pytest
|
||||||
|
@ -274,7 +276,6 @@ def show_skipped(terminalreporter, lines):
|
||||||
|
|
||||||
|
|
||||||
def shower(stat, format):
|
def shower(stat, format):
|
||||||
|
|
||||||
def show_(terminalreporter, lines):
|
def show_(terminalreporter, lines):
|
||||||
return show_simple(terminalreporter, lines, stat, format)
|
return show_simple(terminalreporter, lines, stat, format)
|
||||||
|
|
||||||
|
|
|
@ -220,7 +220,6 @@ class WarningReport(object):
|
||||||
|
|
||||||
|
|
||||||
class TerminalReporter(object):
|
class TerminalReporter(object):
|
||||||
|
|
||||||
def __init__(self, config, file=None):
|
def __init__(self, config, file=None):
|
||||||
import _pytest.config
|
import _pytest.config
|
||||||
|
|
||||||
|
@ -407,13 +406,16 @@ class TerminalReporter(object):
|
||||||
def pytest_runtest_logfinish(self, nodeid):
|
def pytest_runtest_logfinish(self, nodeid):
|
||||||
if self.verbosity <= 0 and self._show_progress_info:
|
if self.verbosity <= 0 and self._show_progress_info:
|
||||||
self._progress_nodeids_reported.add(nodeid)
|
self._progress_nodeids_reported.add(nodeid)
|
||||||
last_item = len(
|
last_item = (
|
||||||
self._progress_nodeids_reported
|
len(self._progress_nodeids_reported) == self._session.testscollected
|
||||||
) == self._session.testscollected
|
)
|
||||||
if last_item:
|
if last_item:
|
||||||
self._write_progress_information_filling_space()
|
self._write_progress_information_filling_space()
|
||||||
else:
|
else:
|
||||||
past_edge = self._tw.chars_on_current_line + self._PROGRESS_LENGTH + 1 >= self._screen_width
|
past_edge = (
|
||||||
|
self._tw.chars_on_current_line + self._PROGRESS_LENGTH + 1
|
||||||
|
>= self._screen_width
|
||||||
|
)
|
||||||
if past_edge:
|
if past_edge:
|
||||||
msg = self._get_progress_information_message()
|
msg = self._get_progress_information_message()
|
||||||
self._tw.write(msg + "\n", cyan=True)
|
self._tw.write(msg + "\n", cyan=True)
|
||||||
|
@ -462,8 +464,8 @@ class TerminalReporter(object):
|
||||||
line = "collected "
|
line = "collected "
|
||||||
else:
|
else:
|
||||||
line = "collecting "
|
line = "collecting "
|
||||||
line += str(self._numcollected) + " item" + (
|
line += (
|
||||||
"" if self._numcollected == 1 else "s"
|
str(self._numcollected) + " item" + ("" if self._numcollected == 1 else "s")
|
||||||
)
|
)
|
||||||
if errors:
|
if errors:
|
||||||
line += " / %d errors" % errors
|
line += " / %d errors" % errors
|
||||||
|
@ -495,7 +497,9 @@ class TerminalReporter(object):
|
||||||
verinfo = ".".join(map(str, sys.pypy_version_info[:3]))
|
verinfo = ".".join(map(str, sys.pypy_version_info[:3]))
|
||||||
msg += "[pypy-%s-%s]" % (verinfo, sys.pypy_version_info[3])
|
msg += "[pypy-%s-%s]" % (verinfo, sys.pypy_version_info[3])
|
||||||
msg += ", pytest-%s, py-%s, pluggy-%s" % (
|
msg += ", pytest-%s, py-%s, pluggy-%s" % (
|
||||||
pytest.__version__, py.__version__, pluggy.__version__
|
pytest.__version__,
|
||||||
|
py.__version__,
|
||||||
|
pluggy.__version__,
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
self.verbosity > 0
|
self.verbosity > 0
|
||||||
|
@ -624,7 +628,6 @@ class TerminalReporter(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def _locationline(self, nodeid, fspath, lineno, domain):
|
def _locationline(self, nodeid, fspath, lineno, domain):
|
||||||
|
|
||||||
def mkrel(nodeid):
|
def mkrel(nodeid):
|
||||||
line = self.config.cwd_relative_nodeid(nodeid)
|
line = self.config.cwd_relative_nodeid(nodeid)
|
||||||
if domain and line.endswith(domain):
|
if domain and line.endswith(domain):
|
||||||
|
|
|
@ -163,15 +163,13 @@ class TestCaseFunction(Function):
|
||||||
# implements the skipping machinery (see #2137)
|
# implements the skipping machinery (see #2137)
|
||||||
# analog to pythons Lib/unittest/case.py:run
|
# analog to pythons Lib/unittest/case.py:run
|
||||||
testMethod = getattr(self._testcase, self._testcase._testMethodName)
|
testMethod = getattr(self._testcase, self._testcase._testMethodName)
|
||||||
if (
|
if getattr(self._testcase.__class__, "__unittest_skip__", False) or getattr(
|
||||||
getattr(self._testcase.__class__, "__unittest_skip__", False)
|
testMethod, "__unittest_skip__", False
|
||||||
or getattr(testMethod, "__unittest_skip__", False)
|
|
||||||
):
|
):
|
||||||
# If the class or method was skipped.
|
# If the class or method was skipped.
|
||||||
skip_why = (
|
skip_why = getattr(
|
||||||
getattr(self._testcase.__class__, "__unittest_skip_why__", "")
|
self._testcase.__class__, "__unittest_skip_why__", ""
|
||||||
or getattr(testMethod, "__unittest_skip_why__", "")
|
) or getattr(testMethod, "__unittest_skip_why__", "")
|
||||||
)
|
|
||||||
try: # PY3, unittest2 on PY2
|
try: # PY3, unittest2 on PY2
|
||||||
self._testcase._addSkip(self, self._testcase, skip_why)
|
self._testcase._addSkip(self, self._testcase, skip_why)
|
||||||
except TypeError: # PY2
|
except TypeError: # PY2
|
||||||
|
|
|
@ -75,9 +75,8 @@ def catch_warnings_for_item(item):
|
||||||
warn_msg = warning.message
|
warn_msg = warning.message
|
||||||
unicode_warning = False
|
unicode_warning = False
|
||||||
|
|
||||||
if (
|
if compat._PY2 and any(
|
||||||
compat._PY2
|
isinstance(m, compat.UNICODE_TYPES) for m in warn_msg.args
|
||||||
and any(isinstance(m, compat.UNICODE_TYPES) for m in warn_msg.args)
|
|
||||||
):
|
):
|
||||||
new_args = []
|
new_args = []
|
||||||
for m in warn_msg.args:
|
for m in warn_msg.args:
|
||||||
|
|
|
@ -22,16 +22,16 @@ def announce(ctx, version):
|
||||||
|
|
||||||
contributors = set(stdout.splitlines())
|
contributors = set(stdout.splitlines())
|
||||||
|
|
||||||
template_name = "release.minor.rst" if version.endswith(
|
template_name = (
|
||||||
".0"
|
"release.minor.rst" if version.endswith(".0") else "release.patch.rst"
|
||||||
) else "release.patch.rst"
|
)
|
||||||
template_text = Path(__file__).parent.joinpath(template_name).read_text(
|
template_text = (
|
||||||
encoding="UTF-8"
|
Path(__file__).parent.joinpath(template_name).read_text(encoding="UTF-8")
|
||||||
)
|
)
|
||||||
|
|
||||||
contributors_text = "\n".join(
|
contributors_text = (
|
||||||
"* {}".format(name) for name in sorted(contributors)
|
"\n".join("* {}".format(name) for name in sorted(contributors)) + "\n"
|
||||||
) + "\n"
|
)
|
||||||
text = template_text.format(version=version, contributors=contributors_text)
|
text = template_text.format(version=version, contributors=contributors_text)
|
||||||
|
|
||||||
target = Path(__file__).parent.joinpath(
|
target = Path(__file__).parent.joinpath(
|
||||||
|
|
|
@ -13,7 +13,6 @@ from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR
|
||||||
|
|
||||||
|
|
||||||
class TestGeneralUsage(object):
|
class TestGeneralUsage(object):
|
||||||
|
|
||||||
def test_config_error(self, testdir):
|
def test_config_error(self, testdir):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -458,7 +457,6 @@ class TestGeneralUsage(object):
|
||||||
|
|
||||||
|
|
||||||
class TestInvocationVariants(object):
|
class TestInvocationVariants(object):
|
||||||
|
|
||||||
def test_earlyinit(self, testdir):
|
def test_earlyinit(self, testdir):
|
||||||
p = testdir.makepyfile(
|
p = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -557,9 +555,7 @@ class TestInvocationVariants(object):
|
||||||
out, err = capsys.readouterr()
|
out, err = capsys.readouterr()
|
||||||
|
|
||||||
def test_invoke_plugin_api(self, testdir, capsys):
|
def test_invoke_plugin_api(self, testdir, capsys):
|
||||||
|
|
||||||
class MyPlugin(object):
|
class MyPlugin(object):
|
||||||
|
|
||||||
def pytest_addoption(self, parser):
|
def pytest_addoption(self, parser):
|
||||||
parser.addoption("--myopt")
|
parser.addoption("--myopt")
|
||||||
|
|
||||||
|
@ -798,9 +794,10 @@ class TestInvocationVariants(object):
|
||||||
"""Test backward compatibility for get_plugin_manager function. See #787."""
|
"""Test backward compatibility for get_plugin_manager function. See #787."""
|
||||||
import _pytest.config
|
import _pytest.config
|
||||||
|
|
||||||
assert type(
|
assert (
|
||||||
_pytest.config.get_plugin_manager()
|
type(_pytest.config.get_plugin_manager())
|
||||||
) is _pytest.config.PytestPluginManager
|
is _pytest.config.PytestPluginManager
|
||||||
|
)
|
||||||
|
|
||||||
def test_has_plugin(self, request):
|
def test_has_plugin(self, request):
|
||||||
"""Test hasplugin function of the plugin manager (#932)."""
|
"""Test hasplugin function of the plugin manager (#932)."""
|
||||||
|
|
|
@ -26,7 +26,6 @@ def test_code_gives_back_name_for_not_existing_file():
|
||||||
|
|
||||||
|
|
||||||
def test_code_with_class():
|
def test_code_with_class():
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -54,7 +53,6 @@ def test_code_source():
|
||||||
|
|
||||||
|
|
||||||
def test_frame_getsourcelineno_myself():
|
def test_frame_getsourcelineno_myself():
|
||||||
|
|
||||||
def func():
|
def func():
|
||||||
return sys._getframe(0)
|
return sys._getframe(0)
|
||||||
|
|
||||||
|
@ -65,7 +63,6 @@ def test_frame_getsourcelineno_myself():
|
||||||
|
|
||||||
|
|
||||||
def test_getstatement_empty_fullsource():
|
def test_getstatement_empty_fullsource():
|
||||||
|
|
||||||
def func():
|
def func():
|
||||||
return sys._getframe(0)
|
return sys._getframe(0)
|
||||||
|
|
||||||
|
@ -111,7 +108,6 @@ def test_unicode_handling_syntax_error():
|
||||||
|
|
||||||
|
|
||||||
def test_code_getargs():
|
def test_code_getargs():
|
||||||
|
|
||||||
def f1(x):
|
def f1(x):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -138,7 +134,6 @@ def test_code_getargs():
|
||||||
|
|
||||||
|
|
||||||
def test_frame_getargs():
|
def test_frame_getargs():
|
||||||
|
|
||||||
def f1(x):
|
def f1(x):
|
||||||
return sys._getframe(0)
|
return sys._getframe(0)
|
||||||
|
|
||||||
|
@ -165,7 +160,6 @@ def test_frame_getargs():
|
||||||
|
|
||||||
|
|
||||||
class TestExceptionInfo(object):
|
class TestExceptionInfo(object):
|
||||||
|
|
||||||
def test_bad_getsource(self):
|
def test_bad_getsource(self):
|
||||||
try:
|
try:
|
||||||
if False:
|
if False:
|
||||||
|
@ -178,7 +172,6 @@ class TestExceptionInfo(object):
|
||||||
|
|
||||||
|
|
||||||
class TestTracebackEntry(object):
|
class TestTracebackEntry(object):
|
||||||
|
|
||||||
def test_getsource(self):
|
def test_getsource(self):
|
||||||
try:
|
try:
|
||||||
if False:
|
if False:
|
||||||
|
@ -194,7 +187,6 @@ class TestTracebackEntry(object):
|
||||||
|
|
||||||
|
|
||||||
class TestReprFuncArgs(object):
|
class TestReprFuncArgs(object):
|
||||||
|
|
||||||
def test_not_raise_exception_with_mixed_encoding(self):
|
def test_not_raise_exception_with_mixed_encoding(self):
|
||||||
from _pytest._code.code import ReprFuncArgs
|
from _pytest._code.code import ReprFuncArgs
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,6 @@ def test_excinfo_simple():
|
||||||
|
|
||||||
|
|
||||||
def test_excinfo_getstatement():
|
def test_excinfo_getstatement():
|
||||||
|
|
||||||
def g():
|
def g():
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
@ -112,7 +111,6 @@ def h():
|
||||||
|
|
||||||
|
|
||||||
class TestTraceback_f_g_h(object):
|
class TestTraceback_f_g_h(object):
|
||||||
|
|
||||||
def setup_method(self, method):
|
def setup_method(self, method):
|
||||||
try:
|
try:
|
||||||
h()
|
h()
|
||||||
|
@ -194,7 +192,6 @@ class TestTraceback_f_g_h(object):
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_traceback_filter_selective(self, tracebackhide, matching):
|
def test_traceback_filter_selective(self, tracebackhide, matching):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
#
|
#
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
@ -224,7 +221,6 @@ class TestTraceback_f_g_h(object):
|
||||||
assert len(ntraceback) == len(traceback) - 1
|
assert len(ntraceback) == len(traceback) - 1
|
||||||
|
|
||||||
def test_traceback_recursion_index(self):
|
def test_traceback_recursion_index(self):
|
||||||
|
|
||||||
def f(n):
|
def f(n):
|
||||||
if n < 10:
|
if n < 10:
|
||||||
n += 1
|
n += 1
|
||||||
|
@ -236,7 +232,6 @@ class TestTraceback_f_g_h(object):
|
||||||
assert recindex == 3
|
assert recindex == 3
|
||||||
|
|
||||||
def test_traceback_only_specific_recursion_errors(self, monkeypatch):
|
def test_traceback_only_specific_recursion_errors(self, monkeypatch):
|
||||||
|
|
||||||
def f(n):
|
def f(n):
|
||||||
if n == 0:
|
if n == 0:
|
||||||
raise RuntimeError("hello")
|
raise RuntimeError("hello")
|
||||||
|
@ -248,7 +243,6 @@ class TestTraceback_f_g_h(object):
|
||||||
assert "RuntimeError: hello" in str(repr.reprcrash)
|
assert "RuntimeError: hello" in str(repr.reprcrash)
|
||||||
|
|
||||||
def test_traceback_no_recursion_index(self):
|
def test_traceback_no_recursion_index(self):
|
||||||
|
|
||||||
def do_stuff():
|
def do_stuff():
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
|
|
||||||
|
@ -288,7 +282,6 @@ class TestTraceback_f_g_h(object):
|
||||||
assert excinfo.traceback.recursionindex() is None
|
assert excinfo.traceback.recursionindex() is None
|
||||||
|
|
||||||
def test_traceback_getcrashentry(self):
|
def test_traceback_getcrashentry(self):
|
||||||
|
|
||||||
def i():
|
def i():
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
@ -312,7 +305,6 @@ class TestTraceback_f_g_h(object):
|
||||||
assert entry.frame.code.name == "h"
|
assert entry.frame.code.name == "h"
|
||||||
|
|
||||||
def test_traceback_getcrashentry_empty(self):
|
def test_traceback_getcrashentry_empty(self):
|
||||||
|
|
||||||
def g():
|
def g():
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
@ -429,10 +421,8 @@ def test_match_raises_error(testdir):
|
||||||
|
|
||||||
|
|
||||||
class TestFormattedExcinfo(object):
|
class TestFormattedExcinfo(object):
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def importasmod(self, request):
|
def importasmod(self, request):
|
||||||
|
|
||||||
def importasmod(source):
|
def importasmod(source):
|
||||||
source = _pytest._code.Source(source)
|
source = _pytest._code.Source(source)
|
||||||
tmpdir = request.getfixturevalue("tmpdir")
|
tmpdir = request.getfixturevalue("tmpdir")
|
||||||
|
@ -519,7 +509,6 @@ raise ValueError()
|
||||||
pr = FormattedExcinfo()
|
pr = FormattedExcinfo()
|
||||||
|
|
||||||
class FakeCode(object):
|
class FakeCode(object):
|
||||||
|
|
||||||
class raw(object):
|
class raw(object):
|
||||||
co_filename = "?"
|
co_filename = "?"
|
||||||
|
|
||||||
|
@ -537,7 +526,6 @@ raise ValueError()
|
||||||
f_globals = {}
|
f_globals = {}
|
||||||
|
|
||||||
class FakeTracebackEntry(_pytest._code.Traceback.Entry):
|
class FakeTracebackEntry(_pytest._code.Traceback.Entry):
|
||||||
|
|
||||||
def __init__(self, tb, excinfo=None):
|
def __init__(self, tb, excinfo=None):
|
||||||
self.lineno = 5 + 3
|
self.lineno = 5 + 3
|
||||||
|
|
||||||
|
@ -882,7 +870,6 @@ raise ValueError()
|
||||||
from _pytest._code.code import TerminalRepr
|
from _pytest._code.code import TerminalRepr
|
||||||
|
|
||||||
class MyRepr(TerminalRepr):
|
class MyRepr(TerminalRepr):
|
||||||
|
|
||||||
def toterminal(self, tw):
|
def toterminal(self, tw):
|
||||||
tw.line(py.builtin._totext("я", "utf-8"))
|
tw.line(py.builtin._totext("я", "utf-8"))
|
||||||
|
|
||||||
|
@ -1303,7 +1290,6 @@ def test_exception_repr_extraction_error_on_recursion():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class numpy_like(object):
|
class numpy_like(object):
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if type(other) is numpy_like:
|
if type(other) is numpy_like:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -1343,7 +1329,6 @@ def test_no_recursion_index_on_recursion_error():
|
||||||
try:
|
try:
|
||||||
|
|
||||||
class RecursionDepthError(object):
|
class RecursionDepthError(object):
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
return getattr(self, "_" + attr)
|
return getattr(self, "_" + attr)
|
||||||
|
|
||||||
|
|
|
@ -58,9 +58,7 @@ def test_source_from_function():
|
||||||
|
|
||||||
|
|
||||||
def test_source_from_method():
|
def test_source_from_method():
|
||||||
|
|
||||||
class TestClass(object):
|
class TestClass(object):
|
||||||
|
|
||||||
def test_method(self):
|
def test_method(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -75,7 +73,6 @@ def test_source_from_lines():
|
||||||
|
|
||||||
|
|
||||||
def test_source_from_inner_function():
|
def test_source_from_inner_function():
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -199,7 +196,6 @@ class TestSourceParsingAndCompiling(object):
|
||||||
assert str(source) == "x=3"
|
assert str(source) == "x=3"
|
||||||
|
|
||||||
def test_compile_and_getsource_through_same_function(self):
|
def test_compile_and_getsource_through_same_function(self):
|
||||||
|
|
||||||
def gensource(source):
|
def gensource(source):
|
||||||
return _pytest._code.compile(source)
|
return _pytest._code.compile(source)
|
||||||
|
|
||||||
|
@ -337,13 +333,12 @@ class TestSourceParsingAndCompiling(object):
|
||||||
|
|
||||||
@pytest.mark.parametrize("name", ["", None, "my"])
|
@pytest.mark.parametrize("name", ["", None, "my"])
|
||||||
def test_compilefuncs_and_path_sanity(self, name):
|
def test_compilefuncs_and_path_sanity(self, name):
|
||||||
|
|
||||||
def check(comp, name):
|
def check(comp, name):
|
||||||
co = comp(self.source, name)
|
co = comp(self.source, name)
|
||||||
if not name:
|
if not name:
|
||||||
expected = "codegen %s:%d>" % (mypath, mylineno + 2 + 3)
|
expected = "codegen %s:%d>" % (mypath, mylineno + 2 + 2)
|
||||||
else:
|
else:
|
||||||
expected = "codegen %r %s:%d>" % (name, mypath, mylineno + 2 + 3)
|
expected = "codegen %r %s:%d>" % (name, mypath, mylineno + 2 + 2)
|
||||||
fn = co.co_filename
|
fn = co.co_filename
|
||||||
assert fn.endswith(expected)
|
assert fn.endswith(expected)
|
||||||
|
|
||||||
|
@ -359,9 +354,7 @@ class TestSourceParsingAndCompiling(object):
|
||||||
|
|
||||||
|
|
||||||
def test_getstartingblock_singleline():
|
def test_getstartingblock_singleline():
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
frame = sys._getframe(1)
|
frame = sys._getframe(1)
|
||||||
self.source = _pytest._code.Frame(frame).statement
|
self.source = _pytest._code.Frame(frame).statement
|
||||||
|
@ -373,7 +366,6 @@ def test_getstartingblock_singleline():
|
||||||
|
|
||||||
|
|
||||||
def test_getline_finally():
|
def test_getline_finally():
|
||||||
|
|
||||||
def c():
|
def c():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -406,7 +398,6 @@ def test_getfuncsource_dynamic():
|
||||||
|
|
||||||
|
|
||||||
def test_getfuncsource_with_multine_string():
|
def test_getfuncsource_with_multine_string():
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
c = """while True:
|
c = """while True:
|
||||||
pass
|
pass
|
||||||
|
@ -538,14 +529,12 @@ def test_getfslineno():
|
||||||
|
|
||||||
|
|
||||||
def test_code_of_object_instance_with_call():
|
def test_code_of_object_instance_with_call():
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
pytest.raises(TypeError, lambda: _pytest._code.Source(A()))
|
pytest.raises(TypeError, lambda: _pytest._code.Source(A()))
|
||||||
|
|
||||||
class WithCall(object):
|
class WithCall(object):
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -553,7 +542,6 @@ def test_code_of_object_instance_with_call():
|
||||||
assert "pass" in str(code.source())
|
assert "pass" in str(code.source())
|
||||||
|
|
||||||
class Hello(object):
|
class Hello(object):
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ def test_getstartingblock_multiline():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
frame = sys._getframe(1)
|
frame = sys._getframe(1)
|
||||||
self.source = _pytest._code.Frame(frame).statement
|
self.source = _pytest._code.Frame(frame).statement
|
||||||
|
|
|
@ -84,7 +84,6 @@ def test_str_args_deprecated(tmpdir, testdir):
|
||||||
warnings = []
|
warnings = []
|
||||||
|
|
||||||
class Collect(object):
|
class Collect(object):
|
||||||
|
|
||||||
def pytest_logwarning(self, message):
|
def pytest_logwarning(self, message):
|
||||||
warnings.append(message)
|
warnings.append(message)
|
||||||
|
|
||||||
|
@ -260,6 +259,7 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_false_positives(
|
||||||
)
|
)
|
||||||
res = testdir.runpytest_subprocess()
|
res = testdir.runpytest_subprocess()
|
||||||
assert res.ret == 0
|
assert res.ret == 0
|
||||||
assert str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[
|
assert (
|
||||||
0
|
str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
|
||||||
] not in res.stderr.str()
|
not in res.stderr.str()
|
||||||
|
)
|
||||||
|
|
|
@ -17,9 +17,7 @@ def checked_order():
|
||||||
|
|
||||||
yield order
|
yield order
|
||||||
pprint.pprint(order)
|
pprint.pprint(order)
|
||||||
assert (
|
assert order == [
|
||||||
order
|
|
||||||
== [
|
|
||||||
("testing/example_scripts/issue_519.py", "fix1", "arg1v1"),
|
("testing/example_scripts/issue_519.py", "fix1", "arg1v1"),
|
||||||
("test_one[arg1v1-arg2v1]", "fix2", "arg2v1"),
|
("test_one[arg1v1-arg2v1]", "fix2", "arg2v1"),
|
||||||
("test_two[arg1v1-arg2v1]", "fix2", "arg2v1"),
|
("test_two[arg1v1-arg2v1]", "fix2", "arg2v1"),
|
||||||
|
@ -31,7 +29,6 @@ def checked_order():
|
||||||
("test_one[arg1v2-arg2v2]", "fix2", "arg2v2"),
|
("test_one[arg1v2-arg2v2]", "fix2", "arg2v2"),
|
||||||
("test_two[arg1v2-arg2v2]", "fix2", "arg2v2"),
|
("test_two[arg1v2-arg2v2]", "fix2", "arg2v2"),
|
||||||
]
|
]
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(scope="module")
|
@pytest.yield_fixture(scope="module")
|
||||||
|
|
|
@ -18,7 +18,6 @@ def test_coloredlogformatter():
|
||||||
)
|
)
|
||||||
|
|
||||||
class ColorConfig(object):
|
class ColorConfig(object):
|
||||||
|
|
||||||
class option(object):
|
class option(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -26,9 +25,8 @@ def test_coloredlogformatter():
|
||||||
tw.hasmarkup = True
|
tw.hasmarkup = True
|
||||||
formatter = ColoredLevelFormatter(tw, logfmt)
|
formatter = ColoredLevelFormatter(tw, logfmt)
|
||||||
output = formatter.format(record)
|
output = formatter.format(record)
|
||||||
assert (
|
assert output == (
|
||||||
output
|
"dummypath 10 " "\x1b[32mINFO \x1b[0m Test Message"
|
||||||
== ("dummypath 10 " "\x1b[32mINFO \x1b[0m Test Message")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
tw.hasmarkup = False
|
tw.hasmarkup = False
|
||||||
|
|
|
@ -520,16 +520,22 @@ def test_sections_single_new_line_after_test_outcome(testdir, request):
|
||||||
"=* 1 passed in *=",
|
"=* 1 passed in *=",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
assert re.search(
|
assert (
|
||||||
|
re.search(
|
||||||
r"(.+)live log teardown(.+)\n(.+)WARNING(.+)\n(.+)WARNING(.+)",
|
r"(.+)live log teardown(.+)\n(.+)WARNING(.+)\n(.+)WARNING(.+)",
|
||||||
result.stdout.str(),
|
result.stdout.str(),
|
||||||
re.MULTILINE,
|
re.MULTILINE,
|
||||||
) is not None
|
)
|
||||||
assert re.search(
|
is not None
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
re.search(
|
||||||
r"(.+)live log finish(.+)\n(.+)WARNING(.+)\n(.+)WARNING(.+)",
|
r"(.+)live log finish(.+)\n(.+)WARNING(.+)\n(.+)WARNING(.+)",
|
||||||
result.stdout.str(),
|
result.stdout.str(),
|
||||||
re.MULTILINE,
|
re.MULTILINE,
|
||||||
) is not None
|
)
|
||||||
|
is not None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_log_cli_level(testdir):
|
def test_log_cli_level(testdir):
|
||||||
|
@ -850,7 +856,6 @@ def test_live_logging_suspends_capture(has_capture_manager, request):
|
||||||
assert CaptureManager.resume_global_capture
|
assert CaptureManager.resume_global_capture
|
||||||
|
|
||||||
class DummyTerminal(six.StringIO):
|
class DummyTerminal(six.StringIO):
|
||||||
|
|
||||||
def section(self, *args, **kwargs):
|
def section(self, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -865,10 +870,10 @@ def test_live_logging_suspends_capture(has_capture_manager, request):
|
||||||
|
|
||||||
logger.critical("some message")
|
logger.critical("some message")
|
||||||
if has_capture_manager:
|
if has_capture_manager:
|
||||||
assert (
|
assert MockCaptureManager.calls == [
|
||||||
MockCaptureManager.calls
|
"suspend_global_capture",
|
||||||
== ["suspend_global_capture", "resume_global_capture"]
|
"resume_global_capture",
|
||||||
)
|
]
|
||||||
else:
|
else:
|
||||||
assert MockCaptureManager.calls == []
|
assert MockCaptureManager.calls == []
|
||||||
assert out_file.getvalue() == "\nsome message\n"
|
assert out_file.getvalue() == "\nsome message\n"
|
||||||
|
|
|
@ -13,7 +13,6 @@ inf, nan = float("inf"), float("nan")
|
||||||
|
|
||||||
|
|
||||||
class MyDocTestRunner(doctest.DocTestRunner):
|
class MyDocTestRunner(doctest.DocTestRunner):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
doctest.DocTestRunner.__init__(self)
|
doctest.DocTestRunner.__init__(self)
|
||||||
|
|
||||||
|
@ -26,28 +25,27 @@ class MyDocTestRunner(doctest.DocTestRunner):
|
||||||
|
|
||||||
|
|
||||||
class TestApprox(object):
|
class TestApprox(object):
|
||||||
|
@pytest.fixture
|
||||||
|
def plus_minus(self):
|
||||||
|
return u"\u00b1" if sys.version_info[0] > 2 else u"+-"
|
||||||
|
|
||||||
def test_repr_string(self):
|
def test_repr_string(self, plus_minus):
|
||||||
plus_minus = u"\u00b1" if sys.version_info[0] > 2 else u"+-"
|
|
||||||
tol1, tol2, infr = "1.0e-06", "2.0e-06", "inf"
|
tol1, tol2, infr = "1.0e-06", "2.0e-06", "inf"
|
||||||
assert repr(approx(1.0)) == "1.0 {pm} {tol1}".format(pm=plus_minus, tol1=tol1)
|
assert repr(approx(1.0)) == "1.0 {pm} {tol1}".format(pm=plus_minus, tol1=tol1)
|
||||||
assert (
|
assert repr(
|
||||||
repr(approx([1.0, 2.0]))
|
approx([1.0, 2.0])
|
||||||
== "approx([1.0 {pm} {tol1}, 2.0 {pm} {tol2}])".format(
|
) == "approx([1.0 {pm} {tol1}, 2.0 {pm} {tol2}])".format(
|
||||||
pm=plus_minus, tol1=tol1, tol2=tol2
|
pm=plus_minus, tol1=tol1, tol2=tol2
|
||||||
)
|
)
|
||||||
)
|
assert repr(
|
||||||
assert (
|
approx((1.0, 2.0))
|
||||||
repr(approx((1.0, 2.0)))
|
) == "approx((1.0 {pm} {tol1}, 2.0 {pm} {tol2}))".format(
|
||||||
== "approx((1.0 {pm} {tol1}, 2.0 {pm} {tol2}))".format(
|
|
||||||
pm=plus_minus, tol1=tol1, tol2=tol2
|
pm=plus_minus, tol1=tol1, tol2=tol2
|
||||||
)
|
)
|
||||||
)
|
|
||||||
assert repr(approx(inf)) == "inf"
|
assert repr(approx(inf)) == "inf"
|
||||||
assert repr(approx(1.0, rel=nan)) == "1.0 {pm} ???".format(pm=plus_minus)
|
assert repr(approx(1.0, rel=nan)) == "1.0 {pm} ???".format(pm=plus_minus)
|
||||||
assert (
|
assert repr(approx(1.0, rel=inf)) == "1.0 {pm} {infr}".format(
|
||||||
repr(approx(1.0, rel=inf))
|
pm=plus_minus, infr=infr
|
||||||
== "1.0 {pm} {infr}".format(pm=plus_minus, infr=infr)
|
|
||||||
)
|
)
|
||||||
assert repr(approx(1.0j, rel=inf)) == "1j"
|
assert repr(approx(1.0j, rel=inf)) == "1j"
|
||||||
|
|
||||||
|
@ -61,6 +59,18 @@ class TestApprox(object):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_repr_0d_array(self, plus_minus):
|
||||||
|
np = pytest.importorskip("numpy")
|
||||||
|
np_array = np.array(5.)
|
||||||
|
assert approx(np_array) == 5.0
|
||||||
|
string_expected = "approx([5.0 {} 5.0e-06])".format(plus_minus)
|
||||||
|
|
||||||
|
assert repr(approx(np_array)) == string_expected
|
||||||
|
|
||||||
|
np_array = np.array([5.])
|
||||||
|
assert approx(np_array) == 5.0
|
||||||
|
assert repr(approx(np_array)) == string_expected
|
||||||
|
|
||||||
def test_operator_overloading(self):
|
def test_operator_overloading(self):
|
||||||
assert 1 == approx(1, rel=1e-6, abs=1e-12)
|
assert 1 == approx(1, rel=1e-6, abs=1e-12)
|
||||||
assert not (1 != approx(1, rel=1e-6, abs=1e-12))
|
assert not (1 != approx(1, rel=1e-6, abs=1e-12))
|
||||||
|
|
|
@ -14,7 +14,6 @@ ignore_parametrized_marks = pytest.mark.filterwarnings(
|
||||||
|
|
||||||
|
|
||||||
class TestModule(object):
|
class TestModule(object):
|
||||||
|
|
||||||
def test_failing_import(self, testdir):
|
def test_failing_import(self, testdir):
|
||||||
modcol = testdir.getmodulecol("import alksdjalskdjalkjals")
|
modcol = testdir.getmodulecol("import alksdjalskdjalkjals")
|
||||||
pytest.raises(Collector.CollectError, modcol.collect)
|
pytest.raises(Collector.CollectError, modcol.collect)
|
||||||
|
@ -141,7 +140,6 @@ class TestModule(object):
|
||||||
|
|
||||||
|
|
||||||
class TestClass(object):
|
class TestClass(object):
|
||||||
|
|
||||||
def test_class_with_init_warning(self, testdir):
|
def test_class_with_init_warning(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -246,7 +244,6 @@ class TestClass(object):
|
||||||
|
|
||||||
|
|
||||||
class TestGenerator(object):
|
class TestGenerator(object):
|
||||||
|
|
||||||
def test_generative_functions(self, testdir):
|
def test_generative_functions(self, testdir):
|
||||||
modcol = testdir.getmodulecol(
|
modcol = testdir.getmodulecol(
|
||||||
"""
|
"""
|
||||||
|
@ -458,7 +455,6 @@ class TestGenerator(object):
|
||||||
|
|
||||||
|
|
||||||
class TestFunction(object):
|
class TestFunction(object):
|
||||||
|
|
||||||
def test_getmodulecollector(self, testdir):
|
def test_getmodulecollector(self, testdir):
|
||||||
item = testdir.getitem("def test_func(): pass")
|
item = testdir.getitem("def test_func(): pass")
|
||||||
modcol = item.getparent(pytest.Module)
|
modcol = item.getparent(pytest.Module)
|
||||||
|
@ -673,12 +669,10 @@ class TestFunction(object):
|
||||||
config = item.config
|
config = item.config
|
||||||
|
|
||||||
class MyPlugin1(object):
|
class MyPlugin1(object):
|
||||||
|
|
||||||
def pytest_pyfunc_call(self, pyfuncitem):
|
def pytest_pyfunc_call(self, pyfuncitem):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
class MyPlugin2(object):
|
class MyPlugin2(object):
|
||||||
|
|
||||||
def pytest_pyfunc_call(self, pyfuncitem):
|
def pytest_pyfunc_call(self, pyfuncitem):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -831,7 +825,6 @@ class TestFunction(object):
|
||||||
|
|
||||||
|
|
||||||
class TestSorting(object):
|
class TestSorting(object):
|
||||||
|
|
||||||
def test_check_equality(self, testdir):
|
def test_check_equality(self, testdir):
|
||||||
modcol = testdir.getmodulecol(
|
modcol = testdir.getmodulecol(
|
||||||
"""
|
"""
|
||||||
|
@ -886,7 +879,6 @@ class TestSorting(object):
|
||||||
|
|
||||||
|
|
||||||
class TestConftestCustomization(object):
|
class TestConftestCustomization(object):
|
||||||
|
|
||||||
def test_pytest_pycollect_module(self, testdir):
|
def test_pytest_pycollect_module(self, testdir):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -1062,7 +1054,6 @@ def test_modulecol_roundtrip(testdir):
|
||||||
|
|
||||||
|
|
||||||
class TestTracebackCutting(object):
|
class TestTracebackCutting(object):
|
||||||
|
|
||||||
def test_skip_simple(self):
|
def test_skip_simple(self):
|
||||||
excinfo = pytest.raises(pytest.skip.Exception, 'pytest.skip("xxx")')
|
excinfo = pytest.raises(pytest.skip.Exception, 'pytest.skip("xxx")')
|
||||||
assert excinfo.traceback[-1].frame.code.name == "skip"
|
assert excinfo.traceback[-1].frame.code.name == "skip"
|
||||||
|
@ -1191,7 +1182,6 @@ class TestTracebackCutting(object):
|
||||||
|
|
||||||
|
|
||||||
class TestReportInfo(object):
|
class TestReportInfo(object):
|
||||||
|
|
||||||
def test_itemreport_reportinfo(self, testdir, linecomp):
|
def test_itemreport_reportinfo(self, testdir, linecomp):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -1497,7 +1487,10 @@ def test_class_injection_does_not_break_collection(testdir):
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
assert "RuntimeError: dictionary changed size during iteration" not in result.stdout.str()
|
assert (
|
||||||
|
"RuntimeError: dictionary changed size during iteration"
|
||||||
|
not in result.stdout.str()
|
||||||
|
)
|
||||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ from _pytest import fixtures
|
||||||
|
|
||||||
|
|
||||||
def test_getfuncargnames():
|
def test_getfuncargnames():
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -30,7 +29,6 @@ def test_getfuncargnames():
|
||||||
assert fixtures.getfuncargnames(h) == ("arg1", "arg2")
|
assert fixtures.getfuncargnames(h) == ("arg1", "arg2")
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
|
|
||||||
def f(self, arg1, arg2="hello"):
|
def f(self, arg1, arg2="hello"):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -43,7 +41,6 @@ def test_getfuncargnames():
|
||||||
|
|
||||||
|
|
||||||
class TestFillFixtures(object):
|
class TestFillFixtures(object):
|
||||||
|
|
||||||
def test_fillfuncargs_exposed(self):
|
def test_fillfuncargs_exposed(self):
|
||||||
# used by oejskit, kept for compatibility
|
# used by oejskit, kept for compatibility
|
||||||
assert pytest._fillfuncargs == fixtures.fillfixtures
|
assert pytest._fillfuncargs == fixtures.fillfixtures
|
||||||
|
@ -570,7 +567,6 @@ class TestFillFixtures(object):
|
||||||
|
|
||||||
|
|
||||||
class TestRequestBasic(object):
|
class TestRequestBasic(object):
|
||||||
|
|
||||||
def test_request_attributes(self, testdir):
|
def test_request_attributes(self, testdir):
|
||||||
item = testdir.getitem(
|
item = testdir.getitem(
|
||||||
"""
|
"""
|
||||||
|
@ -1003,7 +999,6 @@ class TestRequestBasic(object):
|
||||||
|
|
||||||
|
|
||||||
class TestRequestMarking(object):
|
class TestRequestMarking(object):
|
||||||
|
|
||||||
def test_applymarker(self, testdir):
|
def test_applymarker(self, testdir):
|
||||||
item1, item2 = testdir.getitems(
|
item1, item2 = testdir.getitems(
|
||||||
"""
|
"""
|
||||||
|
@ -1073,7 +1068,6 @@ class TestRequestMarking(object):
|
||||||
|
|
||||||
|
|
||||||
class TestRequestCachedSetup(object):
|
class TestRequestCachedSetup(object):
|
||||||
|
|
||||||
def test_request_cachedsetup_defaultmodule(self, testdir):
|
def test_request_cachedsetup_defaultmodule(self, testdir):
|
||||||
reprec = testdir.inline_runsource(
|
reprec = testdir.inline_runsource(
|
||||||
"""
|
"""
|
||||||
|
@ -1245,7 +1239,6 @@ class TestRequestCachedSetup(object):
|
||||||
|
|
||||||
|
|
||||||
class TestFixtureUsages(object):
|
class TestFixtureUsages(object):
|
||||||
|
|
||||||
def test_noargfixturedec(self, testdir):
|
def test_noargfixturedec(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -1540,7 +1533,6 @@ class TestFixtureUsages(object):
|
||||||
|
|
||||||
|
|
||||||
class TestFixtureManagerParseFactories(object):
|
class TestFixtureManagerParseFactories(object):
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def testdir(self, request):
|
def testdir(self, request):
|
||||||
testdir = request.getfixturevalue("testdir")
|
testdir = request.getfixturevalue("testdir")
|
||||||
|
@ -1668,7 +1660,6 @@ class TestFixtureManagerParseFactories(object):
|
||||||
|
|
||||||
|
|
||||||
class TestAutouseDiscovery(object):
|
class TestAutouseDiscovery(object):
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def testdir(self, testdir):
|
def testdir(self, testdir):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
|
@ -1845,7 +1836,6 @@ class TestAutouseDiscovery(object):
|
||||||
|
|
||||||
|
|
||||||
class TestAutouseManagement(object):
|
class TestAutouseManagement(object):
|
||||||
|
|
||||||
def test_autouse_conftest_mid_directory(self, testdir):
|
def test_autouse_conftest_mid_directory(self, testdir):
|
||||||
pkgdir = testdir.mkpydir("xyz123")
|
pkgdir = testdir.mkpydir("xyz123")
|
||||||
pkgdir.join("conftest.py").write(
|
pkgdir.join("conftest.py").write(
|
||||||
|
@ -2112,7 +2102,6 @@ class TestAutouseManagement(object):
|
||||||
|
|
||||||
|
|
||||||
class TestFixtureMarker(object):
|
class TestFixtureMarker(object):
|
||||||
|
|
||||||
def test_parametrize(self, testdir):
|
def test_parametrize(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -2938,9 +2927,7 @@ class TestFixtureMarker(object):
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=6)
|
reprec.assertoutcome(passed=6)
|
||||||
values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
|
values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
|
||||||
assert (
|
assert values == [
|
||||||
values
|
|
||||||
== [
|
|
||||||
"test_hello",
|
"test_hello",
|
||||||
"fin John",
|
"fin John",
|
||||||
"test_hello",
|
"test_hello",
|
||||||
|
@ -2952,7 +2939,6 @@ class TestFixtureMarker(object):
|
||||||
"test_population",
|
"test_population",
|
||||||
"fin Doe",
|
"fin Doe",
|
||||||
]
|
]
|
||||||
)
|
|
||||||
|
|
||||||
def test_parametrize_setup_function(self, testdir):
|
def test_parametrize_setup_function(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
|
@ -3135,7 +3121,6 @@ class TestRequestScopeAccess(object):
|
||||||
|
|
||||||
|
|
||||||
class TestErrors(object):
|
class TestErrors(object):
|
||||||
|
|
||||||
def test_subfactory_missing_funcarg(self, testdir):
|
def test_subfactory_missing_funcarg(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -3203,7 +3188,6 @@ class TestErrors(object):
|
||||||
|
|
||||||
|
|
||||||
class TestShowFixtures(object):
|
class TestShowFixtures(object):
|
||||||
|
|
||||||
def test_funcarg_compat(self, testdir):
|
def test_funcarg_compat(self, testdir):
|
||||||
config = testdir.parseconfigure("--funcargs")
|
config = testdir.parseconfigure("--funcargs")
|
||||||
assert config.option.showfixtures
|
assert config.option.showfixtures
|
||||||
|
@ -3480,7 +3464,6 @@ class TestShowFixtures(object):
|
||||||
|
|
||||||
@pytest.mark.parametrize("flavor", ["fixture", "yield_fixture"])
|
@pytest.mark.parametrize("flavor", ["fixture", "yield_fixture"])
|
||||||
class TestContextManagerFixtureFuncs(object):
|
class TestContextManagerFixtureFuncs(object):
|
||||||
|
|
||||||
def test_simple(self, testdir, flavor):
|
def test_simple(self, testdir, flavor):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -3622,7 +3605,6 @@ class TestContextManagerFixtureFuncs(object):
|
||||||
|
|
||||||
|
|
||||||
class TestParameterizedSubRequest(object):
|
class TestParameterizedSubRequest(object):
|
||||||
|
|
||||||
def test_call_from_fixture(self, testdir):
|
def test_call_from_fixture(self, testdir):
|
||||||
testfile = testdir.makepyfile(
|
testfile = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -4,7 +4,6 @@ from _pytest import runner
|
||||||
|
|
||||||
|
|
||||||
class TestOEJSKITSpecials(object):
|
class TestOEJSKITSpecials(object):
|
||||||
|
|
||||||
def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage
|
def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -70,7 +69,6 @@ class TestOEJSKITSpecials(object):
|
||||||
|
|
||||||
|
|
||||||
def test_wrapped_getfslineno():
|
def test_wrapped_getfslineno():
|
||||||
|
|
||||||
def func():
|
def func():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -89,12 +87,10 @@ def test_wrapped_getfslineno():
|
||||||
|
|
||||||
|
|
||||||
class TestMockDecoration(object):
|
class TestMockDecoration(object):
|
||||||
|
|
||||||
def test_wrapped_getfuncargnames(self):
|
def test_wrapped_getfuncargnames(self):
|
||||||
from _pytest.compat import getfuncargnames
|
from _pytest.compat import getfuncargnames
|
||||||
|
|
||||||
def wrap(f):
|
def wrap(f):
|
||||||
|
|
||||||
def func():
|
def func():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -115,7 +111,6 @@ class TestMockDecoration(object):
|
||||||
from _pytest.compat import getfuncargnames
|
from _pytest.compat import getfuncargnames
|
||||||
|
|
||||||
def wrap(f):
|
def wrap(f):
|
||||||
|
|
||||||
def func():
|
def func():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -269,7 +264,6 @@ class TestMockDecoration(object):
|
||||||
|
|
||||||
|
|
||||||
class TestReRunTests(object):
|
class TestReRunTests(object):
|
||||||
|
|
||||||
def test_rerun(self, testdir):
|
def test_rerun(self, testdir):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -316,7 +310,6 @@ def test_pytestconfig_is_session_scoped():
|
||||||
|
|
||||||
|
|
||||||
class TestNoselikeTestAttribute(object):
|
class TestNoselikeTestAttribute(object):
|
||||||
|
|
||||||
def test_module_with_global_test(self, testdir):
|
def test_module_with_global_test(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -402,7 +395,6 @@ class TestNoselikeTestAttribute(object):
|
||||||
|
|
||||||
@pytest.mark.issue351
|
@pytest.mark.issue351
|
||||||
class TestParameterize(object):
|
class TestParameterize(object):
|
||||||
|
|
||||||
def test_idfn_marker(self, testdir):
|
def test_idfn_marker(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -14,7 +14,6 @@ PY3 = sys.version_info >= (3, 0)
|
||||||
|
|
||||||
|
|
||||||
class TestMetafunc(object):
|
class TestMetafunc(object):
|
||||||
|
|
||||||
def Metafunc(self, func, config=None):
|
def Metafunc(self, func, config=None):
|
||||||
# the unit tests of this class check if things work correctly
|
# the unit tests of this class check if things work correctly
|
||||||
# on the funcarg level, so we don't need a full blown
|
# on the funcarg level, so we don't need a full blown
|
||||||
|
@ -35,7 +34,6 @@ class TestMetafunc(object):
|
||||||
return python.Metafunc(definition, fixtureinfo, config)
|
return python.Metafunc(definition, fixtureinfo, config)
|
||||||
|
|
||||||
def test_no_funcargs(self, testdir):
|
def test_no_funcargs(self, testdir):
|
||||||
|
|
||||||
def function():
|
def function():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -44,7 +42,6 @@ class TestMetafunc(object):
|
||||||
repr(metafunc._calls)
|
repr(metafunc._calls)
|
||||||
|
|
||||||
def test_function_basic(self):
|
def test_function_basic(self):
|
||||||
|
|
||||||
def func(arg1, arg2="qwe"):
|
def func(arg1, arg2="qwe"):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -55,7 +52,6 @@ class TestMetafunc(object):
|
||||||
assert metafunc.cls is None
|
assert metafunc.cls is None
|
||||||
|
|
||||||
def test_addcall_no_args(self):
|
def test_addcall_no_args(self):
|
||||||
|
|
||||||
def func(arg1):
|
def func(arg1):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -67,7 +63,6 @@ class TestMetafunc(object):
|
||||||
assert not hasattr(call, "param")
|
assert not hasattr(call, "param")
|
||||||
|
|
||||||
def test_addcall_id(self):
|
def test_addcall_id(self):
|
||||||
|
|
||||||
def func(arg1):
|
def func(arg1):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -83,7 +78,6 @@ class TestMetafunc(object):
|
||||||
assert metafunc._calls[1].id == "2"
|
assert metafunc._calls[1].id == "2"
|
||||||
|
|
||||||
def test_addcall_param(self):
|
def test_addcall_param(self):
|
||||||
|
|
||||||
def func(arg1):
|
def func(arg1):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -101,7 +95,6 @@ class TestMetafunc(object):
|
||||||
assert metafunc._calls[2].getparam("arg1") == 1
|
assert metafunc._calls[2].getparam("arg1") == 1
|
||||||
|
|
||||||
def test_addcall_funcargs(self):
|
def test_addcall_funcargs(self):
|
||||||
|
|
||||||
def func(x):
|
def func(x):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -119,7 +112,6 @@ class TestMetafunc(object):
|
||||||
assert not hasattr(metafunc._calls[1], "param")
|
assert not hasattr(metafunc._calls[1], "param")
|
||||||
|
|
||||||
def test_parametrize_error(self):
|
def test_parametrize_error(self):
|
||||||
|
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -132,7 +124,6 @@ class TestMetafunc(object):
|
||||||
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
|
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
|
||||||
|
|
||||||
def test_parametrize_bad_scope(self, testdir):
|
def test_parametrize_bad_scope(self, testdir):
|
||||||
|
|
||||||
def func(x):
|
def func(x):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -143,7 +134,6 @@ class TestMetafunc(object):
|
||||||
assert "has an unsupported scope value 'doggy'" in str(ve)
|
assert "has an unsupported scope value 'doggy'" in str(ve)
|
||||||
|
|
||||||
def test_parametrize_and_id(self):
|
def test_parametrize_and_id(self):
|
||||||
|
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -166,7 +156,6 @@ class TestMetafunc(object):
|
||||||
assert ids == [u"basic", u"advanced"]
|
assert ids == [u"basic", u"advanced"]
|
||||||
|
|
||||||
def test_parametrize_with_wrong_number_of_ids(self, testdir):
|
def test_parametrize_with_wrong_number_of_ids(self, testdir):
|
||||||
|
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -185,12 +174,10 @@ class TestMetafunc(object):
|
||||||
|
|
||||||
@pytest.mark.issue510
|
@pytest.mark.issue510
|
||||||
def test_parametrize_empty_list(self):
|
def test_parametrize_empty_list(self):
|
||||||
|
|
||||||
def func(y):
|
def func(y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class MockConfig(object):
|
class MockConfig(object):
|
||||||
|
|
||||||
def getini(self, name):
|
def getini(self, name):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@ -206,7 +193,6 @@ class TestMetafunc(object):
|
||||||
assert "skip" == metafunc._calls[0].marks[0].name
|
assert "skip" == metafunc._calls[0].marks[0].name
|
||||||
|
|
||||||
def test_parametrize_with_userobjects(self):
|
def test_parametrize_with_userobjects(self):
|
||||||
|
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -338,9 +324,7 @@ class TestMetafunc(object):
|
||||||
pytest.param(b"\xc3\xb4", totext("other")),
|
pytest.param(b"\xc3\xb4", totext("other")),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
assert (
|
assert result == [
|
||||||
result
|
|
||||||
== [
|
|
||||||
"1.0--1.1",
|
"1.0--1.1",
|
||||||
"2--202",
|
"2--202",
|
||||||
"three-three hundred",
|
"three-three hundred",
|
||||||
|
@ -354,7 +338,6 @@ class TestMetafunc(object):
|
||||||
"\\xc3\\xb4-name",
|
"\\xc3\\xb4-name",
|
||||||
"\\xc3\\xb4-other",
|
"\\xc3\\xb4-other",
|
||||||
]
|
]
|
||||||
)
|
|
||||||
|
|
||||||
def test_idmaker_enum(self):
|
def test_idmaker_enum(self):
|
||||||
from _pytest.python import idmaker
|
from _pytest.python import idmaker
|
||||||
|
@ -424,9 +407,7 @@ class TestMetafunc(object):
|
||||||
idfn=ids,
|
idfn=ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert (
|
assert [str(i.message) for i in rec.list] == [
|
||||||
[str(i.message) for i in rec.list]
|
|
||||||
== [
|
|
||||||
"Raised while trying to determine id of parameter a at position 0."
|
"Raised while trying to determine id of parameter a at position 0."
|
||||||
"\nUpdate your code as this will raise an error in pytest-4.0.",
|
"\nUpdate your code as this will raise an error in pytest-4.0.",
|
||||||
"Raised while trying to determine id of parameter b at position 0."
|
"Raised while trying to determine id of parameter b at position 0."
|
||||||
|
@ -440,7 +421,6 @@ class TestMetafunc(object):
|
||||||
"Raised while trying to determine id of parameter b at position 2."
|
"Raised while trying to determine id of parameter b at position 2."
|
||||||
"\nUpdate your code as this will raise an error in pytest-4.0.",
|
"\nUpdate your code as this will raise an error in pytest-4.0.",
|
||||||
]
|
]
|
||||||
)
|
|
||||||
|
|
||||||
def test_parametrize_ids_exception(self, testdir):
|
def test_parametrize_ids_exception(self, testdir):
|
||||||
"""
|
"""
|
||||||
|
@ -496,7 +476,6 @@ class TestMetafunc(object):
|
||||||
assert result == ["a0", "a1", "b0", "c", "b1"]
|
assert result == ["a0", "a1", "b0", "c", "b1"]
|
||||||
|
|
||||||
def test_addcall_and_parametrize(self):
|
def test_addcall_and_parametrize(self):
|
||||||
|
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -511,7 +490,6 @@ class TestMetafunc(object):
|
||||||
|
|
||||||
@pytest.mark.issue714
|
@pytest.mark.issue714
|
||||||
def test_parametrize_indirect(self):
|
def test_parametrize_indirect(self):
|
||||||
|
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -526,7 +504,6 @@ class TestMetafunc(object):
|
||||||
|
|
||||||
@pytest.mark.issue714
|
@pytest.mark.issue714
|
||||||
def test_parametrize_indirect_list(self):
|
def test_parametrize_indirect_list(self):
|
||||||
|
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -537,7 +514,6 @@ class TestMetafunc(object):
|
||||||
|
|
||||||
@pytest.mark.issue714
|
@pytest.mark.issue714
|
||||||
def test_parametrize_indirect_list_all(self):
|
def test_parametrize_indirect_list_all(self):
|
||||||
|
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -548,7 +524,6 @@ class TestMetafunc(object):
|
||||||
|
|
||||||
@pytest.mark.issue714
|
@pytest.mark.issue714
|
||||||
def test_parametrize_indirect_list_empty(self):
|
def test_parametrize_indirect_list_empty(self):
|
||||||
|
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -588,7 +563,6 @@ class TestMetafunc(object):
|
||||||
|
|
||||||
@pytest.mark.issue714
|
@pytest.mark.issue714
|
||||||
def test_parametrize_indirect_list_error(self, testdir):
|
def test_parametrize_indirect_list_error(self, testdir):
|
||||||
|
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -704,7 +678,6 @@ class TestMetafunc(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_addcalls_and_parametrize_indirect(self):
|
def test_addcalls_and_parametrize_indirect(self):
|
||||||
|
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -837,7 +810,6 @@ class TestMetafunc(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_format_args(self):
|
def test_format_args(self):
|
||||||
|
|
||||||
def function1():
|
def function1():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -860,7 +832,6 @@ class TestMetafunc(object):
|
||||||
|
|
||||||
|
|
||||||
class TestMetafuncFunctional(object):
|
class TestMetafuncFunctional(object):
|
||||||
|
|
||||||
def test_attributes(self, testdir):
|
def test_attributes(self, testdir):
|
||||||
p = testdir.makepyfile(
|
p = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -1494,7 +1465,6 @@ class TestMetafuncFunctionalAuto(object):
|
||||||
@pytest.mark.filterwarnings("ignore:Applying marks directly to parameters")
|
@pytest.mark.filterwarnings("ignore:Applying marks directly to parameters")
|
||||||
@pytest.mark.issue308
|
@pytest.mark.issue308
|
||||||
class TestMarkersWithParametrization(object):
|
class TestMarkersWithParametrization(object):
|
||||||
|
|
||||||
def test_simple_mark(self, testdir):
|
def test_simple_mark(self, testdir):
|
||||||
s = """
|
s = """
|
||||||
import pytest
|
import pytest
|
||||||
|
|
|
@ -4,7 +4,6 @@ import sys
|
||||||
|
|
||||||
|
|
||||||
class TestRaises(object):
|
class TestRaises(object):
|
||||||
|
|
||||||
def test_raises(self):
|
def test_raises(self):
|
||||||
source = "int('qwe')"
|
source = "int('qwe')"
|
||||||
excinfo = pytest.raises(ValueError, source)
|
excinfo = pytest.raises(ValueError, source)
|
||||||
|
@ -22,9 +21,7 @@ class TestRaises(object):
|
||||||
pytest.raises(ValueError, int, "hello")
|
pytest.raises(ValueError, int, "hello")
|
||||||
|
|
||||||
def test_raises_callable_no_exception(self):
|
def test_raises_callable_no_exception(self):
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -109,7 +106,6 @@ class TestRaises(object):
|
||||||
import gc
|
import gc
|
||||||
|
|
||||||
class T(object):
|
class T(object):
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
@ -160,7 +156,6 @@ class TestRaises(object):
|
||||||
from six import add_metaclass
|
from six import add_metaclass
|
||||||
|
|
||||||
class Meta(type(object)):
|
class Meta(type(object)):
|
||||||
|
|
||||||
def __getitem__(self, item):
|
def __getitem__(self, item):
|
||||||
return 1 / 0
|
return 1 / 0
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,6 @@ class FilesCompleter(object):
|
||||||
|
|
||||||
|
|
||||||
class TestArgComplete(object):
|
class TestArgComplete(object):
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
||||||
def test_compare_with_compgen(self):
|
def test_compare_with_compgen(self):
|
||||||
from _pytest._argcomplete import FastFilesCompleter
|
from _pytest._argcomplete import FastFilesCompleter
|
||||||
|
|
|
@ -14,7 +14,6 @@ PY3 = sys.version_info >= (3, 0)
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_config():
|
def mock_config():
|
||||||
|
|
||||||
class Config(object):
|
class Config(object):
|
||||||
verbose = False
|
verbose = False
|
||||||
|
|
||||||
|
@ -27,7 +26,6 @@ def mock_config():
|
||||||
|
|
||||||
|
|
||||||
class TestImportHookInstallation(object):
|
class TestImportHookInstallation(object):
|
||||||
|
|
||||||
@pytest.mark.parametrize("initial_conftest", [True, False])
|
@pytest.mark.parametrize("initial_conftest", [True, False])
|
||||||
@pytest.mark.parametrize("mode", ["plain", "rewrite"])
|
@pytest.mark.parametrize("mode", ["plain", "rewrite"])
|
||||||
def test_conftest_assertion_rewrite(self, testdir, initial_conftest, mode):
|
def test_conftest_assertion_rewrite(self, testdir, initial_conftest, mode):
|
||||||
|
@ -288,7 +286,6 @@ class TestImportHookInstallation(object):
|
||||||
|
|
||||||
|
|
||||||
class TestBinReprIntegration(object):
|
class TestBinReprIntegration(object):
|
||||||
|
|
||||||
def test_pytest_assertrepr_compare_called(self, testdir):
|
def test_pytest_assertrepr_compare_called(self, testdir):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -321,7 +318,6 @@ def callequal(left, right, verbose=False):
|
||||||
|
|
||||||
|
|
||||||
class TestAssert_reprcompare(object):
|
class TestAssert_reprcompare(object):
|
||||||
|
|
||||||
def test_different_types(self):
|
def test_different_types(self):
|
||||||
assert callequal([0, 1], "foo") is None
|
assert callequal([0, 1], "foo") is None
|
||||||
|
|
||||||
|
@ -459,7 +455,6 @@ class TestAssert_reprcompare(object):
|
||||||
MutableSequence = col.MutableSequence
|
MutableSequence = col.MutableSequence
|
||||||
|
|
||||||
class TestSequence(MutableSequence): # works with a Sequence subclass
|
class TestSequence(MutableSequence): # works with a Sequence subclass
|
||||||
|
|
||||||
def __init__(self, iterable):
|
def __init__(self, iterable):
|
||||||
self.elements = list(iterable)
|
self.elements = list(iterable)
|
||||||
|
|
||||||
|
@ -488,9 +483,7 @@ class TestAssert_reprcompare(object):
|
||||||
assert len(expl) > 1
|
assert len(expl) > 1
|
||||||
|
|
||||||
def test_list_bad_repr(self):
|
def test_list_bad_repr(self):
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
raise ValueError(42)
|
raise ValueError(42)
|
||||||
|
|
||||||
|
@ -506,7 +499,6 @@ class TestAssert_reprcompare(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class A(str):
|
class A(str):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@ -532,7 +524,6 @@ class TestAssert_reprcompare(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class A(str):
|
class A(str):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "\xff"
|
return "\xff"
|
||||||
|
|
||||||
|
@ -557,7 +548,6 @@ class TestAssert_reprcompare(object):
|
||||||
|
|
||||||
|
|
||||||
class TestFormatExplanation(object):
|
class TestFormatExplanation(object):
|
||||||
|
|
||||||
def test_special_chars_full(self, testdir):
|
def test_special_chars_full(self, testdir):
|
||||||
# Issue 453, for the bug this would raise IndexError
|
# Issue 453, for the bug this would raise IndexError
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
|
@ -781,24 +771,19 @@ def test_rewritten(testdir):
|
||||||
def test_reprcompare_notin(mock_config):
|
def test_reprcompare_notin(mock_config):
|
||||||
detail = plugin.pytest_assertrepr_compare(
|
detail = plugin.pytest_assertrepr_compare(
|
||||||
mock_config, "not in", "foo", "aaafoobbb"
|
mock_config, "not in", "foo", "aaafoobbb"
|
||||||
)[
|
)[1:]
|
||||||
1:
|
|
||||||
]
|
|
||||||
assert detail == ["'foo' is contained here:", " aaafoobbb", "? +++"]
|
assert detail == ["'foo' is contained here:", " aaafoobbb", "? +++"]
|
||||||
|
|
||||||
|
|
||||||
def test_reprcompare_whitespaces(mock_config):
|
def test_reprcompare_whitespaces(mock_config):
|
||||||
detail = plugin.pytest_assertrepr_compare(mock_config, "==", "\r\n", "\n")
|
detail = plugin.pytest_assertrepr_compare(mock_config, "==", "\r\n", "\n")
|
||||||
assert (
|
assert detail == [
|
||||||
detail
|
|
||||||
== [
|
|
||||||
r"'\r\n' == '\n'",
|
r"'\r\n' == '\n'",
|
||||||
r"Strings contain only whitespace, escaping them using repr()",
|
r"Strings contain only whitespace, escaping them using repr()",
|
||||||
r"- '\r\n'",
|
r"- '\r\n'",
|
||||||
r"? --",
|
r"? --",
|
||||||
r"+ '\n'",
|
r"+ '\n'",
|
||||||
]
|
]
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_pytest_assertrepr_compare_integration(testdir):
|
def test_pytest_assertrepr_compare_integration(testdir):
|
||||||
|
@ -1036,7 +1021,6 @@ def test_AssertionError_message(testdir):
|
||||||
def test_set_with_unsortable_elements():
|
def test_set_with_unsortable_elements():
|
||||||
# issue #718
|
# issue #718
|
||||||
class UnsortableKey(object):
|
class UnsortableKey(object):
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
|
@ -1169,4 +1153,7 @@ def test_issue_1944(testdir):
|
||||||
)
|
)
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
result.stdout.fnmatch_lines(["*1 error*"])
|
result.stdout.fnmatch_lines(["*1 error*"])
|
||||||
assert "AttributeError: 'Module' object has no attribute '_obj'" not in result.stdout.str()
|
assert (
|
||||||
|
"AttributeError: 'Module' object has no attribute '_obj'"
|
||||||
|
not in result.stdout.str()
|
||||||
|
)
|
||||||
|
|
|
@ -78,9 +78,8 @@ def adjust_body_for_new_docstring_in_module_node(m):
|
||||||
various Python 3.7 versions, but we should remove the 3.7 check after
|
various Python 3.7 versions, but we should remove the 3.7 check after
|
||||||
3.7 is released as stable to make this check more straightforward.
|
3.7 is released as stable to make this check more straightforward.
|
||||||
"""
|
"""
|
||||||
if (
|
if sys.version_info < (3, 8) and not (
|
||||||
sys.version_info < (3, 8)
|
(3, 7) <= sys.version_info <= (3, 7, 0, "beta", 4)
|
||||||
and not ((3, 7) <= sys.version_info <= (3, 7, 0, "beta", 4))
|
|
||||||
):
|
):
|
||||||
assert len(m.body) > 1
|
assert len(m.body) > 1
|
||||||
assert isinstance(m.body[0], ast.Expr)
|
assert isinstance(m.body[0], ast.Expr)
|
||||||
|
@ -89,7 +88,6 @@ def adjust_body_for_new_docstring_in_module_node(m):
|
||||||
|
|
||||||
|
|
||||||
class TestAssertionRewrite(object):
|
class TestAssertionRewrite(object):
|
||||||
|
|
||||||
def test_place_initial_imports(self):
|
def test_place_initial_imports(self):
|
||||||
s = """'Doc string'\nother = stuff"""
|
s = """'Doc string'\nother = stuff"""
|
||||||
m = rewrite(s)
|
m = rewrite(s)
|
||||||
|
@ -150,7 +148,6 @@ class TestAssertionRewrite(object):
|
||||||
assert "warnings" not in "".join(result.outlines)
|
assert "warnings" not in "".join(result.outlines)
|
||||||
|
|
||||||
def test_name(self):
|
def test_name(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
@ -181,7 +178,6 @@ class TestAssertionRewrite(object):
|
||||||
assert getmsg(f, {"cls": X}) == "assert cls == 42"
|
assert getmsg(f, {"cls": X}) == "assert cls == 42"
|
||||||
|
|
||||||
def test_assert_already_has_message(self):
|
def test_assert_already_has_message(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
assert False, "something bad!"
|
assert False, "something bad!"
|
||||||
|
|
||||||
|
@ -251,7 +247,6 @@ class TestAssertionRewrite(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_boolop(self):
|
def test_boolop(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
f = g = False
|
f = g = False
|
||||||
assert f and g
|
assert f and g
|
||||||
|
@ -331,7 +326,6 @@ class TestAssertionRewrite(object):
|
||||||
getmsg(f, must_pass=True)
|
getmsg(f, must_pass=True)
|
||||||
|
|
||||||
def test_short_circuit_evaluation(self):
|
def test_short_circuit_evaluation(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
assert True or explode # noqa
|
assert True or explode # noqa
|
||||||
|
|
||||||
|
@ -344,7 +338,6 @@ class TestAssertionRewrite(object):
|
||||||
getmsg(f, must_pass=True)
|
getmsg(f, must_pass=True)
|
||||||
|
|
||||||
def test_unary_op(self):
|
def test_unary_op(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
x = True
|
x = True
|
||||||
assert not x
|
assert not x
|
||||||
|
@ -370,7 +363,6 @@ class TestAssertionRewrite(object):
|
||||||
assert getmsg(f) == "assert (+0 + 0)"
|
assert getmsg(f) == "assert (+0 + 0)"
|
||||||
|
|
||||||
def test_binary_op(self):
|
def test_binary_op(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
x = 1
|
x = 1
|
||||||
y = -1
|
y = -1
|
||||||
|
@ -384,7 +376,6 @@ class TestAssertionRewrite(object):
|
||||||
assert getmsg(f) == "assert not (5 % 4)"
|
assert getmsg(f) == "assert not (5 % 4)"
|
||||||
|
|
||||||
def test_boolop_percent(self):
|
def test_boolop_percent(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
assert 3 % 2 and False
|
assert 3 % 2 and False
|
||||||
|
|
||||||
|
@ -411,7 +402,6 @@ class TestAssertionRewrite(object):
|
||||||
testdir.runpytest().assert_outcomes(passed=1)
|
testdir.runpytest().assert_outcomes(passed=1)
|
||||||
|
|
||||||
def test_call(self):
|
def test_call(self):
|
||||||
|
|
||||||
def g(a=42, *args, **kwargs):
|
def g(a=42, *args, **kwargs):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -483,7 +473,6 @@ class TestAssertionRewrite(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_attribute(self):
|
def test_attribute(self):
|
||||||
|
|
||||||
class X(object):
|
class X(object):
|
||||||
g = 3
|
g = 3
|
||||||
|
|
||||||
|
@ -509,7 +498,6 @@ class TestAssertionRewrite(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_comparisons(self):
|
def test_comparisons(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
a, b = range(2)
|
a, b = range(2)
|
||||||
assert b < a
|
assert b < a
|
||||||
|
@ -542,7 +530,6 @@ class TestAssertionRewrite(object):
|
||||||
getmsg(f, must_pass=True)
|
getmsg(f, must_pass=True)
|
||||||
|
|
||||||
def test_len(self):
|
def test_len(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
values = list(range(10))
|
values = list(range(10))
|
||||||
assert len(values) == 11
|
assert len(values) == 11
|
||||||
|
@ -553,7 +540,6 @@ class TestAssertionRewrite(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_custom_reprcompare(self, monkeypatch):
|
def test_custom_reprcompare(self, monkeypatch):
|
||||||
|
|
||||||
def my_reprcompare(op, left, right):
|
def my_reprcompare(op, left, right):
|
||||||
return "42"
|
return "42"
|
||||||
|
|
||||||
|
@ -575,11 +561,8 @@ class TestAssertionRewrite(object):
|
||||||
assert getmsg(f) == "assert 5 <= 4"
|
assert getmsg(f) == "assert 5 <= 4"
|
||||||
|
|
||||||
def test_assert_raising_nonzero_in_comparison(self):
|
def test_assert_raising_nonzero_in_comparison(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
|
|
||||||
def __nonzero__(self):
|
def __nonzero__(self):
|
||||||
raise ValueError(42)
|
raise ValueError(42)
|
||||||
|
|
||||||
|
@ -597,16 +580,13 @@ class TestAssertionRewrite(object):
|
||||||
assert "<MY42 object> < 0" in getmsg(f)
|
assert "<MY42 object> < 0" in getmsg(f)
|
||||||
|
|
||||||
def test_formatchar(self):
|
def test_formatchar(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
assert "%test" == "test"
|
assert "%test" == "test"
|
||||||
|
|
||||||
assert getmsg(f).startswith("assert '%test' == 'test'")
|
assert getmsg(f).startswith("assert '%test' == 'test'")
|
||||||
|
|
||||||
def test_custom_repr(self):
|
def test_custom_repr(self):
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
|
|
||||||
class Foo(object):
|
class Foo(object):
|
||||||
a = 1
|
a = 1
|
||||||
|
|
||||||
|
@ -620,7 +600,6 @@ class TestAssertionRewrite(object):
|
||||||
|
|
||||||
|
|
||||||
class TestRewriteOnImport(object):
|
class TestRewriteOnImport(object):
|
||||||
|
|
||||||
def test_pycache_is_a_file(self, testdir):
|
def test_pycache_is_a_file(self, testdir):
|
||||||
testdir.tmpdir.join("__pycache__").write("Hello")
|
testdir.tmpdir.join("__pycache__").write("Hello")
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
|
@ -671,9 +650,7 @@ class TestRewriteOnImport(object):
|
||||||
def test_rewritten():
|
def test_rewritten():
|
||||||
assert "@py_builtins" in globals()
|
assert "@py_builtins" in globals()
|
||||||
"""
|
"""
|
||||||
).encode(
|
).encode("utf-8"),
|
||||||
"utf-8"
|
|
||||||
),
|
|
||||||
"wb",
|
"wb",
|
||||||
)
|
)
|
||||||
old_mode = sub.stat().mode
|
old_mode = sub.stat().mode
|
||||||
|
@ -870,7 +847,6 @@ def test_rewritten():
|
||||||
|
|
||||||
|
|
||||||
class TestAssertionRewriteHookDetails(object):
|
class TestAssertionRewriteHookDetails(object):
|
||||||
|
|
||||||
def test_loader_is_package_false_for_module(self, testdir):
|
def test_loader_is_package_false_for_module(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
test_fun="""
|
test_fun="""
|
||||||
|
@ -1090,7 +1066,6 @@ def test_issue731(testdir):
|
||||||
|
|
||||||
|
|
||||||
class TestIssue925(object):
|
class TestIssue925(object):
|
||||||
|
|
||||||
def test_simple_case(self, testdir):
|
def test_simple_case(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -1122,8 +1097,7 @@ class TestIssue925(object):
|
||||||
result.stdout.fnmatch_lines("*E*assert True == ((False == True) == True)")
|
result.stdout.fnmatch_lines("*E*assert True == ((False == True) == True)")
|
||||||
|
|
||||||
|
|
||||||
class TestIssue2121():
|
class TestIssue2121:
|
||||||
|
|
||||||
def test_simple(self, testdir):
|
def test_simple(self, testdir):
|
||||||
testdir.tmpdir.join("tests/file.py").ensure().write(
|
testdir.tmpdir.join("tests/file.py").ensure().write(
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -12,7 +12,6 @@ pytest_plugins = ("pytester",)
|
||||||
|
|
||||||
|
|
||||||
class TestNewAPI(object):
|
class TestNewAPI(object):
|
||||||
|
|
||||||
def test_config_cache_makedir(self, testdir):
|
def test_config_cache_makedir(self, testdir):
|
||||||
testdir.makeini("[pytest]")
|
testdir.makeini("[pytest]")
|
||||||
config = testdir.parseconfigure()
|
config = testdir.parseconfigure()
|
||||||
|
@ -184,7 +183,6 @@ def test_cache_show(testdir):
|
||||||
|
|
||||||
|
|
||||||
class TestLastFailed(object):
|
class TestLastFailed(object):
|
||||||
|
|
||||||
def test_lastfailed_usecase(self, testdir, monkeypatch):
|
def test_lastfailed_usecase(self, testdir, monkeypatch):
|
||||||
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
|
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
|
||||||
p = testdir.makepyfile(
|
p = testdir.makepyfile(
|
||||||
|
@ -559,10 +557,9 @@ class TestLastFailed(object):
|
||||||
)
|
)
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
result.stdout.fnmatch_lines("*1 failed*")
|
result.stdout.fnmatch_lines("*1 failed*")
|
||||||
assert (
|
assert self.get_cached_last_failed(testdir) == [
|
||||||
self.get_cached_last_failed(testdir)
|
"test_xfail_strict_considered_failure.py::test"
|
||||||
== ["test_xfail_strict_considered_failure.py::test"]
|
]
|
||||||
)
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("mark", ["mark.xfail", "mark.skip"])
|
@pytest.mark.parametrize("mark", ["mark.xfail", "mark.skip"])
|
||||||
def test_failed_changed_to_xfail_or_skip(self, testdir, mark):
|
def test_failed_changed_to_xfail_or_skip(self, testdir, mark):
|
||||||
|
@ -574,10 +571,9 @@ class TestLastFailed(object):
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
assert (
|
assert self.get_cached_last_failed(testdir) == [
|
||||||
self.get_cached_last_failed(testdir)
|
"test_failed_changed_to_xfail_or_skip.py::test"
|
||||||
== ["test_failed_changed_to_xfail_or_skip.py::test"]
|
]
|
||||||
)
|
|
||||||
assert result.ret == 1
|
assert result.ret == 1
|
||||||
|
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
|
@ -621,10 +617,10 @@ class TestLastFailed(object):
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
testdir.runpytest()
|
testdir.runpytest()
|
||||||
assert (
|
assert self.get_cached_last_failed(testdir) == [
|
||||||
self.get_cached_last_failed(testdir)
|
"test_bar.py::test_bar_2",
|
||||||
== ["test_bar.py::test_bar_2", "test_foo.py::test_foo_4"]
|
"test_foo.py::test_foo_4",
|
||||||
)
|
]
|
||||||
|
|
||||||
# 2. fix test_bar_2, run only test_bar.py
|
# 2. fix test_bar_2, run only test_bar.py
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
|
@ -697,7 +693,6 @@ class TestLastFailed(object):
|
||||||
|
|
||||||
|
|
||||||
class TestNewFirst(object):
|
class TestNewFirst(object):
|
||||||
|
|
||||||
def test_newfirst_usecase(self, testdir):
|
def test_newfirst_usecase(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
**{
|
**{
|
||||||
|
@ -823,7 +818,6 @@ class TestNewFirst(object):
|
||||||
|
|
||||||
|
|
||||||
class TestReadme(object):
|
class TestReadme(object):
|
||||||
|
|
||||||
def check_readme(self, testdir):
|
def check_readme(self, testdir):
|
||||||
config = testdir.parseconfigure()
|
config = testdir.parseconfigure()
|
||||||
readme = config.cache._cachedir.joinpath("README.md")
|
readme = config.cache._cachedir.joinpath("README.md")
|
||||||
|
|
|
@ -48,10 +48,9 @@ def StdCapture(out=True, err=True, in_=True):
|
||||||
|
|
||||||
|
|
||||||
class TestCaptureManager(object):
|
class TestCaptureManager(object):
|
||||||
|
|
||||||
def test_getmethod_default_no_fd(self, monkeypatch):
|
def test_getmethod_default_no_fd(self, monkeypatch):
|
||||||
from _pytest.capture import pytest_addoption
|
from _pytest.capture import pytest_addoption
|
||||||
from _pytest.config import Parser
|
from _pytest.config.argparsing import Parser
|
||||||
|
|
||||||
parser = Parser()
|
parser = Parser()
|
||||||
pytest_addoption(parser)
|
pytest_addoption(parser)
|
||||||
|
@ -150,7 +149,6 @@ def test_collect_capturing(testdir):
|
||||||
|
|
||||||
|
|
||||||
class TestPerTestCapturing(object):
|
class TestPerTestCapturing(object):
|
||||||
|
|
||||||
def test_capture_and_fixtures(self, testdir):
|
def test_capture_and_fixtures(self, testdir):
|
||||||
p = testdir.makepyfile(
|
p = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -294,7 +292,6 @@ class TestPerTestCapturing(object):
|
||||||
|
|
||||||
|
|
||||||
class TestLoggingInteraction(object):
|
class TestLoggingInteraction(object):
|
||||||
|
|
||||||
def test_logging_stream_ownership(self, testdir):
|
def test_logging_stream_ownership(self, testdir):
|
||||||
p = testdir.makepyfile(
|
p = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -399,7 +396,6 @@ class TestLoggingInteraction(object):
|
||||||
|
|
||||||
|
|
||||||
class TestCaptureFixture(object):
|
class TestCaptureFixture(object):
|
||||||
|
|
||||||
@pytest.mark.parametrize("opt", [[], ["-s"]])
|
@pytest.mark.parametrize("opt", [[], ["-s"]])
|
||||||
def test_std_functional(self, testdir, opt):
|
def test_std_functional(self, testdir, opt):
|
||||||
reprec = testdir.inline_runsource(
|
reprec = testdir.inline_runsource(
|
||||||
|
@ -771,7 +767,6 @@ def test_error_during_readouterr(testdir):
|
||||||
|
|
||||||
|
|
||||||
class TestCaptureIO(object):
|
class TestCaptureIO(object):
|
||||||
|
|
||||||
def test_text(self):
|
def test_text(self):
|
||||||
f = capture.CaptureIO()
|
f = capture.CaptureIO()
|
||||||
f.write("hello")
|
f.write("hello")
|
||||||
|
@ -1337,7 +1332,6 @@ def test_py36_windowsconsoleio_workaround_non_standard_streams():
|
||||||
from _pytest.capture import _py36_windowsconsoleio_workaround
|
from _pytest.capture import _py36_windowsconsoleio_workaround
|
||||||
|
|
||||||
class DummyStream(object):
|
class DummyStream(object):
|
||||||
|
|
||||||
def write(self, s):
|
def write(self, s):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ from _pytest.main import Session, EXIT_NOTESTSCOLLECTED, _in_venv
|
||||||
|
|
||||||
|
|
||||||
class TestCollector(object):
|
class TestCollector(object):
|
||||||
|
|
||||||
def test_collect_versus_item(self):
|
def test_collect_versus_item(self):
|
||||||
from pytest import Collector, Item
|
from pytest import Collector, Item
|
||||||
|
|
||||||
|
@ -115,7 +114,6 @@ class TestCollector(object):
|
||||||
|
|
||||||
|
|
||||||
class TestCollectFS(object):
|
class TestCollectFS(object):
|
||||||
|
|
||||||
def test_ignored_certain_directories(self, testdir):
|
def test_ignored_certain_directories(self, testdir):
|
||||||
tmpdir = testdir.tmpdir
|
tmpdir = testdir.tmpdir
|
||||||
tmpdir.ensure("build", "test_notfound.py")
|
tmpdir.ensure("build", "test_notfound.py")
|
||||||
|
@ -253,12 +251,10 @@ class TestCollectFS(object):
|
||||||
|
|
||||||
|
|
||||||
class TestCollectPluginHookRelay(object):
|
class TestCollectPluginHookRelay(object):
|
||||||
|
|
||||||
def test_pytest_collect_file(self, testdir):
|
def test_pytest_collect_file(self, testdir):
|
||||||
wascalled = []
|
wascalled = []
|
||||||
|
|
||||||
class Plugin(object):
|
class Plugin(object):
|
||||||
|
|
||||||
def pytest_collect_file(self, path, parent):
|
def pytest_collect_file(self, path, parent):
|
||||||
if not path.basename.startswith("."):
|
if not path.basename.startswith("."):
|
||||||
# Ignore hidden files, e.g. .testmondata.
|
# Ignore hidden files, e.g. .testmondata.
|
||||||
|
@ -273,7 +269,6 @@ class TestCollectPluginHookRelay(object):
|
||||||
wascalled = []
|
wascalled = []
|
||||||
|
|
||||||
class Plugin(object):
|
class Plugin(object):
|
||||||
|
|
||||||
def pytest_collect_directory(self, path, parent):
|
def pytest_collect_directory(self, path, parent):
|
||||||
wascalled.append(path.basename)
|
wascalled.append(path.basename)
|
||||||
|
|
||||||
|
@ -285,7 +280,6 @@ class TestCollectPluginHookRelay(object):
|
||||||
|
|
||||||
|
|
||||||
class TestPrunetraceback(object):
|
class TestPrunetraceback(object):
|
||||||
|
|
||||||
def test_custom_repr_failure(self, testdir):
|
def test_custom_repr_failure(self, testdir):
|
||||||
p = testdir.makepyfile(
|
p = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -335,7 +329,6 @@ class TestPrunetraceback(object):
|
||||||
|
|
||||||
|
|
||||||
class TestCustomConftests(object):
|
class TestCustomConftests(object):
|
||||||
|
|
||||||
def test_ignore_collect_path(self, testdir):
|
def test_ignore_collect_path(self, testdir):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -437,7 +430,6 @@ class TestCustomConftests(object):
|
||||||
|
|
||||||
|
|
||||||
class TestSession(object):
|
class TestSession(object):
|
||||||
|
|
||||||
def test_parsearg(self, testdir):
|
def test_parsearg(self, testdir):
|
||||||
p = testdir.makepyfile("def test_func(): pass")
|
p = testdir.makepyfile("def test_func(): pass")
|
||||||
subdir = testdir.mkdir("sub")
|
subdir = testdir.mkdir("sub")
|
||||||
|
@ -634,7 +626,6 @@ class TestSession(object):
|
||||||
|
|
||||||
|
|
||||||
class Test_getinitialnodes(object):
|
class Test_getinitialnodes(object):
|
||||||
|
|
||||||
def test_global_file(self, testdir, tmpdir):
|
def test_global_file(self, testdir, tmpdir):
|
||||||
x = tmpdir.ensure("x.py")
|
x = tmpdir.ensure("x.py")
|
||||||
with tmpdir.as_cwd():
|
with tmpdir.as_cwd():
|
||||||
|
@ -662,7 +653,6 @@ class Test_getinitialnodes(object):
|
||||||
|
|
||||||
|
|
||||||
class Test_genitems(object):
|
class Test_genitems(object):
|
||||||
|
|
||||||
def test_check_collect_hashes(self, testdir):
|
def test_check_collect_hashes(self, testdir):
|
||||||
p = testdir.makepyfile(
|
p = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -776,7 +766,6 @@ def test_matchnodes_two_collections_same_file(testdir):
|
||||||
|
|
||||||
|
|
||||||
class TestNodekeywords(object):
|
class TestNodekeywords(object):
|
||||||
|
|
||||||
def test_no_under(self, testdir):
|
def test_no_under(self, testdir):
|
||||||
modcol = testdir.getmodulecol(
|
modcol = testdir.getmodulecol(
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -7,7 +7,6 @@ from _pytest.outcomes import OutcomeException
|
||||||
|
|
||||||
|
|
||||||
def test_is_generator():
|
def test_is_generator():
|
||||||
|
|
||||||
def zap():
|
def zap():
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
@ -19,9 +18,7 @@ def test_is_generator():
|
||||||
|
|
||||||
|
|
||||||
def test_real_func_loop_limit():
|
def test_real_func_loop_limit():
|
||||||
|
|
||||||
class Evil(object):
|
class Evil(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.left = 1000
|
self.left = 1000
|
||||||
|
|
||||||
|
@ -86,7 +83,6 @@ def test_is_generator_async_syntax(testdir):
|
||||||
|
|
||||||
|
|
||||||
class ErrorsHelper(object):
|
class ErrorsHelper(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def raise_exception(self):
|
def raise_exception(self):
|
||||||
raise Exception("exception should be catched")
|
raise Exception("exception should be catched")
|
||||||
|
|
|
@ -4,17 +4,12 @@ import textwrap
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
from _pytest.config import (
|
from _pytest.config.findpaths import getcfg, get_common_ancestor, determine_setup
|
||||||
getcfg,
|
from _pytest.config import _iter_rewritable_modules
|
||||||
get_common_ancestor,
|
|
||||||
determine_setup,
|
|
||||||
_iter_rewritable_modules,
|
|
||||||
)
|
|
||||||
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
||||||
|
|
||||||
|
|
||||||
class TestParseIni(object):
|
class TestParseIni(object):
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"section, filename", [("pytest", "pytest.ini"), ("tool:pytest", "setup.cfg")]
|
"section, filename", [("pytest", "pytest.ini"), ("tool:pytest", "setup.cfg")]
|
||||||
)
|
)
|
||||||
|
@ -122,7 +117,6 @@ class TestParseIni(object):
|
||||||
|
|
||||||
|
|
||||||
class TestConfigCmdlineParsing(object):
|
class TestConfigCmdlineParsing(object):
|
||||||
|
|
||||||
def test_parsing_again_fails(self, testdir):
|
def test_parsing_again_fails(self, testdir):
|
||||||
config = testdir.parseconfig()
|
config = testdir.parseconfig()
|
||||||
pytest.raises(AssertionError, lambda: config.parse([]))
|
pytest.raises(AssertionError, lambda: config.parse([]))
|
||||||
|
@ -176,7 +170,6 @@ class TestConfigCmdlineParsing(object):
|
||||||
|
|
||||||
|
|
||||||
class TestConfigAPI(object):
|
class TestConfigAPI(object):
|
||||||
|
|
||||||
def test_config_trace(self, testdir):
|
def test_config_trace(self, testdir):
|
||||||
config = testdir.parseconfig()
|
config = testdir.parseconfig()
|
||||||
values = []
|
values = []
|
||||||
|
@ -416,7 +409,6 @@ class TestConfigAPI(object):
|
||||||
|
|
||||||
|
|
||||||
class TestConfigFromdictargs(object):
|
class TestConfigFromdictargs(object):
|
||||||
|
|
||||||
def test_basic_behavior(self):
|
def test_basic_behavior(self):
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
|
|
||||||
|
@ -483,7 +475,6 @@ class TestConfigFromdictargs(object):
|
||||||
|
|
||||||
|
|
||||||
def test_options_on_small_file_do_not_blow_up(testdir):
|
def test_options_on_small_file_do_not_blow_up(testdir):
|
||||||
|
|
||||||
def runfiletest(opts):
|
def runfiletest(opts):
|
||||||
reprec = testdir.inline_run(*opts)
|
reprec = testdir.inline_run(*opts)
|
||||||
passed, skipped, failed = reprec.countoutcomes()
|
passed, skipped, failed = reprec.countoutcomes()
|
||||||
|
@ -530,7 +521,6 @@ def test_preparse_ordering_with_setuptools(testdir, monkeypatch):
|
||||||
dist = Dist()
|
dist = Dist()
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
|
|
||||||
class PseudoPlugin(object):
|
class PseudoPlugin(object):
|
||||||
x = 42
|
x = 42
|
||||||
|
|
||||||
|
@ -610,9 +600,9 @@ def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch, block
|
||||||
assert "mytestplugin" not in sys.modules
|
assert "mytestplugin" not in sys.modules
|
||||||
assert config.pluginmanager.get_plugin("mytestplugin") is None
|
assert config.pluginmanager.get_plugin("mytestplugin") is None
|
||||||
else:
|
else:
|
||||||
assert config.pluginmanager.get_plugin(
|
assert (
|
||||||
"mytestplugin"
|
config.pluginmanager.get_plugin("mytestplugin") is plugin_module_placeholder
|
||||||
) is plugin_module_placeholder
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_cmdline_processargs_simple(testdir):
|
def test_cmdline_processargs_simple(testdir):
|
||||||
|
@ -713,7 +703,6 @@ def test_notify_exception(testdir, capfd):
|
||||||
assert "ValueError" in err
|
assert "ValueError" in err
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
|
|
||||||
def pytest_internalerror(self, excrepr):
|
def pytest_internalerror(self, excrepr):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -729,7 +718,6 @@ def test_load_initial_conftest_last_ordering(testdir):
|
||||||
pm = get_config().pluginmanager
|
pm = get_config().pluginmanager
|
||||||
|
|
||||||
class My(object):
|
class My(object):
|
||||||
|
|
||||||
def pytest_load_initial_conftests(self):
|
def pytest_load_initial_conftests(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -758,7 +746,6 @@ def test_get_plugin_specs_as_list():
|
||||||
|
|
||||||
|
|
||||||
class TestWarning(object):
|
class TestWarning(object):
|
||||||
|
|
||||||
def test_warn_config(self, testdir):
|
def test_warn_config(self, testdir):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -808,7 +795,6 @@ class TestWarning(object):
|
||||||
|
|
||||||
|
|
||||||
class TestRootdir(object):
|
class TestRootdir(object):
|
||||||
|
|
||||||
def test_simple_noini(self, tmpdir):
|
def test_simple_noini(self, tmpdir):
|
||||||
assert get_common_ancestor([tmpdir]) == tmpdir
|
assert get_common_ancestor([tmpdir]) == tmpdir
|
||||||
a = tmpdir.mkdir("a")
|
a = tmpdir.mkdir("a")
|
||||||
|
@ -867,7 +853,6 @@ class TestRootdir(object):
|
||||||
|
|
||||||
|
|
||||||
class TestOverrideIniArgs(object):
|
class TestOverrideIniArgs(object):
|
||||||
|
|
||||||
@pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
|
@pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
|
||||||
def test_override_ini_names(self, testdir, name):
|
def test_override_ini_names(self, testdir, name):
|
||||||
testdir.tmpdir.join(name).write(
|
testdir.tmpdir.join(name).write(
|
||||||
|
|
|
@ -28,9 +28,7 @@ def ConftestWithSetinitial(path):
|
||||||
|
|
||||||
|
|
||||||
def conftest_setinitial(conftest, args, confcutdir=None):
|
def conftest_setinitial(conftest, args, confcutdir=None):
|
||||||
|
|
||||||
class Namespace(object):
|
class Namespace(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.file_or_dir = args
|
self.file_or_dir = args
|
||||||
self.confcutdir = str(confcutdir)
|
self.confcutdir = str(confcutdir)
|
||||||
|
@ -40,7 +38,6 @@ def conftest_setinitial(conftest, args, confcutdir=None):
|
||||||
|
|
||||||
|
|
||||||
class TestConftestValueAccessGlobal(object):
|
class TestConftestValueAccessGlobal(object):
|
||||||
|
|
||||||
def test_basic_init(self, basedir):
|
def test_basic_init(self, basedir):
|
||||||
conftest = PytestPluginManager()
|
conftest = PytestPluginManager()
|
||||||
p = basedir.join("adir")
|
p = basedir.join("adir")
|
||||||
|
@ -311,7 +308,6 @@ def test_conftest_found_with_double_dash(testdir):
|
||||||
|
|
||||||
|
|
||||||
class TestConftestVisibility(object):
|
class TestConftestVisibility(object):
|
||||||
|
|
||||||
def _setup_tree(self, testdir): # for issue616
|
def _setup_tree(self, testdir): # for issue616
|
||||||
# example mostly taken from:
|
# example mostly taken from:
|
||||||
# https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html
|
# https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html
|
||||||
|
|
|
@ -8,7 +8,6 @@ import pytest
|
||||||
|
|
||||||
|
|
||||||
class TestDoctests(object):
|
class TestDoctests(object):
|
||||||
|
|
||||||
def test_collect_testtextfile(self, testdir):
|
def test_collect_testtextfile(self, testdir):
|
||||||
w = testdir.maketxtfile(whatever="")
|
w = testdir.maketxtfile(whatever="")
|
||||||
checkfile = testdir.maketxtfile(
|
checkfile = testdir.maketxtfile(
|
||||||
|
@ -655,6 +654,22 @@ class TestDoctests(object):
|
||||||
result = testdir.runpytest(p, "--doctest-modules")
|
result = testdir.runpytest(p, "--doctest-modules")
|
||||||
result.stdout.fnmatch_lines(["* 1 passed *"])
|
result.stdout.fnmatch_lines(["* 1 passed *"])
|
||||||
|
|
||||||
|
def test_print_unicode_value(self, testdir):
|
||||||
|
"""
|
||||||
|
Test case for issue 3583: Printing Unicode in doctest under Python 2.7
|
||||||
|
doesn't work
|
||||||
|
"""
|
||||||
|
p = testdir.maketxtfile(
|
||||||
|
test_print_unicode_value=r"""
|
||||||
|
Here is a doctest::
|
||||||
|
|
||||||
|
>>> print(u'\xE5\xE9\xEE\xF8\xFC')
|
||||||
|
åéîøü
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = testdir.runpytest(p)
|
||||||
|
result.stdout.fnmatch_lines(["* 1 passed *"])
|
||||||
|
|
||||||
def test_reportinfo(self, testdir):
|
def test_reportinfo(self, testdir):
|
||||||
"""
|
"""
|
||||||
Test case to make sure that DoctestItem.reportinfo() returns lineno.
|
Test case to make sure that DoctestItem.reportinfo() returns lineno.
|
||||||
|
@ -707,7 +722,6 @@ class TestDoctests(object):
|
||||||
|
|
||||||
|
|
||||||
class TestLiterals(object):
|
class TestLiterals(object):
|
||||||
|
|
||||||
@pytest.mark.parametrize("config_mode", ["ini", "comment"])
|
@pytest.mark.parametrize("config_mode", ["ini", "comment"])
|
||||||
def test_allow_unicode(self, testdir, config_mode):
|
def test_allow_unicode(self, testdir, config_mode):
|
||||||
"""Test that doctests which output unicode work in all python versions
|
"""Test that doctests which output unicode work in all python versions
|
||||||
|
@ -825,7 +839,6 @@ class TestDoctestSkips(object):
|
||||||
|
|
||||||
@pytest.fixture(params=["text", "module"])
|
@pytest.fixture(params=["text", "module"])
|
||||||
def makedoctest(self, testdir, request):
|
def makedoctest(self, testdir, request):
|
||||||
|
|
||||||
def makeit(doctest):
|
def makeit(doctest):
|
||||||
mode = request.param
|
mode = request.param
|
||||||
if mode == "text":
|
if mode == "text":
|
||||||
|
@ -1106,7 +1119,6 @@ class TestDoctestNamespaceFixture(object):
|
||||||
|
|
||||||
|
|
||||||
class TestDoctestReportingOption(object):
|
class TestDoctestReportingOption(object):
|
||||||
|
|
||||||
def _run_doctest_report(self, testdir, format):
|
def _run_doctest_report(self, testdir, format):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -29,7 +29,6 @@ def assert_attr(node, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
class DomNode(object):
|
class DomNode(object):
|
||||||
|
|
||||||
def __init__(self, dom):
|
def __init__(self, dom):
|
||||||
self.__node = dom
|
self.__node = dom
|
||||||
|
|
||||||
|
@ -81,7 +80,6 @@ class DomNode(object):
|
||||||
|
|
||||||
|
|
||||||
class TestPython(object):
|
class TestPython(object):
|
||||||
|
|
||||||
def test_summing_simple(self, testdir):
|
def test_summing_simple(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -713,7 +711,6 @@ def test_dont_configure_on_slaves(tmpdir):
|
||||||
gotten = []
|
gotten = []
|
||||||
|
|
||||||
class FakeConfig(object):
|
class FakeConfig(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.pluginmanager = self
|
self.pluginmanager = self
|
||||||
self.option = self
|
self.option = self
|
||||||
|
@ -737,7 +734,6 @@ def test_dont_configure_on_slaves(tmpdir):
|
||||||
|
|
||||||
|
|
||||||
class TestNonPython(object):
|
class TestNonPython(object):
|
||||||
|
|
||||||
def test_summing_simple(self, testdir):
|
def test_summing_simple(self, testdir):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -1127,9 +1123,7 @@ def test_fancy_items_regression(testdir):
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
pprint.pprint(items)
|
pprint.pprint(items)
|
||||||
assert (
|
assert items == [
|
||||||
items
|
|
||||||
== [
|
|
||||||
u"conftest a conftest.py",
|
u"conftest a conftest.py",
|
||||||
u"conftest a conftest.py",
|
u"conftest a conftest.py",
|
||||||
u"conftest b conftest.py",
|
u"conftest b conftest.py",
|
||||||
|
@ -1138,7 +1132,6 @@ def test_fancy_items_regression(testdir):
|
||||||
u"test_fancy_items_regression b test_fancy_items_regression.py",
|
u"test_fancy_items_regression b test_fancy_items_regression.py",
|
||||||
u"test_fancy_items_regression test_pass" u" test_fancy_items_regression.py",
|
u"test_fancy_items_regression test_pass" u" test_fancy_items_regression.py",
|
||||||
]
|
]
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_global_properties(testdir):
|
def test_global_properties(testdir):
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
import mock
|
import mock
|
||||||
|
except ImportError:
|
||||||
|
import unittest.mock as mock
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.mark import (
|
from _pytest.mark import (
|
||||||
MarkGenerator as Mark,
|
MarkGenerator as Mark,
|
||||||
|
@ -17,7 +21,6 @@ ignore_markinfo = pytest.mark.filterwarnings(
|
||||||
|
|
||||||
|
|
||||||
class TestMark(object):
|
class TestMark(object):
|
||||||
|
|
||||||
def test_markinfo_repr(self):
|
def test_markinfo_repr(self):
|
||||||
from _pytest.mark import MarkInfo, Mark
|
from _pytest.mark import MarkInfo, Mark
|
||||||
|
|
||||||
|
@ -35,7 +38,6 @@ class TestMark(object):
|
||||||
pytest.raises((AttributeError, TypeError), mark)
|
pytest.raises((AttributeError, TypeError), mark)
|
||||||
|
|
||||||
def test_mark_with_param(self):
|
def test_mark_with_param(self):
|
||||||
|
|
||||||
def some_function(abc):
|
def some_function(abc):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -483,7 +485,6 @@ def test_parametrized_with_kwargs(testdir):
|
||||||
|
|
||||||
|
|
||||||
class TestFunctional(object):
|
class TestFunctional(object):
|
||||||
|
|
||||||
def test_mark_per_function(self, testdir):
|
def test_mark_per_function(self, testdir):
|
||||||
p = testdir.makepyfile(
|
p = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -880,7 +881,6 @@ class TestFunctional(object):
|
||||||
|
|
||||||
|
|
||||||
class TestKeywordSelection(object):
|
class TestKeywordSelection(object):
|
||||||
|
|
||||||
def test_select_simple(self, testdir):
|
def test_select_simple(self, testdir):
|
||||||
file_test = testdir.makepyfile(
|
file_test = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -1033,7 +1033,6 @@ def test_parameterset_extractfrom(argval, expected):
|
||||||
|
|
||||||
|
|
||||||
def test_legacy_transfer():
|
def test_legacy_transfer():
|
||||||
|
|
||||||
class FakeModule(object):
|
class FakeModule(object):
|
||||||
pytestmark = []
|
pytestmark = []
|
||||||
|
|
||||||
|
@ -1054,7 +1053,6 @@ def test_legacy_transfer():
|
||||||
|
|
||||||
|
|
||||||
class TestMarkDecorator(object):
|
class TestMarkDecorator(object):
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"lhs, rhs, expected",
|
"lhs, rhs, expected",
|
||||||
[
|
[
|
||||||
|
|
|
@ -17,7 +17,6 @@ def mp():
|
||||||
|
|
||||||
|
|
||||||
def test_setattr():
|
def test_setattr():
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
|
@ -42,7 +41,6 @@ def test_setattr():
|
||||||
|
|
||||||
|
|
||||||
class TestSetattrWithImportPath(object):
|
class TestSetattrWithImportPath(object):
|
||||||
|
|
||||||
def test_string_expression(self, monkeypatch):
|
def test_string_expression(self, monkeypatch):
|
||||||
monkeypatch.setattr("os.path.abspath", lambda x: "hello2")
|
monkeypatch.setattr("os.path.abspath", lambda x: "hello2")
|
||||||
assert os.path.abspath("123") == "hello2"
|
assert os.path.abspath("123") == "hello2"
|
||||||
|
@ -84,7 +82,6 @@ class TestSetattrWithImportPath(object):
|
||||||
|
|
||||||
|
|
||||||
def test_delattr():
|
def test_delattr():
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
|
@ -311,7 +308,6 @@ def test_importerror(testdir):
|
||||||
|
|
||||||
|
|
||||||
class SampleNew(object):
|
class SampleNew(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def hello():
|
def hello():
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -33,7 +33,6 @@ def test_setup_func_with_setup_decorator():
|
||||||
values = []
|
values = []
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def f(self):
|
def f(self):
|
||||||
values.append(1)
|
values.append(1)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import sys
|
||||||
import os
|
import os
|
||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest import config as parseopt
|
from _pytest.config import argparsing as parseopt
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -13,7 +13,6 @@ def parser():
|
||||||
|
|
||||||
|
|
||||||
class TestParser(object):
|
class TestParser(object):
|
||||||
|
|
||||||
def test_no_help_by_default(self, capsys):
|
def test_no_help_by_default(self, capsys):
|
||||||
parser = parseopt.Parser(usage="xyz")
|
parser = parseopt.Parser(usage="xyz")
|
||||||
pytest.raises(SystemExit, lambda: parser.parse(["-h"]))
|
pytest.raises(SystemExit, lambda: parser.parse(["-h"]))
|
||||||
|
@ -34,9 +33,8 @@ class TestParser(object):
|
||||||
assert argument.dest == "test"
|
assert argument.dest == "test"
|
||||||
argument = parseopt.Argument("-t", "--test", dest="abc")
|
argument = parseopt.Argument("-t", "--test", dest="abc")
|
||||||
assert argument.dest == "abc"
|
assert argument.dest == "abc"
|
||||||
assert (
|
assert str(argument) == (
|
||||||
str(argument)
|
"Argument(_short_opts: ['-t'], _long_opts: ['--test'], dest: 'abc')"
|
||||||
== ("Argument(_short_opts: ['-t'], _long_opts: ['--test'], dest: 'abc')")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_argument_type(self):
|
def test_argument_type(self):
|
||||||
|
@ -180,7 +178,6 @@ class TestParser(object):
|
||||||
assert args.S is False
|
assert args.S is False
|
||||||
|
|
||||||
def test_parse_defaultgetter(self):
|
def test_parse_defaultgetter(self):
|
||||||
|
|
||||||
def defaultget(option):
|
def defaultget(option):
|
||||||
if not hasattr(option, "type"):
|
if not hasattr(option, "type"):
|
||||||
return
|
return
|
||||||
|
@ -204,15 +201,11 @@ class TestParser(object):
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-t", "--twoword", "--duo", "--two-word", "--two", help="foo"
|
"-t", "--twoword", "--duo", "--two-word", "--two", help="foo"
|
||||||
).map_long_option = {
|
).map_long_option = {"two": "two-word"}
|
||||||
"two": "two-word"
|
|
||||||
}
|
|
||||||
# throws error on --deux only!
|
# throws error on --deux only!
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-d", "--deuxmots", "--deux-mots", action="store_true", help="foo"
|
"-d", "--deuxmots", "--deux-mots", action="store_true", help="foo"
|
||||||
).map_long_option = {
|
).map_long_option = {"deux": "deux-mots"}
|
||||||
"deux": "deux-mots"
|
|
||||||
}
|
|
||||||
parser.add_argument("-s", action="store_true", help="single short")
|
parser.add_argument("-s", action="store_true", help="single short")
|
||||||
parser.add_argument("--abc", "-a", action="store_true", help="bar")
|
parser.add_argument("--abc", "-a", action="store_true", help="bar")
|
||||||
parser.add_argument("--klm", "-k", "--kl-m", action="store_true", help="bar")
|
parser.add_argument("--klm", "-k", "--kl-m", action="store_true", help="bar")
|
||||||
|
@ -224,9 +217,7 @@ class TestParser(object):
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-x", "--exit-on-first", "--exitfirst", action="store_true", help="spam"
|
"-x", "--exit-on-first", "--exitfirst", action="store_true", help="spam"
|
||||||
).map_long_option = {
|
).map_long_option = {"exitfirst": "exit-on-first"}
|
||||||
"exitfirst": "exit-on-first"
|
|
||||||
}
|
|
||||||
parser.add_argument("files_and_dirs", nargs="*")
|
parser.add_argument("files_and_dirs", nargs="*")
|
||||||
args = parser.parse_args(["-k", "--duo", "hallo", "--exitfirst"])
|
args = parser.parse_args(["-k", "--duo", "hallo", "--exitfirst"])
|
||||||
assert args.twoword == "hallo"
|
assert args.twoword == "hallo"
|
||||||
|
|
|
@ -5,7 +5,6 @@ import pytest
|
||||||
|
|
||||||
|
|
||||||
class TestPasteCapture(object):
|
class TestPasteCapture(object):
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def pastebinlist(self, monkeypatch, request):
|
def pastebinlist(self, monkeypatch, request):
|
||||||
pastebinlist = []
|
pastebinlist = []
|
||||||
|
@ -85,7 +84,6 @@ class TestPasteCapture(object):
|
||||||
|
|
||||||
|
|
||||||
class TestPaste(object):
|
class TestPaste(object):
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def pastebin(self, request):
|
def pastebin(self, request):
|
||||||
return request.config.pluginmanager.getplugin("pastebin")
|
return request.config.pluginmanager.getplugin("pastebin")
|
||||||
|
@ -102,7 +100,6 @@ class TestPaste(object):
|
||||||
calls.append((url, data))
|
calls.append((url, data))
|
||||||
|
|
||||||
class DummyFile(object):
|
class DummyFile(object):
|
||||||
|
|
||||||
def read(self):
|
def read(self):
|
||||||
# part of html of a normal response
|
# part of html of a normal response
|
||||||
return b'View <a href="/raw/3c0c6750bd">raw</a>.'
|
return b'View <a href="/raw/3c0c6750bd">raw</a>.'
|
||||||
|
|
|
@ -25,7 +25,6 @@ def custom_pdb_calls():
|
||||||
|
|
||||||
# install dummy debugger class and track which methods were called on it
|
# install dummy debugger class and track which methods were called on it
|
||||||
class _CustomPdb(object):
|
class _CustomPdb(object):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
called.append("init")
|
called.append("init")
|
||||||
|
|
||||||
|
@ -45,7 +44,6 @@ def custom_debugger_hook():
|
||||||
|
|
||||||
# install dummy debugger class and track which methods were called on it
|
# install dummy debugger class and track which methods were called on it
|
||||||
class _CustomDebugger(object):
|
class _CustomDebugger(object):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
called.append("init")
|
called.append("init")
|
||||||
|
|
||||||
|
@ -65,7 +63,6 @@ def custom_debugger_hook():
|
||||||
|
|
||||||
|
|
||||||
class TestPDB(object):
|
class TestPDB(object):
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def pdblist(self, request):
|
def pdblist(self, request):
|
||||||
monkeypatch = request.getfixturevalue("monkeypatch")
|
monkeypatch = request.getfixturevalue("monkeypatch")
|
||||||
|
@ -563,7 +560,6 @@ class TestPDB(object):
|
||||||
|
|
||||||
|
|
||||||
class TestDebuggingBreakpoints(object):
|
class TestDebuggingBreakpoints(object):
|
||||||
|
|
||||||
def test_supports_breakpoint_module_global(self):
|
def test_supports_breakpoint_module_global(self):
|
||||||
"""
|
"""
|
||||||
Test that supports breakpoint global marks on Python 3.7+ and not on
|
Test that supports breakpoint global marks on Python 3.7+ and not on
|
||||||
|
|
|
@ -16,7 +16,6 @@ def pytestpm():
|
||||||
|
|
||||||
|
|
||||||
class TestPytestPluginInteractions(object):
|
class TestPytestPluginInteractions(object):
|
||||||
|
|
||||||
def test_addhooks_conftestplugin(self, testdir):
|
def test_addhooks_conftestplugin(self, testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
newhooks="""
|
newhooks="""
|
||||||
|
@ -104,7 +103,6 @@ class TestPytestPluginInteractions(object):
|
||||||
values = []
|
values = []
|
||||||
|
|
||||||
class A(object):
|
class A(object):
|
||||||
|
|
||||||
def pytest_configure(self, config):
|
def pytest_configure(self, config):
|
||||||
values.append(self)
|
values.append(self)
|
||||||
|
|
||||||
|
@ -125,12 +123,10 @@ class TestPytestPluginInteractions(object):
|
||||||
saveindent = []
|
saveindent = []
|
||||||
|
|
||||||
class api1(object):
|
class api1(object):
|
||||||
|
|
||||||
def pytest_plugin_registered(self):
|
def pytest_plugin_registered(self):
|
||||||
saveindent.append(pytestpm.trace.root.indent)
|
saveindent.append(pytestpm.trace.root.indent)
|
||||||
|
|
||||||
class api2(object):
|
class api2(object):
|
||||||
|
|
||||||
def pytest_plugin_registered(self):
|
def pytest_plugin_registered(self):
|
||||||
saveindent.append(pytestpm.trace.root.indent)
|
saveindent.append(pytestpm.trace.root.indent)
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
@ -175,12 +171,10 @@ class TestPytestPluginInteractions(object):
|
||||||
warnings = []
|
warnings = []
|
||||||
|
|
||||||
class get_warnings(object):
|
class get_warnings(object):
|
||||||
|
|
||||||
def pytest_logwarning(self, code, fslocation, message, nodeid):
|
def pytest_logwarning(self, code, fslocation, message, nodeid):
|
||||||
warnings.append(message)
|
warnings.append(message)
|
||||||
|
|
||||||
class Plugin(object):
|
class Plugin(object):
|
||||||
|
|
||||||
def pytest_testhook():
|
def pytest_testhook():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -232,7 +226,6 @@ def test_importplugin_error_message(testdir, pytestpm):
|
||||||
|
|
||||||
|
|
||||||
class TestPytestPluginManager(object):
|
class TestPytestPluginManager(object):
|
||||||
|
|
||||||
def test_register_imported_modules(self):
|
def test_register_imported_modules(self):
|
||||||
pm = PytestPluginManager()
|
pm = PytestPluginManager()
|
||||||
mod = types.ModuleType("x.y.pytest_hello")
|
mod = types.ModuleType("x.y.pytest_hello")
|
||||||
|
@ -363,7 +356,6 @@ class TestPytestPluginManager(object):
|
||||||
|
|
||||||
|
|
||||||
class TestPytestPluginManagerBootstrapming(object):
|
class TestPytestPluginManagerBootstrapming(object):
|
||||||
|
|
||||||
def test_preparse_args(self, pytestpm):
|
def test_preparse_args(self, pytestpm):
|
||||||
pytest.raises(
|
pytest.raises(
|
||||||
ImportError, lambda: pytestpm.consider_preparse(["xyz", "-p", "hello123"])
|
ImportError, lambda: pytestpm.consider_preparse(["xyz", "-p", "hello123"])
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue