[Python-modules-commits] [pytest] 01/06: Import pytest_3.0.4.orig.tar.gz

Sebastian Ramacher sramacher at moszumanska.debian.org
Tue Nov 15 22:19:10 UTC 2016


This is an automated email from the git hooks/post-receive script.

sramacher pushed a commit to branch master
in repository pytest.

commit a1b7b4becdc2cab51918c0c562cfd75cdcb0111b
Author: Sebastian Ramacher <sramacher at debian.org>
Date:   Tue Nov 15 22:56:15 2016 +0100

    Import pytest_3.0.4.orig.tar.gz
---
 AUTHORS                             |  4 +++
 CHANGELOG.rst                       | 61 +++++++++++++++++++++++++++++++++++--
 PKG-INFO                            |  2 +-
 _pytest/__init__.py                 |  2 +-
 _pytest/_code/code.py               | 20 ++++++++----
 _pytest/assertion/rewrite.py        |  7 ++++-
 _pytest/compat.py                   | 16 +++++++++-
 _pytest/config.py                   |  5 +--
 _pytest/helpconfig.py               |  4 +--
 _pytest/junitxml.py                 |  6 +++-
 _pytest/pytester.py                 |  2 --
 _pytest/python.py                   | 58 +++++++++++++++++++++++------------
 _pytest/recwarn.py                  |  7 ++++-
 _pytest/terminal.py                 | 12 ++++++++
 _pytest/unittest.py                 |  3 ++
 doc/en/announce/index.rst           |  1 +
 doc/en/announce/release-3.0.4.rst   | 29 ++++++++++++++++++
 doc/en/assert.rst                   |  4 +--
 doc/en/cache.rst                    |  6 ++--
 doc/en/capture.rst                  |  2 +-
 doc/en/doctest.rst                  |  2 +-
 doc/en/example/markers.rst          | 28 ++++++++---------
 doc/en/example/nonpython.rst        |  6 ++--
 doc/en/example/parametrize.rst      | 12 ++++----
 doc/en/example/pythoncollection.rst |  6 ++--
 doc/en/example/reportingdemo.rst    |  4 +--
 doc/en/example/simple.rst           | 22 ++++++-------
 doc/en/fixture.rst                  | 16 ++++++----
 doc/en/getting-started.rst          |  4 +--
 doc/en/goodpractices.rst            |  3 +-
 doc/en/index.rst                    |  2 +-
 doc/en/monkeypatch.rst              |  8 +++++
 doc/en/parametrize.rst              |  4 +--
 doc/en/skipping.rst                 |  2 +-
 doc/en/talks.rst                    |  2 +-
 doc/en/tmpdir.rst                   |  2 +-
 doc/en/unittest.rst                 |  2 +-
 doc/en/usage.rst                    |  4 ---
 pytest.egg-info/PKG-INFO            |  2 +-
 pytest.egg-info/SOURCES.txt         |  1 +
 pytest.egg-info/entry_points.txt    |  2 +-
 pytest.egg-info/requires.txt        |  6 ++--
 testing/acceptance_test.py          |  2 +-
 testing/code/test_excinfo.py        | 44 ++++++++++++++++++++++++++
 testing/python/collect.py           | 35 ++++++++++++++++++++-
 testing/python/raises.py            | 30 ++++++++++++++++++
 testing/test_assertion.py           | 31 +++++++++++++++++++
 testing/test_assertrewrite.py       | 16 ++++++++++
 testing/test_collection.py          | 11 -------
 testing/test_junitxml.py            | 24 +++++++++++++++
 testing/test_parseopt.py            | 14 ++++++++-
 testing/test_pdb.py                 | 47 +++++++++++++---------------
 testing/test_pluginmanager.py       | 12 ++++++--
 testing/test_skipping.py            |  2 +-
 testing/test_terminal.py            | 27 +++++++++++++++-
 testing/test_unittest.py            | 23 ++++++++++++++
 tox.ini                             | 28 +++++++++++------
 57 files changed, 570 insertions(+), 167 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index d8c431d..6de0a11 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -36,6 +36,7 @@ Christopher Gilling
 Daniel Grana
 Daniel Hahler
 Daniel Nuri
+Daniel Wandschneider
 Danielle Jenkins
 Dave Hunt
 David Díaz-Barquero
@@ -59,6 +60,7 @@ Georgy Dyuldin
 Graham Horler
 Greg Price
 Grig Gheorghiu
+Grigorii Eremeev (budulianin)
 Guido Wesdorp
 Harald Armin Massa
 Ian Bicking
