Merge remote-tracking branch 'upstream/master' into merge-master-into-features
This commit is contained in:
		
						commit
						2f2d5861bb
					
				|  | @ -5,13 +5,13 @@ repos: | ||||||
|     hooks: |     hooks: | ||||||
|     -   id: black |     -   id: black | ||||||
|         args: [--safe, --quiet] |         args: [--safe, --quiet] | ||||||
|         language_version: python3.6 |         language_version: python3 | ||||||
| -   repo: https://github.com/asottile/blacken-docs | -   repo: https://github.com/asottile/blacken-docs | ||||||
|     rev: v0.2.0 |     rev: v0.2.0 | ||||||
|     hooks: |     hooks: | ||||||
|     -   id: blacken-docs |     -   id: blacken-docs | ||||||
|         additional_dependencies: [black==18.6b4] |         additional_dependencies: [black==18.6b4] | ||||||
|         language_version: python3.6 |         language_version: python3 | ||||||
| -   repo: https://github.com/pre-commit/pre-commit-hooks | -   repo: https://github.com/pre-commit/pre-commit-hooks | ||||||
|     rev: v1.3.0 |     rev: v1.3.0 | ||||||
|     hooks: |     hooks: | ||||||
|  | @ -37,7 +37,6 @@ repos: | ||||||
|         files: ^(CHANGELOG.rst|HOWTORELEASE.rst|README.rst|changelog/.*)$ |         files: ^(CHANGELOG.rst|HOWTORELEASE.rst|README.rst|changelog/.*)$ | ||||||
|         language: python |         language: python | ||||||
|         additional_dependencies: [pygments, restructuredtext_lint] |         additional_dependencies: [pygments, restructuredtext_lint] | ||||||
|         python_version: python3.6 |  | ||||||
|     -   id: changelogs-rst |     -   id: changelogs-rst | ||||||
|         name: changelog files must end in .rst |         name: changelog files must end in .rst | ||||||
|         entry: ./scripts/fail |         entry: ./scripts/fail | ||||||
|  |  | ||||||
|  | @ -62,12 +62,7 @@ jobs: | ||||||
|           repo: pytest-dev/pytest |           repo: pytest-dev/pytest | ||||||
|     - stage: linting |     - stage: linting | ||||||
|       python: '3.6' |       python: '3.6' | ||||||
|       env: |       env: TOXENV=linting | ||||||
|       install: |  | ||||||
|       - pip install pre-commit |  | ||||||
|       - pre-commit install-hooks |  | ||||||
|       script: |  | ||||||
|       - pre-commit run --all-files |  | ||||||
| 
 | 
 | ||||||
| script: tox --recreate | script: tox --recreate | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								AUTHORS
								
								
								
								
							
							
						
						
									
										1
									
								
								AUTHORS
								
								
								
								
							|  | @ -98,6 +98,7 @@ Javier Domingo Cansino | ||||||
| Javier Romero | Javier Romero | ||||||
| Jeff Rackauckas | Jeff Rackauckas | ||||||
| Jeff Widman | Jeff Widman | ||||||
|  | Jenni Rinker | ||||||
| John Eddie Ayson | John Eddie Ayson | ||||||
| John Towler | John Towler | ||||||
| Jon Sonesen | Jon Sonesen | ||||||
|  |  | ||||||
|  | @ -18,6 +18,61 @@ with advance notice in the **Deprecations** section of releases. | ||||||
| 
 | 
 | ||||||
| .. towncrier release notes start | .. towncrier release notes start | ||||||
| 
 | 
 | ||||||
|  | pytest 3.7.3 (2018-08-26) | ||||||
|  | ========================= | ||||||
|  | 
 | ||||||
|  | Bug Fixes | ||||||
|  | --------- | ||||||
|  | 
 | ||||||
|  | - `#3033 <https://github.com/pytest-dev/pytest/issues/3033>`_: Fixtures during teardown can again use ``capsys`` and ``capfd`` to inspect output captured during tests. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#3773 <https://github.com/pytest-dev/pytest/issues/3773>`_: Fix collection of tests from ``__init__.py`` files if they match the ``python_files`` configuration option. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#3796 <https://github.com/pytest-dev/pytest/issues/3796>`_: Fix issue where teardown of fixtures of consecutive sub-packages were executed once, at the end of the outer | ||||||
|  |   package. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#3816 <https://github.com/pytest-dev/pytest/issues/3816>`_: Fix bug where ``--show-capture=no`` option would still show logs printed during fixture teardown. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#3819 <https://github.com/pytest-dev/pytest/issues/3819>`_: Fix ``stdout/stderr`` not getting captured when real-time cli logging is active. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#3843 <https://github.com/pytest-dev/pytest/issues/3843>`_: Fix collection error when specifying test functions directly in the command line using ``test.py::test`` syntax together with ``--doctest-modules``. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#3848 <https://github.com/pytest-dev/pytest/issues/3848>`_: Fix bugs where unicode arguments could not be passed to ``testdir.runpytest`` on Python 2. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#3854 <https://github.com/pytest-dev/pytest/issues/3854>`_: Fix double collection of tests within packages when the filename starts with a capital letter. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Improved Documentation | ||||||
|  | ---------------------- | ||||||
|  | 
 | ||||||
|  | - `#3824 <https://github.com/pytest-dev/pytest/issues/3824>`_: Added example for multiple glob pattern matches in ``python_files``. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#3833 <https://github.com/pytest-dev/pytest/issues/3833>`_: Added missing docs for ``pytester.Testdir``. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#3870 <https://github.com/pytest-dev/pytest/issues/3870>`_: Correct documentation for setuptools integration. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Trivial/Internal Changes | ||||||
|  | ------------------------ | ||||||
|  | 
 | ||||||
|  | - `#3826 <https://github.com/pytest-dev/pytest/issues/3826>`_: Replace broken type annotations with type comments. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#3845 <https://github.com/pytest-dev/pytest/issues/3845>`_: Remove a reference to issue `#568 <https://github.com/pytest-dev/pytest/issues/568>`_ from the documentation, which has since been | ||||||
|  |   fixed. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| pytest 3.7.2 (2018-08-16) | pytest 3.7.2 (2018-08-16) | ||||||
| ========================= | ========================= | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import py | import six | ||||||
| 
 | 
 | ||||||
| for i in range(1000): | for i in range(1000): | ||||||
|     py.builtin.exec_("def test_func_%d(): pass" % i) |     six.exec_("def test_func_%d(): pass" % i) | ||||||
|  |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| Fix ``stdout/stderr`` not getting captured when real-time cli logging is active. |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| Replace broken type annotations with type comments. |  | ||||||
|  | @ -6,6 +6,7 @@ Release announcements | ||||||
|    :maxdepth: 2 |    :maxdepth: 2 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |    release-3.7.3 | ||||||
|    release-3.7.2 |    release-3.7.2 | ||||||
|    release-3.7.1 |    release-3.7.1 | ||||||
|    release-3.7.0 |    release-3.7.0 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,33 @@ | ||||||
|  | pytest-3.7.3 | ||||||
|  | ======================================= | ||||||
|  | 
 | ||||||
|  | pytest 3.7.3 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: | ||||||
|  | 
 | ||||||
|  | * Andrew Champion | ||||||
|  | * Anthony Sottile | ||||||
|  | * Bruno Oliveira | ||||||
|  | * Daniel Hahler | ||||||
|  | * Gandalf Saxe | ||||||
|  | * Jennifer Rinker | ||||||
|  | * Natan Lao | ||||||
|  | * Ondřej Súkup | ||||||
|  | * Ronny Pfannschmidt | ||||||
|  | * Sankt Petersbug | ||||||
|  | * Tyler Richard | ||||||
|  | * Victor | ||||||
|  | * Vlad Shcherbina | ||||||
|  | * turturica | ||||||
|  | * victor | ||||||
|  | * wim glenn | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Happy testing, | ||||||
|  | The pytest Development Team | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| from pytest import raises | from pytest import raises | ||||||
| import _pytest._code | import _pytest._code | ||||||
| import py | import six | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def otherfunc(a, b): | def otherfunc(a, b): | ||||||
|  | @ -177,7 +177,7 @@ def test_dynamic_compile_shows_nicely(): | ||||||
|     name = "abc-123" |     name = "abc-123" | ||||||
|     module = imp.new_module(name) |     module = imp.new_module(name) | ||||||
|     code = _pytest._code.compile(src, name, "exec") |     code = _pytest._code.compile(src, name, "exec") | ||||||
|     py.builtin.exec_(code, module.__dict__) |     six.exec_(code, module.__dict__) | ||||||
|     sys.modules[name] = module |     sys.modules[name] = module | ||||||
|     module.foo() |     module.foo() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,4 +10,4 @@ def pytest_runtest_setup(item): | ||||||
|             return |             return | ||||||
|         mod = item.getparent(pytest.Module).obj |         mod = item.getparent(pytest.Module).obj | ||||||
|         if hasattr(mod, "hello"): |         if hasattr(mod, "hello"): | ||||||
|             print("mod.hello %r" % (mod.hello,)) |             print("mod.hello {!r}".format(mod.hello)) | ||||||
|  |  | ||||||
|  | @ -2,9 +2,10 @@ | ||||||
| module containing a parametrized tests testing cross-python | module containing a parametrized tests testing cross-python | ||||||
| serialization via the pickle module. | serialization via the pickle module. | ||||||
| """ | """ | ||||||
|  | import textwrap | ||||||
|  | 
 | ||||||
| import py | import py | ||||||
| import pytest | import pytest | ||||||
| import _pytest._code |  | ||||||
| 
 | 
 | ||||||
| pythonlist = ["python2.7", "python3.4", "python3.5"] | pythonlist = ["python2.7", "python3.4", "python3.5"] | ||||||
| 
 | 
 | ||||||
|  | @ -24,42 +25,44 @@ 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: | ||||||
|             pytest.skip("%r not found" % (version,)) |             pytest.skip("{!r} not found".format(version)) | ||||||
|         self.picklefile = picklefile |         self.picklefile = picklefile | ||||||
| 
 | 
 | ||||||
|     def dumps(self, obj): |     def dumps(self, obj): | ||||||
|         dumpfile = self.picklefile.dirpath("dump.py") |         dumpfile = self.picklefile.dirpath("dump.py") | ||||||
|         dumpfile.write( |         dumpfile.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pickle |                 import pickle | ||||||
|             f = open(%r, 'wb') |                 f = open({!r}, 'wb') | ||||||
|             s = pickle.dump(%r, f, protocol=2) |                 s = pickle.dump({!r}, f, protocol=2) | ||||||
|                 f.close() |                 f.close() | ||||||
|         """ |                 """.format( | ||||||
|                 % (str(self.picklefile), obj) |                     str(self.picklefile), obj | ||||||
|                 ) |                 ) | ||||||
|             ) |             ) | ||||||
|         py.process.cmdexec("%s %s" % (self.pythonpath, dumpfile)) |         ) | ||||||
|  |         py.process.cmdexec("{} {}".format(self.pythonpath, dumpfile)) | ||||||
| 
 | 
 | ||||||
|     def load_and_is_true(self, expression): |     def load_and_is_true(self, expression): | ||||||
|         loadfile = self.picklefile.dirpath("load.py") |         loadfile = self.picklefile.dirpath("load.py") | ||||||
|         loadfile.write( |         loadfile.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pickle |                 import pickle | ||||||
|             f = open(%r, 'rb') |                 f = open({!r}, 'rb') | ||||||
|                 obj = pickle.load(f) |                 obj = pickle.load(f) | ||||||
|                 f.close() |                 f.close() | ||||||
|             res = eval(%r) |                 res = eval({!r}) | ||||||
|                 if not res: |                 if not res: | ||||||
|                     raise SystemExit(1) |                     raise SystemExit(1) | ||||||
|         """ |                 """.format( | ||||||
|                 % (str(self.picklefile), expression) |                     str(self.picklefile), expression | ||||||
|  |                 ) | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         print(loadfile) |         print(loadfile) | ||||||
|         py.process.cmdexec("%s %s" % (self.pythonpath, loadfile)) |         py.process.cmdexec("{} {}".format(self.pythonpath, loadfile)) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @pytest.mark.parametrize("obj", [42, {}, {1: 3}]) | @pytest.mark.parametrize("obj", [42, {}, {1: 3}]) | ||||||
|  |  | ||||||
|  | @ -413,7 +413,7 @@ Running it results in some skips if we don't have all the python interpreters in | ||||||
|    . $ pytest -rs -q multipython.py |    . $ pytest -rs -q multipython.py | ||||||
|    ...sss...sssssssss...sss...                                          [100%] |    ...sss...sssssssss...sss...                                          [100%] | ||||||
|    ========================= short test summary info ========================== |    ========================= short test summary info ========================== | ||||||
|    SKIP [15] $REGENDOC_TMPDIR/CWD/multipython.py:28: 'python3.4' not found |    SKIP [15] $REGENDOC_TMPDIR/CWD/multipython.py:29: 'python3.4' not found | ||||||
|    12 passed, 15 skipped in 0.12 seconds |    12 passed, 15 skipped in 0.12 seconds | ||||||
| 
 | 
 | ||||||
| Indirect parametrization of optional implementations/imports | Indirect parametrization of optional implementations/imports | ||||||
|  |  | ||||||
|  | @ -100,9 +100,11 @@ Changing naming conventions | ||||||
| 
 | 
 | ||||||
| You can configure different naming conventions by setting | You can configure different naming conventions by setting | ||||||
| the :confval:`python_files`, :confval:`python_classes` and | the :confval:`python_files`, :confval:`python_classes` and | ||||||
| :confval:`python_functions` configuration options.  Example:: | :confval:`python_functions` configuration options. | ||||||
|  | Here is an example:: | ||||||
| 
 | 
 | ||||||
|     # content of pytest.ini |     # content of pytest.ini | ||||||
|  |     # Example 1: have pytest look for "check" instead of "test" | ||||||
|     # can also be defined in tox.ini or setup.cfg file, although the section |     # can also be defined in tox.ini or setup.cfg file, although the section | ||||||
|     # name in setup.cfg files should be "tool:pytest" |     # name in setup.cfg files should be "tool:pytest" | ||||||
|     [pytest] |     [pytest] | ||||||
|  | @ -121,7 +123,7 @@ that match ``*_check``.  For example, if we have:: | ||||||
|         def complex_check(self): |         def complex_check(self): | ||||||
|             pass |             pass | ||||||
| 
 | 
 | ||||||
| then the test collection looks like this:: | The test collection would look like this:: | ||||||
| 
 | 
 | ||||||
|     $ pytest --collect-only |     $ pytest --collect-only | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|  | @ -136,11 +138,19 @@ then the test collection looks like this:: | ||||||
| 
 | 
 | ||||||
|     ======================= no tests ran in 0.12 seconds ======================= |     ======================= no tests ran in 0.12 seconds ======================= | ||||||
| 
 | 
 | ||||||
|  | You can check for multiple glob patterns by adding a space between the patterns:: | ||||||
|  | 
 | ||||||
|  |     # Example 2: have pytest look for files with "test" and "example" | ||||||
|  |     # content of pytest.ini, tox.ini, or setup.cfg file (replace "pytest" | ||||||
|  |     # with "tool:pytest" for setup.cfg) | ||||||
|  |     [pytest] | ||||||
|  |     python_files = test_*.py example_*.py | ||||||
|  | 
 | ||||||
| .. note:: | .. note:: | ||||||
| 
 | 
 | ||||||
|    the ``python_functions`` and ``python_classes`` options has no effect |    the ``python_functions`` and ``python_classes`` options has no effect | ||||||
|    for ``unittest.TestCase`` test discovery because pytest delegates |    for ``unittest.TestCase`` test discovery because pytest delegates | ||||||
|    detection of test case methods to unittest code. |    discovery of test case methods to unittest code. | ||||||
| 
 | 
 | ||||||
| Interpreting cmdline arguments as Python packages | Interpreting cmdline arguments as Python packages | ||||||
| ----------------------------------------------------- | ----------------------------------------------------- | ||||||
|  |  | ||||||
|  | @ -423,7 +423,7 @@ get on the terminal - we are working on that):: | ||||||
|             name = "abc-123" |             name = "abc-123" | ||||||
|             module = imp.new_module(name) |             module = imp.new_module(name) | ||||||
|             code = _pytest._code.compile(src, name, "exec") |             code = _pytest._code.compile(src, name, "exec") | ||||||
|             py.builtin.exec_(code, module.__dict__) |             six.exec_(code, module.__dict__) | ||||||
|             sys.modules[name] = module |             sys.modules[name] = module | ||||||
|     >       module.foo() |     >       module.foo() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,27 @@ | ||||||
| Good Integration Practices | Good Integration Practices | ||||||
| ================================================= | ================================================= | ||||||
| 
 | 
 | ||||||
|  | Install package with pip | ||||||
|  | ------------------------------------------------- | ||||||
|  | 
 | ||||||
|  | For development, we recommend to use virtualenv_ environments and pip_ | ||||||
|  | for installing your application and any dependencies | ||||||
|  | as well as the ``pytest`` package itself. This ensures your code and | ||||||
|  | dependencies are isolated from the system Python installation. | ||||||
|  | 
 | ||||||
|  | First you need to place a ``setup.py`` file in the root of your package with the following minimum content:: | ||||||
|  | 
 | ||||||
|  |     from setuptools import setup, find_packages | ||||||
|  | 
 | ||||||
|  |     setup(name="PACKAGENAME", packages=find_packages()) | ||||||
|  | 
 | ||||||
|  | Where ``PACKAGENAME`` is the name of your package. You can then install your package in "editable" mode by running from the same directory:: | ||||||
|  | 
 | ||||||
|  |      pip install -e . | ||||||
|  | 
 | ||||||
|  | which lets you change your source code (both tests and application) and rerun tests at will. | ||||||
|  | This is similar to running ``python setup.py develop`` or ``conda develop`` in that it installs | ||||||
|  | your package using a symlink to your development code. | ||||||
| 
 | 
 | ||||||
| .. _`test discovery`: | .. _`test discovery`: | ||||||
| .. _`Python test discovery`: | .. _`Python test discovery`: | ||||||
|  | @ -177,19 +198,6 @@ Note that this layout also works in conjunction with the ``src`` layout mentione | ||||||
| tox | tox | ||||||
| ------ | ------ | ||||||
| 
 | 
 | ||||||
| For development, we recommend to use virtualenv_ environments and pip_ |  | ||||||
| for installing your application and any dependencies |  | ||||||
| as well as the ``pytest`` package itself. This ensures your code and |  | ||||||
| dependencies are isolated from the system Python installation. |  | ||||||
| 
 |  | ||||||
| You can then install your package in "editable" mode:: |  | ||||||
| 
 |  | ||||||
|      pip install -e . |  | ||||||
| 
 |  | ||||||
| which lets you change your source code (both tests and application) and rerun tests at will. |  | ||||||
| This is similar to running ``python setup.py develop`` or ``conda develop`` in that it installs |  | ||||||
| your package using a symlink to your development code. |  | ||||||
| 
 |  | ||||||
