Skip to content

Merge master into features #3831

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 58 commits into from
Aug 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
dff7b20
tox: clean up docs target
blueyed Jun 7, 2018
dcafb8c
Add example for package recursion bug
nicoddemus Aug 2, 2018
fe0a76e
Fix recursion bug if a pytest_ignore_collect returns False instead of…
nicoddemus Aug 3, 2018
0a1c2a7
Add a changelog blurb and title, similar to tox
nicoddemus Aug 4, 2018
ef8ec01
Fix issue where fixtures would lose the decorated functionality
nicoddemus Aug 4, 2018
2c0d2ee
Only consider actual functions when considering hooks
nicoddemus Aug 4, 2018
d117819
Merge pull request #3782 from nicoddemus/pytest-non-functions
nicoddemus Aug 5, 2018
855fd17
Merge pull request #3779 from nicoddemus/changelog-title
nicoddemus Aug 5, 2018
e723069
Merge pull request #3771 from nicoddemus/package-infinite-recursion-bug
nicoddemus Aug 6, 2018
aa35843
Fix AttributeError bug in TestCaseFunction.teardown by creating TestC…
westhomas Aug 8, 2018
051db6a
Trimming Trailing Whitespace
westhomas Aug 8, 2018
74d9f56
Improve CHANGELOG a bit
nicoddemus Aug 9, 2018
5d3c512
Merge pull request #3792 from decisio/pr-3788-fix-teardown-exception
RonnyPfannschmidt Aug 9, 2018
67106f0
Use a custom holder class so we can be sure __pytest_wrapper__ was se…
nicoddemus Aug 9, 2018
4d8903f
Merge pull request #3780 from nicoddemus/mock-integration-fix
nicoddemus Aug 9, 2018
220288a
Add CHANGELOG for issue #3774, missing from PR #3780
nicoddemus Aug 9, 2018
266f05c
Fix #3751
Aug 10, 2018
be11d3e
Improve warning messages when addoption is called with string as `type`
nicoddemus Aug 10, 2018
bfd0add
Fix test collection from packages mixed with directories. #3768 and #…
Aug 10, 2018
50db718
Add a test description.
Aug 10, 2018
27b5435
Fix docs formatting and improve test a bit
nicoddemus Aug 10, 2018
e92893e
Add test for packages mixed with modules.
Aug 11, 2018
abae60c
Add CHANGELOG entries
nicoddemus Aug 11, 2018
abbd7c3
Unhide documentation for metafunc.config
keysmashes Aug 11, 2018
87a9927
Merge pull request #3807 from anowlcalledjosh/metafunc-config-doc
asottile Aug 13, 2018
22ee209
Merge pull request #3801 from nicoddemus/improve-warning-addoption
RonnyPfannschmidt Aug 14, 2018
68bbd42
Merge pull request #3795 from nicoddemus/changelog-3774
RonnyPfannschmidt Aug 14, 2018
b88e09a
Merge pull request #3548 from blueyed/fix-docs
blueyed Aug 14, 2018
6367f0f
fix `filterwarnings` mark not registered
sankt-petersbug Aug 14, 2018
cb77e65
updated AUTHORS
sankt-petersbug Aug 14, 2018
e06a077
added changelog
sankt-petersbug Aug 14, 2018
c1c0885
lint checks
sankt-petersbug Aug 15, 2018
212ee45
simplified test function
sankt-petersbug Aug 15, 2018
78ef531
corrected the position of myname
sankt-petersbug Aug 15, 2018
ca1bb9a
Merge pull request #3815 from sankt-petersbug/fix-3671
asottile Aug 16, 2018
64faa41
Merge pull request #3802 from jonozzz/fix-3768
nicoddemus Aug 16, 2018
17644ff
Fix traceback reporting for exceptions with `__cause__` cycles.
asottile Aug 11, 2018
939a792
Merge pull request #3798 from jonozzz/fix-3751
RonnyPfannschmidt Aug 16, 2018
7d4c4c6
Merge pull request #3805 from asottile/cause_cycles
RonnyPfannschmidt Aug 16, 2018
da9d814
Added test.
Aug 16, 2018
2b71cb9
Added activation/deactivation of capture fixture in logging emit.
Aug 16, 2018
e5a3c87
Preparing release version 3.7.2
nicoddemus Aug 16, 2018
e0b088b
Changelog tweaks
nicoddemus Aug 16, 2018
f66764e
Added changelog and updated AUTHORS.
Aug 16, 2018
e391c47
Update capture suspend test for logging.
Aug 16, 2018
3059bfb
Update test with another problem.
Aug 17, 2018
090f67a
Refactored implementation and updated tests.
Aug 17, 2018
c3e494f
Replace broken type annotations with type comments
Vlad-Shcherbina Aug 17, 2018
14db2f9
Fixed global not called if no capsys fixture. Using now capsys contex…
Aug 18, 2018
9fa7745
Refactor, tests passing.
Aug 18, 2018
eb2d074
Black changes.
Aug 18, 2018
9f7345d
Avoid leaving a reference to the last item on CaptureManager
nicoddemus Aug 18, 2018
f674217
Moved dummy_context_manager to compat module
nicoddemus Aug 18, 2018
2fe824b
Merge pull request #3821 from nicoddemus/release-3.7.2
nicoddemus Aug 18, 2018
5cf7d1d
"suspend" method of capture fixture private
nicoddemus Aug 18, 2018
29975e5
Merge pull request #3827 from Vlad-Shcherbina/funcfixtureinfo-type-hints
nicoddemus Aug 18, 2018
28aff05
Merge pull request #3822 from Sup3rGeo/bugfix/capsys-with-cli-logging
nicoddemus Aug 18, 2018
c64a8c9
Merge remote-tracking branch 'upstream/master' into merge-master-into…
nicoddemus Aug 18, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ Russel Winder
Ryan Wooden
Samuel Dion-Girardeau
Samuele Pedroni
Sankt Petersbug
Segev Finer
Serhii Mozghovyi
Simon Gomizelj
Expand All @@ -205,6 +206,7 @@ Trevor Bekolay
Tyler Goodlet
Tzu-ping Chung
Vasily Kuznetsov
Victor Maryama
Victor Uriarte
Vidar T. Fauske
Virgil Dupras
Expand Down
44 changes: 44 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
=================
Changelog history
=================

Versions follow `Semantic Versioning <https://semver.org/>`_ (``<major>.<minor>.<patch>``).

Backward incompatible (breaking) changes will only be introduced in major versions
with advance notice in the **Deprecations** section of releases.


..
You should *NOT* be adding new change log entries to this file, this
file is managed by towncrier. You *may* edit previous change logs to
Expand All @@ -8,6 +18,40 @@

.. towncrier release notes start

pytest 3.7.2 (2018-08-16)
=========================

Bug Fixes
---------

- `#3671 <https://github.com/pytest-dev/pytest/issues/3671>`_: Fix ``filterwarnings`` not being registered as a builtin mark.


- `#3768 <https://github.com/pytest-dev/pytest/issues/3768>`_, `#3789 <https://github.com/pytest-dev/pytest/issues/3789>`_: Fix test collection from packages mixed with normal directories.


- `#3771 <https://github.com/pytest-dev/pytest/issues/3771>`_: Fix infinite recursion during collection if a ``pytest_ignore_collect`` hook returns ``False`` instead of ``None``.


- `#3774 <https://github.com/pytest-dev/pytest/issues/3774>`_: Fix bug where decorated fixtures would lose functionality (for example ``@mock.patch``).


- `#3775 <https://github.com/pytest-dev/pytest/issues/3775>`_: Fix bug where importing modules or other objects with prefix ``pytest_`` prefix would raise a ``PluginValidationError``.


- `#3788 <https://github.com/pytest-dev/pytest/issues/3788>`_: Fix ``AttributeError`` during teardown of ``TestCase`` subclasses which raise an exception during ``__init__``.


- `#3804 <https://github.com/pytest-dev/pytest/issues/3804>`_: Fix traceback reporting for exceptions with ``__cause__`` cycles.



Improved Documentation
----------------------

- `#3746 <https://github.com/pytest-dev/pytest/issues/3746>`_: Add documentation for ``metafunc.config`` that had been mistakenly hidden.


pytest 3.7.1 (2018-08-02)
=========================

Expand Down
1 change: 1 addition & 0 deletions changelog/3819.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix ``stdout/stderr`` not getting captured when real-time cli logging is active.
1 change: 1 addition & 0 deletions changelog/3826.trivial.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Replace broken type annotations with type comments.
1 change: 1 addition & 0 deletions doc/en/announce/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Release announcements
:maxdepth: 2


release-3.7.2
release-3.7.1
release-3.7.0
release-3.6.4
Expand Down
25 changes: 25 additions & 0 deletions doc/en/announce/release-3.7.2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
pytest-3.7.2
=======================================

pytest 3.7.2 has just been released to PyPI.

This is a bug-fix release, being a drop-in replacement. To upgrade::

pip install --upgrade pytest

The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.

Thanks to all who contributed to this release, among them:

* Anthony Sottile
* Bruno Oliveira
* Daniel Hahler
* Josh Holland
* Ronny Pfannschmidt
* Sankt Petersbug
* Wes Thomas
* turturica


Happy testing,
The pytest Development Team
3 changes: 0 additions & 3 deletions doc/en/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@

.. _changelog:

Changelog history
=================================

.. include:: ../../CHANGELOG.rst
4 changes: 4 additions & 0 deletions doc/en/example/markers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ You can ask which markers exist for your test suite - the list includes our just
$ pytest --markers
@pytest.mark.webtest: mark a test as a webtest.

@pytest.mark.filterwarnings(warning): add a warning filter to the given test. see http://pytest.org/latest/warnings.html#pytest-mark-filterwarnings

@pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.

@pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html
Expand Down Expand Up @@ -374,6 +376,8 @@ The ``--markers`` option always gives you a list of available markers::
$ pytest --markers
@pytest.mark.env(name): mark test to run only on named environment

@pytest.mark.filterwarnings(warning): add a warning filter to the given test. see http://pytest.org/latest/warnings.html#pytest-mark-filterwarnings

@pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.

@pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html
Expand Down
7 changes: 4 additions & 3 deletions doc/en/example/nonpython.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ interesting to just look at the collection tree::
platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
collected 2 items
<YamlFile 'test_simple.yml'>
<YamlItem 'hello'>
<YamlItem 'ok'>
<Package '$REGENDOC_TMPDIR/nonpython'>
<YamlFile 'test_simple.yml'>
<YamlItem 'hello'>
<YamlItem 'ok'>

======================= no tests ran in 0.12 seconds =======================
7 changes: 3 additions & 4 deletions doc/en/example/parametrize.rst
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,10 @@ is to be run with different sets of arguments for its three arguments:
Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (5 interpreters times 5 interpreters times 3 objects to serialize/deserialize)::

. $ pytest -rs -q multipython.py
...ssssssssssssssssssssssss [100%]
...sss...sssssssss...sss... [100%]
========================= short test summary info ==========================
SKIP [12] $REGENDOC_TMPDIR/CWD/multipython.py:28: 'python3.4' not found
SKIP [12] $REGENDOC_TMPDIR/CWD/multipython.py:28: 'python3.5' not found
3 passed, 24 skipped in 0.12 seconds
SKIP [15] $REGENDOC_TMPDIR/CWD/multipython.py:28: 'python3.4' not found
12 passed, 15 skipped in 0.12 seconds

Indirect parametrization of optional implementations/imports
--------------------------------------------------------------------
Expand Down
4 changes: 3 additions & 1 deletion src/_pytest/_code/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,9 @@ def repr_excinfo(self, excinfo):
repr_chain = []
e = excinfo.value
descr = None
while e is not None:
seen = set()
while e is not None and id(e) not in seen:
seen.add(id(e))
if excinfo:
reprtraceback = self.repr_traceback(excinfo)
reprcrash = excinfo._getreprcrash()
Expand Down
37 changes: 30 additions & 7 deletions src/_pytest/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

import six
import pytest
from _pytest.compat import CaptureIO

from _pytest.compat import CaptureIO, dummy_context_manager

patchsysdict = {0: "stdin", 1: "stdout", 2: "stderr"}

Expand Down Expand Up @@ -85,6 +84,7 @@ class CaptureManager(object):
def __init__(self, method):
self._method = method
self._global_capturing = None
self._current_item = None

def _getcapture(self, method):
if method == "fd":
Expand Down Expand Up @@ -121,6 +121,19 @@ def suspend_global_capture(self, item=None, in_=False):
cap.suspend_capturing(in_=in_)
return outerr

@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
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):
"""If the current item is using ``capsys`` or ``capfd``, activate them so they take precedence over
the global capture.
Expand Down Expand Up @@ -151,28 +164,34 @@ def pytest_make_collect_report(self, collector):

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_setup(self, 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
self.suspend_capture_item(item, "setup")
self._current_item = None

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_call(self, item):
self._current_item = 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
self.suspend_capture_item(item, "call")
self._current_item = None

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_teardown(self, item):
self._current_item = item
self.resume_global_capture()
self.activate_fixture(item)
yield
self.suspend_capture_item(item, "teardown")
self._current_item = None

@pytest.hookimpl(tryfirst=True)
def pytest_keyboard_interrupt(self, excinfo):
Expand Down Expand Up @@ -314,17 +333,21 @@ def readouterr(self):
return self._outerr

@contextlib.contextmanager
def disabled(self):
"""Temporarily disables capture while inside the 'with' block."""
def _suspend(self):
"""Suspends this fixture's own capturing temporarily."""
self._capture.suspend_capturing()
capmanager = self.request.config.pluginmanager.getplugin("capturemanager")
capmanager.suspend_global_capture(item=None, in_=False)
try:
yield
finally:
capmanager.resume_global_capture()
self._capture.resume_capturing()

@contextlib.contextmanager
def disabled(self):
"""Temporarily disables capture while inside the 'with' block."""
capmanager = self.request.config.pluginmanager.getplugin("capturemanager")
with capmanager.global_and_fixture_disabled():
yield


def safe_text_dupfile(f, mode, default_encoding="UTF8"):
""" return an open text file object that's a duplicate of f on the
Expand Down
27 changes: 27 additions & 0 deletions src/_pytest/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import inspect
import re
import sys
from contextlib import contextmanager

import py

Expand Down Expand Up @@ -151,6 +152,13 @@ def getfuncargnames(function, is_method=False, cls=None):
return arg_names


@contextmanager
def dummy_context_manager():
"""Context manager that does nothing, useful in situations where you might need an actual context manager or not
depending on some condition. Using this allow to keep the same code"""
yield


def get_default_arg_names(function):
# Note: this code intentionally mirrors the code at the beginning of getfuncargnames,
# to get the arguments which were excluded from its result because they had default values
Expand Down Expand Up @@ -228,12 +236,31 @@ def ascii_escaped(val):
return val.encode("unicode-escape")


class _PytestWrapper(object):
"""Dummy wrapper around a function object for internal use only.

Used to correctly unwrap the underlying function object
when we are creating fixtures, because we wrap the function object ourselves with a decorator
to issue warnings when the fixture function is called directly.
"""

def __init__(self, obj):
self.obj = obj


def get_real_func(obj):
""" gets the real function object of the (possibly) wrapped object by
functools.wraps or functools.partial.
"""
start_obj = obj
for i in range(100):
# __pytest_wrapped__ is set by @pytest.fixture when wrapping the fixture function
# to trigger a warning if it gets called directly instead of by pytest: we don't
# want to unwrap further than this otherwise we lose useful wrappings like @mock.patch (#3774)
new_obj = getattr(obj, "__pytest_wrapped__", None)
if isinstance(new_obj, _PytestWrapper):
obj = new_obj.obj
break
new_obj = getattr(obj, "__wrapped__", None)
if new_obj is None:
break
Expand Down
5 changes: 5 additions & 0 deletions src/_pytest/config/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
""" command line options, ini-file and conftest.py processing. """
from __future__ import absolute_import, division, print_function
import argparse
import inspect
import shlex
import traceback
import types
Expand Down Expand Up @@ -252,6 +253,10 @@ def parse_hookimpl_opts(self, plugin, name):
method = getattr(plugin, name)
opts = super(PytestPluginManager, self).parse_hookimpl_opts(plugin, name)

# consider only actual functions for hooks (#3775)
if not inspect.isroutine(method):
return

# collect unmarked hooks as long as they have the `pytest_' prefix
if opts is None and name.startswith("pytest_"):
opts = {}
Expand Down
14 changes: 7 additions & 7 deletions src/_pytest/config/argparsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,23 +174,23 @@ def __init__(self, *names, **attrs):
if isinstance(typ, six.string_types):
if typ == "choice":
warnings.warn(
"type argument to addoption() is a string %r."
" For parsearg this is optional and when supplied"
" should be a type."
"`type` argument to addoption() is the string %r."
" For choices this is optional and can be omitted, "
" but when supplied should be a type (for example `str` or `int`)."
" (options: %s)" % (typ, names),
DeprecationWarning,
stacklevel=3,
stacklevel=4,
)
# argparse expects a type here take it from
# the type of the first element
attrs["type"] = type(attrs["choices"][0])
else:
warnings.warn(
"type argument to addoption() is a string %r."
" For parsearg this should be a type."
"`type` argument to addoption() is the string %r, "
" but when supplied should be a type (for example `str` or `int`)."
" (options: %s)" % (typ, names),
DeprecationWarning,
stacklevel=3,
stacklevel=4,
)
attrs["type"] = Argument._typ_map[typ]
# used in test_parseopt -> test_parse_defaultgetter
Expand Down
Loading