@@ -89,6 +91,7 @@ Markus Unterwaditzer
 Martijn Faassen
 Martin K. Scherer
 Martin Prusse
+Mathieu Clabaut
 Matt Bachmann
 Matt Williams
 Matthias Hafner
@@ -96,6 +99,7 @@ mbyt
 Michael Aquilina
 Michael Birtwell
 Michael Droettboom
+Michael Seifert
 Mike Lundy
 Nicolas Delaby
 Oleg Pidsadnyi
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 4f6be4f..178e540 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,3 +1,57 @@
+3.0.4
+=====
+
+* Import errors when collecting test modules now display the full traceback (`#1976`_).
+  Thanks `@cwitty`_ for the report and `@nicoddemus`_ for the PR.
+
+* Fix confusing command-line help message for custom options with two or more ``metavar`` properties (`#2004`_).
+  Thanks `@okulynyak`_ and `@davehunt`_ for the report and `@nicoddemus`_ for the PR.
+
+* When loading plugins, import errors which contain non-ascii messages are now properly handled in Python 2 (`#1998`_).
+  Thanks `@nicoddemus`_ for the PR.
+
+* Fixed cyclic reference when ``pytest.raises`` is used in context-manager form (`#1965`_). Also as a
+  result of this fix, ``sys.exc_info()`` is left empty in both context-manager and function call usages.
+  Previously, ``sys.exc_info`` would contain the exception caught by the context manager,
+  even when the expected exception occurred.
+  Thanks `@MSeifert04`_ for the report and the PR.
+
+* Fixed false-positives warnings from assertion rewrite hook for modules that were rewritten but
+  were later marked explicitly by ``pytest.register_assert_rewrite``
+  or implicitly as a plugin (`#2005`_).
+  Thanks `@RonnyPfannschmidt`_ for the report and `@nicoddemus`_ for the PR.
+
+* Report teardown output on test failure (`#442`_).
+  Thanks `@matclab`_ or the PR.
+
+* Fix teardown error message in generated xUnit XML.
+  Thanks `@gdyuldin`_ or the PR.
+
+* Properly handle exceptions in ``multiprocessing`` tasks (`#1984`_).
+  Thanks `@adborden`_ for the report and `@nicoddemus`_ for the PR.
+
+* Clean up unittest TestCase objects after tests are complete (`#1649`_).
+  Thanks `@d_b_w`_ for the report and PR.
+
+
+.. _ at adborden: https://github.com/adborden
+.. _ at cwitty: https://github.com/cwitty
+.. _ at d_b_w: https://github.com/d_b_w
+.. _ at gdyuldin: https://github.com/gdyuldin
+.. _ at matclab: https://github.com/matclab
+.. _ at MSeifert04: https://github.com/MSeifert04
+.. _ at okulynyak: https://github.com/okulynyak
+
+.. _#442: https://github.com/pytest-dev/pytest/issues/442
+.. _#1965: https://github.com/pytest-dev/pytest/issues/1965
+.. _#1976: https://github.com/pytest-dev/pytest/issues/1976
+.. _#1984: https://github.com/pytest-dev/pytest/issues/1984
+.. _#1998: https://github.com/pytest-dev/pytest/issues/1998
+.. _#2004: https://github.com/pytest-dev/pytest/issues/2004
+.. _#2005: https://github.com/pytest-dev/pytest/issues/2005
+.. _#1649: https://github.com/pytest-dev/pytest/issues/1649
+
+
 3.0.3
 =====
 
@@ -9,7 +63,7 @@
   (``pip install -e``) (`#1934`_).
   Thanks `@nicoddemus`_ for the PR.
 
-* Fix pkg_resources import error in Jython projects (`#1853`).
+* Fix pkg_resources import error in Jython projects (`#1853`_).
   Thanks `@raquel-ucl`_ for the PR.
 
 * Got rid of ``AttributeError: 'Module' object has no attribute '_obj'`` exception
@@ -29,6 +83,7 @@
 .. _ at axil: https://github.com/axil
 .. _ at tgoodlet: https://github.com/tgoodlet
 
+.. _#1853: https://github.com/pytest-dev/pytest/issues/1853
 .. _#1905: https://github.com/pytest-dev/pytest/issues/1905
 .. _#1934: https://github.com/pytest-dev/pytest/issues/1934
 .. _#1944: https://github.com/pytest-dev/pytest/issues/1944
@@ -59,7 +114,7 @@
   enabled. This allows proper post mortem debugging for all applications
   which have significant logic in their tearDown machinery (`#1890`_). Thanks
   `@mbyt`_ for the PR.
-  
+
 * Fix use of deprecated ``getfuncargvalue`` method in the internal doctest plugin.
   Thanks `@ViviCoder`_ for the report (`#1898`_).
 
@@ -356,7 +411,7 @@ time or change existing behaviors in order to make them less surprising/more use
 
 * Refined logic for determining the ``rootdir``, considering only valid
   paths which fixes a number of issues: `#1594`_, `#1435`_ and `#1471`_.
-  Updated the documentation according to current behavior. Thanks to 
+  Updated the documentation according to current behavior. Thanks to
   `@blueyed`_, `@davehunt`_ and `@matthiasha`_ for the PR.
 
 * Always include full assertion explanation. The previous behaviour was hiding
diff --git a/PKG-INFO b/PKG-INFO
index b8b5ae8..a6bdd4a 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: pytest
-Version: 3.0.3
+Version: 3.0.4
 Summary: pytest: simple powerful testing with Python
 Home-page: http://pytest.org
 Author: Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others
diff --git a/_pytest/__init__.py b/_pytest/__init__.py
index 4c3823e..97cf252 100644
--- a/_pytest/__init__.py
+++ b/_pytest/__init__.py
@@ -1,2 +1,2 @@
 #
-__version__ = '3.0.3'
+__version__ = '3.0.4'
diff --git a/_pytest/_code/code.py b/_pytest/_code/code.py
index 30e1294..5b42379 100644
--- a/_pytest/_code/code.py
+++ b/_pytest/_code/code.py
@@ -1,6 +1,7 @@
 import sys
 from inspect import CO_VARARGS, CO_VARKEYWORDS
 import re
+from weakref import ref
 
 import py
 builtin_repr = repr
@@ -230,7 +231,7 @@ class TracebackEntry(object):
                 return False
 
         if py.builtin.callable(tbh):
-            return tbh(self._excinfo)
+            return tbh(None if self._excinfo is None else self._excinfo())
         else:
             return tbh
 
@@ -370,7 +371,7 @@ class ExceptionInfo(object):
         #: the exception type name
         self.typename = self.type.__name__
         #: the exception traceback (_pytest._code.Traceback instance)
-        self.traceback = _pytest._code.Traceback(self.tb, excinfo=self)
+        self.traceback = _pytest._code.Traceback(self.tb, excinfo=ref(self))
 
     def __repr__(self):
         return "<ExceptionInfo %s tblen=%d>" % (self.typename, len(self.traceback))
@@ -623,16 +624,23 @@ class FormattedExcinfo(object):
             e = excinfo.value
             descr = None
             while e is not None:
-                reprtraceback = self.repr_traceback(excinfo)
-                reprcrash = excinfo._getreprcrash()
+                if excinfo:
+                    reprtraceback = self.repr_traceback(excinfo)
+                    reprcrash = excinfo._getreprcrash()
+                else:
+                    # fallback to native repr if the exception doesn't have a traceback:
+                    # ExceptionInfo objects require a full traceback to work
+                    reprtraceback = ReprTracebackNative(py.std.traceback.format_exception(type(e), e, None))
+                    reprcrash = None
+
                 repr_chain += [(reprtraceback, reprcrash, descr)]
                 if e.__cause__ is not None:
                     e = e.__cause__
-                    excinfo = ExceptionInfo((type(e), e, e.__traceback__))
+                    excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
                     descr = 'The above exception was the direct cause of the following exception:'
                 elif e.__context__ is not None:
                     e = e.__context__
-                    excinfo = ExceptionInfo((type(e), e, e.__traceback__))
+                    excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
                     descr = 'During handling of the above exception, another exception occurred:'
                 else:
                     e = None
diff --git a/_pytest/assertion/rewrite.py b/_pytest/assertion/rewrite.py
index 80d6ee3..6b4c1f4 100644
--- a/_pytest/assertion/rewrite.py
+++ b/_pytest/assertion/rewrite.py
@@ -51,6 +51,7 @@ class AssertionRewritingHook(object):
         self.fnpats = config.getini("python_files")
         self.session = None
         self.modules = {}
+        self._rewritten_names = set()
         self._register_with_pkg_resources()
         self._must_rewrite = set()
 
@@ -92,6 +93,8 @@ class AssertionRewritingHook(object):
         if not self._should_rewrite(name, fn_pypath, state):
             return None
 
+        self._rewritten_names.add(name)
+
         # The requested module looks like a test file, so rewrite it. This is
         # the most magical part of the process: load the source, rewrite the
         # asserts, and load the rewritten source. We also cache the rewritten
@@ -178,7 +181,9 @@ class AssertionRewritingHook(object):
         """
         already_imported = set(names).intersection(set(sys.modules))
         if already_imported:
-            self._warn_already_imported(already_imported)
+            for name in names:
+                if name not in self._rewritten_names:
+                    self._warn_already_imported(already_imported)
         self._must_rewrite.update(names)
 
     def _warn_already_imported(self, names):
diff --git a/_pytest/compat.py b/_pytest/compat.py
index 1d8c2f3..51fc3bc 100644
--- a/_pytest/compat.py
+++ b/_pytest/compat.py
@@ -213,4 +213,18 @@ def _is_unittest_unexpected_success_a_failure():
         Changed in version 3.4: Returns False if there were any
         unexpectedSuccesses from tests marked with the expectedFailure() decorator.
     """
-    return sys.version_info >= (3, 4)
\ No newline at end of file
+    return sys.version_info >= (3, 4)
+
+
+if _PY3:
+    def safe_str(v):
+        """returns v as string"""
+        return str(v)
+else:
+    def safe_str(v):
+        """returns v as string, converting to ascii if necessary"""
+        try:
+            return str(v)
+        except UnicodeError:
+            errors = 'replace'
+            return v.encode('ascii', errors)
diff --git a/_pytest/config.py b/_pytest/config.py
index 661a851..5df198e 100644
--- a/_pytest/config.py
+++ b/_pytest/config.py
@@ -12,6 +12,7 @@ import _pytest._code
 import _pytest.hookspec  # the extension point definitions
 import _pytest.assertion
 from _pytest._pluggy import PluginManager, HookimplMarker, HookspecMarker
+from _pytest.compat import safe_str
 
 hookimpl = HookimplMarker("pytest")
 hookspec = HookspecMarker("pytest")
@@ -405,7 +406,7 @@ class PytestPluginManager(PluginManager):
         try:
             __import__(importspec)
         except ImportError as e:
-            new_exc = ImportError('Error importing plugin "%s": %s' % (modname, e))
+            new_exc = ImportError('Error importing plugin "%s": %s' % (modname, safe_str(e.args[0])))
             # copy over name and path attributes
             for attr in ('name', 'path'):
                 if hasattr(e, attr):
@@ -792,7 +793,7 @@ class DropShorterLongHelpFormatter(argparse.HelpFormatter):
             if len(option) == 2 or option[2] == ' ':
                 return_list.append(option)
             if option[2:] == short_long.get(option.replace('-', '')):
-                return_list.append(option.replace(' ', '='))
+                return_list.append(option.replace(' ', '=', 1))
         action._formatted_action_invocation = ', '.join(return_list)
         return action._formatted_action_invocation
 
diff --git a/_pytest/helpconfig.py b/_pytest/helpconfig.py
index 84f419a..538a763 100644
--- a/_pytest/helpconfig.py
+++ b/_pytest/helpconfig.py
@@ -71,8 +71,8 @@ def showhelp(config):
     tw.write(config._parser.optparser.format_help())
     tw.line()
     tw.line()
-    tw.line("[pytest] ini-options in the next "
-            "pytest.ini|tox.ini|setup.cfg file:")
+    tw.line("[pytest] ini-options in the first "
+            "pytest.ini|tox.ini|setup.cfg file found:")
     tw.line()
 
     for name in config._parser._ininames:
diff --git a/_pytest/junitxml.py b/_pytest/junitxml.py
index da190ff..97d0675 100644
--- a/_pytest/junitxml.py
+++ b/_pytest/junitxml.py
@@ -156,8 +156,12 @@ class _NodeReporter(object):
             Junit.skipped, "collection skipped", report.longrepr)
 
     def append_error(self, report):
+        if getattr(report, 'when', None) == 'teardown':
+            msg = "test teardown failure"
+        else:
+            msg = "test setup failure"
         self._add_simple(
-            Junit.error, "test setup failure", report.longrepr)
+            Junit.error, msg, report.longrepr)
         self._write_captured_output(report)
 
     def append_skipped(self, report):
diff --git a/_pytest/pytester.py b/_pytest/pytester.py
index 651160c..a8bb397 100644
--- a/_pytest/pytester.py
+++ b/_pytest/pytester.py
@@ -1002,8 +1002,6 @@ class Testdir:
         pexpect = pytest.importorskip("pexpect", "3.0")
         if hasattr(sys, 'pypy_version_info') and '64' in platform.machine():
             pytest.skip("pypy-64 bit not supported")
-        if sys.platform == "darwin":
-            pytest.xfail("pexpect does not work reliably on darwin?!")
         if sys.platform.startswith("freebsd"):
             pytest.xfail("pexpect does not work reliably on freebsd")
         logfile = self.tmpdir.join("spawn.out").open("wb")
diff --git a/_pytest/python.py b/_pytest/python.py
index eacea99..18432c1 100644
--- a/_pytest/python.py
+++ b/_pytest/python.py
@@ -22,11 +22,16 @@ from _pytest.compat import (
     getlocation, enum,
 )
 
-cutdir2 = py.path.local(_pytest.__file__).dirpath()
 cutdir1 = py.path.local(pluggy.__file__.rstrip("oc"))
+cutdir2 = py.path.local(_pytest.__file__).dirpath()
+cutdir3 = py.path.local(py.__file__).dirpath()
 
 
 def filter_traceback(entry):
+    """Return True if a TracebackEntry instance should be removed from tracebacks:
+    * dynamically generated code (no code to show up for it);
+    * internal traceback from pytest or its internal libraries, py and pluggy.
+    """
     # entry.path might sometimes return a str object when the entry
     # points to dynamically generated code
     # see https://bitbucket.org/pytest-dev/py/issues/71
@@ -37,7 +42,7 @@ def filter_traceback(entry):
     # entry.path might point to an inexisting file, in which case it will
     # alsso return a str object. see #1133
     p = py.path.local(entry.path)
-    return p != cutdir1 and not p.relto(cutdir2)
+    return p != cutdir1 and not p.relto(cutdir2) and not p.relto(cutdir3)
 
 
 
@@ -424,20 +429,25 @@ class Module(pytest.File, PyCollector):
                  % e.args
             )
         except ImportError:
-            exc_class, exc, _ = sys.exc_info()
+            from _pytest._code.code import ExceptionInfo
+            exc_info = ExceptionInfo()
+            if self.config.getoption('verbose') < 2:
+                exc_info.traceback = exc_info.traceback.filter(filter_traceback)
+            exc_repr = exc_info.getrepr(style='short') if exc_info.traceback else exc_info.exconly()
+            formatted_tb = py._builtin._totext(exc_repr)
             raise self.CollectError(
-                "ImportError while importing test module '%s'.\n"
-                "Original error message:\n'%s'\n"
-                "Make sure your test modules/packages have valid Python names."
-                % (self.fspath, exc or exc_class)
+                "ImportError while importing test module '{fspath}'.\n"
+                "Hint: make sure your test modules/packages have valid Python names.\n"
+                "Traceback:\n"
+                "{traceback}".format(fspath=self.fspath, traceback=formatted_tb)
             )
         except _pytest.runner.Skipped as e:
             if e.allow_module_level:
                 raise
             raise self.CollectError(
-                "Using @pytest.skip outside of a test (e.g. as a test "
-                "function decorator) is not allowed. Use @pytest.mark.skip or "
-                "@pytest.mark.skipif instead."
+                "Using pytest.skip outside of a test is not allowed. If you are "
+                "trying to decorate a test function, use the @pytest.mark.skip "
+                "or @pytest.mark.skipif decorators instead."
             )
         self.config.pluginmanager.consider_module(mod)
         return mod
@@ -1095,7 +1105,9 @@ def raises(expected_exception, *args, **kwargs):
 
         >>> with raises(ZeroDivisionError, message="Expecting ZeroDivisionError"):
         ...    pass
-        ... Failed: Expecting ZeroDivisionError
+        Traceback (most recent call last):
+          ...
+        Failed: Expecting ZeroDivisionError
 
 
     .. note::
@@ -1106,19 +1118,21 @@ def raises(expected_exception, *args, **kwargs):
        Lines of code after that, within the scope of the context manager will
        not be executed. For example::
 
-           >>> with raises(OSError) as exc_info:
-                   assert 1 == 1  # this will execute as expected
-                   raise OSError(errno.EEXISTS, 'directory exists')
-                   assert exc_info.value.errno == errno.EEXISTS  # this will not execute
+           >>> value = 15
+           >>> with raises(ValueError) as exc_info:
+           ...     if value > 10:
+           ...         raise ValueError("value must be <= 10")
+           ...     assert str(exc_info.value) == "value must be <= 10"  # this will not execute
 
        Instead, the following approach must be taken (note the difference in
        scope)::
 
-           >>> with raises(OSError) as exc_info:
-                   assert 1 == 1  # this will execute as expected
-                   raise OSError(errno.EEXISTS, 'directory exists')
+           >>> with raises(ValueError) as exc_info:
+           ...     if value > 10:
+           ...         raise ValueError("value must be <= 10")
+           ...
+           >>> assert str(exc_info.value) == "value must be <= 10"
 
-               assert exc_info.value.errno == errno.EEXISTS  # this will now execute
 
     Or you can specify a callable by passing a to-be-called lambda::
 
@@ -1223,7 +1237,11 @@ class RaisesContext(object):
                 exc_type, value, traceback = tp
                 tp = exc_type, exc_type(value), traceback
         self.excinfo.__init__(tp)
-        return issubclass(self.excinfo.type, self.expected_exception)
+        suppress_exception = issubclass(self.excinfo.type, self.expected_exception)
+        if sys.version_info[0] == 2 and suppress_exception:
+            sys.exc_clear()
+        return suppress_exception
+
 
 # builtin pytest.approx helper
 
diff --git a/_pytest/recwarn.py b/_pytest/recwarn.py
index a89474c..87823bf 100644
--- a/_pytest/recwarn.py
+++ b/_pytest/recwarn.py
@@ -36,8 +36,13 @@ def deprecated_call(func=None, *args, **kwargs):
 
     This function can be used as a context manager::
 
+        >>> import warnings
+        >>> def api_call_v2():
+        ...     warnings.warn('use v3 of this api', DeprecationWarning)
+        ...     return 200
+
         >>> with deprecated_call():
-        ...    myobject.deprecated_method()
+        ...    assert api_call_v2() == 200
 
     Note: we cannot use WarningsRecorder here because it is still subject
     to the mechanism that prevents warnings of the same type from being
diff --git a/_pytest/terminal.py b/_pytest/terminal.py
index fdbe4ec..16bf757 100644
--- a/_pytest/terminal.py
+++ b/_pytest/terminal.py
@@ -458,6 +458,15 @@ class TerminalReporter:
                     self.write_sep("_", msg)
                     self._outrep_summary(rep)
 
+    def print_teardown_sections(self, rep):
+        for secname, content in rep.sections:
+            if 'teardown' in secname:
+                self._tw.sep('-', secname)
+                if content[-1:] == "\n":
+                    content = content[:-1]
+                self._tw.line(content)
+
+
     def summary_failures(self):
         if self.config.option.tbstyle != "no":
             reports = self.getreports('failed')
@@ -473,6 +482,9 @@ class TerminalReporter:
                     markup = {'red': True, 'bold': True}
                     self.write_sep("_", msg, **markup)
                     self._outrep_summary(rep)
+                    for report in self.getreports(''):
+                        if report.nodeid == rep.nodeid and report.when == 'teardown':
+                            self.print_teardown_sections(report)
 
     def summary_errors(self):
         if self.config.option.tbstyle != "no":
diff --git a/_pytest/unittest.py b/_pytest/unittest.py
index 47868f4..4355efe 100644
--- a/_pytest/unittest.py
+++ b/_pytest/unittest.py
@@ -94,6 +94,9 @@ class TestCaseFunction(pytest.Function):
     def teardown(self):
         if hasattr(self._testcase, 'teardown_method'):
             self._testcase.teardown_method(self._obj)
+        # Allow garbage collection on TestCase instance attributes.
+        self._testcase = None
+        self._obj = None
 
     def startTest(self, testcase):
         pass
diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst
index 9cb4527..a1bf7be 100644
--- a/doc/en/announce/index.rst
+++ b/doc/en/announce/index.rst
@@ -6,6 +6,7 @@ Release announcements
    :maxdepth: 2
 
    
+   release-3.0.4
    release-3.0.3
    release-3.0.2
    release-3.0.1
diff --git a/doc/en/announce/release-3.0.4.rst b/doc/en/announce/release-3.0.4.rst
new file mode 100644
index 0000000..8520570
--- /dev/null
+++ b/doc/en/announce/release-3.0.4.rst
@@ -0,0 +1,29 @@
+pytest-3.0.4
+============
+
+pytest 3.0.4 has just been released to PyPI.
+
+This release fixes some regressions and bugs reported in the last version, 
+being a drop-in replacement. To upgrade::
+
+  pip install --upgrade pytest
+  
+The changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Bruno Oliveira
+* Dan Wandschneider
+* Florian Bruhin
+* Georgy Dyuldin
+* Grigorii Eremeev
+* Jason R. Coombs
+* Manuel Jacob
+* Mathieu Clabaut
+* Michael Seifert
+* Nikolaus Rath
+* Ronny Pfannschmidt
+* Tom V
+
+Happy testing,
+The pytest Development Team
diff --git a/doc/en/assert.rst b/doc/en/assert.rst
index 59d810c..675dece 100644
--- a/doc/en/assert.rst
+++ b/doc/en/assert.rst
@@ -26,7 +26,7 @@ you will see the return value of the function call::
 
     $ pytest test_assert1.py
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 1 items
     
@@ -170,7 +170,7 @@ if you run this module::
 
     $ pytest test_assert2.py
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 1 items
     
diff --git a/doc/en/cache.rst b/doc/en/cache.rst
index d94020f..4baae4c 100644
--- a/doc/en/cache.rst
+++ b/doc/en/cache.rst
@@ -80,7 +80,7 @@ If you then run it with ``--lf``::
 
     $ pytest --lf
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     run-last-failure: rerun last 2 failures
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 50 items
@@ -122,7 +122,7 @@ of ``FF`` and dots)::
 
     $ pytest --ff
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     run-last-failure: rerun last 2 failures first
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 50 items
@@ -227,7 +227,7 @@ You can always peek at the content of the cache using the
 
     $ py.test --cache-show
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     cachedir: $REGENDOC_TMPDIR/.cache
     ------------------------------- cache values -------------------------------
diff --git a/doc/en/capture.rst b/doc/en/capture.rst
index afec55f..454655d 100644
--- a/doc/en/capture.rst
+++ b/doc/en/capture.rst
@@ -64,7 +64,7 @@ of the failing function and hide the other one::
 
     $ pytest
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 2 items
     
diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst
index 1cdae8a..5a11225 100644
--- a/doc/en/doctest.rst
+++ b/doc/en/doctest.rst
@@ -49,7 +49,7 @@ then you can just invoke ``pytest`` without command line options::
 
     $ pytest
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
     collected 1 items
     
diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst
index f0c9b0e..2f5f29e 100644
--- a/doc/en/example/markers.rst
+++ b/doc/en/example/markers.rst
@@ -31,7 +31,7 @@ You can then restrict a test run to only run tests marked with ``webtest``::
 
     $ pytest -v -m webtest
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
     cachedir: .cache
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collecting ... collected 4 items
@@ -45,7 +45,7 @@ Or the inverse, running all tests except the webtest ones::
 
     $ pytest -v -m "not webtest"
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
     cachedir: .cache
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collecting ... collected 4 items
@@ -66,7 +66,7 @@ tests based on their module, class, method, or function name::
 
     $ pytest -v test_server.py::TestClass::test_method
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
     cachedir: .cache
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collecting ... collected 5 items
@@ -79,7 +79,7 @@ You can also select on the class::
 
     $ pytest -v test_server.py::TestClass
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
     cachedir: .cache
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collecting ... collected 4 items
@@ -92,7 +92,7 @@ Or select multiple nodes::
 
   $ pytest -v test_server.py::TestClass test_server.py::test_send_http
   ======= test session starts ========
-  platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
+  platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
   cachedir: .cache
   rootdir: $REGENDOC_TMPDIR, inifile: 
   collecting ... collected 8 items
@@ -130,7 +130,7 @@ select tests based on their names::
 
     $ pytest -v -k http  # running with the above defined example module
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
     cachedir: .cache
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collecting ... collected 4 items
@@ -144,7 +144,7 @@ And you can also run all tests except the ones that match the keyword::
 
     $ pytest -k "not send_http" -v
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
     cachedir: .cache
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collecting ... collected 4 items
@@ -160,7 +160,7 @@ Or to select "http" and "quick" tests::
 
     $ pytest -k "http or quick" -v
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
     cachedir: .cache
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collecting ... collected 4 items
@@ -352,7 +352,7 @@ the test needs::
 
     $ pytest -E stage2
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 1 items
     
@@ -364,7 +364,7 @@ and here is one that specifies exactly the environment needed::
 
     $ pytest -E stage1
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 1 items
     
@@ -485,7 +485,7 @@ then you will see two test skipped and two executed tests as expected::
 
     $ pytest -rs # this option reports skip reasons
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 4 items
     
@@ -499,7 +499,7 @@ Note that if you specify a platform via the marker-command line option like this
 
     $ pytest -m linux2
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 4 items
     
@@ -551,7 +551,7 @@ We can now use the ``-m option`` to select one set::
 
   $ pytest -m interface --tb=short
   ======= test session starts ========
-  platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+  platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
   rootdir: $REGENDOC_TMPDIR, inifile: 
   collected 4 items
   
@@ -573,7 +573,7 @@ or to select both "event" and "interface" tests::
 
   $ pytest -m "interface or event" --tb=short
   ======= test session starts ========
-  platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+  platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
   rootdir: $REGENDOC_TMPDIR, inifile: 
   collected 4 items
   
diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst
index 4fc9bc5..e0670ae 100644
--- a/doc/en/example/nonpython.rst
+++ b/doc/en/example/nonpython.rst
@@ -27,7 +27,7 @@ now execute the test specification::
 
     nonpython $ pytest test_simple.yml
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR/nonpython, inifile: 
     collected 2 items
     
@@ -59,7 +59,7 @@ consulted when reporting in ``verbose`` mode::
 
     nonpython $ pytest -v
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
     cachedir: .cache
     rootdir: $REGENDOC_TMPDIR/nonpython, inifile: 
     collecting ... collected 2 items
@@ -81,7 +81,7 @@ interesting to just look at the collection tree::
 
     nonpython $ pytest --collect-only
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR/nonpython, inifile: 
     collected 2 items
     <YamlFile 'test_simple.yml'>
diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst
index a5e6226..fee2b6d 100644
--- a/doc/en/example/parametrize.rst
+++ b/doc/en/example/parametrize.rst
@@ -130,7 +130,7 @@ objects, they are still using the default pytest representation::
 
     $ pytest test_time.py --collect-only
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 6 items
     <Module 'test_time.py'>
@@ -181,7 +181,7 @@ this is a fully self-contained example which you can run with::
 
     $ pytest test_scenarios.py
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 4 items
     
@@ -194,7 +194,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia
 
     $ pytest --collect-only test_scenarios.py
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 4 items
     <Module 'test_scenarios.py'>
@@ -259,7 +259,7 @@ Let's first see how it looks like at collection time::
 
     $ pytest test_backends.py --collect-only
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 2 items
     <Module 'test_backends.py'>
@@ -320,7 +320,7 @@ The result of this test will be successful::
 
     $ pytest test_indirect_list.py --collect-only
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 1 items
     <Module 'test_indirect_list.py'>
@@ -447,7 +447,7 @@ If you run this with reporting for skips enabled::
 
     $ pytest -rs test_module.py
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
     collected 2 items
     
diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst
index 15ec22e..f1e9a97 100644
--- a/doc/en/example/pythoncollection.rst
+++ b/doc/en/example/pythoncollection.rst
@@ -117,7 +117,7 @@ then the test collection looks like this::
 
     $ pytest --collect-only
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
     collected 2 items
     <Module 'check_myapp.py'>
@@ -163,7 +163,7 @@ You can always peek at the collection tree without running tests like this::
 
     . $ pytest --collect-only pythoncollection.py
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
     collected 3 items
     <Module 'CWD/pythoncollection.py'>
@@ -230,7 +230,7 @@ will be left out::
 
     $ pytest --collect-only
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
     collected 0 items
     
diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst
index 93704ea..061097c 100644
--- a/doc/en/example/reportingdemo.rst
+++ b/doc/en/example/reportingdemo.rst
@@ -11,7 +11,7 @@ get on the terminal - we are working on that)::
 
     assertion $ pytest failure_demo.py
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR/assertion, inifile: 
     collected 42 items
     
@@ -359,7 +359,7 @@ get on the terminal - we are working on that)::
     >   int(s)
     E   ValueError: invalid literal for int() with base 10: 'qwe'
     
-    <0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python.py:1190>:1: ValueError
+    <0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python.py:1204>:1: ValueError
     _______ TestRaises.test_raises_doesnt ________
     
     self = <failure_demo.TestRaises object at 0xdeadbeef>
diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst
index 9c758e6..032f83c 100644
--- a/doc/en/example/simple.rst
+++ b/doc/en/example/simple.rst
@@ -113,7 +113,7 @@ directory with the above conftest.py::
 
     $ pytest
     ======= test session starts ========
-    platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
+    platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
     rootdir: $REGENDOC_TMPDIR, inifile: 
... 1043 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/pytest.git



More information about the Python-modules-commits mailing list