| Once you are done with your work and want to make sure that your actual | Once you are done with your work and want to make sure that your actual | ||||||
| package passes all tests you may want to look into `tox`_, the | package passes all tests you may want to look into `tox`_, the | ||||||
| virtualenv test automation tool and its `pytest support | virtualenv test automation tool and its `pytest support | ||||||
|  | @ -282,7 +290,7 @@ your own setuptools Test command for invoking pytest. | ||||||
|     setup( |     setup( | ||||||
|         # ..., |         # ..., | ||||||
|         tests_require=["pytest"], |         tests_require=["pytest"], | ||||||
|         cmdclass={"test": PyTest}, |         cmdclass={"pytest": PyTest}, | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| Now if you run:: | Now if you run:: | ||||||
|  |  | ||||||
|  | @ -460,7 +460,7 @@ To use it, include in your top-most ``conftest.py`` file:: | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| .. autoclass:: Testdir() | .. autoclass:: Testdir() | ||||||
|     :members: runpytest,runpytest_subprocess,runpytest_inprocess,makeconftest,makepyfile |     :members: | ||||||
| 
 | 
 | ||||||
| .. autoclass:: RunResult() | .. autoclass:: RunResult() | ||||||
|     :members: |     :members: | ||||||
|  | @ -1234,7 +1234,8 @@ passed multiple times. The expected format is ``name=value``. For example:: | ||||||
| .. confval:: python_classes | .. confval:: python_classes | ||||||
| 
 | 
 | ||||||
|    One or more name prefixes or glob-style patterns determining which classes |    One or more name prefixes or glob-style patterns determining which classes | ||||||
|    are considered for test collection. By default, pytest will consider any |    are considered for test collection. Search for multiple glob patterns by | ||||||
|  |    adding a space between patterns. By default, pytest will consider any | ||||||
|    class prefixed with ``Test`` as a test collection.  Here is an example of how |    class prefixed with ``Test`` as a test collection.  Here is an example of how | ||||||
|    to collect tests from classes that end in ``Suite``: |    to collect tests from classes that end in ``Suite``: | ||||||
| 
 | 
 | ||||||
|  | @ -1251,15 +1252,23 @@ passed multiple times. The expected format is ``name=value``. For example:: | ||||||
| .. confval:: python_files | .. confval:: python_files | ||||||
| 
 | 
 | ||||||
|    One or more Glob-style file patterns determining which python files |    One or more Glob-style file patterns determining which python files | ||||||
|    are considered as test modules. By default, pytest will consider |    are considered as test modules. Search for multiple glob patterns by | ||||||
|    any file matching with ``test_*.py`` and ``*_test.py`` globs as a test |    adding a space between patterns:: | ||||||
|    module. | 
 | ||||||
|  |    .. code-block:: ini | ||||||
|  | 
 | ||||||
|  |         [pytest] | ||||||
|  |         python_files = test_*.py check_*.py example_*.py | ||||||
|  | 
 | ||||||
|  |    By default, pytest will consider any file matching with ``test_*.py`` | ||||||
|  |    and ``*_test.py`` globs as a test module. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| .. confval:: python_functions | .. confval:: python_functions | ||||||
| 
 | 
 | ||||||
|    One or more name prefixes or glob-patterns determining which test functions |    One or more name prefixes or glob-patterns determining which test functions | ||||||
|    and methods are considered tests. By default, pytest will consider any |    and methods are considered tests. Search for multiple glob patterns by | ||||||
|  |    adding a space between patterns. By default, pytest will consider any | ||||||
|    function prefixed with ``test`` as a test.  Here is an example of how |    function prefixed with ``test`` as a test.  Here is an example of how | ||||||
|    to collect test functions and methods that end in ``_test``: |    to collect test functions and methods that end in ``_test``: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -136,12 +136,6 @@ You can use the ``skipif`` marker (as any other marker) on classes:: | ||||||
| If the condition is ``True``, this marker will produce a skip result for | If the condition is ``True``, this marker will produce a skip result for | ||||||
| each of the test methods of that class. | each of the test methods of that class. | ||||||
| 
 | 
 | ||||||
| .. warning:: |  | ||||||
| 
 |  | ||||||
|    The use of ``skipif`` on classes that use inheritance is strongly |  | ||||||
|    discouraged. `A Known bug <https://github.com/pytest-dev/pytest/issues/568>`_ |  | ||||||
|    in pytest's markers may cause unexpected behavior in super classes. |  | ||||||
| 
 |  | ||||||
| If you want to skip all test functions of a module, you may use | If you want to skip all test functions of a module, you may use | ||||||
| the ``pytestmark`` name on the global level: | the ``pytestmark`` name on the global level: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| # CHANGES: | # CHANGES: | ||||||
| # - some_str is replaced, trying to create unicode strings | # - some_str is replaced, trying to create unicode strings | ||||||
| # | # | ||||||
| from __future__ import absolute_import, division, print_function | from __future__ import absolute_import, division, print_function, unicode_literals | ||||||
| import types | import types | ||||||
| from six import text_type | from six import text_type | ||||||
| 
 | 
 | ||||||
|  | @ -51,17 +51,17 @@ def format_exception_only(etype, value): | ||||||
|         pass |         pass | ||||||
|     else: |     else: | ||||||
|         filename = filename or "<string>" |         filename = filename or "<string>" | ||||||
|         lines.append('  File "%s", line %d\n' % (filename, lineno)) |         lines.append('  File "{}", line {}\n'.format(filename, lineno)) | ||||||
|         if badline is not None: |         if badline is not None: | ||||||
|             if isinstance(badline, bytes):  # python 2 only |             if isinstance(badline, bytes):  # python 2 only | ||||||
|                 badline = badline.decode("utf-8", "replace") |                 badline = badline.decode("utf-8", "replace") | ||||||
|             lines.append(u"    %s\n" % badline.strip()) |             lines.append("    {}\n".format(badline.strip())) | ||||||
|             if offset is not None: |             if offset is not None: | ||||||
|                 caretspace = badline.rstrip("\n")[:offset].lstrip() |                 caretspace = badline.rstrip("\n")[:offset].lstrip() | ||||||
|                 # non-space whitespace (likes tabs) must be kept for alignment |                 # non-space whitespace (likes tabs) must be kept for alignment | ||||||
|                 caretspace = ((c.isspace() and c or " ") for c in caretspace) |                 caretspace = ((c.isspace() and c or " ") for c in caretspace) | ||||||
|                 # only three spaces to account for offset1 == pos 0 |                 # only three spaces to account for offset1 == pos 0 | ||||||
|                 lines.append("   %s^\n" % "".join(caretspace)) |                 lines.append("   {}^\n".format("".join(caretspace))) | ||||||
|         value = msg |         value = msg | ||||||
| 
 | 
 | ||||||
|     lines.append(_format_final_exc_line(stype, value)) |     lines.append(_format_final_exc_line(stype, value)) | ||||||
|  | @ -72,9 +72,9 @@ def _format_final_exc_line(etype, value): | ||||||
|     """Return a list of a single line -- normal case for format_exception_only""" |     """Return a list of a single line -- normal case for format_exception_only""" | ||||||
|     valuestr = _some_str(value) |     valuestr = _some_str(value) | ||||||
|     if value is None or not valuestr: |     if value is None or not valuestr: | ||||||
|         line = "%s\n" % etype |         line = "{}\n".format(etype) | ||||||
|     else: |     else: | ||||||
|         line = "%s: %s\n" % (etype, valuestr) |         line = "{}: {}\n".format(etype, valuestr) | ||||||
|     return line |     return line | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -83,7 +83,7 @@ def _some_str(value): | ||||||
|         return text_type(value) |         return text_type(value) | ||||||
|     except Exception: |     except Exception: | ||||||
|         try: |         try: | ||||||
|             return str(value) |             return bytes(value).decode("UTF-8", "replace") | ||||||
|         except Exception: |         except Exception: | ||||||
|             pass |             pass | ||||||
|     return "<unprintable %s object>" % type(value).__name__ |     return "<unprintable {} object>".format(type(value).__name__) | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ from weakref import ref | ||||||
| from _pytest.compat import _PY2, _PY3, PY35, safe_str | from _pytest.compat import _PY2, _PY3, PY35, safe_str | ||||||
| from six import text_type | from six import text_type | ||||||
| import py | import py | ||||||
|  | import six | ||||||
| 
 | 
 | ||||||
| builtin_repr = repr | builtin_repr = repr | ||||||
| 
 | 
 | ||||||
|  | @ -128,7 +129,7 @@ class Frame(object): | ||||||
|         """ |         """ | ||||||
|         f_locals = self.f_locals.copy() |         f_locals = self.f_locals.copy() | ||||||
|         f_locals.update(vars) |         f_locals.update(vars) | ||||||
|         py.builtin.exec_(code, self.f_globals, f_locals) |         six.exec_(code, self.f_globals, f_locals) | ||||||
| 
 | 
 | ||||||
|     def repr(self, object): |     def repr(self, object): | ||||||
|         """ return a 'safe' (non-recursive, one-line) string repr for 'object' |         """ return a 'safe' (non-recursive, one-line) string repr for 'object' | ||||||
|  |  | ||||||
|  | @ -223,7 +223,7 @@ class AssertionRewritingHook(object): | ||||||
|             mod.__loader__ = self |             mod.__loader__ = self | ||||||
|             # Normally, this attribute is 3.4+ |             # Normally, this attribute is 3.4+ | ||||||
|             mod.__spec__ = spec_from_file_location(name, co.co_filename, loader=self) |             mod.__spec__ = spec_from_file_location(name, co.co_filename, loader=self) | ||||||
|             py.builtin.exec_(co, mod.__dict__) |             six.exec_(co, mod.__dict__) | ||||||
|         except:  # noqa |         except:  # noqa | ||||||
|             if name in sys.modules: |             if name in sys.modules: | ||||||
|                 del sys.modules[name] |                 del sys.modules[name] | ||||||
|  | @ -402,12 +402,11 @@ def _saferepr(obj): | ||||||
|     JSON reprs. |     JSON reprs. | ||||||
| 
 | 
 | ||||||
|     """ |     """ | ||||||
|     repr = py.io.saferepr(obj) |     r = py.io.saferepr(obj) | ||||||
|     if isinstance(repr, six.text_type): |     if isinstance(r, six.text_type): | ||||||
|         t = six.text_type |         return r.replace(u"\n", u"\\n") | ||||||
|     else: |     else: | ||||||
|         t = six.binary_type |         return r.replace(b"\n", b"\\n") | ||||||
|     return repr.replace(t("\n"), t("\\n")) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| from _pytest.assertion.util import format_explanation as _format_explanation  # noqa | from _pytest.assertion.util import format_explanation as _format_explanation  # noqa | ||||||
|  | @ -446,10 +445,9 @@ def _should_repr_global_name(obj): | ||||||
| def _format_boolop(explanations, is_or): | def _format_boolop(explanations, is_or): | ||||||
|     explanation = "(" + (is_or and " or " or " and ").join(explanations) + ")" |     explanation = "(" + (is_or and " or " or " and ").join(explanations) + ")" | ||||||
|     if isinstance(explanation, six.text_type): |     if isinstance(explanation, six.text_type): | ||||||
|         t = six.text_type |         return explanation.replace(u"%", u"%%") | ||||||
|     else: |     else: | ||||||
|         t = six.binary_type |         return explanation.replace(b"%", b"%%") | ||||||
|     return explanation.replace(t("%"), t("%%")) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _call_reprcompare(ops, results, expls, each_obj): | def _call_reprcompare(ops, results, expls, each_obj): | ||||||
|  |  | ||||||
|  | @ -187,9 +187,9 @@ def _diff_text(left, right, verbose=False): | ||||||
|         r = r.replace(r"\r", "\r") |         r = r.replace(r"\r", "\r") | ||||||
|         return r |         return r | ||||||
| 
 | 
 | ||||||
|     if isinstance(left, six.binary_type): |     if isinstance(left, bytes): | ||||||
|         left = escape_for_readable_diff(left) |         left = escape_for_readable_diff(left) | ||||||
|     if isinstance(right, six.binary_type): |     if isinstance(right, bytes): | ||||||
|         right = escape_for_readable_diff(right) |         right = escape_for_readable_diff(right) | ||||||
|     if not verbose: |     if not verbose: | ||||||
|         i = 0  # just in case left or right has zero length |         i = 0  # just in case left or right has zero length | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ from tempfile import TemporaryFile | ||||||
| 
 | 
 | ||||||
| import six | import six | ||||||
| import pytest | import pytest | ||||||
| from _pytest.compat import CaptureIO, dummy_context_manager | from _pytest.compat import CaptureIO | ||||||
| 
 | 
 | ||||||
| patchsysdict = {0: "stdin", 1: "stdout", 2: "stderr"} | patchsysdict = {0: "stdin", 1: "stdout", 2: "stderr"} | ||||||
| 
 | 
 | ||||||
|  | @ -62,8 +62,9 @@ def pytest_load_initial_conftests(early_config, parser, args): | ||||||
|     # finally trigger conftest loading but while capturing (issue93) |     # finally trigger conftest loading but while capturing (issue93) | ||||||
|     capman.start_global_capturing() |     capman.start_global_capturing() | ||||||
|     outcome = yield |     outcome = yield | ||||||
|     out, err = capman.suspend_global_capture() |     capman.suspend_global_capture() | ||||||
|     if outcome.excinfo is not None: |     if outcome.excinfo is not None: | ||||||
|  |         out, err = capman.read_global_capture() | ||||||
|         sys.stdout.write(out) |         sys.stdout.write(out) | ||||||
|         sys.stderr.write(err) |         sys.stderr.write(err) | ||||||
| 
 | 
 | ||||||
|  | @ -96,6 +97,8 @@ class CaptureManager(object): | ||||||
|         else: |         else: | ||||||
|             raise ValueError("unknown capturing method: %r" % method) |             raise ValueError("unknown capturing method: %r" % method) | ||||||
| 
 | 
 | ||||||
|  |     # Global capturing control | ||||||
|  | 
 | ||||||
|     def start_global_capturing(self): |     def start_global_capturing(self): | ||||||
|         assert self._global_capturing is None |         assert self._global_capturing is None | ||||||
|         self._global_capturing = self._getcapture(self._method) |         self._global_capturing = self._getcapture(self._method) | ||||||
|  | @ -110,29 +113,15 @@ class CaptureManager(object): | ||||||
|     def resume_global_capture(self): |     def resume_global_capture(self): | ||||||
|         self._global_capturing.resume_capturing() |         self._global_capturing.resume_capturing() | ||||||
| 
 | 
 | ||||||
|     def suspend_global_capture(self, item=None, in_=False): |     def suspend_global_capture(self, in_=False): | ||||||
|         if item is not None: |  | ||||||
|             self.deactivate_fixture(item) |  | ||||||
|         cap = getattr(self, "_global_capturing", None) |         cap = getattr(self, "_global_capturing", None) | ||||||
|         if cap is not None: |         if cap is not None: | ||||||
|             try: |  | ||||||
|                 outerr = cap.readouterr() |  | ||||||
|             finally: |  | ||||||
|             cap.suspend_capturing(in_=in_) |             cap.suspend_capturing(in_=in_) | ||||||
|             return outerr |  | ||||||
| 
 | 
 | ||||||
|     @contextlib.contextmanager |     def read_global_capture(self): | ||||||
|     def global_and_fixture_disabled(self): |         return self._global_capturing.readouterr() | ||||||
|         """Context manager to temporarily disables global and current fixture capturing.""" | 
 | ||||||
|         # Need to undo local capsys-et-al if exists before disabling global capture |     # Fixture Control (its just forwarding, think about removing this later) | ||||||
|         fixture = getattr(self._current_item, "_capture_fixture", None) |  | ||||||
|         ctx_manager = fixture._suspend() if fixture else dummy_context_manager() |  | ||||||
|         with ctx_manager: |  | ||||||
|             self.suspend_global_capture(item=None, in_=False) |  | ||||||
|             try: |  | ||||||
|                 yield |  | ||||||
|             finally: |  | ||||||
|                 self.resume_global_capture() |  | ||||||
| 
 | 
 | ||||||
|     def activate_fixture(self, item): |     def activate_fixture(self, item): | ||||||
|         """If the current item is using ``capsys`` or ``capfd``, activate them so they take precedence over |         """If the current item is using ``capsys`` or ``capfd``, activate them so they take precedence over | ||||||
|  | @ -148,12 +137,53 @@ class CaptureManager(object): | ||||||
|         if fixture is not None: |         if fixture is not None: | ||||||
|             fixture.close() |             fixture.close() | ||||||
| 
 | 
 | ||||||
|  |     def suspend_fixture(self, item): | ||||||
|  |         fixture = getattr(item, "_capture_fixture", None) | ||||||
|  |         if fixture is not None: | ||||||
|  |             fixture._suspend() | ||||||
|  | 
 | ||||||
|  |     def resume_fixture(self, item): | ||||||
|  |         fixture = getattr(item, "_capture_fixture", None) | ||||||
|  |         if fixture is not None: | ||||||
|  |             fixture._resume() | ||||||
|  | 
 | ||||||
|  |     # Helper context managers | ||||||
|  | 
 | ||||||
|  |     @contextlib.contextmanager | ||||||
|  |     def global_and_fixture_disabled(self): | ||||||
|  |         """Context manager to temporarily disables global and current fixture capturing.""" | ||||||
|  |         # Need to undo local capsys-et-al if exists before disabling global capture | ||||||
|  |         self.suspend_fixture(self._current_item) | ||||||
|  |         self.suspend_global_capture(in_=False) | ||||||
|  |         try: | ||||||
|  |             yield | ||||||
|  |         finally: | ||||||
|  |             self.resume_global_capture() | ||||||
|  |             self.resume_fixture(self._current_item) | ||||||
|  | 
 | ||||||
|  |     @contextlib.contextmanager | ||||||
|  |     def item_capture(self, when, item): | ||||||
|  |         self.resume_global_capture() | ||||||
|  |         self.activate_fixture(item) | ||||||
|  |         try: | ||||||
|  |             yield | ||||||
|  |         finally: | ||||||
|  |             self.deactivate_fixture(item) | ||||||
|  |             self.suspend_global_capture(in_=False) | ||||||
|  | 
 | ||||||
|  |         out, err = self.read_global_capture() | ||||||
|  |         item.add_report_section(when, "stdout", out) | ||||||
|  |         item.add_report_section(when, "stderr", err) | ||||||
|  | 
 | ||||||
|  |     # Hooks | ||||||
|  | 
 | ||||||
|     @pytest.hookimpl(hookwrapper=True) |     @pytest.hookimpl(hookwrapper=True) | ||||||
|     def pytest_make_collect_report(self, collector): |     def pytest_make_collect_report(self, collector): | ||||||
|         if isinstance(collector, pytest.File): |         if isinstance(collector, pytest.File): | ||||||
|             self.resume_global_capture() |             self.resume_global_capture() | ||||||
|             outcome = yield |             outcome = yield | ||||||
|             out, err = self.suspend_global_capture() |             self.suspend_global_capture() | ||||||
|  |             out, err = self.read_global_capture() | ||||||
|             rep = outcome.get_result() |             rep = outcome.get_result() | ||||||
|             if out: |             if out: | ||||||
|                 rep.sections.append(("Captured stdout", out)) |                 rep.sections.append(("Captured stdout", out)) | ||||||
|  | @ -163,35 +193,25 @@ class CaptureManager(object): | ||||||
|             yield |             yield | ||||||
| 
 | 
 | ||||||
|     @pytest.hookimpl(hookwrapper=True) |     @pytest.hookimpl(hookwrapper=True) | ||||||
|     def pytest_runtest_setup(self, item): |     def pytest_runtest_protocol(self, item): | ||||||
|         self._current_item = item |         self._current_item = item | ||||||
|         self.resume_global_capture() |  | ||||||
|         # no need to activate a capture fixture because they activate themselves during creation; this |  | ||||||
|         # only makes sense when a fixture uses a capture fixture, otherwise the capture fixture will |  | ||||||
|         # be activated during pytest_runtest_call |  | ||||||
|         yield |         yield | ||||||
|         self.suspend_capture_item(item, "setup") |  | ||||||
|         self._current_item = None |         self._current_item = None | ||||||
| 
 | 
 | ||||||
|  |     @pytest.hookimpl(hookwrapper=True) | ||||||
|  |     def pytest_runtest_setup(self, item): | ||||||
|  |         with self.item_capture("setup", item): | ||||||
|  |             yield | ||||||
|  | 
 | ||||||
|     @pytest.hookimpl(hookwrapper=True) |     @pytest.hookimpl(hookwrapper=True) | ||||||
|     def pytest_runtest_call(self, item): |     def pytest_runtest_call(self, item): | ||||||
|         self._current_item = item |         with self.item_capture("call", item): | ||||||
|         self.resume_global_capture() |  | ||||||
|         # it is important to activate this fixture during the call phase so it overwrites the "global" |  | ||||||
|         # capture |  | ||||||
|         self.activate_fixture(item) |  | ||||||
|             yield |             yield | ||||||
|         self.suspend_capture_item(item, "call") |  | ||||||
|         self._current_item = None |  | ||||||
| 
 | 
 | ||||||
|     @pytest.hookimpl(hookwrapper=True) |     @pytest.hookimpl(hookwrapper=True) | ||||||
|     def pytest_runtest_teardown(self, item): |     def pytest_runtest_teardown(self, item): | ||||||
|         self._current_item = item |         with self.item_capture("teardown", item): | ||||||
|         self.resume_global_capture() |  | ||||||
|         self.activate_fixture(item) |  | ||||||
|             yield |             yield | ||||||
|         self.suspend_capture_item(item, "teardown") |  | ||||||
|         self._current_item = None |  | ||||||
| 
 | 
 | ||||||
|     @pytest.hookimpl(tryfirst=True) |     @pytest.hookimpl(tryfirst=True) | ||||||
|     def pytest_keyboard_interrupt(self, excinfo): |     def pytest_keyboard_interrupt(self, excinfo): | ||||||
|  | @ -201,11 +221,6 @@ class CaptureManager(object): | ||||||
|     def pytest_internalerror(self, excinfo): |     def pytest_internalerror(self, excinfo): | ||||||
|         self.stop_global_capturing() |         self.stop_global_capturing() | ||||||
| 
 | 
 | ||||||
|     def suspend_capture_item(self, item, when, in_=False): |  | ||||||
|         out, err = self.suspend_global_capture(item, in_=in_) |  | ||||||
|         item.add_report_section(when, "stdout", out) |  | ||||||
|         item.add_report_section(when, "stderr", err) |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| capture_fixtures = {"capfd", "capfdbinary", "capsys", "capsysbinary"} | capture_fixtures = {"capfd", "capfdbinary", "capsys", "capsysbinary"} | ||||||
| 
 | 
 | ||||||
|  | @ -309,36 +324,46 @@ class CaptureFixture(object): | ||||||
|     def __init__(self, captureclass, request): |     def __init__(self, captureclass, request): | ||||||
|         self.captureclass = captureclass |         self.captureclass = captureclass | ||||||
|         self.request = request |         self.request = request | ||||||
|  |         self._capture = None | ||||||
|  |         self._captured_out = self.captureclass.EMPTY_BUFFER | ||||||
|  |         self._captured_err = self.captureclass.EMPTY_BUFFER | ||||||
| 
 | 
 | ||||||
|     def _start(self): |     def _start(self): | ||||||
|  |         # Start if not started yet | ||||||
|  |         if getattr(self, "_capture", None) is None: | ||||||
|             self._capture = MultiCapture( |             self._capture = MultiCapture( | ||||||
|                 out=True, err=True, in_=False, Capture=self.captureclass |                 out=True, err=True, in_=False, Capture=self.captureclass | ||||||
|             ) |             ) | ||||||
|             self._capture.start_capturing() |             self._capture.start_capturing() | ||||||
| 
 | 
 | ||||||
|     def close(self): |     def close(self): | ||||||
|         cap = self.__dict__.pop("_capture", None) |         if self._capture is not None: | ||||||
|         if cap is not None: |             out, err = self._capture.pop_outerr_to_orig() | ||||||
|             self._outerr = cap.pop_outerr_to_orig() |             self._captured_out += out | ||||||
|             cap.stop_capturing() |             self._captured_err += err | ||||||
|  |             self._capture.stop_capturing() | ||||||
|  |             self._capture = None | ||||||
| 
 | 
 | ||||||
|     def readouterr(self): |     def readouterr(self): | ||||||
|         """Read and return the captured output so far, resetting the internal buffer. |         """Read and return the captured output so far, resetting the internal buffer. | ||||||
| 
 | 
 | ||||||
|         :return: captured content as a namedtuple with  ``out`` and ``err`` string attributes |         :return: captured content as a namedtuple with  ``out`` and ``err`` string attributes | ||||||
|         """ |         """ | ||||||
|         try: |         captured_out, captured_err = self._captured_out, self._captured_err | ||||||
|             return self._capture.readouterr() |         if self._capture is not None: | ||||||
|         except AttributeError: |             out, err = self._capture.readouterr() | ||||||
|             return self._outerr |             captured_out += out | ||||||
|  |             captured_err += err | ||||||
|  |         self._captured_out = self.captureclass.EMPTY_BUFFER | ||||||
|  |         self._captured_err = self.captureclass.EMPTY_BUFFER | ||||||
|  |         return CaptureResult(captured_out, captured_err) | ||||||
| 
 | 
 | ||||||
|     @contextlib.contextmanager |  | ||||||
|     def _suspend(self): |     def _suspend(self): | ||||||
|         """Suspends this fixture's own capturing temporarily.""" |         """Suspends this fixture's own capturing temporarily.""" | ||||||
|         self._capture.suspend_capturing() |         self._capture.suspend_capturing() | ||||||
|         try: | 
 | ||||||
|             yield |     def _resume(self): | ||||||
|         finally: |         """Resumes this fixture's own capturing temporarily.""" | ||||||
|         self._capture.resume_capturing() |         self._capture.resume_capturing() | ||||||
| 
 | 
 | ||||||
|     @contextlib.contextmanager |     @contextlib.contextmanager | ||||||
|  | @ -463,6 +488,7 @@ class MultiCapture(object): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NoCapture(object): | class NoCapture(object): | ||||||
|  |     EMPTY_BUFFER = None | ||||||
|     __init__ = start = done = suspend = resume = lambda *args: None |     __init__ = start = done = suspend = resume = lambda *args: None | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -472,6 +498,8 @@ class FDCaptureBinary(object): | ||||||
|     snap() produces `bytes` |     snap() produces `bytes` | ||||||
|     """ |     """ | ||||||
| 
 | 
 | ||||||
|  |     EMPTY_BUFFER = bytes() | ||||||
|  | 
 | ||||||
|     def __init__(self, targetfd, tmpfile=None): |     def __init__(self, targetfd, tmpfile=None): | ||||||
|         self.targetfd = targetfd |         self.targetfd = targetfd | ||||||
|         try: |         try: | ||||||
|  | @ -545,6 +573,8 @@ class FDCapture(FDCaptureBinary): | ||||||
|     snap() produces text |     snap() produces text | ||||||
|     """ |     """ | ||||||
| 
 | 
 | ||||||
|  |     EMPTY_BUFFER = str() | ||||||
|  | 
 | ||||||
|     def snap(self): |     def snap(self): | ||||||
|         res = FDCaptureBinary.snap(self) |         res = FDCaptureBinary.snap(self) | ||||||
|         enc = getattr(self.tmpfile, "encoding", None) |         enc = getattr(self.tmpfile, "encoding", None) | ||||||
|  | @ -554,6 +584,9 @@ class FDCapture(FDCaptureBinary): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SysCapture(object): | class SysCapture(object): | ||||||
|  | 
 | ||||||
|  |     EMPTY_BUFFER = str() | ||||||
|  | 
 | ||||||
|     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) | ||||||
|  | @ -591,6 +624,8 @@ class SysCapture(object): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SysCaptureBinary(SysCapture): | class SysCaptureBinary(SysCapture): | ||||||
|  |     EMPTY_BUFFER = bytes() | ||||||
|  | 
 | ||||||
|     def snap(self): |     def snap(self): | ||||||
|         res = self.tmpfile.buffer.getvalue() |         res = self.tmpfile.buffer.getvalue() | ||||||
|         self.tmpfile.seek(0) |         self.tmpfile.seek(0) | ||||||
|  |  | ||||||
|  | @ -2,6 +2,8 @@ import six | ||||||
| import warnings | import warnings | ||||||
| import argparse | import argparse | ||||||
| 
 | 
 | ||||||
|  | import py | ||||||
|  | 
 | ||||||
| FILE_OR_DIR = "file_or_dir" | FILE_OR_DIR = "file_or_dir" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -70,7 +72,8 @@ class Parser(object): | ||||||
| 
 | 
 | ||||||
|         self.optparser = self._getparser() |         self.optparser = self._getparser() | ||||||
|         try_argcomplete(self.optparser) |         try_argcomplete(self.optparser) | ||||||
|         return self.optparser.parse_args([str(x) for x in args], namespace=namespace) |         args = [str(x) if isinstance(x, py.path.local) else x for x in args] | ||||||
|  |         return self.optparser.parse_args(args, namespace=namespace) | ||||||
| 
 | 
 | ||||||
|     def _getparser(self): |     def _getparser(self): | ||||||
|         from _pytest._argcomplete import filescompleter |         from _pytest._argcomplete import filescompleter | ||||||
|  | @ -106,7 +109,7 @@ class Parser(object): | ||||||
|         the remaining arguments unknown at this point. |         the remaining arguments unknown at this point. | ||||||
|         """ |         """ | ||||||
|         optparser = self._getparser() |         optparser = self._getparser() | ||||||
|         args = [str(x) for x in args] |         args = [str(x) if isinstance(x, py.path.local) else x for x in args] | ||||||
|         return optparser.parse_known_args(args, namespace=namespace) |         return optparser.parse_known_args(args, namespace=namespace) | ||||||
| 
 | 
 | ||||||
|     def addini(self, name, help, type=None, default=None): |     def addini(self, name, help, type=None, default=None): | ||||||
|  |  | ||||||
|  | @ -102,7 +102,8 @@ 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: | ||||||
|             out, err = capman.suspend_global_capture(in_=True) |             capman.suspend_global_capture(in_=True) | ||||||
|  |             out, err = capman.read_global_capture() | ||||||
|             sys.stdout.write(out) |             sys.stdout.write(out) | ||||||
|             sys.stdout.write(err) |             sys.stdout.write(err) | ||||||
|         _enter_pdb(node, call.excinfo, report) |         _enter_pdb(node, call.excinfo, report) | ||||||
|  |  | ||||||
|  | @ -2,7 +2,6 @@ from __future__ import absolute_import, division, print_function | ||||||
| 
 | 
 | ||||||
| import functools | import functools | ||||||
| import inspect | import inspect | ||||||
| import os |  | ||||||
| import sys | import sys | ||||||
| import warnings | import warnings | ||||||
| from collections import OrderedDict, deque, defaultdict | from collections import OrderedDict, deque, defaultdict | ||||||
|  | @ -93,7 +92,7 @@ def get_scope_package(node, fixturedef): | ||||||
| 
 | 
 | ||||||
|     cls = pytest.Package |     cls = pytest.Package | ||||||
|     current = node |     current = node | ||||||
|     fixture_package_name = os.path.join(fixturedef.baseid, "__init__.py") |     fixture_package_name = "%s/%s" % (fixturedef.baseid, "__init__.py") | ||||||
|     while current and ( |     while current and ( | ||||||
|         type(current) is not cls or fixture_package_name != current.nodeid |         type(current) is not cls or fixture_package_name != current.nodeid | ||||||
|     ): |     ): | ||||||
|  | @ -858,7 +857,7 @@ class FixtureDef(object): | ||||||
|             if exceptions: |             if exceptions: | ||||||
|                 e = exceptions[0] |                 e = exceptions[0] | ||||||
|                 del exceptions  # ensure we don't keep all frames alive because of the traceback |                 del exceptions  # ensure we don't keep all frames alive because of the traceback | ||||||
|                 py.builtin._reraise(*e) |                 six.reraise(*e) | ||||||
| 
 | 
 | ||||||
|         finally: |         finally: | ||||||
|             hook = self._fixturemanager.session.gethookproxy(request.node.fspath) |             hook = self._fixturemanager.session.gethookproxy(request.node.fspath) | ||||||
|  | @ -885,7 +884,7 @@ class FixtureDef(object): | ||||||
|             result, cache_key, err = cached_result |             result, cache_key, err = cached_result | ||||||
|             if my_cache_key == cache_key: |             if my_cache_key == cache_key: | ||||||
|                 if err is not None: |                 if err is not None: | ||||||
|                     py.builtin._reraise(*err) |                     six.reraise(*err) | ||||||
|                 else: |                 else: | ||||||
|                     return result |                     return result | ||||||
|             # we have a previous but differently parametrized fixture instance |             # we have a previous but differently parametrized fixture instance | ||||||
|  |  | ||||||
|  | @ -625,11 +625,12 @@ class Session(nodes.FSCollector): | ||||||
|                     resultnodes.append(node) |                     resultnodes.append(node) | ||||||
|                 continue |                 continue | ||||||
|             assert isinstance(node, nodes.Collector) |             assert isinstance(node, nodes.Collector) | ||||||
|             if node.nodeid in self._node_cache: |             key = (type(node), node.nodeid) | ||||||
|                 rep = self._node_cache[node.nodeid] |             if key in self._node_cache: | ||||||
|  |                 rep = self._node_cache[key] | ||||||
|             else: |             else: | ||||||
|                 rep = collect_one_node(node) |                 rep = collect_one_node(node) | ||||||
|                 self._node_cache[node.nodeid] = rep |                 self._node_cache[key] = rep | ||||||
|             if rep.passed: |             if rep.passed: | ||||||
|                 has_matched = False |                 has_matched = False | ||||||
|                 for x in rep.result: |                 for x in rep.result: | ||||||
|  |  | ||||||
|  | @ -3,7 +3,6 @@ exception classes and constants handling test outcomes | ||||||
| as well as functions creating them | as well as functions creating them | ||||||
| """ | """ | ||||||
| from __future__ import absolute_import, division, print_function | from __future__ import absolute_import, division, print_function | ||||||
| import py |  | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -21,7 +20,7 @@ class OutcomeException(BaseException): | ||||||
|         if self.msg: |         if self.msg: | ||||||
|             val = self.msg |             val = self.msg | ||||||
|             if isinstance(val, bytes): |             if isinstance(val, bytes): | ||||||
|                 val = py._builtin._totext(val, errors="replace") |                 val = val.decode("UTF-8", errors="replace") | ||||||
|             return val |             return val | ||||||
|         return "<%s instance>" % (self.__class__.__name__,) |         return "<%s instance>" % (self.__class__.__name__,) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,6 +22,7 @@ import pytest | ||||||
| from _pytest.main import Session, EXIT_OK | from _pytest.main import Session, EXIT_OK | ||||||
| from _pytest.assertion.rewrite import AssertionRewritingHook | from _pytest.assertion.rewrite import AssertionRewritingHook | ||||||
| from _pytest.compat import Path | from _pytest.compat import Path | ||||||
|  | from _pytest.compat import safe_str | ||||||
| 
 | 
 | ||||||
| IGNORE_PAM = [  # filenames added when obtaining details about the current user | IGNORE_PAM = [  # filenames added when obtaining details about the current user | ||||||
|     u"/var/lib/sss/mc/passwd" |     u"/var/lib/sss/mc/passwd" | ||||||
|  | @ -34,7 +35,7 @@ def pytest_addoption(parser): | ||||||
|         action="store_true", |         action="store_true", | ||||||
|         dest="lsof", |         dest="lsof", | ||||||
|         default=False, |         default=False, | ||||||
|         help=("run FD checks if lsof is available"), |         help="run FD checks if lsof is available", | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     parser.addoption( |     parser.addoption( | ||||||
|  | @ -273,7 +274,7 @@ class HookRecorder(object): | ||||||
|                 del self.calls[i] |                 del self.calls[i] | ||||||
|                 return call |                 return call | ||||||
|         lines = ["could not find call %r, in:" % (name,)] |         lines = ["could not find call %r, in:" % (name,)] | ||||||
|         lines.extend(["  %s" % str(x) for x in self.calls]) |         lines.extend(["  %s" % x for x in self.calls]) | ||||||
|         pytest.fail("\n".join(lines)) |         pytest.fail("\n".join(lines)) | ||||||
| 
 | 
 | ||||||
|     def getcall(self, name): |     def getcall(self, name): | ||||||
|  | @ -560,18 +561,22 @@ class Testdir(object): | ||||||
|         return ret |         return ret | ||||||
| 
 | 
 | ||||||
|     def makefile(self, ext, *args, **kwargs): |     def makefile(self, ext, *args, **kwargs): | ||||||
|         """Create a new file in the testdir. |         r"""Create new file(s) in the testdir. | ||||||
| 
 | 
 | ||||||
|         ext: The extension the file should use, including the dot, e.g. `.py`. |         :param str ext: The extension the file(s) should use, including the dot, e.g. `.py`. | ||||||
| 
 |         :param list[str] args: All args will be treated as strings and joined using newlines. | ||||||
|         args: All args will be treated as strings and joined using newlines. |  | ||||||
|            The result will be written as contents to the file.  The name of the |            The result will be written as contents to the file.  The name of the | ||||||
|            file will be based on the test function requesting this fixture. |            file will be based on the test function requesting this fixture. | ||||||
|            E.g. "testdir.makefile('.txt', 'line1', 'line2')" |         :param kwargs: Each keyword is the name of a file, while the value of it will | ||||||
| 
 |  | ||||||
|         kwargs: Each keyword is the name of a file, while the value of it will |  | ||||||
|            be written as contents of the file. |            be written as contents of the file. | ||||||
|            E.g. "testdir.makefile('.ini', pytest='[pytest]\naddopts=-rs\n')" | 
 | ||||||
|  |         Examples: | ||||||
|  | 
 | ||||||
|  |         .. code-block:: python | ||||||
|  | 
 | ||||||
|  |             testdir.makefile(".txt", "line1", "line2") | ||||||
|  | 
 | ||||||
|  |             testdir.makefile(".ini", pytest="[pytest]\naddopts=-rs\n") | ||||||
| 
 | 
 | ||||||
|         """ |         """ | ||||||
|         return self._makefile(ext, args, kwargs) |         return self._makefile(ext, args, kwargs) | ||||||
|  | @ -677,7 +682,9 @@ class Testdir(object): | ||||||
|             example_path.copy(result) |             example_path.copy(result) | ||||||
|             return result |             return result | ||||||
|         else: |         else: | ||||||
|             raise LookupError("example is not found as a file or directory") |             raise LookupError( | ||||||
|  |                 'example "{}" is not found as a file or directory'.format(example_path) | ||||||
|  |             ) | ||||||
| 
 | 
 | ||||||
|     Session = Session |     Session = Session | ||||||
| 
 | 
 | ||||||
|  | @ -891,14 +898,12 @@ class Testdir(object): | ||||||
|         return self._runpytest_method(*args, **kwargs) |         return self._runpytest_method(*args, **kwargs) | ||||||
| 
 | 
 | ||||||
|     def _ensure_basetemp(self, args): |     def _ensure_basetemp(self, args): | ||||||
|         args = [str(x) for x in args] |         args = list(args) | ||||||
|         for x in args: |         for x in args: | ||||||
|             if str(x).startswith("--basetemp"): |             if safe_str(x).startswith("--basetemp"): | ||||||
|                 # print("basedtemp exists: %s" %(args,)) |  | ||||||
|                 break |                 break | ||||||
|         else: |         else: | ||||||
|             args.append("--basetemp=%s" % self.tmpdir.dirpath("basetemp")) |             args.append("--basetemp=%s" % self.tmpdir.dirpath("basetemp")) | ||||||
|             # print("added basetemp: %s" %(args,)) |  | ||||||
|         return args |         return args | ||||||
| 
 | 
 | ||||||
|     def parseconfig(self, *args): |     def parseconfig(self, *args): | ||||||
|  | @ -1024,7 +1029,7 @@ class Testdir(object): | ||||||
|         """ |         """ | ||||||
|         env = os.environ.copy() |         env = os.environ.copy() | ||||||
|         env["PYTHONPATH"] = os.pathsep.join( |         env["PYTHONPATH"] = os.pathsep.join( | ||||||
|             filter(None, [str(os.getcwd()), env.get("PYTHONPATH", "")]) |             filter(None, [os.getcwd(), env.get("PYTHONPATH", "")]) | ||||||
|         ) |         ) | ||||||
|         kw["env"] = env |         kw["env"] = env | ||||||
| 
 | 
 | ||||||
|  | @ -1043,14 +1048,13 @@ class Testdir(object): | ||||||
|         Returns a :py:class:`RunResult`. |         Returns a :py:class:`RunResult`. | ||||||
| 
 | 
 | ||||||
|         """ |         """ | ||||||
|         return self._run(*cmdargs) |         cmdargs = [ | ||||||
| 
 |             str(arg) if isinstance(arg, py.path.local) else arg for arg in cmdargs | ||||||
|     def _run(self, *cmdargs): |         ] | ||||||
|         cmdargs = [str(x) for x in cmdargs] |  | ||||||
|         p1 = self.tmpdir.join("stdout") |         p1 = self.tmpdir.join("stdout") | ||||||
|         p2 = self.tmpdir.join("stderr") |         p2 = self.tmpdir.join("stderr") | ||||||
|         print("running:", " ".join(cmdargs)) |         print("running:", *cmdargs) | ||||||
|         print("     in:", str(py.path.local())) |         print("     in:", py.path.local()) | ||||||
|         f1 = codecs.open(str(p1), "w", encoding="utf8") |         f1 = codecs.open(str(p1), "w", encoding="utf8") | ||||||
|         f2 = codecs.open(str(p2), "w", encoding="utf8") |         f2 = codecs.open(str(p2), "w", encoding="utf8") | ||||||
|         try: |         try: | ||||||
|  | @ -1082,7 +1086,7 @@ class Testdir(object): | ||||||
|             print("couldn't print to %s because of encoding" % (fp,)) |             print("couldn't print to %s because of encoding" % (fp,)) | ||||||
| 
 | 
 | ||||||
|     def _getpytestargs(self): |     def _getpytestargs(self): | ||||||
|         return (sys.executable, "-mpytest") |         return sys.executable, "-mpytest" | ||||||
| 
 | 
 | ||||||
|     def runpython(self, script): |     def runpython(self, script): | ||||||
|         """Run a python script using sys.executable as interpreter. |         """Run a python script using sys.executable as interpreter. | ||||||
|  |  | ||||||
|  | @ -201,15 +201,19 @@ def pytest_collect_file(path, parent): | ||||||
|     ext = path.ext |     ext = path.ext | ||||||
|     if ext == ".py": |     if ext == ".py": | ||||||
|         if not parent.session.isinitpath(path): |         if not parent.session.isinitpath(path): | ||||||
|             for pat in parent.config.getini("python_files") + ["__init__.py"]: |             if not path_matches_patterns( | ||||||
|                 if path.fnmatch(pat): |                 path, parent.config.getini("python_files") + ["__init__.py"] | ||||||
|                     break |             ): | ||||||
|             else: |  | ||||||
|                 return |                 return | ||||||
|         ihook = parent.session.gethookproxy(path) |         ihook = parent.session.gethookproxy(path) | ||||||
|         return ihook.pytest_pycollect_makemodule(path=path, parent=parent) |         return ihook.pytest_pycollect_makemodule(path=path, parent=parent) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | def path_matches_patterns(path, patterns): | ||||||
|  |     """Returns True if the given py.path.local matches one of the patterns in the list of globs given""" | ||||||
|  |     return any(path.fnmatch(pattern) for pattern in patterns) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def pytest_pycollect_makemodule(path, parent): | def pytest_pycollect_makemodule(path, parent): | ||||||
|     if path.basename == "__init__.py": |     if path.basename == "__init__.py": | ||||||
|         return Package(path, parent) |         return Package(path, parent) | ||||||
|  | @ -590,17 +594,33 @@ class Package(Module): | ||||||
|                 self.session.config.pluginmanager._duplicatepaths.remove(path) |                 self.session.config.pluginmanager._duplicatepaths.remove(path) | ||||||
| 
 | 
 | ||||||
|         this_path = self.fspath.dirpath() |         this_path = self.fspath.dirpath() | ||||||
|         pkg_prefix = None |         init_module = this_path.join("__init__.py") | ||||||
|  |         if init_module.check(file=1) and path_matches_patterns( | ||||||
|  |             init_module, self.config.getini("python_files") | ||||||
|  |         ): | ||||||
|  |             yield Module(init_module, self) | ||||||
|  |         pkg_prefixes = set() | ||||||
|         for path in this_path.visit(rec=self._recurse, bf=True, sort=True): |         for path in this_path.visit(rec=self._recurse, bf=True, sort=True): | ||||||
|             # we will visit our own __init__.py file, in which case we skip it |             # we will visit our own __init__.py file, in which case we skip it | ||||||
|  |             skip = False | ||||||
|             if path.basename == "__init__.py" and path.dirpath() == this_path: |             if path.basename == "__init__.py" and path.dirpath() == this_path: | ||||||
|                 continue |                 continue | ||||||
|             if pkg_prefix and pkg_prefix in path.parts(): | 
 | ||||||
|  |             for pkg_prefix in pkg_prefixes: | ||||||
|  |                 if ( | ||||||
|  |                     pkg_prefix in path.parts() | ||||||
|  |                     and pkg_prefix.join("__init__.py") != path | ||||||
|  |                 ): | ||||||
|  |                     skip = True | ||||||
|  | 
 | ||||||
|  |             if skip: | ||||||
|                 continue |                 continue | ||||||
|  | 
 | ||||||
|  |             if path.isdir() and path.join("__init__.py").check(file=1): | ||||||
|  |                 pkg_prefixes.add(path) | ||||||
|  | 
 | ||||||
|             for x in self._collectfile(path): |             for x in self._collectfile(path): | ||||||
|                 yield x |                 yield x | ||||||
|                 if isinstance(x, Package): |  | ||||||
|                     pkg_prefix = path.dirpath() |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _get_xunit_setup_teardown(holder, attr_name, param_obj=None): | def _get_xunit_setup_teardown(holder, attr_name, param_obj=None): | ||||||
|  | @ -741,7 +761,7 @@ class FunctionMixin(PyobjMixin): | ||||||
|     def _repr_failure_py(self, excinfo, style="long"): |     def _repr_failure_py(self, excinfo, style="long"): | ||||||
|         if excinfo.errisinstance(fail.Exception): |         if excinfo.errisinstance(fail.Exception): | ||||||
|             if not excinfo.value.pytrace: |             if not excinfo.value.pytrace: | ||||||
|                 return py._builtin._totext(excinfo.value) |                 return six.text_type(excinfo.value) | ||||||
|         return super(FunctionMixin, self)._repr_failure_py(excinfo, style=style) |         return super(FunctionMixin, self)._repr_failure_py(excinfo, style=style) | ||||||
| 
 | 
 | ||||||
|     def repr_failure(self, excinfo, outerr=None): |     def repr_failure(self, excinfo, outerr=None): | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ import sys | ||||||
| from numbers import Number | from numbers import Number | ||||||
| from decimal import Decimal | from decimal import Decimal | ||||||
| 
 | 
 | ||||||
| import py | import six | ||||||
| from six.moves import zip, filterfalse | from six.moves import zip, filterfalse | ||||||
| from more_itertools.more import always_iterable | from more_itertools.more import always_iterable | ||||||
| 
 | 
 | ||||||
|  | @ -680,8 +680,8 @@ def raises(expected_exception, *args, **kwargs): | ||||||
|         # print "raises frame scope: %r" % frame.f_locals |         # print "raises frame scope: %r" % frame.f_locals | ||||||
|         try: |         try: | ||||||
|             code = _pytest._code.Source(code).compile() |             code = _pytest._code.Source(code).compile() | ||||||
|             py.builtin.exec_(code, frame.f_globals, loc) |             six.exec_(code, frame.f_globals, loc) | ||||||
|             # XXX didn'T mean f_globals == f_locals something special? |             # XXX didn't mean f_globals == f_locals something special? | ||||||
|             #     this is destroyed here ... |             #     this is destroyed here ... | ||||||
|         except expected_exception: |         except expected_exception: | ||||||
|             return _pytest._code.ExceptionInfo() |             return _pytest._code.ExceptionInfo() | ||||||
|  |  | ||||||
|  | @ -4,11 +4,11 @@ from __future__ import absolute_import, division, print_function | ||||||
| import inspect | import inspect | ||||||
| 
 | 
 | ||||||
| import _pytest._code | import _pytest._code | ||||||
| import py | import re | ||||||
| import sys | import sys | ||||||
| import warnings | import warnings | ||||||
| 
 | 
 | ||||||
| import re | import six | ||||||
| 
 | 
 | ||||||
| from _pytest.fixtures import yield_fixture | from _pytest.fixtures import yield_fixture | ||||||
| from _pytest.outcomes import fail | from _pytest.outcomes import fail | ||||||
|  | @ -130,7 +130,7 @@ def warns(expected_warning, *args, **kwargs): | ||||||
| 
 | 
 | ||||||
|         with WarningsChecker(expected_warning, match_expr=match_expr): |         with WarningsChecker(expected_warning, match_expr=match_expr): | ||||||
|             code = _pytest._code.Source(code).compile() |             code = _pytest._code.Source(code).compile() | ||||||
|             py.builtin.exec_(code, frame.f_globals, loc) |             six.exec_(code, frame.f_globals, loc) | ||||||
|     else: |     else: | ||||||
|         func = args[0] |         func = args[0] | ||||||
|         with WarningsChecker(expected_warning, match_expr=match_expr): |         with WarningsChecker(expected_warning, match_expr=match_expr): | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ import os | ||||||
| import sys | import sys | ||||||
| from time import time | from time import time | ||||||
| 
 | 
 | ||||||
| import py | import six | ||||||
| from _pytest._code.code import ExceptionInfo | from _pytest._code.code import ExceptionInfo | ||||||
| from _pytest.outcomes import skip, Skipped, TEST_OUTCOME | from _pytest.outcomes import skip, Skipped, TEST_OUTCOME | ||||||
| 
 | 
 | ||||||
|  | @ -317,7 +317,7 @@ class SetupState(object): | ||||||
|                 if exc is None: |                 if exc is None: | ||||||
|                     exc = sys.exc_info() |                     exc = sys.exc_info() | ||||||
|         if exc: |         if exc: | ||||||
|             py.builtin._reraise(*exc) |             six.reraise(*exc) | ||||||
| 
 | 
 | ||||||
|     def _teardown_with_finalization(self, colitem): |     def _teardown_with_finalization(self, colitem): | ||||||
|         self._callfinalizers(colitem) |         self._callfinalizers(colitem) | ||||||
|  | @ -352,7 +352,7 @@ class SetupState(object): | ||||||
|                 if exc is None: |                 if exc is None: | ||||||
|                     exc = sys.exc_info() |                     exc = sys.exc_info() | ||||||
|         if exc: |         if exc: | ||||||
|             py.builtin._reraise(*exc) |             six.reraise(*exc) | ||||||
| 
 | 
 | ||||||
|     def prepare(self, colitem): |     def prepare(self, colitem): | ||||||
|         """ setup objects along the collector chain to the test-method |         """ setup objects along the collector chain to the test-method | ||||||
|  | @ -363,7 +363,7 @@ class SetupState(object): | ||||||
|         # check if the last collection node has raised an error |         # check if the last collection node has raised an error | ||||||
|         for col in self.stack: |         for col in self.stack: | ||||||
|             if hasattr(col, "_prepare_exc"): |             if hasattr(col, "_prepare_exc"): | ||||||
|                 py.builtin._reraise(*col._prepare_exc) |                 six.reraise(*col._prepare_exc) | ||||||
|         for col in needed_collectors[len(self.stack) :]: |         for col in needed_collectors[len(self.stack) :]: | ||||||
|             self.stack.append(col) |             self.stack.append(col) | ||||||
|             try: |             try: | ||||||
|  |  | ||||||
|  | @ -51,7 +51,8 @@ def _show_fixture_action(fixturedef, msg): | ||||||
|     config = fixturedef._fixturemanager.config |     config = fixturedef._fixturemanager.config | ||||||
|     capman = config.pluginmanager.getplugin("capturemanager") |     capman = config.pluginmanager.getplugin("capturemanager") | ||||||
|     if capman: |     if capman: | ||||||
|         out, err = capman.suspend_global_capture() |         capman.suspend_global_capture() | ||||||
|  |         out, err = capman.read_global_capture() | ||||||
| 
 | 
 | ||||||
|     tw = config.get_terminal_writer() |     tw = config.get_terminal_writer() | ||||||
|     tw.line() |     tw.line() | ||||||
|  |  | ||||||
|  | @ -706,7 +706,12 @@ class TerminalReporter(object): | ||||||
|                     self._outrep_summary(rep) |                     self._outrep_summary(rep) | ||||||
| 
 | 
 | ||||||
|     def print_teardown_sections(self, rep): |     def print_teardown_sections(self, rep): | ||||||
|  |         showcapture = self.config.option.showcapture | ||||||
|  |         if showcapture == "no": | ||||||
|  |             return | ||||||
|         for secname, content in rep.sections: |         for secname, content in rep.sections: | ||||||
|  |             if showcapture != "all" and showcapture not in secname: | ||||||
|  |                 continue | ||||||
|             if "teardown" in secname: |             if "teardown" in secname: | ||||||
|                 self._tw.sep("-", secname) |                 self._tw.sep("-", secname) | ||||||
|                 if content[-1:] == "\n": |                 if content[-1:] == "\n": | ||||||
|  |  | ||||||
|  | @ -2,11 +2,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 | ||||||
|  | import textwrap | ||||||
| import types | import types | ||||||
| 
 | 
 | ||||||
| import six | import six | ||||||
| 
 | 
 | ||||||
| import _pytest._code |  | ||||||
| import py | import py | ||||||
| import pytest | import pytest | ||||||
| from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR | from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR | ||||||
|  | @ -131,7 +131,7 @@ class TestGeneralUsage(object): | ||||||
|         p2 = testdir.makefile(".pyc", "123") |         p2 = testdir.makefile(".pyc", "123") | ||||||
|         result = testdir.runpytest(p1, p2) |         result = testdir.runpytest(p1, p2) | ||||||
|         assert result.ret |         assert result.ret | ||||||
|         result.stderr.fnmatch_lines(["*ERROR: not found:*%s" % (p2.basename,)]) |         result.stderr.fnmatch_lines(["*ERROR: not found:*{}".format(p2.basename)]) | ||||||
| 
 | 
 | ||||||
|     def test_issue486_better_reporting_on_conftest_load_failure(self, testdir): |     def test_issue486_better_reporting_on_conftest_load_failure(self, testdir): | ||||||
|         testdir.makepyfile("") |         testdir.makepyfile("") | ||||||
|  | @ -201,8 +201,8 @@ class TestGeneralUsage(object): | ||||||
|         testdir.tmpdir.join("py").mksymlinkto(py._pydir) |         testdir.tmpdir.join("py").mksymlinkto(py._pydir) | ||||||
|         p = testdir.tmpdir.join("main.py") |         p = testdir.tmpdir.join("main.py") | ||||||
|         p.write( |         p.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import sys, os |                 import sys, os | ||||||
|                 sys.path.insert(0, '') |                 sys.path.insert(0, '') | ||||||
|                 import py |                 import py | ||||||
|  | @ -453,7 +453,7 @@ class TestInvocationVariants(object): | ||||||
|     @pytest.mark.xfail("sys.platform.startswith('java')") |     @pytest.mark.xfail("sys.platform.startswith('java')") | ||||||
|     def test_pydoc(self, testdir): |     def test_pydoc(self, testdir): | ||||||
|         for name in ("py.test", "pytest"): |         for name in ("py.test", "pytest"): | ||||||
|             result = testdir.runpython_c("import %s;help(%s)" % (name, name)) |             result = testdir.runpython_c("import {};help({})".format(name, name)) | ||||||
|             assert result.ret == 0 |             assert result.ret == 0 | ||||||
|             s = result.stdout.str() |             s = result.stdout.str() | ||||||
|             assert "MarkGenerator" in s |             assert "MarkGenerator" in s | ||||||
|  | @ -660,6 +660,16 @@ class TestInvocationVariants(object): | ||||||
|             ["*test_world.py::test_other*PASSED*", "*1 passed*"] |             ["*test_world.py::test_other*PASSED*", "*1 passed*"] | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|  |     def test_invoke_test_and_doctestmodules(self, testdir): | ||||||
|  |         p = testdir.makepyfile( | ||||||
|  |             """ | ||||||
|  |             def test(): | ||||||
|  |                 pass | ||||||
|  |         """ | ||||||
|  |         ) | ||||||
|  |         result = testdir.runpytest(str(p) + "::test", "--doctest-modules") | ||||||
|  |         result.stdout.fnmatch_lines(["*1 passed*"]) | ||||||
|  | 
 | ||||||
|     @pytest.mark.skipif(not hasattr(os, "symlink"), reason="requires symlinks") |     @pytest.mark.skipif(not hasattr(os, "symlink"), reason="requires symlinks") | ||||||
|     def test_cmdline_python_package_symlink(self, testdir, monkeypatch): |     def test_cmdline_python_package_symlink(self, testdir, monkeypatch): | ||||||
|         """ |         """ | ||||||
|  | @ -826,7 +836,7 @@ class TestDurations(object): | ||||||
|                     if ("test_%s" % x) in line and y in line: |                     if ("test_%s" % x) in line and y in line: | ||||||
|                         break |                         break | ||||||
|                 else: |                 else: | ||||||
|                     raise AssertionError("not found %s %s" % (x, y)) |                     raise AssertionError("not found {} {}".format(x, y)) | ||||||
| 
 | 
 | ||||||
|     def test_with_deselected(self, testdir): |     def test_with_deselected(self, testdir): | ||||||
|         testdir.makepyfile(self.source) |         testdir.makepyfile(self.source) | ||||||
|  |  | ||||||
|  | @ -3,8 +3,8 @@ from __future__ import absolute_import, division, print_function | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
| import _pytest._code | import _pytest._code | ||||||
| import py |  | ||||||
| import pytest | import pytest | ||||||
|  | import mock | ||||||
| from test_excinfo import TWMock | from test_excinfo import TWMock | ||||||
| from six import text_type | from six import text_type | ||||||
| 
 | 
 | ||||||
|  | @ -68,12 +68,8 @@ def test_getstatement_empty_fullsource(): | ||||||
| 
 | 
 | ||||||
|     f = func() |     f = func() | ||||||
|     f = _pytest._code.Frame(f) |     f = _pytest._code.Frame(f) | ||||||
|     prop = f.code.__class__.fullsource |     with mock.patch.object(f.code.__class__, "fullsource", None): | ||||||
|     try: |         assert f.statement == "" | ||||||
|         f.code.__class__.fullsource = None |  | ||||||
|         assert f.statement == _pytest._code.Source("") |  | ||||||
|     finally: |  | ||||||
|         f.code.__class__.fullsource = prop |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_code_from_func(): | def test_code_from_func(): | ||||||
|  | @ -83,7 +79,7 @@ def test_code_from_func(): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_unicode_handling(): | def test_unicode_handling(): | ||||||
|     value = py.builtin._totext("\xc4\x85\xc4\x87\n", "utf-8").encode("utf8") |     value = u"ąć".encode("UTF-8") | ||||||
| 
 | 
 | ||||||
|     def f(): |     def f(): | ||||||
|         raise Exception(value) |         raise Exception(value) | ||||||
|  | @ -96,7 +92,7 @@ def test_unicode_handling(): | ||||||
| 
 | 
 | ||||||
| @pytest.mark.skipif(sys.version_info[0] >= 3, reason="python 2 only issue") | @pytest.mark.skipif(sys.version_info[0] >= 3, reason="python 2 only issue") | ||||||
| def test_unicode_handling_syntax_error(): | def test_unicode_handling_syntax_error(): | ||||||
|     value = py.builtin._totext("\xc4\x85\xc4\x87\n", "utf-8").encode("utf8") |     value = u"ąć".encode("UTF-8") | ||||||
| 
 | 
 | ||||||
|     def f(): |     def f(): | ||||||
|         raise SyntaxError("invalid syntax", (None, 1, 3, value)) |         raise SyntaxError("invalid syntax", (None, 1, 3, value)) | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ import textwrap | ||||||
| import _pytest | import _pytest | ||||||
| import py | import py | ||||||
| import pytest | import pytest | ||||||
|  | import six | ||||||
| from _pytest._code.code import ( | from _pytest._code.code import ( | ||||||
|     ExceptionInfo, |     ExceptionInfo, | ||||||
|     FormattedExcinfo, |     FormattedExcinfo, | ||||||
|  | @ -251,7 +252,7 @@ class TestTraceback_f_g_h(object): | ||||||
|             import sys |             import sys | ||||||
| 
 | 
 | ||||||
|             exc, val, tb = sys.exc_info() |             exc, val, tb = sys.exc_info() | ||||||
|             py.builtin._reraise(exc, val, tb) |             six.reraise(exc, val, tb) | ||||||
| 
 | 
 | ||||||
|         def f(n): |         def f(n): | ||||||
|             try: |             try: | ||||||
|  | @ -269,7 +270,7 @@ class TestTraceback_f_g_h(object): | ||||||
|         decorator = pytest.importorskip("decorator").decorator |         decorator = pytest.importorskip("decorator").decorator | ||||||
| 
 | 
 | ||||||
|         def log(f, *k, **kw): |         def log(f, *k, **kw): | ||||||
|             print("%s %s" % (k, kw)) |             print("{} {}".format(k, kw)) | ||||||
|             f(*k, **kw) |             f(*k, **kw) | ||||||
| 
 | 
 | ||||||
|         log = decorator(log) |         log = decorator(log) | ||||||
|  | @ -425,7 +426,7 @@ 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 = textwrap.dedent(source) | ||||||
|             tmpdir = request.getfixturevalue("tmpdir") |             tmpdir = request.getfixturevalue("tmpdir") | ||||||
|             modpath = tmpdir.join("mod.py") |             modpath = tmpdir.join("mod.py") | ||||||
|             tmpdir.ensure("__init__.py") |             tmpdir.ensure("__init__.py") | ||||||
|  | @ -449,7 +450,7 @@ class TestFormattedExcinfo(object): | ||||||
|     def test_repr_source(self): |     def test_repr_source(self): | ||||||
|         pr = FormattedExcinfo() |         pr = FormattedExcinfo() | ||||||
|         source = _pytest._code.Source( |         source = _pytest._code.Source( | ||||||
|             """ |             """\ | ||||||
|             def f(x): |             def f(x): | ||||||
|                 pass |                 pass | ||||||
|             """ |             """ | ||||||
|  | @ -884,10 +885,10 @@ raise ValueError() | ||||||
| 
 | 
 | ||||||
|         class MyRepr(TerminalRepr): |         class MyRepr(TerminalRepr): | ||||||
|             def toterminal(self, tw): |             def toterminal(self, tw): | ||||||
|                 tw.line(py.builtin._totext("я", "utf-8")) |                 tw.line(u"я") | ||||||
| 
 | 
 | ||||||
|         x = py.builtin._totext(MyRepr()) |         x = six.text_type(MyRepr()) | ||||||
|         assert x == py.builtin._totext("я", "utf-8") |         assert x == u"я" | ||||||
| 
 | 
 | ||||||
|     def test_toterminal_long(self, importasmod): |     def test_toterminal_long(self, importasmod): | ||||||
|         mod = importasmod( |         mod = importasmod( | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ import inspect | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
| import _pytest._code | import _pytest._code | ||||||
| import py |  | ||||||
| import pytest | import pytest | ||||||
|  | import six | ||||||
| from _pytest._code import Source | from _pytest._code import Source | ||||||
| from _pytest._code.source import ast | from _pytest._code.source import ast | ||||||
| 
 | 
 | ||||||
|  | @ -323,7 +323,7 @@ class TestSourceParsingAndCompiling(object): | ||||||
| 
 | 
 | ||||||
|     def test_compile_and_getsource(self): |     def test_compile_and_getsource(self): | ||||||
|         co = self.source.compile() |         co = self.source.compile() | ||||||
|         py.builtin.exec_(co, globals()) |         six.exec_(co, globals()) | ||||||
|         f(7) |         f(7) | ||||||
|         excinfo = pytest.raises(AssertionError, "f(6)") |         excinfo = pytest.raises(AssertionError, "f(6)") | ||||||
|         frame = excinfo.traceback[-1].frame |         frame = excinfo.traceback[-1].frame | ||||||
|  | @ -392,7 +392,7 @@ def test_getfuncsource_dynamic(): | ||||||
|         def g(): pass |         def g(): pass | ||||||
|     """ |     """ | ||||||
|     co = _pytest._code.compile(source) |     co = _pytest._code.compile(source) | ||||||
|     py.builtin.exec_(co, globals()) |     six.exec_(co, globals()) | ||||||
|     assert str(_pytest._code.Source(f)).strip() == "def f():\n    raise ValueError" |     assert str(_pytest._code.Source(f)).strip() == "def f():\n    raise ValueError" | ||||||
|     assert str(_pytest._code.Source(g)).strip() == "def g(): pass" |     assert str(_pytest._code.Source(g)).strip() == "def g(): pass" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,9 @@ | ||||||
| """Reproduces issue #3774""" | """Reproduces issue #3774""" | ||||||
| 
 | 
 | ||||||
|  | try: | ||||||
|     import mock |     import mock | ||||||
|  | except ImportError: | ||||||
|  |     import unittest.mock as mock | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | [pytest] | ||||||
|  | python_files = *.py | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | def test_init(): | ||||||
|  |     pass | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | def test_foo(): | ||||||
|  |     pass | ||||||
|  | @ -878,7 +878,6 @@ def test_live_logging_suspends_capture(has_capture_manager, request): | ||||||
|     import logging |     import logging | ||||||
|     import contextlib |     import contextlib | ||||||
|     from functools import partial |     from functools import partial | ||||||
|     from _pytest.capture import CaptureManager |  | ||||||
|     from _pytest.logging import _LiveLoggingStreamHandler |     from _pytest.logging import _LiveLoggingStreamHandler | ||||||
| 
 | 
 | ||||||
|     class MockCaptureManager: |     class MockCaptureManager: | ||||||
|  | @ -890,10 +889,6 @@ def test_live_logging_suspends_capture(has_capture_manager, request): | ||||||
|             yield |             yield | ||||||
|             self.calls.append("exit disabled") |             self.calls.append("exit disabled") | ||||||
| 
 | 
 | ||||||
|     # sanity check |  | ||||||
|     assert CaptureManager.suspend_capture_item |  | ||||||
|     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 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| from textwrap import dedent | import textwrap | ||||||
| 
 | 
 | ||||||
| import _pytest._code | import _pytest._code | ||||||
| import pytest | import pytest | ||||||
|  | @ -47,13 +47,14 @@ class TestModule(object): | ||||||
|         p = root2.join("test_x456.py") |         p = root2.join("test_x456.py") | ||||||
|         monkeypatch.syspath_prepend(str(root1)) |         monkeypatch.syspath_prepend(str(root1)) | ||||||
|         p.write( |         p.write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 import x456 |                 import x456 | ||||||
|                 def test(): |                 def test(): | ||||||
|                 assert x456.__file__.startswith(%r) |                     assert x456.__file__.startswith({!r}) | ||||||
|         """ |                 """.format( | ||||||
|                 % str(root2) |                     str(root2) | ||||||
|  |                 ) | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         with root2.as_cwd(): |         with root2.as_cwd(): | ||||||
|  | @ -929,8 +930,8 @@ class TestConftestCustomization(object): | ||||||
|     def test_customized_pymakemodule_issue205_subdir(self, testdir): |     def test_customized_pymakemodule_issue205_subdir(self, testdir): | ||||||
|         b = testdir.mkdir("a").mkdir("b") |         b = testdir.mkdir("a").mkdir("b") | ||||||
|         b.join("conftest.py").write( |         b.join("conftest.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 @pytest.hookimpl(hookwrapper=True) |                 @pytest.hookimpl(hookwrapper=True) | ||||||
|                 def pytest_pycollect_makemodule(): |                 def pytest_pycollect_makemodule(): | ||||||
|  | @ -941,8 +942,8 @@ class TestConftestCustomization(object): | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         b.join("test_module.py").write( |         b.join("test_module.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 def test_hello(): |                 def test_hello(): | ||||||
|                     assert hello == "world" |                     assert hello == "world" | ||||||
|                 """ |                 """ | ||||||
|  | @ -954,8 +955,8 @@ class TestConftestCustomization(object): | ||||||
|     def test_customized_pymakeitem(self, testdir): |     def test_customized_pymakeitem(self, testdir): | ||||||
|         b = testdir.mkdir("a").mkdir("b") |         b = testdir.mkdir("a").mkdir("b") | ||||||
|         b.join("conftest.py").write( |         b.join("conftest.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 @pytest.hookimpl(hookwrapper=True) |                 @pytest.hookimpl(hookwrapper=True) | ||||||
|                 def pytest_pycollect_makeitem(): |                 def pytest_pycollect_makeitem(): | ||||||
|  | @ -969,8 +970,8 @@ class TestConftestCustomization(object): | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         b.join("test_module.py").write( |         b.join("test_module.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
| 
 | 
 | ||||||
|                 @pytest.fixture() |                 @pytest.fixture() | ||||||
|  | @ -1033,7 +1034,7 @@ class TestConftestCustomization(object): | ||||||
|         ) |         ) | ||||||
|         testdir.makefile( |         testdir.makefile( | ||||||
|             ".narf", |             ".narf", | ||||||
|             """ |             """\ | ||||||
|             def test_something(): |             def test_something(): | ||||||
|                 assert 1 + 1 == 2""", |                 assert 1 + 1 == 2""", | ||||||
|         ) |         ) | ||||||
|  | @ -1046,8 +1047,8 @@ def test_setup_only_available_in_subdir(testdir): | ||||||
|     sub1 = testdir.mkpydir("sub1") |     sub1 = testdir.mkpydir("sub1") | ||||||
|     sub2 = testdir.mkpydir("sub2") |     sub2 = testdir.mkpydir("sub2") | ||||||
|     sub1.join("conftest.py").write( |     sub1.join("conftest.py").write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             import pytest |             import pytest | ||||||
|             def pytest_runtest_setup(item): |             def pytest_runtest_setup(item): | ||||||
|                 assert item.fspath.purebasename == "test_in_sub1" |                 assert item.fspath.purebasename == "test_in_sub1" | ||||||
|  | @ -1059,8 +1060,8 @@ def test_setup_only_available_in_subdir(testdir): | ||||||
|         ) |         ) | ||||||
|     ) |     ) | ||||||
|     sub2.join("conftest.py").write( |     sub2.join("conftest.py").write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             import pytest |             import pytest | ||||||
|             def pytest_runtest_setup(item): |             def pytest_runtest_setup(item): | ||||||
|                 assert item.fspath.purebasename == "test_in_sub2" |                 assert item.fspath.purebasename == "test_in_sub2" | ||||||
|  | @ -1547,8 +1548,8 @@ def test_skip_duplicates_by_default(testdir): | ||||||
|     a = testdir.mkdir("a") |     a = testdir.mkdir("a") | ||||||
|     fh = a.join("test_a.py") |     fh = a.join("test_a.py") | ||||||
|     fh.write( |     fh.write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             import pytest |             import pytest | ||||||
|             def test_real(): |             def test_real(): | ||||||
|                 pass |                 pass | ||||||
|  | @ -1567,8 +1568,8 @@ def test_keep_duplicates(testdir): | ||||||
|     a = testdir.mkdir("a") |     a = testdir.mkdir("a") | ||||||
|     fh = a.join("test_a.py") |     fh = a.join("test_a.py") | ||||||
|     fh.write( |     fh.write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             import pytest |             import pytest | ||||||
|             def test_real(): |             def test_real(): | ||||||
|                 pass |                 pass | ||||||
|  | @ -1623,3 +1624,38 @@ def test_package_with_modules(testdir): | ||||||
|     root.chdir() |     root.chdir() | ||||||
|     result = testdir.runpytest("-v", "-s") |     result = testdir.runpytest("-v", "-s") | ||||||
|     result.assert_outcomes(passed=2) |     result.assert_outcomes(passed=2) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def test_package_ordering(testdir): | ||||||
|  |     """ | ||||||
|  |     . | ||||||
|  |     └── root | ||||||
|  |         ├── Test_root.py | ||||||
|  |         ├── __init__.py | ||||||
|  |         ├── sub1 | ||||||
|  |         │   ├── Test_sub1.py | ||||||
|  |         │   └── __init__.py | ||||||
|  |         └── sub2 | ||||||
|  |             └── test | ||||||
|  |                 └── test_sub2.py | ||||||
|  | 
 | ||||||
|  |     """ | ||||||
|  |     testdir.makeini( | ||||||
|  |         """ | ||||||
|  |         [pytest] | ||||||
|  |         python_files=*.py | ||||||
|  |     """ | ||||||
|  |     ) | ||||||
|  |     root = testdir.mkpydir("root") | ||||||
|  |     sub1 = root.mkdir("sub1") | ||||||
|  |     sub1.ensure("__init__.py") | ||||||
|  |     sub2 = root.mkdir("sub2") | ||||||
|  |     sub2_test = sub2.mkdir("sub2") | ||||||
|  | 
 | ||||||
|  |     root.join("Test_root.py").write("def test_1(): pass") | ||||||
|  |     sub1.join("Test_sub1.py").write("def test_2(): pass") | ||||||
|  |     sub2_test.join("test_sub2.py").write("def test_3(): pass") | ||||||
|  | 
 | ||||||
|  |     # Execute from . | ||||||
|  |     result = testdir.runpytest("-v", "-s") | ||||||
|  |     result.assert_outcomes(passed=3) | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| from textwrap import dedent | # -*- coding: utf-8 -*- | ||||||
|  | import textwrap | ||||||
| 
 | 
 | ||||||
| import _pytest._code |  | ||||||
| import pytest | import pytest | ||||||
| from _pytest.pytester import get_public_names | from _pytest.pytester import get_public_names | ||||||
| from _pytest.fixtures import FixtureLookupError, FixtureRequest | from _pytest.fixtures import FixtureLookupError, FixtureRequest | ||||||
|  | @ -208,8 +208,8 @@ class TestFillFixtures(object): | ||||||
|         ) |         ) | ||||||
|         subdir = testdir.mkpydir("subdir") |         subdir = testdir.mkpydir("subdir") | ||||||
|         subdir.join("conftest.py").write( |         subdir.join("conftest.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
| 
 | 
 | ||||||
|                 @pytest.fixture |                 @pytest.fixture | ||||||
|  | @ -220,8 +220,8 @@ class TestFillFixtures(object): | ||||||
|         ) |         ) | ||||||
|         testfile = subdir.join("test_spam.py") |         testfile = subdir.join("test_spam.py") | ||||||
|         testfile.write( |         testfile.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 def test_spam(spam): |                 def test_spam(spam): | ||||||
|                     assert spam == "spam" |                     assert spam == "spam" | ||||||
|                 """ |                 """ | ||||||
|  | @ -276,8 +276,8 @@ class TestFillFixtures(object): | ||||||
|         ) |         ) | ||||||
|         subdir = testdir.mkpydir("subdir") |         subdir = testdir.mkpydir("subdir") | ||||||
|         subdir.join("conftest.py").write( |         subdir.join("conftest.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
| 
 | 
 | ||||||
|                 @pytest.fixture(params=[1, 2, 3]) |                 @pytest.fixture(params=[1, 2, 3]) | ||||||
|  | @ -288,8 +288,8 @@ class TestFillFixtures(object): | ||||||
|         ) |         ) | ||||||
|         testfile = subdir.join("test_spam.py") |         testfile = subdir.join("test_spam.py") | ||||||
|         testfile.write( |         testfile.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 params = {'spam': 1} |                 params = {'spam': 1} | ||||||
| 
 | 
 | ||||||
|                 def test_spam(spam): |                 def test_spam(spam): | ||||||
|  | @ -320,8 +320,8 @@ class TestFillFixtures(object): | ||||||
|         ) |         ) | ||||||
|         subdir = testdir.mkpydir("subdir") |         subdir = testdir.mkpydir("subdir") | ||||||
|         subdir.join("conftest.py").write( |         subdir.join("conftest.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
| 
 | 
 | ||||||
|                 @pytest.fixture(params=[1, 2, 3]) |                 @pytest.fixture(params=[1, 2, 3]) | ||||||
|  | @ -332,8 +332,8 @@ class TestFillFixtures(object): | ||||||
|         ) |         ) | ||||||
|         testfile = subdir.join("test_spam.py") |         testfile = subdir.join("test_spam.py") | ||||||
|         testfile.write( |         testfile.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 params = {'spam': 1} |                 params = {'spam': 1} | ||||||
| 
 | 
 | ||||||
|                 def test_spam(spam): |                 def test_spam(spam): | ||||||
|  | @ -807,8 +807,8 @@ class TestRequestBasic(object): | ||||||
|         # this tests that normalization of nodeids takes place |         # this tests that normalization of nodeids takes place | ||||||
|         b = testdir.mkdir("tests").mkdir("unit") |         b = testdir.mkdir("tests").mkdir("unit") | ||||||
|         b.join("conftest.py").write( |         b.join("conftest.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 @pytest.fixture |                 @pytest.fixture | ||||||
|                 def arg1(): |                 def arg1(): | ||||||
|  | @ -1484,7 +1484,7 @@ class TestFixtureManagerParseFactories(object): | ||||||
|         runner = testdir.mkdir("runner") |         runner = testdir.mkdir("runner") | ||||||
|         package = testdir.mkdir("package") |         package = testdir.mkdir("package") | ||||||
|         package.join("conftest.py").write( |         package.join("conftest.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|             import pytest |             import pytest | ||||||
|             @pytest.fixture |             @pytest.fixture | ||||||
|  | @ -1494,7 +1494,7 @@ class TestFixtureManagerParseFactories(object): | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         package.join("test_x.py").write( |         package.join("test_x.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 def test_x(one): |                 def test_x(one): | ||||||
|                     assert one == 1 |                     assert one == 1 | ||||||
|  | @ -1504,7 +1504,7 @@ class TestFixtureManagerParseFactories(object): | ||||||
|         sub = package.mkdir("sub") |         sub = package.mkdir("sub") | ||||||
|         sub.join("__init__.py").ensure() |         sub.join("__init__.py").ensure() | ||||||
|         sub.join("conftest.py").write( |         sub.join("conftest.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 @pytest.fixture |                 @pytest.fixture | ||||||
|  | @ -1514,7 +1514,7 @@ class TestFixtureManagerParseFactories(object): | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         sub.join("test_y.py").write( |         sub.join("test_y.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 def test_x(one): |                 def test_x(one): | ||||||
|                     assert one == 2 |                     assert one == 2 | ||||||
|  | @ -1535,7 +1535,7 @@ class TestFixtureManagerParseFactories(object): | ||||||
|         ) |         ) | ||||||
|         package = testdir.mkdir("package") |         package = testdir.mkdir("package") | ||||||
|         package.join("__init__.py").write( |         package.join("__init__.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 from .. import values |                 from .. import values | ||||||
|                 def setup_module(): |                 def setup_module(): | ||||||
|  | @ -1546,7 +1546,7 @@ class TestFixtureManagerParseFactories(object): | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         package.join("test_x.py").write( |         package.join("test_x.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 from .. import values |                 from .. import values | ||||||
|                 def test_x(): |                 def test_x(): | ||||||
|  | @ -1556,7 +1556,7 @@ class TestFixtureManagerParseFactories(object): | ||||||
|         ) |         ) | ||||||
|         package = testdir.mkdir("package2") |         package = testdir.mkdir("package2") | ||||||
|         package.join("__init__.py").write( |         package.join("__init__.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 from .. import values |                 from .. import values | ||||||
|                 def setup_module(): |                 def setup_module(): | ||||||
|  | @ -1567,7 +1567,7 @@ class TestFixtureManagerParseFactories(object): | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         package.join("test_x.py").write( |         package.join("test_x.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 from .. import values |                 from .. import values | ||||||
|                 def test_x(): |                 def test_x(): | ||||||
|  | @ -1587,7 +1587,7 @@ class TestFixtureManagerParseFactories(object): | ||||||
|         package = testdir.mkdir("package") |         package = testdir.mkdir("package") | ||||||
|         package.join("__init__.py").write("") |         package.join("__init__.py").write("") | ||||||
|         package.join("conftest.py").write( |         package.join("conftest.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 from .. import values |                 from .. import values | ||||||
|  | @ -1605,7 +1605,7 @@ class TestFixtureManagerParseFactories(object): | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         package.join("test_x.py").write( |         package.join("test_x.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 from .. import values |                 from .. import values | ||||||
|                 def test_package_autouse(): |                 def test_package_autouse(): | ||||||
|  | @ -1804,8 +1804,8 @@ 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( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 @pytest.fixture(autouse=True) |                 @pytest.fixture(autouse=True) | ||||||
|                 def app(): |                 def app(): | ||||||
|  | @ -1816,8 +1816,8 @@ class TestAutouseManagement(object): | ||||||
|         ) |         ) | ||||||
|         t = pkgdir.ensure("tests", "test_app.py") |         t = pkgdir.ensure("tests", "test_app.py") | ||||||
|         t.write( |         t.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import sys |                 import sys | ||||||
|                 def test_app(): |                 def test_app(): | ||||||
|                     assert sys._myapp == "hello" |                     assert sys._myapp == "hello" | ||||||
|  | @ -2715,8 +2715,8 @@ class TestFixtureMarker(object): | ||||||
|         ) |         ) | ||||||
|         b = testdir.mkdir("subdir") |         b = testdir.mkdir("subdir") | ||||||
|         b.join("test_overridden_fixture_finalizer.py").write( |         b.join("test_overridden_fixture_finalizer.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 @pytest.fixture |                 @pytest.fixture | ||||||
|                 def browser(browser): |                 def browser(browser): | ||||||
|  | @ -3217,8 +3217,8 @@ class TestShowFixtures(object): | ||||||
| 
 | 
 | ||||||
|     def test_show_fixtures_trimmed_doc(self, testdir): |     def test_show_fixtures_trimmed_doc(self, testdir): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 ''' |                 '''\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 @pytest.fixture |                 @pytest.fixture | ||||||
|                 def arg1(): |                 def arg1(): | ||||||
|  | @ -3239,8 +3239,8 @@ class TestShowFixtures(object): | ||||||
|         ) |         ) | ||||||
|         result = testdir.runpytest("--fixtures", p) |         result = testdir.runpytest("--fixtures", p) | ||||||
|         result.stdout.fnmatch_lines( |         result.stdout.fnmatch_lines( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 * fixtures defined from test_show_fixtures_trimmed_doc * |                 * fixtures defined from test_show_fixtures_trimmed_doc * | ||||||
|                 arg2 |                 arg2 | ||||||
|                     line1 |                     line1 | ||||||
|  | @ -3248,15 +3248,14 @@ class TestShowFixtures(object): | ||||||
|                 arg1 |                 arg1 | ||||||
|                     line1 |                     line1 | ||||||
|                     line2 |                     line2 | ||||||
| 
 |  | ||||||
|                 """ |                 """ | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def test_show_fixtures_indented_doc(self, testdir): |     def test_show_fixtures_indented_doc(self, testdir): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 ''' |                 '''\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 @pytest.fixture |                 @pytest.fixture | ||||||
|                 def fixture1(): |                 def fixture1(): | ||||||
|  | @ -3269,8 +3268,8 @@ class TestShowFixtures(object): | ||||||
|         ) |         ) | ||||||
|         result = testdir.runpytest("--fixtures", p) |         result = testdir.runpytest("--fixtures", p) | ||||||
|         result.stdout.fnmatch_lines( |         result.stdout.fnmatch_lines( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 * fixtures defined from test_show_fixtures_indented_doc * |                 * fixtures defined from test_show_fixtures_indented_doc * | ||||||
|                 fixture1 |                 fixture1 | ||||||
|                     line1 |                     line1 | ||||||
|  | @ -3281,8 +3280,8 @@ class TestShowFixtures(object): | ||||||
| 
 | 
 | ||||||
|     def test_show_fixtures_indented_doc_first_line_unindented(self, testdir): |     def test_show_fixtures_indented_doc_first_line_unindented(self, testdir): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 ''' |                 '''\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 @pytest.fixture |                 @pytest.fixture | ||||||
|                 def fixture1(): |                 def fixture1(): | ||||||
|  | @ -3295,8 +3294,8 @@ class TestShowFixtures(object): | ||||||
|         ) |         ) | ||||||
|         result = testdir.runpytest("--fixtures", p) |         result = testdir.runpytest("--fixtures", p) | ||||||
|         result.stdout.fnmatch_lines( |         result.stdout.fnmatch_lines( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 * fixtures defined from test_show_fixtures_indented_doc_first_line_unindented * |                 * fixtures defined from test_show_fixtures_indented_doc_first_line_unindented * | ||||||
|                 fixture1 |                 fixture1 | ||||||
|                     line1 |                     line1 | ||||||
|  | @ -3308,8 +3307,8 @@ class TestShowFixtures(object): | ||||||
| 
 | 
 | ||||||
|     def test_show_fixtures_indented_in_class(self, testdir): |     def test_show_fixtures_indented_in_class(self, testdir): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 ''' |                 '''\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 class TestClass(object): |                 class TestClass(object): | ||||||
|                     @pytest.fixture |                     @pytest.fixture | ||||||
|  | @ -3323,8 +3322,8 @@ class TestShowFixtures(object): | ||||||
|         ) |         ) | ||||||
|         result = testdir.runpytest("--fixtures", p) |         result = testdir.runpytest("--fixtures", p) | ||||||
|         result.stdout.fnmatch_lines( |         result.stdout.fnmatch_lines( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 * fixtures defined from test_show_fixtures_indented_in_class * |                 * fixtures defined from test_show_fixtures_indented_in_class * | ||||||
|                 fixture1 |                 fixture1 | ||||||
|                     line1 |                     line1 | ||||||
|  | @ -3667,8 +3666,8 @@ class TestParameterizedSubRequest(object): | ||||||
|         fixdir = testdir.mkdir("fixtures") |         fixdir = testdir.mkdir("fixtures") | ||||||
|         fixfile = fixdir.join("fix.py") |         fixfile = fixdir.join("fix.py") | ||||||
|         fixfile.write( |         fixfile.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
| 
 | 
 | ||||||
|                 @pytest.fixture(params=[0, 1, 2]) |                 @pytest.fixture(params=[0, 1, 2]) | ||||||
|  | @ -3680,8 +3679,8 @@ class TestParameterizedSubRequest(object): | ||||||
| 
 | 
 | ||||||
|         testfile = tests_dir.join("test_foos.py") |         testfile = tests_dir.join("test_foos.py") | ||||||
|         testfile.write( |         testfile.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 from fix import fix_with_param |                 from fix import fix_with_param | ||||||
| 
 | 
 | ||||||
|                 def test_foo(request): |                 def test_foo(request): | ||||||
|  | @ -3698,9 +3697,9 @@ class TestParameterizedSubRequest(object): | ||||||
|             E*Failed: The requested fixture has no parameter defined for the current test. |             E*Failed: The requested fixture has no parameter defined for the current test. | ||||||
|             E* |             E* | ||||||
|             E*Requested fixture 'fix_with_param' defined in: |             E*Requested fixture 'fix_with_param' defined in: | ||||||
|             E*fix.py:5 |             E*fix.py:4 | ||||||
|             E*Requested here: |             E*Requested here: | ||||||
|             E*test_foos.py:5 |             E*test_foos.py:4 | ||||||
|             *1 failed* |             *1 failed* | ||||||
|             """ |             """ | ||||||
|         ) |         ) | ||||||
|  | @ -3979,3 +3978,71 @@ class TestScopeOrdering(object): | ||||||
|         items, _ = testdir.inline_genitems() |         items, _ = testdir.inline_genitems() | ||||||
|         request = FixtureRequest(items[0]) |         request = FixtureRequest(items[0]) | ||||||
|         assert request.fixturenames == "s1 p1 m1 m2 c1 f2 f1".split() |         assert request.fixturenames == "s1 p1 m1 m2 c1 f2 f1".split() | ||||||
|  | 
 | ||||||
|  |     def test_multiple_packages(self, testdir): | ||||||
|  |         """Complex test involving multiple package fixtures. Make sure teardowns | ||||||
|  |         are executed in order. | ||||||
|  |         . | ||||||
|  |         └── root | ||||||
|  |             ├── __init__.py | ||||||
|  |             ├── sub1 | ||||||
|  |             │   ├── __init__.py | ||||||
|  |             │   ├── conftest.py | ||||||
|  |             │   └── test_1.py | ||||||
|  |             └── sub2 | ||||||
|  |                 ├── __init__.py | ||||||
|  |                 ├── conftest.py | ||||||
|  |                 └── test_2.py | ||||||
|  |         """ | ||||||
|  |         root = testdir.mkdir("root") | ||||||
|  |         root.join("__init__.py").write("values = []") | ||||||
|  |         sub1 = root.mkdir("sub1") | ||||||
|  |         sub1.ensure("__init__.py") | ||||||
|  |         sub1.join("conftest.py").write( | ||||||
|  |             textwrap.dedent( | ||||||
|  |                 """\ | ||||||
|  |             import pytest | ||||||
|  |             from .. import values | ||||||
|  |             @pytest.fixture(scope="package") | ||||||
|  |             def fix(): | ||||||
|  |                 values.append("pre-sub1") | ||||||
|  |                 yield values | ||||||
|  |                 assert values.pop() == "pre-sub1" | ||||||
|  |         """ | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  |         sub1.join("test_1.py").write( | ||||||
|  |             textwrap.dedent( | ||||||
|  |                 """\ | ||||||
|  |             from .. import values | ||||||
|  |             def test_1(fix): | ||||||
|  |                 assert values == ["pre-sub1"] | ||||||
|  |         """ | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  |         sub2 = root.mkdir("sub2") | ||||||
|  |         sub2.ensure("__init__.py") | ||||||
|  |         sub2.join("conftest.py").write( | ||||||
|  |             textwrap.dedent( | ||||||
|  |                 """\ | ||||||
|  |             import pytest | ||||||
|  |             from .. import values | ||||||
|  |             @pytest.fixture(scope="package") | ||||||
|  |             def fix(): | ||||||
|  |                 values.append("pre-sub2") | ||||||
|  |                 yield values | ||||||
|  |                 assert values.pop() == "pre-sub2" | ||||||
|  |         """ | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  |         sub2.join("test_2.py").write( | ||||||
|  |             textwrap.dedent( | ||||||
|  |                 """\ | ||||||
|  |             from .. import values | ||||||
|  |             def test_2(fix): | ||||||
|  |                 assert values == ["pre-sub2"] | ||||||
|  |         """ | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  |         reprec = testdir.inline_run() | ||||||
|  |         reprec.assertoutcome(passed=2) | ||||||
|  |  | ||||||
|  | @ -2,8 +2,7 @@ | ||||||
| import re | import re | ||||||
| import sys | import sys | ||||||
| import attr | import attr | ||||||
| import _pytest._code | import textwrap | ||||||
| import py |  | ||||||
| import pytest | import pytest | ||||||
| from _pytest import python, fixtures | from _pytest import python, fixtures | ||||||
| 
 | 
 | ||||||
|  | @ -295,9 +294,7 @@ class TestMetafunc(object): | ||||||
|         ) |         ) | ||||||
|         assert result == ["a0-1.0", "a1-b1"] |         assert result == ["a0-1.0", "a1-b1"] | ||||||
|         # unicode mixing, issue250 |         # unicode mixing, issue250 | ||||||
|         result = idmaker( |         result = idmaker((u"a", "b"), [pytest.param({}, b"\xc3\xb4")]) | ||||||
|             (py.builtin._totext("a"), "b"), [pytest.param({}, b"\xc3\xb4")] |  | ||||||
|         ) |  | ||||||
|         assert result == ["a0-\\xc3\\xb4"] |         assert result == ["a0-\\xc3\\xb4"] | ||||||
| 
 | 
 | ||||||
|     def test_idmaker_with_bytes_regex(self): |     def test_idmaker_with_bytes_regex(self): | ||||||
|  | @ -309,7 +306,6 @@ class TestMetafunc(object): | ||||||
|     def test_idmaker_native_strings(self): |     def test_idmaker_native_strings(self): | ||||||
|         from _pytest.python import idmaker |         from _pytest.python import idmaker | ||||||
| 
 | 
 | ||||||
|         totext = py.builtin._totext |  | ||||||
|         result = idmaker( |         result = idmaker( | ||||||
|             ("a", "b"), |             ("a", "b"), | ||||||
|             [ |             [ | ||||||
|  | @ -324,7 +320,7 @@ class TestMetafunc(object): | ||||||
|                 pytest.param({7}, set("seven")), |                 pytest.param({7}, set("seven")), | ||||||
|                 pytest.param(tuple("eight"), (8, -8, 8)), |                 pytest.param(tuple("eight"), (8, -8, 8)), | ||||||
|                 pytest.param(b"\xc3\xb4", b"name"), |                 pytest.param(b"\xc3\xb4", b"name"), | ||||||
|                 pytest.param(b"\xc3\xb4", totext("other")), |                 pytest.param(b"\xc3\xb4", u"other"), | ||||||
|             ], |             ], | ||||||
|         ) |         ) | ||||||
|         assert result == [ |         assert result == [ | ||||||
|  | @ -1275,16 +1271,16 @@ class TestMetafuncFunctional(object): | ||||||
|         sub1 = testdir.mkpydir("sub1") |         sub1 = testdir.mkpydir("sub1") | ||||||
|         sub2 = testdir.mkpydir("sub2") |         sub2 = testdir.mkpydir("sub2") | ||||||
|         sub1.join("conftest.py").write( |         sub1.join("conftest.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 def pytest_generate_tests(metafunc): |                 def pytest_generate_tests(metafunc): | ||||||
|                     assert metafunc.function.__name__ == "test_1" |                     assert metafunc.function.__name__ == "test_1" | ||||||
|                 """ |                 """ | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         sub2.join("conftest.py").write( |         sub2.join("conftest.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 def pytest_generate_tests(metafunc): |                 def pytest_generate_tests(metafunc): | ||||||
|                     assert metafunc.function.__name__ == "test_2" |                     assert metafunc.function.__name__ == "test_2" | ||||||
|                 """ |                 """ | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ def equal_with_bash(prefix, ffc, fc, out=None): | ||||||
|     res_bash = set(fc(prefix)) |     res_bash = set(fc(prefix)) | ||||||
|     retval = set(res) == res_bash |     retval = set(res) == res_bash | ||||||
|     if out: |     if out: | ||||||
|         out.write("equal_with_bash %s %s\n" % (retval, res)) |         out.write("equal_with_bash {} {}\n".format(retval, res)) | ||||||
|         if not retval: |         if not retval: | ||||||
|             out.write(" python - bash: %s\n" % (set(res) - res_bash)) |             out.write(" python - bash: %s\n" % (set(res) - res_bash)) | ||||||
|             out.write(" bash - python: %s\n" % (res_bash - set(res))) |             out.write(" bash - python: %s\n" % (res_bash - set(res))) | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ import textwrap | ||||||
| import _pytest.assertion as plugin | import _pytest.assertion as plugin | ||||||
| import py | import py | ||||||
| import pytest | import pytest | ||||||
|  | import six | ||||||
| from _pytest.assertion import util | from _pytest.assertion import util | ||||||
| from _pytest.assertion import truncate | from _pytest.assertion import truncate | ||||||
| 
 | 
 | ||||||
|  | @ -509,12 +510,12 @@ class TestAssert_reprcompare(object): | ||||||
|         assert "raised in repr()" not in expl |         assert "raised in repr()" not in expl | ||||||
| 
 | 
 | ||||||
|     def test_unicode(self): |     def test_unicode(self): | ||||||
|         left = py.builtin._totext("£€", "utf-8") |         left = u"£€" | ||||||
|         right = py.builtin._totext("£", "utf-8") |         right = u"£" | ||||||
|         expl = callequal(left, right) |         expl = callequal(left, right) | ||||||
|         assert expl[0] == py.builtin._totext("'£€' == '£'", "utf-8") |         assert expl[0] == u"'£€' == '£'" | ||||||
|         assert expl[1] == py.builtin._totext("- £€", "utf-8") |         assert expl[1] == u"- £€" | ||||||
|         assert expl[2] == py.builtin._totext("+ £", "utf-8") |         assert expl[2] == u"+ £" | ||||||
| 
 | 
 | ||||||
|     def test_nonascii_text(self): |     def test_nonascii_text(self): | ||||||
|         """ |         """ | ||||||
|  | @ -541,8 +542,8 @@ class TestAssert_reprcompare(object): | ||||||
|             right = bytes(right, "utf-8") |             right = bytes(right, "utf-8") | ||||||
|         expl = callequal(left, right) |         expl = callequal(left, right) | ||||||
|         for line in expl: |         for line in expl: | ||||||
|             assert isinstance(line, py.builtin.text) |             assert isinstance(line, six.text_type) | ||||||
|         msg = py.builtin._totext("\n").join(expl) |         msg = u"\n".join(expl) | ||||||
|         assert msg |         assert msg | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ import textwrap | ||||||
| import zipfile | import zipfile | ||||||
| import py | import py | ||||||
| import pytest | import pytest | ||||||
|  | import six | ||||||
| 
 | 
 | ||||||
| import _pytest._code | import _pytest._code | ||||||
| from _pytest.assertion import util | from _pytest.assertion import util | ||||||
|  | @ -49,7 +50,7 @@ def getmsg(f, extra_ns=None, must_pass=False): | ||||||
|     ns = {} |     ns = {} | ||||||
|     if extra_ns is not None: |     if extra_ns is not None: | ||||||
|         ns.update(extra_ns) |         ns.update(extra_ns) | ||||||
|     py.builtin.exec_(code, ns) |     six.exec_(code, ns) | ||||||
|     func = ns[f.__name__] |     func = ns[f.__name__] | ||||||
|     try: |     try: | ||||||
|         func() |         func() | ||||||
|  | @ -560,7 +561,7 @@ class TestAssertionRewrite(object): | ||||||
|         assert getmsg(f) == "assert 42" |         assert getmsg(f) == "assert 42" | ||||||
| 
 | 
 | ||||||
|         def my_reprcompare(op, left, right): |         def my_reprcompare(op, left, right): | ||||||
|             return "%s %s %s" % (left, op, right) |             return "{} {} {}".format(left, op, right) | ||||||
| 
 | 
 | ||||||
|         monkeypatch.setattr(util, "_reprcompare", my_reprcompare) |         monkeypatch.setattr(util, "_reprcompare", my_reprcompare) | ||||||
| 
 | 
 | ||||||
|  | @ -654,12 +655,10 @@ class TestRewriteOnImport(object): | ||||||
|     def test_readonly(self, testdir): |     def test_readonly(self, testdir): | ||||||
|         sub = testdir.mkdir("testing") |         sub = testdir.mkdir("testing") | ||||||
|         sub.join("test_readonly.py").write( |         sub.join("test_readonly.py").write( | ||||||
|             py.builtin._totext( |             b""" | ||||||
|                 """ |  | ||||||
| def test_rewritten(): | def test_rewritten(): | ||||||
|     assert "@py_builtins" in globals() |     assert "@py_builtins" in globals() | ||||||
|             """ |             """, | ||||||
|             ).encode("utf-8"), |  | ||||||
|             "wb", |             "wb", | ||||||
|         ) |         ) | ||||||
|         old_mode = sub.stat().mode |         old_mode = sub.stat().mode | ||||||
|  | @ -1040,8 +1039,8 @@ class TestAssertionRewriteHookDetails(object): | ||||||
|         """ |         """ | ||||||
|         path = testdir.mkpydir("foo") |         path = testdir.mkpydir("foo") | ||||||
|         path.join("test_foo.py").write( |         path.join("test_foo.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 class Test(object): |                 class Test(object): | ||||||
|                     def test_foo(self): |                     def test_foo(self): | ||||||
|                         import pkgutil |                         import pkgutil | ||||||
|  |  | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| from __future__ import absolute_import, division, print_function | from __future__ import absolute_import, division, print_function | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
|  | import textwrap | ||||||
| 
 | 
 | ||||||
| import py | import py | ||||||
| import _pytest |  | ||||||
| import pytest | import pytest | ||||||
| import os | import os | ||||||
| import shutil | import shutil | ||||||
|  | @ -224,8 +224,8 @@ class TestLastFailed(object): | ||||||
|         result = testdir.runpytest() |         result = testdir.runpytest() | ||||||
|         result.stdout.fnmatch_lines(["*2 failed*"]) |         result.stdout.fnmatch_lines(["*2 failed*"]) | ||||||
|         p.write( |         p.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 def test_1(): |                 def test_1(): | ||||||
|                     assert 1 |                     assert 1 | ||||||
| 
 | 
 | ||||||
|  | @ -252,16 +252,16 @@ class TestLastFailed(object): | ||||||
| 
 | 
 | ||||||
|     def test_failedfirst_order(self, testdir): |     def test_failedfirst_order(self, testdir): | ||||||
|         testdir.tmpdir.join("test_a.py").write( |         testdir.tmpdir.join("test_a.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 def test_always_passes(): |                 def test_always_passes(): | ||||||
|                     assert 1 |                     assert 1 | ||||||
|                 """ |                 """ | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         testdir.tmpdir.join("test_b.py").write( |         testdir.tmpdir.join("test_b.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 def test_always_fails(): |                 def test_always_fails(): | ||||||
|                     assert 0 |                     assert 0 | ||||||
|                 """ |                 """ | ||||||
|  | @ -277,11 +277,11 @@ class TestLastFailed(object): | ||||||
|     def test_lastfailed_failedfirst_order(self, testdir): |     def test_lastfailed_failedfirst_order(self, testdir): | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             **{ |             **{ | ||||||
|                 "test_a.py": """ |                 "test_a.py": """\ | ||||||
|                 def test_always_passes(): |                 def test_always_passes(): | ||||||
|                     assert 1 |                     assert 1 | ||||||
|                 """, |                 """, | ||||||
|                 "test_b.py": """ |                 "test_b.py": """\ | ||||||
|                 def test_always_fails(): |                 def test_always_fails(): | ||||||
|                     assert 0 |                     assert 0 | ||||||
|                 """, |                 """, | ||||||
|  | @ -298,13 +298,13 @@ class TestLastFailed(object): | ||||||
|     def test_lastfailed_difference_invocations(self, testdir, monkeypatch): |     def test_lastfailed_difference_invocations(self, testdir, monkeypatch): | ||||||
|         monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) |         monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             test_a=""" |             test_a="""\ | ||||||
|             def test_a1(): |             def test_a1(): | ||||||
|                 assert 0 |                 assert 0 | ||||||
|             def test_a2(): |             def test_a2(): | ||||||
|                 assert 1 |                 assert 1 | ||||||
|             """, |             """, | ||||||
|             test_b=""" |             test_b="""\ | ||||||
|             def test_b1(): |             def test_b1(): | ||||||
|                 assert 0 |                 assert 0 | ||||||
|             """, |             """, | ||||||
|  | @ -317,8 +317,8 @@ class TestLastFailed(object): | ||||||
|         result = testdir.runpytest("--lf", p2) |         result = testdir.runpytest("--lf", p2) | ||||||
|         result.stdout.fnmatch_lines(["*1 failed*"]) |         result.stdout.fnmatch_lines(["*1 failed*"]) | ||||||
|         p2.write( |         p2.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 def test_b1(): |                 def test_b1(): | ||||||
|                     assert 1 |                     assert 1 | ||||||
|                 """ |                 """ | ||||||
|  | @ -332,15 +332,15 @@ class TestLastFailed(object): | ||||||
|     def test_lastfailed_usecase_splice(self, testdir, monkeypatch): |     def test_lastfailed_usecase_splice(self, testdir, monkeypatch): | ||||||
|         monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) |         monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             def test_1(): |             def test_1(): | ||||||
|                 assert 0 |                 assert 0 | ||||||
|             """ |             """ | ||||||
|         ) |         ) | ||||||
|         p2 = testdir.tmpdir.join("test_something.py") |         p2 = testdir.tmpdir.join("test_something.py") | ||||||
|         p2.write( |         p2.write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 def test_2(): |                 def test_2(): | ||||||
|                     assert 0 |                     assert 0 | ||||||
|                 """ |                 """ | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | # -*- coding: utf-8 -*- | ||||||
| from __future__ import absolute_import, division, print_function | from __future__ import absolute_import, division, print_function | ||||||
| 
 | 
 | ||||||
| # note: py.io capture tests where copied from | # note: py.io capture tests where copied from | ||||||
|  | @ -5,13 +6,13 @@ from __future__ import absolute_import, division, print_function | ||||||
| import pickle | import pickle | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
|  | import textwrap | ||||||
| from io import UnsupportedOperation | from io import UnsupportedOperation | ||||||
| 
 | 
 | ||||||
| import _pytest._code |  | ||||||
| import py | import py | ||||||
| import pytest | import pytest | ||||||
| import contextlib | import contextlib | ||||||
| from six import binary_type, text_type | from six import text_type | ||||||
| from _pytest import capture | from _pytest import capture | ||||||
| from _pytest.capture import CaptureManager | from _pytest.capture import CaptureManager | ||||||
| from _pytest.main import EXIT_NOTESTSCOLLECTED | from _pytest.main import EXIT_NOTESTSCOLLECTED | ||||||
|  | @ -23,12 +24,12 @@ needsosdup = pytest.mark.xfail("not hasattr(os, 'dup')") | ||||||
| def tobytes(obj): | def tobytes(obj): | ||||||
|     if isinstance(obj, text_type): |     if isinstance(obj, text_type): | ||||||
|         obj = obj.encode("UTF-8") |         obj = obj.encode("UTF-8") | ||||||
|     assert isinstance(obj, binary_type) |     assert isinstance(obj, bytes) | ||||||
|     return obj |     return obj | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def totext(obj): | def totext(obj): | ||||||
|     if isinstance(obj, binary_type): |     if isinstance(obj, bytes): | ||||||
|         obj = text_type(obj, "UTF-8") |         obj = text_type(obj, "UTF-8") | ||||||
|     assert isinstance(obj, text_type) |     assert isinstance(obj, text_type) | ||||||
|     return obj |     return obj | ||||||
|  | @ -70,19 +71,23 @@ class TestCaptureManager(object): | ||||||
|         try: |         try: | ||||||
|             capman = CaptureManager(method) |             capman = CaptureManager(method) | ||||||
|             capman.start_global_capturing() |             capman.start_global_capturing() | ||||||
|             outerr = capman.suspend_global_capture() |             capman.suspend_global_capture() | ||||||
|  |             outerr = capman.read_global_capture() | ||||||
|             assert outerr == ("", "") |             assert outerr == ("", "") | ||||||
|             outerr = capman.suspend_global_capture() |             capman.suspend_global_capture() | ||||||
|  |             outerr = capman.read_global_capture() | ||||||
|             assert outerr == ("", "") |             assert outerr == ("", "") | ||||||
|             print("hello") |             print("hello") | ||||||
|             out, err = capman.suspend_global_capture() |             capman.suspend_global_capture() | ||||||
|  |             out, err = capman.read_global_capture() | ||||||
|             if method == "no": |             if method == "no": | ||||||
|                 assert old == (sys.stdout, sys.stderr, sys.stdin) |                 assert old == (sys.stdout, sys.stderr, sys.stdin) | ||||||
|             else: |             else: | ||||||
|                 assert not out |                 assert not out | ||||||
|             capman.resume_global_capture() |             capman.resume_global_capture() | ||||||
|             print("hello") |             print("hello") | ||||||
|             out, err = capman.suspend_global_capture() |             capman.suspend_global_capture() | ||||||
|  |             out, err = capman.read_global_capture() | ||||||
|             if method != "no": |             if method != "no": | ||||||
|                 assert out == "hello\n" |                 assert out == "hello\n" | ||||||
|             capman.stop_global_capturing() |             capman.stop_global_capturing() | ||||||
|  | @ -264,7 +269,7 @@ class TestPerTestCapturing(object): | ||||||
| 
 | 
 | ||||||
|     def test_capturing_outerr(self, testdir): |     def test_capturing_outerr(self, testdir): | ||||||
|         p1 = testdir.makepyfile( |         p1 = testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             import sys |             import sys | ||||||
|             def test_capturing(): |             def test_capturing(): | ||||||
|                 print (42) |                 print (42) | ||||||
|  | @ -293,7 +298,7 @@ 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( | ||||||
|             """ |             """\ | ||||||
|             def test_logging(): |             def test_logging(): | ||||||
|                 import logging |                 import logging | ||||||
|                 import pytest |                 import pytest | ||||||
|  | @ -307,7 +312,7 @@ class TestLoggingInteraction(object): | ||||||
| 
 | 
 | ||||||
|     def test_logging_and_immediate_setupteardown(self, testdir): |     def test_logging_and_immediate_setupteardown(self, testdir): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             import logging |             import logging | ||||||
|             def setup_function(function): |             def setup_function(function): | ||||||
|                 logging.warn("hello1") |                 logging.warn("hello1") | ||||||
|  | @ -333,7 +338,7 @@ class TestLoggingInteraction(object): | ||||||
| 
 | 
 | ||||||
|     def test_logging_and_crossscope_fixtures(self, testdir): |     def test_logging_and_crossscope_fixtures(self, testdir): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             import logging |             import logging | ||||||
|             def setup_module(function): |             def setup_module(function): | ||||||
|                 logging.warn("hello1") |                 logging.warn("hello1") | ||||||
|  | @ -359,7 +364,7 @@ class TestLoggingInteraction(object): | ||||||
| 
 | 
 | ||||||
|     def test_conftestlogging_is_shown(self, testdir): |     def test_conftestlogging_is_shown(self, testdir): | ||||||
|         testdir.makeconftest( |         testdir.makeconftest( | ||||||
|             """ |             """\ | ||||||
|                 import logging |                 import logging | ||||||
|                 logging.basicConfig() |                 logging.basicConfig() | ||||||
|                 logging.warn("hello435") |                 logging.warn("hello435") | ||||||
|  | @ -373,14 +378,14 @@ class TestLoggingInteraction(object): | ||||||
| 
 | 
 | ||||||
|     def test_conftestlogging_and_test_logging(self, testdir): |     def test_conftestlogging_and_test_logging(self, testdir): | ||||||
|         testdir.makeconftest( |         testdir.makeconftest( | ||||||
|             """ |             """\ | ||||||
|                 import logging |                 import logging | ||||||
|                 logging.basicConfig() |                 logging.basicConfig() | ||||||
|             """ |             """ | ||||||
|         ) |         ) | ||||||
|         # make sure that logging is still captured in tests |         # make sure that logging is still captured in tests | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             def test_hello(): |             def test_hello(): | ||||||
|                 import logging |                 import logging | ||||||
|                 logging.warn("hello433") |                 logging.warn("hello433") | ||||||
|  | @ -398,7 +403,7 @@ 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( | ||||||
|             """ |             """\ | ||||||
|             def test_hello(capsys): |             def test_hello(capsys): | ||||||
|                 print (42) |                 print (42) | ||||||
|                 out, err = capsys.readouterr() |                 out, err = capsys.readouterr() | ||||||
|  | @ -410,7 +415,7 @@ class TestCaptureFixture(object): | ||||||
| 
 | 
 | ||||||
|     def test_capsyscapfd(self, testdir): |     def test_capsyscapfd(self, testdir): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             def test_one(capsys, capfd): |             def test_one(capsys, capfd): | ||||||
|                 pass |                 pass | ||||||
|             def test_two(capfd, capsys): |             def test_two(capfd, capsys): | ||||||
|  | @ -433,7 +438,7 @@ class TestCaptureFixture(object): | ||||||
|         in the same test is an error. |         in the same test is an error. | ||||||
|         """ |         """ | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             def test_one(capsys, request): |             def test_one(capsys, request): | ||||||
|                 request.getfixturevalue("capfd") |                 request.getfixturevalue("capfd") | ||||||
|             def test_two(capfd, request): |             def test_two(capfd, request): | ||||||
|  | @ -453,7 +458,7 @@ class TestCaptureFixture(object): | ||||||
| 
 | 
 | ||||||
|     def test_capsyscapfdbinary(self, testdir): |     def test_capsyscapfdbinary(self, testdir): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             def test_one(capsys, capfdbinary): |             def test_one(capsys, capfdbinary): | ||||||
|                 pass |                 pass | ||||||
|             """ |             """ | ||||||
|  | @ -466,12 +471,13 @@ class TestCaptureFixture(object): | ||||||
|     @pytest.mark.parametrize("method", ["sys", "fd"]) |     @pytest.mark.parametrize("method", ["sys", "fd"]) | ||||||
|     def test_capture_is_represented_on_failure_issue128(self, testdir, method): |     def test_capture_is_represented_on_failure_issue128(self, testdir, method): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             def test_hello(cap%s): |             def test_hello(cap{}): | ||||||
|                 print ("xxx42xxx") |                 print ("xxx42xxx") | ||||||
|                 assert 0 |                 assert 0 | ||||||
|         """ |             """.format( | ||||||
|             % method |                 method | ||||||
|  |             ) | ||||||
|         ) |         ) | ||||||
|         result = testdir.runpytest(p) |         result = testdir.runpytest(p) | ||||||
|         result.stdout.fnmatch_lines(["xxx42xxx"]) |         result.stdout.fnmatch_lines(["xxx42xxx"]) | ||||||
|  | @ -479,7 +485,7 @@ class TestCaptureFixture(object): | ||||||
|     @needsosdup |     @needsosdup | ||||||
|     def test_stdfd_functional(self, testdir): |     def test_stdfd_functional(self, testdir): | ||||||
|         reprec = testdir.inline_runsource( |         reprec = testdir.inline_runsource( | ||||||
|             """ |             """\ | ||||||
|             def test_hello(capfd): |             def test_hello(capfd): | ||||||
|                 import os |                 import os | ||||||
|                 os.write(1, "42".encode('ascii')) |                 os.write(1, "42".encode('ascii')) | ||||||
|  | @ -493,7 +499,7 @@ class TestCaptureFixture(object): | ||||||
|     @needsosdup |     @needsosdup | ||||||
|     def test_capfdbinary(self, testdir): |     def test_capfdbinary(self, testdir): | ||||||
|         reprec = testdir.inline_runsource( |         reprec = testdir.inline_runsource( | ||||||
|             """ |             """\ | ||||||
|             def test_hello(capfdbinary): |             def test_hello(capfdbinary): | ||||||
|                 import os |                 import os | ||||||
|                 # some likely un-decodable bytes |                 # some likely un-decodable bytes | ||||||
|  | @ -510,7 +516,7 @@ class TestCaptureFixture(object): | ||||||
|     ) |     ) | ||||||
|     def test_capsysbinary(self, testdir): |     def test_capsysbinary(self, testdir): | ||||||
|         reprec = testdir.inline_runsource( |         reprec = testdir.inline_runsource( | ||||||
|             """ |             """\ | ||||||
|             def test_hello(capsysbinary): |             def test_hello(capsysbinary): | ||||||
|                 import sys |                 import sys | ||||||
|                 # some likely un-decodable bytes |                 # some likely un-decodable bytes | ||||||
|  | @ -527,7 +533,7 @@ class TestCaptureFixture(object): | ||||||
|     ) |     ) | ||||||
|     def test_capsysbinary_forbidden_in_python2(self, testdir): |     def test_capsysbinary_forbidden_in_python2(self, testdir): | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             def test_hello(capsysbinary): |             def test_hello(capsysbinary): | ||||||
|                 pass |                 pass | ||||||
|             """ |             """ | ||||||
|  | @ -543,7 +549,7 @@ class TestCaptureFixture(object): | ||||||
| 
 | 
 | ||||||
|     def test_partial_setup_failure(self, testdir): |     def test_partial_setup_failure(self, testdir): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             def test_hello(capsys, missingarg): |             def test_hello(capsys, missingarg): | ||||||
|                 pass |                 pass | ||||||
|             """ |             """ | ||||||
|  | @ -554,7 +560,7 @@ class TestCaptureFixture(object): | ||||||
|     @needsosdup |     @needsosdup | ||||||
|     def test_keyboardinterrupt_disables_capturing(self, testdir): |     def test_keyboardinterrupt_disables_capturing(self, testdir): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             def test_hello(capfd): |             def test_hello(capfd): | ||||||
|                 import os |                 import os | ||||||
|                 os.write(1, str(42).encode('ascii')) |                 os.write(1, str(42).encode('ascii')) | ||||||
|  | @ -568,7 +574,7 @@ class TestCaptureFixture(object): | ||||||
|     @pytest.mark.issue14 |     @pytest.mark.issue14 | ||||||
|     def test_capture_and_logging(self, testdir): |     def test_capture_and_logging(self, testdir): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             import logging |             import logging | ||||||
|             def test_log(capsys): |             def test_log(capsys): | ||||||
|                 logging.error('x') |                 logging.error('x') | ||||||
|  | @ -581,7 +587,7 @@ class TestCaptureFixture(object): | ||||||
|     @pytest.mark.parametrize("no_capture", [True, False]) |     @pytest.mark.parametrize("no_capture", [True, False]) | ||||||
|     def test_disabled_capture_fixture(self, testdir, fixture, no_capture): |     def test_disabled_capture_fixture(self, testdir, fixture, no_capture): | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             def test_disabled({fixture}): |             def test_disabled({fixture}): | ||||||
|                 print('captured before') |                 print('captured before') | ||||||
|                 with {fixture}.disabled(): |                 with {fixture}.disabled(): | ||||||
|  | @ -615,7 +621,7 @@ class TestCaptureFixture(object): | ||||||
|         Ensure that capsys and capfd can be used by other fixtures during setup and teardown. |         Ensure that capsys and capfd can be used by other fixtures during setup and teardown. | ||||||
|         """ |         """ | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             """ |             """\ | ||||||
|             from __future__ import print_function |             from __future__ import print_function | ||||||
|             import sys |             import sys | ||||||
|             import pytest |             import pytest | ||||||
|  | @ -647,12 +653,40 @@ class TestCaptureFixture(object): | ||||||
|         assert "stdout contents begin" not in result.stdout.str() |         assert "stdout contents begin" not in result.stdout.str() | ||||||
|         assert "stderr contents begin" not in result.stdout.str() |         assert "stderr contents begin" not in result.stdout.str() | ||||||
| 
 | 
 | ||||||
|  |     @pytest.mark.parametrize("cap", ["capsys", "capfd"]) | ||||||
|  |     def test_fixture_use_by_other_fixtures_teardown(self, testdir, cap): | ||||||
|  |         """Ensure we can access setup and teardown buffers from teardown when using capsys/capfd (##3033)""" | ||||||
|  |         testdir.makepyfile( | ||||||
|  |             """\ | ||||||
|  |             import sys | ||||||
|  |             import pytest | ||||||
|  |             import os | ||||||
|  | 
 | ||||||
|  |             @pytest.fixture() | ||||||
|  |             def fix({cap}): | ||||||
|  |                 print("setup out") | ||||||
|  |                 sys.stderr.write("setup err\\n") | ||||||
|  |                 yield | ||||||
|  |                 out, err = {cap}.readouterr() | ||||||
|  |                 assert out == 'setup out\\ncall out\\n' | ||||||
|  |                 assert err == 'setup err\\ncall err\\n' | ||||||
|  | 
 | ||||||
|  |             def test_a(fix): | ||||||
|  |                 print("call out") | ||||||
|  |                 sys.stderr.write("call err\\n") | ||||||
|  |         """.format( | ||||||
|  |                 cap=cap | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  |         reprec = testdir.inline_run() | ||||||
|  |         reprec.assertoutcome(passed=1) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| def test_setup_failure_does_not_kill_capturing(testdir): | def test_setup_failure_does_not_kill_capturing(testdir): | ||||||
|     sub1 = testdir.mkpydir("sub1") |     sub1 = testdir.mkpydir("sub1") | ||||||
|     sub1.join("conftest.py").write( |     sub1.join("conftest.py").write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             def pytest_runtest_setup(item): |             def pytest_runtest_setup(item): | ||||||
|                 raise ValueError(42) |                 raise ValueError(42) | ||||||
|             """ |             """ | ||||||
|  | @ -1051,9 +1085,9 @@ class TestStdCapture(object): | ||||||
| 
 | 
 | ||||||
|     def test_capturing_readouterr_unicode(self): |     def test_capturing_readouterr_unicode(self): | ||||||
|         with self.getcapture() as cap: |         with self.getcapture() as cap: | ||||||
|             print("hx\xc4\x85\xc4\x87") |             print("hxąć") | ||||||
|             out, err = cap.readouterr() |             out, err = cap.readouterr() | ||||||
|         assert out == py.builtin._totext("hx\xc4\x85\xc4\x87\n", "utf8") |         assert out == u"hxąć\n" | ||||||
| 
 | 
 | ||||||
|     @pytest.mark.skipif( |     @pytest.mark.skipif( | ||||||
|         "sys.version_info >= (3,)", reason="text output different for bytes on python3" |         "sys.version_info >= (3,)", reason="text output different for bytes on python3" | ||||||
|  | @ -1063,7 +1097,7 @@ class TestStdCapture(object): | ||||||
|             # triggered an internal error in pytest |             # triggered an internal error in pytest | ||||||
|             print("\xa6") |             print("\xa6") | ||||||
|             out, err = cap.readouterr() |             out, err = cap.readouterr() | ||||||
|         assert out == py.builtin._totext("\ufffd\n", "unicode-escape") |         assert out == u"\ufffd\n" | ||||||
| 
 | 
 | ||||||
|     def test_reset_twice_error(self): |     def test_reset_twice_error(self): | ||||||
|         with self.getcapture() as cap: |         with self.getcapture() as cap: | ||||||
|  | @ -1387,9 +1421,69 @@ def test_pickling_and_unpickling_encoded_file(): | ||||||
|     pickle.loads(ef_as_str) |     pickle.loads(ef_as_str) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_capsys_with_cli_logging(testdir): | def test_global_capture_with_live_logging(testdir): | ||||||
|     # Issue 3819 |     # Issue 3819 | ||||||
|     # capsys should work with real-time cli logging |     # capture should work with live cli logging | ||||||
|  | 
 | ||||||
|  |     # Teardown report seems to have the capture for the whole process (setup, capture, teardown) | ||||||
|  |     testdir.makeconftest( | ||||||
|  |         """ | ||||||
|  |         def pytest_runtest_logreport(report): | ||||||
|  |             if "test_global" in report.nodeid: | ||||||
|  |                 if report.when == "teardown": | ||||||
|  |                     with open("caplog", "w") as f: | ||||||
|  |                         f.write(report.caplog) | ||||||
|  |                     with open("capstdout", "w") as f: | ||||||
|  |                         f.write(report.capstdout) | ||||||
|  |         """ | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     testdir.makepyfile( | ||||||
|  |         """ | ||||||
|  |         import logging | ||||||
|  |         import sys | ||||||
|  |         import pytest | ||||||
|  | 
 | ||||||
|  |         logger = logging.getLogger(__name__) | ||||||
|  | 
 | ||||||
|  |         @pytest.fixture | ||||||
|  |         def fix1(): | ||||||
|  |             print("fix setup") | ||||||
|  |             logging.info("fix setup") | ||||||
|  |             yield | ||||||
|  |             logging.info("fix teardown") | ||||||
|  |             print("fix teardown") | ||||||
|  | 
 | ||||||
|  |         def test_global(fix1): | ||||||
|  |             print("begin test") | ||||||
|  |             logging.info("something in test") | ||||||
|  |             print("end test") | ||||||
|  |         """ | ||||||
|  |     ) | ||||||
|  |     result = testdir.runpytest_subprocess("--log-cli-level=INFO") | ||||||
|  |     assert result.ret == 0 | ||||||
|  | 
 | ||||||
|  |     with open("caplog", "r") as f: | ||||||
|  |         caplog = f.read() | ||||||
|  | 
 | ||||||
|  |     assert "fix setup" in caplog | ||||||
|  |     assert "something in test" in caplog | ||||||
|  |     assert "fix teardown" in caplog | ||||||
|  | 
 | ||||||
|  |     with open("capstdout", "r") as f: | ||||||
|  |         capstdout = f.read() | ||||||
|  | 
 | ||||||
|  |     assert "fix setup" in capstdout | ||||||
|  |     assert "begin test" in capstdout | ||||||
|  |     assert "end test" in capstdout | ||||||
|  |     assert "fix teardown" in capstdout | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @pytest.mark.parametrize("capture_fixture", ["capsys", "capfd"]) | ||||||
|  | def test_capture_with_live_logging(testdir, capture_fixture): | ||||||
|  |     # Issue 3819 | ||||||
|  |     # capture should work with live cli logging | ||||||
|  | 
 | ||||||
|     testdir.makepyfile( |     testdir.makepyfile( | ||||||
|         """ |         """ | ||||||
|         import logging |         import logging | ||||||
|  | @ -1397,22 +1491,23 @@ def test_capsys_with_cli_logging(testdir): | ||||||
| 
 | 
 | ||||||
|         logger = logging.getLogger(__name__) |         logger = logging.getLogger(__name__) | ||||||
| 
 | 
 | ||||||
|         def test_myoutput(capsys):  # or use "capfd" for fd-level |         def test_capture({0}): | ||||||
|             print("hello") |             print("hello") | ||||||
|             sys.stderr.write("world\\n") |             sys.stderr.write("world\\n") | ||||||
|             captured = capsys.readouterr() |             captured = {0}.readouterr() | ||||||
|             assert captured.out == "hello\\n" |             assert captured.out == "hello\\n" | ||||||
|             assert captured.err == "world\\n" |             assert captured.err == "world\\n" | ||||||
| 
 | 
 | ||||||
|             logging.info("something") |             logging.info("something") | ||||||
| 
 |  | ||||||
|             print("next") |             print("next") | ||||||
| 
 |  | ||||||
|             logging.info("something") |             logging.info("something") | ||||||
| 
 | 
 | ||||||
|             captured = capsys.readouterr() |             captured = {0}.readouterr() | ||||||
|             assert captured.out == "next\\n" |             assert captured.out == "next\\n" | ||||||
|         """ |         """.format( | ||||||
|  |             capture_fixture | ||||||
|         ) |         ) | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|     result = testdir.runpytest_subprocess("--log-cli-level=INFO") |     result = testdir.runpytest_subprocess("--log-cli-level=INFO") | ||||||
|     assert result.ret == 0 |     assert result.ret == 0 | ||||||
|  |  | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| from __future__ import absolute_import, division, print_function | from __future__ import absolute_import, division, print_function | ||||||
| import pprint | import pprint | ||||||
| import sys | import sys | ||||||
|  | import textwrap | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| import _pytest._code |  | ||||||
| from _pytest.main import Session, EXIT_NOTESTSCOLLECTED, _in_venv | from _pytest.main import Session, EXIT_NOTESTSCOLLECTED, _in_venv | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -913,8 +913,8 @@ def test_fixture_scope_sibling_conftests(testdir): | ||||||
|     """Regression test case for https://github.com/pytest-dev/pytest/issues/2836""" |     """Regression test case for https://github.com/pytest-dev/pytest/issues/2836""" | ||||||
|     foo_path = testdir.mkdir("foo") |     foo_path = testdir.mkdir("foo") | ||||||
|     foo_path.join("conftest.py").write( |     foo_path.join("conftest.py").write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             import pytest |             import pytest | ||||||
|             @pytest.fixture |             @pytest.fixture | ||||||
|             def fix(): |             def fix(): | ||||||
|  | @ -938,3 +938,17 @@ def test_fixture_scope_sibling_conftests(testdir): | ||||||
|             "*1 passed, 1 error*", |             "*1 passed, 1 error*", | ||||||
|         ] |         ] | ||||||
|     ) |     ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def test_collect_init_tests(testdir): | ||||||
|  |     """Check that we collect files from __init__.py files when they patch the 'python_files' (#3773)""" | ||||||
|  |     p = testdir.copy_example("collect/collect_init_tests") | ||||||
|  |     result = testdir.runpytest(p, "--collect-only") | ||||||
|  |     result.stdout.fnmatch_lines( | ||||||
|  |         [ | ||||||
|  |             "*<Module '__init__.py'>", | ||||||
|  |             "*<Function 'test_init'>", | ||||||
|  |             "*<Module 'test_foo.py'>", | ||||||
|  |             "*<Function 'test_foo'>", | ||||||
|  |         ] | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  | @ -17,8 +17,8 @@ class TestParseIni(object): | ||||||
|         sub = tmpdir.mkdir("sub") |         sub = tmpdir.mkdir("sub") | ||||||
|         sub.chdir() |         sub.chdir() | ||||||
|         tmpdir.join(filename).write( |         tmpdir.join(filename).write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 [{section}] |                 [{section}] | ||||||
|                 name = value |                 name = value | ||||||
|                 """.format( |                 """.format( | ||||||
|  | @ -38,8 +38,8 @@ class TestParseIni(object): | ||||||
|     def test_append_parse_args(self, testdir, tmpdir, monkeypatch): |     def test_append_parse_args(self, testdir, tmpdir, monkeypatch): | ||||||
|         monkeypatch.setenv("PYTEST_ADDOPTS", '--color no -rs --tb="short"') |         monkeypatch.setenv("PYTEST_ADDOPTS", '--color no -rs --tb="short"') | ||||||
|         tmpdir.join("pytest.ini").write( |         tmpdir.join("pytest.ini").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 [pytest] |                 [pytest] | ||||||
|                 addopts = --verbose |                 addopts = --verbose | ||||||
|                 """ |                 """ | ||||||
|  | @ -438,8 +438,8 @@ class TestConfigFromdictargs(object): | ||||||
| 
 | 
 | ||||||
|     def test_inifilename(self, tmpdir): |     def test_inifilename(self, tmpdir): | ||||||
|         tmpdir.join("foo/bar.ini").ensure().write( |         tmpdir.join("foo/bar.ini").ensure().write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 [pytest] |                 [pytest] | ||||||
|                 name = value |                 name = value | ||||||
|                 """ |                 """ | ||||||
|  | @ -453,8 +453,8 @@ class TestConfigFromdictargs(object): | ||||||
| 
 | 
 | ||||||
|         cwd = tmpdir.join("a/b") |         cwd = tmpdir.join("a/b") | ||||||
|         cwd.join("pytest.ini").ensure().write( |         cwd.join("pytest.ini").ensure().write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 [pytest] |                 [pytest] | ||||||
|                 name = wrong-value |                 name = wrong-value | ||||||
|                 should_not_be_set = true |                 should_not_be_set = true | ||||||
|  |  | ||||||
|  | @ -1,7 +1,6 @@ | ||||||
| from __future__ import absolute_import, division, print_function | from __future__ import absolute_import, division, print_function | ||||||
| from textwrap import dedent | import textwrap | ||||||
| 
 | 
 | ||||||
| import _pytest._code |  | ||||||
| import py | import py | ||||||
| import pytest | import pytest | ||||||
| from _pytest.config import PytestPluginManager | from _pytest.config import PytestPluginManager | ||||||
|  | @ -174,8 +173,8 @@ def test_conftest_confcutdir(testdir): | ||||||
|     testdir.makeconftest("assert 0") |     testdir.makeconftest("assert 0") | ||||||
|     x = testdir.mkdir("x") |     x = testdir.mkdir("x") | ||||||
|     x.join("conftest.py").write( |     x.join("conftest.py").write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             def pytest_addoption(parser): |             def pytest_addoption(parser): | ||||||
|                 parser.addoption("--xyz", action="store_true") |                 parser.addoption("--xyz", action="store_true") | ||||||
|             """ |             """ | ||||||
|  | @ -198,8 +197,8 @@ def test_no_conftest(testdir): | ||||||
| def test_conftest_existing_resultlog(testdir): | def test_conftest_existing_resultlog(testdir): | ||||||
|     x = testdir.mkdir("tests") |     x = testdir.mkdir("tests") | ||||||
|     x.join("conftest.py").write( |     x.join("conftest.py").write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             def pytest_addoption(parser): |             def pytest_addoption(parser): | ||||||
|                 parser.addoption("--xyz", action="store_true") |                 parser.addoption("--xyz", action="store_true") | ||||||
|             """ |             """ | ||||||
|  | @ -213,8 +212,8 @@ def test_conftest_existing_resultlog(testdir): | ||||||
| def test_conftest_existing_junitxml(testdir): | def test_conftest_existing_junitxml(testdir): | ||||||
|     x = testdir.mkdir("tests") |     x = testdir.mkdir("tests") | ||||||
|     x.join("conftest.py").write( |     x.join("conftest.py").write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             def pytest_addoption(parser): |             def pytest_addoption(parser): | ||||||
|                 parser.addoption("--xyz", action="store_true") |                 parser.addoption("--xyz", action="store_true") | ||||||
|             """ |             """ | ||||||
|  | @ -247,8 +246,8 @@ def test_fixture_dependency(testdir, monkeypatch): | ||||||
|     sub = testdir.mkdir("sub") |     sub = testdir.mkdir("sub") | ||||||
|     sub.join("__init__.py").write("") |     sub.join("__init__.py").write("") | ||||||
|     sub.join("conftest.py").write( |     sub.join("conftest.py").write( | ||||||
|         dedent( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             import pytest |             import pytest | ||||||
| 
 | 
 | ||||||
|             @pytest.fixture |             @pytest.fixture | ||||||
|  | @ -268,8 +267,8 @@ def test_fixture_dependency(testdir, monkeypatch): | ||||||
|     subsub = sub.mkdir("subsub") |     subsub = sub.mkdir("subsub") | ||||||
|     subsub.join("__init__.py").write("") |     subsub.join("__init__.py").write("") | ||||||
|     subsub.join("test_bar.py").write( |     subsub.join("test_bar.py").write( | ||||||
|         dedent( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             import pytest |             import pytest | ||||||
| 
 | 
 | ||||||
|             @pytest.fixture |             @pytest.fixture | ||||||
|  | @ -288,8 +287,8 @@ def test_fixture_dependency(testdir, monkeypatch): | ||||||
| def test_conftest_found_with_double_dash(testdir): | def test_conftest_found_with_double_dash(testdir): | ||||||
|     sub = testdir.mkdir("sub") |     sub = testdir.mkdir("sub") | ||||||
|     sub.join("conftest.py").write( |     sub.join("conftest.py").write( | ||||||
|         dedent( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             def pytest_addoption(parser): |             def pytest_addoption(parser): | ||||||
|                 parser.addoption("--hello-world", action="store_true") |                 parser.addoption("--hello-world", action="store_true") | ||||||
|             """ |             """ | ||||||
|  | @ -313,7 +312,7 @@ class TestConftestVisibility(object): | ||||||
|         package = testdir.mkdir("package") |         package = testdir.mkdir("package") | ||||||
| 
 | 
 | ||||||
|         package.join("conftest.py").write( |         package.join("conftest.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 @pytest.fixture |                 @pytest.fixture | ||||||
|  | @ -323,7 +322,7 @@ class TestConftestVisibility(object): | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         package.join("test_pkgroot.py").write( |         package.join("test_pkgroot.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 def test_pkgroot(fxtr): |                 def test_pkgroot(fxtr): | ||||||
|                     assert fxtr == "from-package" |                     assert fxtr == "from-package" | ||||||
|  | @ -334,7 +333,7 @@ class TestConftestVisibility(object): | ||||||
|         swc = package.mkdir("swc") |         swc = package.mkdir("swc") | ||||||
|         swc.join("__init__.py").ensure() |         swc.join("__init__.py").ensure() | ||||||
|         swc.join("conftest.py").write( |         swc.join("conftest.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 import pytest |                 import pytest | ||||||
|                 @pytest.fixture |                 @pytest.fixture | ||||||
|  | @ -344,11 +343,10 @@ class TestConftestVisibility(object): | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|         swc.join("test_with_conftest.py").write( |         swc.join("test_with_conftest.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 def test_with_conftest(fxtr): |                 def test_with_conftest(fxtr): | ||||||
|                     assert fxtr == "from-swc" |                     assert fxtr == "from-swc" | ||||||
| 
 |  | ||||||
|                 """ |                 """ | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|  | @ -356,12 +354,11 @@ class TestConftestVisibility(object): | ||||||
|         snc = package.mkdir("snc") |         snc = package.mkdir("snc") | ||||||
|         snc.join("__init__.py").ensure() |         snc.join("__init__.py").ensure() | ||||||
|         snc.join("test_no_conftest.py").write( |         snc.join("test_no_conftest.py").write( | ||||||
|             dedent( |             textwrap.dedent( | ||||||
|                 """\ |                 """\ | ||||||
|                 def test_no_conftest(fxtr): |                 def test_no_conftest(fxtr): | ||||||
|                     assert fxtr == "from-package"   # No local conftest.py, so should |                     assert fxtr == "from-package"   # No local conftest.py, so should | ||||||
|                                                     # use value from parent dir's |                                                     # use value from parent dir's | ||||||
| 
 |  | ||||||
|                 """ |                 """ | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|  | @ -422,8 +419,8 @@ def test_search_conftest_up_to_inifile(testdir, confcutdir, passed, error): | ||||||
|     src = root.join("src").ensure(dir=1) |     src = root.join("src").ensure(dir=1) | ||||||
|     src.join("pytest.ini").write("[pytest]") |     src.join("pytest.ini").write("[pytest]") | ||||||
|     src.join("conftest.py").write( |     src.join("conftest.py").write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             import pytest |             import pytest | ||||||
|             @pytest.fixture |             @pytest.fixture | ||||||
|             def fix1(): pass |             def fix1(): pass | ||||||
|  | @ -431,8 +428,8 @@ def test_search_conftest_up_to_inifile(testdir, confcutdir, passed, error): | ||||||
|         ) |         ) | ||||||
|     ) |     ) | ||||||
|     src.join("test_foo.py").write( |     src.join("test_foo.py").write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             def test_1(fix1): |             def test_1(fix1): | ||||||
|                 pass |                 pass | ||||||
|             def test_2(out_of_reach): |             def test_2(out_of_reach): | ||||||
|  | @ -441,8 +438,8 @@ def test_search_conftest_up_to_inifile(testdir, confcutdir, passed, error): | ||||||
|         ) |         ) | ||||||
|     ) |     ) | ||||||
|     root.join("conftest.py").write( |     root.join("conftest.py").write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             import pytest |             import pytest | ||||||
|             @pytest.fixture |             @pytest.fixture | ||||||
|             def out_of_reach(): pass |             def out_of_reach(): pass | ||||||
|  | @ -464,7 +461,7 @@ def test_search_conftest_up_to_inifile(testdir, confcutdir, passed, error): | ||||||
| 
 | 
 | ||||||
| def test_issue1073_conftest_special_objects(testdir): | def test_issue1073_conftest_special_objects(testdir): | ||||||
|     testdir.makeconftest( |     testdir.makeconftest( | ||||||
|         """ |         """\ | ||||||
|         class DontTouchMe(object): |         class DontTouchMe(object): | ||||||
|             def __getattr__(self, x): |             def __getattr__(self, x): | ||||||
|                 raise Exception('cant touch me') |                 raise Exception('cant touch me') | ||||||
|  | @ -473,7 +470,7 @@ def test_issue1073_conftest_special_objects(testdir): | ||||||
|         """ |         """ | ||||||
|     ) |     ) | ||||||
|     testdir.makepyfile( |     testdir.makepyfile( | ||||||
|         """ |         """\ | ||||||
|         def test_some(): |         def test_some(): | ||||||
|             pass |             pass | ||||||
|         """ |         """ | ||||||
|  | @ -484,12 +481,12 @@ def test_issue1073_conftest_special_objects(testdir): | ||||||
| 
 | 
 | ||||||
| def test_conftest_exception_handling(testdir): | def test_conftest_exception_handling(testdir): | ||||||
|     testdir.makeconftest( |     testdir.makeconftest( | ||||||
|         """ |         """\ | ||||||
|         raise ValueError() |         raise ValueError() | ||||||
|         """ |         """ | ||||||
|     ) |     ) | ||||||
|     testdir.makepyfile( |     testdir.makepyfile( | ||||||
|         """ |         """\ | ||||||
|         def test_some(): |         def test_some(): | ||||||
|             pass |             pass | ||||||
|         """ |         """ | ||||||
|  | @ -507,7 +504,7 @@ def test_hook_proxy(testdir): | ||||||
|         **{ |         **{ | ||||||
|             "root/demo-0/test_foo1.py": "def test1(): pass", |             "root/demo-0/test_foo1.py": "def test1(): pass", | ||||||
|             "root/demo-a/test_foo2.py": "def test1(): pass", |             "root/demo-a/test_foo2.py": "def test1(): pass", | ||||||
|             "root/demo-a/conftest.py": """ |             "root/demo-a/conftest.py": """\ | ||||||
|             def pytest_ignore_collect(path, config): |             def pytest_ignore_collect(path, config): | ||||||
|                 return True |                 return True | ||||||
|             """, |             """, | ||||||
|  | @ -525,8 +522,8 @@ def test_required_option_help(testdir): | ||||||
|     testdir.makeconftest("assert 0") |     testdir.makeconftest("assert 0") | ||||||
|     x = testdir.mkdir("x") |     x = testdir.mkdir("x") | ||||||
|     x.join("conftest.py").write( |     x.join("conftest.py").write( | ||||||
|         _pytest._code.Source( |         textwrap.dedent( | ||||||
|             """ |             """\ | ||||||
|             def pytest_addoption(parser): |             def pytest_addoption(parser): | ||||||
|                 parser.addoption("--xyz", action="store_true", required=True) |                 parser.addoption("--xyz", action="store_true", required=True) | ||||||
|             """ |             """ | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| # encoding: utf-8 | # encoding: utf-8 | ||||||
| from __future__ import absolute_import, division, print_function | from __future__ import absolute_import, division, print_function | ||||||
| import sys | import sys | ||||||
| import _pytest._code | import textwrap | ||||||
| from _pytest.compat import MODULE_NOT_FOUND_ERROR | from _pytest.compat import MODULE_NOT_FOUND_ERROR | ||||||
| from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile | from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile | ||||||
| import pytest | import pytest | ||||||
|  | @ -258,8 +258,8 @@ class TestDoctests(object): | ||||||
| 
 | 
 | ||||||
|     def test_doctest_linedata_missing(self, testdir): |     def test_doctest_linedata_missing(self, testdir): | ||||||
|         testdir.tmpdir.join("hello.py").write( |         testdir.tmpdir.join("hello.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 class Fun(object): |                 class Fun(object): | ||||||
|                     @property |                     @property | ||||||
|                     def test(self): |                     def test(self): | ||||||
|  | @ -300,8 +300,8 @@ class TestDoctests(object): | ||||||
| 
 | 
 | ||||||
|     def test_doctest_unex_importerror_with_module(self, testdir): |     def test_doctest_unex_importerror_with_module(self, testdir): | ||||||
|         testdir.tmpdir.join("hello.py").write( |         testdir.tmpdir.join("hello.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 import asdalsdkjaslkdjasd |                 import asdalsdkjaslkdjasd | ||||||
|                 """ |                 """ | ||||||
|             ) |             ) | ||||||
|  | @ -339,8 +339,8 @@ class TestDoctests(object): | ||||||
|     def test_doctestmodule_external_and_issue116(self, testdir): |     def test_doctestmodule_external_and_issue116(self, testdir): | ||||||
|         p = testdir.mkpydir("hello") |         p = testdir.mkpydir("hello") | ||||||
|         p.join("__init__.py").write( |         p.join("__init__.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 def somefunc(): |                 def somefunc(): | ||||||
|                     ''' |                     ''' | ||||||
|                         >>> i = 0 |                         >>> i = 0 | ||||||
|  | @ -353,13 +353,13 @@ class TestDoctests(object): | ||||||
|         result = testdir.runpytest(p, "--doctest-modules") |         result = testdir.runpytest(p, "--doctest-modules") | ||||||
|         result.stdout.fnmatch_lines( |         result.stdout.fnmatch_lines( | ||||||
|             [ |             [ | ||||||
|                 "004 *>>> i = 0", |                 "003 *>>> i = 0", | ||||||
|                 "005 *>>> i + 1", |                 "004 *>>> i + 1", | ||||||
|                 "*Expected:", |                 "*Expected:", | ||||||
|                 "*    2", |                 "*    2", | ||||||
|                 "*Got:", |                 "*Got:", | ||||||
|                 "*    1", |                 "*    1", | ||||||
|                 "*:5: DocTestFailure", |                 "*:4: DocTestFailure", | ||||||
|             ] |             ] | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,7 +7,9 @@ def test_version(testdir, pytestconfig): | ||||||
|     result = testdir.runpytest("--version") |     result = testdir.runpytest("--version") | ||||||
|     assert result.ret == 0 |     assert result.ret == 0 | ||||||
|     # p = py.path.local(py.__file__).dirpath() |     # p = py.path.local(py.__file__).dirpath() | ||||||
|     result.stderr.fnmatch_lines(["*pytest*%s*imported from*" % (pytest.__version__,)]) |     result.stderr.fnmatch_lines( | ||||||
|  |         ["*pytest*{}*imported from*".format(pytest.__version__)] | ||||||
|  |     ) | ||||||
|     if pytestconfig.pluginmanager.list_plugin_distinfo(): |     if pytestconfig.pluginmanager.list_plugin_distinfo(): | ||||||
|         result.stderr.fnmatch_lines(["*setuptools registered plugins:", "*at*"]) |         result.stderr.fnmatch_lines(["*setuptools registered plugins:", "*at*"]) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -941,7 +941,7 @@ def test_double_colon_split_method_issue469(testdir): | ||||||
| def test_unicode_issue368(testdir): | def test_unicode_issue368(testdir): | ||||||
|     path = testdir.tmpdir.join("test.xml") |     path = testdir.tmpdir.join("test.xml") | ||||||
|     log = LogXML(str(path), None) |     log = LogXML(str(path), None) | ||||||
|     ustr = py.builtin._totext("ВНИ!", "utf-8") |     ustr = u"ВНИ!" | ||||||
| 
 | 
 | ||||||
|     class Report(BaseReport): |     class Report(BaseReport): | ||||||
|         longrepr = ustr |         longrepr = ustr | ||||||
|  |  | ||||||
|  | @ -228,11 +228,15 @@ def test_syspath_prepend(mp): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_syspath_prepend_double_undo(mp): | def test_syspath_prepend_double_undo(mp): | ||||||
|  |     old_syspath = sys.path[:] | ||||||
|  |     try: | ||||||
|         mp.syspath_prepend("hello world") |         mp.syspath_prepend("hello world") | ||||||
|         mp.undo() |         mp.undo() | ||||||
|         sys.path.append("more hello world") |         sys.path.append("more hello world") | ||||||
|         mp.undo() |         mp.undo() | ||||||
|         assert sys.path[-1] == "more hello world" |         assert sys.path[-1] == "more hello world" | ||||||
|  |     finally: | ||||||
|  |         sys.path[:] = old_syspath | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_chdir_with_path_local(mp, tmpdir): | def test_chdir_with_path_local(mp, tmpdir): | ||||||
|  |  | ||||||
|  | @ -294,7 +294,7 @@ def test_argcomplete(testdir, monkeypatch): | ||||||
|     script = str(testdir.tmpdir.join("test_argcomplete")) |     script = str(testdir.tmpdir.join("test_argcomplete")) | ||||||
|     pytest_bin = sys.argv[0] |     pytest_bin = sys.argv[0] | ||||||
|     if "pytest" not in os.path.basename(pytest_bin): |     if "pytest" not in os.path.basename(pytest_bin): | ||||||
|         pytest.skip("need to be run with pytest executable, not %s" % (pytest_bin,)) |         pytest.skip("need to be run with pytest executable, not {}".format(pytest_bin)) | ||||||
| 
 | 
 | ||||||
|     with open(str(script), "w") as fp: |     with open(str(script), "w") as fp: | ||||||
|         # redirect output from argcomplete to stdin and stderr is not trivial |         # redirect output from argcomplete to stdin and stderr is not trivial | ||||||
|  |  | ||||||
|  | @ -260,7 +260,9 @@ class TestPDB(object): | ||||||
|                 assert False |                 assert False | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|         child = testdir.spawn_pytest("--show-capture=%s --pdb %s" % (showcapture, p1)) |         child = testdir.spawn_pytest( | ||||||
|  |             "--show-capture={} --pdb {}".format(showcapture, p1) | ||||||
|  |         ) | ||||||
|         if showcapture in ("all", "log"): |         if showcapture in ("all", "log"): | ||||||
|             child.expect("captured log") |             child.expect("captured log") | ||||||
|             child.expect("get rekt") |             child.expect("get rekt") | ||||||
|  | @ -473,7 +475,7 @@ class TestPDB(object): | ||||||
|             x = 5 |             x = 5 | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|         child = testdir.spawn("%s %s" % (sys.executable, p1)) |         child = testdir.spawn("{} {}".format(sys.executable, p1)) | ||||||
|         child.expect("x = 5") |         child.expect("x = 5") | ||||||
|         child.sendeof() |         child.sendeof() | ||||||
|         self.flush(child) |         self.flush(child) | ||||||
|  |  | ||||||
|  | @ -25,7 +25,6 @@ class TestPytestPluginInteractions(object): | ||||||
|         ) |         ) | ||||||
|         conf = testdir.makeconftest( |         conf = testdir.makeconftest( | ||||||
|             """ |             """ | ||||||
|             import sys ; sys.path.insert(0, '.') |  | ||||||
|             import newhooks |             import newhooks | ||||||
|             def pytest_addhooks(pluginmanager): |             def pytest_addhooks(pluginmanager): | ||||||
|                 pluginmanager.addhooks(newhooks) |                 pluginmanager.addhooks(newhooks) | ||||||
|  | @ -263,8 +262,7 @@ class TestPytestPluginManager(object): | ||||||
|         mod.pytest_plugins = "pytest_a" |         mod.pytest_plugins = "pytest_a" | ||||||
|         aplugin = testdir.makepyfile(pytest_a="#") |         aplugin = testdir.makepyfile(pytest_a="#") | ||||||
|         reprec = testdir.make_hook_recorder(pytestpm) |         reprec = testdir.make_hook_recorder(pytestpm) | ||||||
|         # syspath.prepend(aplugin.dirpath()) |         testdir.syspathinsert(aplugin.dirpath()) | ||||||
|         sys.path.insert(0, str(aplugin.dirpath())) |  | ||||||
|         pytestpm.consider_module(mod) |         pytestpm.consider_module(mod) | ||||||
|         call = reprec.getcall(pytestpm.hook.pytest_plugin_registered.name) |         call = reprec.getcall(pytestpm.hook.pytest_plugin_registered.name) | ||||||
|         assert call.plugin.__name__ == "pytest_a" |         assert call.plugin.__name__ == "pytest_a" | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ import _pytest.pytester as pytester | ||||||
| from _pytest.pytester import HookRecorder | from _pytest.pytester import HookRecorder | ||||||
| from _pytest.pytester import CwdSnapshot, SysModulesSnapshot, SysPathsSnapshot | from _pytest.pytester import CwdSnapshot, SysModulesSnapshot, SysPathsSnapshot | ||||||
| from _pytest.config import PytestPluginManager | from _pytest.config import PytestPluginManager | ||||||
| from _pytest.main import EXIT_OK, EXIT_TESTSFAILED | from _pytest.main import EXIT_OK, EXIT_TESTSFAILED, EXIT_NOTESTSCOLLECTED | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_make_hook_recorder(testdir): | def test_make_hook_recorder(testdir): | ||||||
|  | @ -266,57 +266,6 @@ class TestInlineRunModulesCleanup(object): | ||||||
|         assert imported.data == 42 |         assert imported.data == 42 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_inline_run_clean_sys_paths(testdir): |  | ||||||
|     def test_sys_path_change_cleanup(self, testdir): |  | ||||||
|         test_path1 = testdir.tmpdir.join("boink1").strpath |  | ||||||
|         test_path2 = testdir.tmpdir.join("boink2").strpath |  | ||||||
|         test_path3 = testdir.tmpdir.join("boink3").strpath |  | ||||||
|         sys.path.append(test_path1) |  | ||||||
|         sys.meta_path.append(test_path1) |  | ||||||
|         original_path = list(sys.path) |  | ||||||
|         original_meta_path = list(sys.meta_path) |  | ||||||
|         test_mod = testdir.makepyfile( |  | ||||||
|             """ |  | ||||||
|             import sys |  | ||||||
|             sys.path.append({:test_path2}) |  | ||||||
|             sys.meta_path.append({:test_path2}) |  | ||||||
|             def test_foo(): |  | ||||||
|                 sys.path.append({:test_path3}) |  | ||||||
|                 sys.meta_path.append({:test_path3})""".format( |  | ||||||
|                 locals() |  | ||||||
|             ) |  | ||||||
|         ) |  | ||||||
|         testdir.inline_run(str(test_mod)) |  | ||||||
|         assert sys.path == original_path |  | ||||||
|         assert sys.meta_path == original_meta_path |  | ||||||
| 
 |  | ||||||
|     def spy_factory(self): |  | ||||||
|         class SysPathsSnapshotSpy(object): |  | ||||||
|             instances = [] |  | ||||||
| 
 |  | ||||||
|             def __init__(self): |  | ||||||
|                 SysPathsSnapshotSpy.instances.append(self) |  | ||||||
|                 self._spy_restore_count = 0 |  | ||||||
|                 self.__snapshot = SysPathsSnapshot() |  | ||||||
| 
 |  | ||||||
|             def restore(self): |  | ||||||
|                 self._spy_restore_count += 1 |  | ||||||
|                 return self.__snapshot.restore() |  | ||||||
| 
 |  | ||||||
|         return SysPathsSnapshotSpy |  | ||||||
| 
 |  | ||||||
|     def test_inline_run_taking_and_restoring_a_sys_paths_snapshot( |  | ||||||
|         self, testdir, monkeypatch |  | ||||||
|     ): |  | ||||||
|         spy_factory = self.spy_factory() |  | ||||||
|         monkeypatch.setattr(pytester, "SysPathsSnapshot", spy_factory) |  | ||||||
|         test_mod = testdir.makepyfile("def test_foo(): pass") |  | ||||||
|         testdir.inline_run(str(test_mod)) |  | ||||||
|         assert len(spy_factory.instances) == 1 |  | ||||||
|         spy = spy_factory.instances[0] |  | ||||||
|         assert spy._spy_restore_count == 1 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def test_assert_outcomes_after_pytest_error(testdir): | def test_assert_outcomes_after_pytest_error(testdir): | ||||||
|     testdir.makepyfile("def test_foo(): assert True") |     testdir.makepyfile("def test_foo(): assert True") | ||||||
| 
 | 
 | ||||||
|  | @ -447,3 +396,8 @@ class TestSysPathsSnapshot(object): | ||||||
| def test_testdir_subprocess(testdir): | def test_testdir_subprocess(testdir): | ||||||
|     testfile = testdir.makepyfile("def test_one(): pass") |     testfile = testdir.makepyfile("def test_one(): pass") | ||||||
|     assert testdir.runpytest_subprocess(testfile).ret == 0 |     assert testdir.runpytest_subprocess(testfile).ret == 0 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def test_unicode_args(testdir): | ||||||
|  |     result = testdir.runpytest("-k", u"💩") | ||||||
|  |     assert result.ret == EXIT_NOTESTSCOLLECTED | ||||||
|  |  | ||||||
|  | @ -4,9 +4,9 @@ terminal reporting of the full testing process. | ||||||
| from __future__ import absolute_import, division, print_function | from __future__ import absolute_import, division, print_function | ||||||
| import collections | import collections | ||||||
| import sys | import sys | ||||||
|  | import textwrap | ||||||
| 
 | 
 | ||||||
| import pluggy | import pluggy | ||||||
| import _pytest._code |  | ||||||
| import py | import py | ||||||
| import pytest | import pytest | ||||||
| from _pytest.main import EXIT_NOTESTSCOLLECTED | from _pytest.main import EXIT_NOTESTSCOLLECTED | ||||||
|  | @ -161,8 +161,8 @@ class TestTerminal(object): | ||||||
|     def test_itemreport_directclasses_not_shown_as_subclasses(self, testdir): |     def test_itemreport_directclasses_not_shown_as_subclasses(self, testdir): | ||||||
|         a = testdir.mkpydir("a123") |         a = testdir.mkpydir("a123") | ||||||
|         a.join("test_hello123.py").write( |         a.join("test_hello123.py").write( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 class TestClass(object): |                 class TestClass(object): | ||||||
|                     def test_method(self): |                     def test_method(self): | ||||||
|                         pass |                         pass | ||||||
|  | @ -312,8 +312,8 @@ class TestCollectonly(object): | ||||||
|         result = testdir.runpytest("--collect-only", p) |         result = testdir.runpytest("--collect-only", p) | ||||||
|         assert result.ret == 2 |         assert result.ret == 2 | ||||||
|         result.stdout.fnmatch_lines( |         result.stdout.fnmatch_lines( | ||||||
|             _pytest._code.Source( |             textwrap.dedent( | ||||||
|                 """ |                 """\ | ||||||
|                 *ERROR* |                 *ERROR* | ||||||
|                 *ImportError* |                 *ImportError* | ||||||
|                 *No module named *Errlk* |                 *No module named *Errlk* | ||||||
|  | @ -948,6 +948,46 @@ def pytest_report_header(config, startdir): | ||||||
|         assert "!This is stderr!" not in stdout |         assert "!This is stderr!" not in stdout | ||||||
|         assert "!This is a warning log msg!" not in stdout |         assert "!This is a warning log msg!" not in stdout | ||||||
| 
 | 
 | ||||||
|  |     def test_show_capture_with_teardown_logs(self, testdir): | ||||||
|  |         """Ensure that the capturing of teardown logs honor --show-capture setting""" | ||||||
|  |         testdir.makepyfile( | ||||||
|  |             """ | ||||||
|  |             import logging | ||||||
|  |             import sys | ||||||
|  |             import pytest | ||||||
|  | 
 | ||||||
|  |             @pytest.fixture(scope="function", autouse="True") | ||||||
|  |             def hook_each_test(request): | ||||||
|  |                 yield | ||||||
|  |                 sys.stdout.write("!stdout!") | ||||||
|  |                 sys.stderr.write("!stderr!") | ||||||
|  |                 logging.warning("!log!") | ||||||
|  | 
 | ||||||
|  |             def test_func(): | ||||||
|  |                 assert False | ||||||
|  |         """ | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         result = testdir.runpytest("--show-capture=stdout", "--tb=short").stdout.str() | ||||||
|  |         assert "!stdout!" in result | ||||||
|  |         assert "!stderr!" not in result | ||||||
|  |         assert "!log!" not in result | ||||||
|  | 
 | ||||||
|  |         result = testdir.runpytest("--show-capture=stderr", "--tb=short").stdout.str() | ||||||
|  |         assert "!stdout!" not in result | ||||||
|  |         assert "!stderr!" in result | ||||||
|  |         assert "!log!" not in result | ||||||
|  | 
 | ||||||
|  |         result = testdir.runpytest("--show-capture=log", "--tb=short").stdout.str() | ||||||
|  |         assert "!stdout!" not in result | ||||||
|  |         assert "!stderr!" not in result | ||||||
|  |         assert "!log!" in result | ||||||
|  | 
 | ||||||
|  |         result = testdir.runpytest("--show-capture=no", "--tb=short").stdout.str() | ||||||
|  |         assert "!stdout!" not in result | ||||||
|  |         assert "!stderr!" not in result | ||||||
|  |         assert "!log!" not in result | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| @pytest.mark.xfail("not hasattr(os, 'dup')") | @pytest.mark.xfail("not hasattr(os, 'dup')") | ||||||
| def test_fdopen_kept_alive_issue124(testdir): | def test_fdopen_kept_alive_issue124(testdir): | ||||||
|  | @ -1078,9 +1118,9 @@ def test_terminal_summary_warnings_are_displayed(testdir): | ||||||
| ) | ) | ||||||
| def test_summary_stats(exp_line, exp_color, stats_arg): | def test_summary_stats(exp_line, exp_color, stats_arg): | ||||||
|     print("Based on stats: %s" % stats_arg) |     print("Based on stats: %s" % stats_arg) | ||||||
|     print('Expect summary: "%s"; with color "%s"' % (exp_line, exp_color)) |     print('Expect summary: "{}"; with color "{}"'.format(exp_line, exp_color)) | ||||||
|     (line, color) = build_summary_stats_line(stats_arg) |     (line, color) = build_summary_stats_line(stats_arg) | ||||||
|     print('Actually got:   "%s"; with color "%s"' % (line, color)) |     print('Actually got:   "{}"; with color "{}"'.format(line, color)) | ||||||
|     assert line == exp_line |     assert line == exp_line | ||||||
|     assert color == exp_color |     assert color == exp_color | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										7
									
								
								tox.ini
								
								
								
								
							
							
						
						
									
										7
									
								
								tox.ini
								
								
								
								
							|  | @ -36,8 +36,7 @@ commands = | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| [testenv:linting] | [testenv:linting] | ||||||
| skipsdist = True | skip_install = True | ||||||
| usedevelop = True |  | ||||||
| basepython = python3.6 | basepython = python3.6 | ||||||
| deps = pre-commit | deps = pre-commit | ||||||
| commands = pre-commit run --all-files --show-diff-on-failure | commands = pre-commit run --all-files --show-diff-on-failure | ||||||
|  | @ -163,16 +162,18 @@ commands = | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| [testenv:coveralls] | [testenv:coveralls] | ||||||
| passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH COVERALLS_REPO_TOKEN | passenv = CI TRAVIS TRAVIS_* COVERALLS_REPO_TOKEN | ||||||
| usedevelop = True | usedevelop = True | ||||||
| changedir = . | changedir = . | ||||||
| deps = | deps = | ||||||
|     {[testenv]deps} |     {[testenv]deps} | ||||||
|     coveralls |     coveralls | ||||||
|  |     codecov | ||||||
| commands = | commands = | ||||||
|     coverage run --source=_pytest -m pytest testing |     coverage run --source=_pytest -m pytest testing | ||||||
|     coverage report -m |     coverage report -m | ||||||
|     coveralls |     coveralls | ||||||
|  |     codecov | ||||||
| 
 | 
 | ||||||
| [testenv:release] | [testenv:release] | ||||||
| decription = do a release, required posarg of the version number | decription = do a release, required posarg of the version number | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue