[Pytest-commit] commit/pytest: 3 new changesets

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Fri Sep 6 12:09:19 CEST 2013


3 new commits in pytest:

https://bitbucket.org/hpk42/pytest/commits/902e8493c89d/
Changeset:   902e8493c89d
User:        hpk42
Date:        2013-09-05 22:32:35
Summary:     another way how bash reacts when no argcomplete is there?
Affected #:  1 file

diff -r 3e3e5213be60c60131b8051805946a8f0822fb58 -r 902e8493c89d57d9ff9121cc3bff7a8c2461160c testing/test_parseopt.py
--- a/testing/test_parseopt.py
+++ b/testing/test_parseopt.py
@@ -266,6 +266,8 @@
     if result.ret == 255:
         # argcomplete not found
         pytest.skip("argcomplete not available")
+    elif not result.stdout.str():
+        pytest.skip("bash provided no output, argcomplete not available?")
     else:
         if py.std.sys.version_info < (2,7):
             result.stdout.lines = result.stdout.lines[0].split('\x0b')


https://bitbucket.org/hpk42/pytest/commits/4fc42aa21181/
Changeset:   4fc42aa21181
User:        hpk42
Date:        2013-09-06 10:07:06
Summary:     xfail some tests for doctest support if pdbpp is installed
Affected #:  2 files

diff -r 902e8493c89d57d9ff9121cc3bff7a8c2461160c -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c _pytest/main.py
--- a/_pytest/main.py
+++ b/_pytest/main.py
@@ -373,7 +373,7 @@
     # the set of exceptions to interpret as "Skip the whole module" during
     # collection
     skip_exceptions = (_pytest.runner.Skipped,)
-    
+
     class CollectError(Exception):
         """ an error during collection, contains a custom message. """
 

diff -r 902e8493c89d57d9ff9121cc3bff7a8c2461160c -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c testing/test_doctest.py
--- a/testing/test_doctest.py
+++ b/testing/test_doctest.py
@@ -1,6 +1,11 @@
 from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile
 import py, pytest
 
+import pdb
+
+xfail_if_pdbpp_installed = pytest.mark.xfail(hasattr(pdb, "__author__"),
+    reason="doctest/pdbpp problem: https://bitbucket.org/antocuni/pdb/issue/24/doctests-fail-when-pdbpp-is-installed")
+
 class TestDoctests:
 
     def test_collect_testtextfile(self, testdir):
@@ -154,6 +159,7 @@
         reprec = testdir.inline_run(p, "--doctest-modules")
         reprec.assertoutcome(failed=1)
 
+    @xfail_if_pdbpp_installed
     def test_doctestmodule_external_and_issue116(self, testdir):
         p = testdir.mkpydir("hello")
         p.join("__init__.py").write(py.code.Source("""
@@ -193,6 +199,7 @@
             "*test_txtfile_failing.txt:2: DocTestFailure"
         ])
 
+    @xfail_if_pdbpp_installed
     def test_txtfile_with_fixtures(self, testdir):
         p = testdir.maketxtfile("""
             >>> dir = getfixture('tmpdir')
@@ -202,6 +209,8 @@
         reprec = testdir.inline_run(p, )
         reprec.assertoutcome(passed=1)
 
+
+    @xfail_if_pdbpp_installed
     def test_doctestmodule_with_fixtures(self, testdir):
         p = testdir.makepyfile("""
             '''
@@ -213,6 +222,7 @@
         reprec = testdir.inline_run(p, "--doctest-modules")
         reprec.assertoutcome(passed=1)
 
+    @xfail_if_pdbpp_installed
     def test_doctestmodule_three_tests(self, testdir):
         p = testdir.makepyfile("""
             '''
@@ -238,6 +248,7 @@
         reprec = testdir.inline_run(p, "--doctest-modules")
         reprec.assertoutcome(passed=3)
 
+    @xfail_if_pdbpp_installed
     def test_doctestmodule_two_tests_one_fail(self, testdir):
         p = testdir.makepyfile("""
             class MyClass:


https://bitbucket.org/hpk42/pytest/commits/1d3ebb313d68/
Changeset:   1d3ebb313d68
User:        hpk42
Date:        2013-09-06 11:56:04
Summary:     - fix issue181: --pdb now also works on collect errors.  This was
  implemented by a slight internal refactoring and the introduction
  of a new hook ``pytest_exception_interact`` hook.

- fix issue341: introduce new experimental hook for IDEs/terminals to
  intercept debugging: ``pytest_exception_interact(node, call, report)``.
Affected #:  12 files

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,14 @@
 Changes between 2.3.5 and 2.4.DEV
 -----------------------------------
 
+- fix issue181: --pdb now also works on collect errors (and 
+  on internal errors) .  This was implemented by a slight internal 
+  refactoring and the introduction of a new hook 
+  ``pytest_exception_interact`` hook (see below).
+
+- fix issue341: introduce new experimental hook for IDEs/terminals to 
+  intercept debugging: ``pytest_exception_interact(node, call, report)``.
+
 - PR27: correctly handle nose.SkipTest during collection.  Thanks
   Antonio Cuni, Ronny Pfannschmidt.
 

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b _pytest/__init__.py
--- a/_pytest/__init__.py
+++ b/_pytest/__init__.py
@@ -1,2 +1,2 @@
 #
-__version__ = '2.4.0.dev11'
+__version__ = '2.4.0.dev12'

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b _pytest/core.py
--- a/_pytest/core.py
+++ b/_pytest/core.py
@@ -298,7 +298,8 @@
             showlocals=getattr(option, 'showlocals', False),
             style=style,
         )
-        res = self.hook.pytest_internalerror(excrepr=excrepr)
+        res = self.hook.pytest_internalerror(excrepr=excrepr,
+                                             excinfo=excinfo)
         if not py.builtin.any(res):
             for line in str(excrepr).split("\n"):
                 sys.stderr.write("INTERNALERROR> %s\n" %line)

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b _pytest/hookspec.py
--- a/_pytest/hookspec.py
+++ b/_pytest/hookspec.py
@@ -241,8 +241,18 @@
 def pytest_plugin_unregistered(plugin):
     """ a py lib plugin got unregistered. """
 
-def pytest_internalerror(excrepr):
+def pytest_internalerror(excrepr, excinfo):
     """ called for internal errors. """
 
 def pytest_keyboard_interrupt(excinfo):
     """ called for keyboard interrupt. """
+
+def pytest_exception_interact(node, call, report):
+    """ (experimental, new in 2.4) called when
+    an exception was raised which can potentially be
+    interactively handled.
+
+    This hook is only called if an exception was raised
+    that is not an internal exception like "skip.Exception".
+    """
+

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b _pytest/main.py
--- a/_pytest/main.py
+++ b/_pytest/main.py
@@ -10,7 +10,7 @@
     from UserDict import DictMixin as MappingMixin
 
 from _pytest.mark import MarkInfo
-import _pytest.runner
+from _pytest.runner import collect_one_node, Skipped
 
 tracebackcutdir = py.path.local(_pytest.__file__).dirpath()
 
@@ -372,7 +372,7 @@
 
     # the set of exceptions to interpret as "Skip the whole module" during
     # collection
-    skip_exceptions = (_pytest.runner.Skipped,)
+    skip_exceptions = (Skipped,)
 
     class CollectError(Exception):
         """ an error during collection, contains a custom message. """
@@ -512,8 +512,7 @@
             parts = self._parsearg(arg)
             self._initialparts.append(parts)
             self._initialpaths.add(parts[0])
-        self.ihook.pytest_collectstart(collector=self)
-        rep = self.ihook.pytest_make_collect_report(collector=self)
+        rep = collect_one_node(self)
         self.ihook.pytest_collectreport(report=rep)
         self.trace.root.indent -= 1
         if self._notfound:
@@ -642,8 +641,7 @@
                     resultnodes.append(node)
                 continue
             assert isinstance(node, pytest.Collector)
-            node.ihook.pytest_collectstart(collector=node)
-            rep = node.ihook.pytest_make_collect_report(collector=node)
+            rep = collect_one_node(node)
             if rep.passed:
                 has_matched = False
                 for x in rep.result:
@@ -664,8 +662,7 @@
             yield node
         else:
             assert isinstance(node, pytest.Collector)
-            node.ihook.pytest_collectstart(collector=node)
-            rep = node.ihook.pytest_make_collect_report(collector=node)
+            rep = collect_one_node(node)
             if rep.passed:
                 for subnode in rep.result:
                     for x in self.genitems(subnode):

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b _pytest/pdb.py
--- a/_pytest/pdb.py
+++ b/_pytest/pdb.py
@@ -52,31 +52,26 @@
     pytestPDB.item = None
 
 class PdbInvoke:
-    @pytest.mark.tryfirst
-    def pytest_runtest_makereport(self, item, call, __multicall__):
-        rep = __multicall__.execute()
-        if not call.excinfo or \
-            call.excinfo.errisinstance(pytest.skip.Exception) or \
-            call.excinfo.errisinstance(py.std.bdb.BdbQuit):
-            return rep
-        if hasattr(rep, "wasxfail"):
-            return rep
-        return _enter_pdb(item, call.excinfo, rep)
+    def pytest_exception_interact(self, node, call, report):
+        return _enter_pdb(node, call.excinfo, report)
 
+    def pytest_internalerror(self, excrepr, excinfo):
+        for line in str(excrepr).split("\n"):
+            sys.stderr.write("INTERNALERROR> %s\n" %line)
+            sys.stderr.flush()
+        tb = _postmortem_traceback(excinfo)
+        post_mortem(tb)
 
 
-
-def _enter_pdb(item, excinfo, rep):
-    # we assume that the above execute() suspended capturing
+def _enter_pdb(node, excinfo, rep):
     # XXX we re-use the TerminalReporter's terminalwriter
     # because this seems to avoid some encoding related troubles
     # for not completely clear reasons.
-    tw = item.config.pluginmanager.getplugin("terminalreporter")._tw
+    tw = node.config.pluginmanager.getplugin("terminalreporter")._tw
     tw.line()
     tw.sep(">", "traceback")
     rep.toterminal(tw)
     tw.sep(">", "entering PDB")
-
     tb = _postmortem_traceback(excinfo)
     post_mortem(tb)
     rep._pdbshown = True

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b _pytest/runner.py
--- a/_pytest/runner.py
+++ b/_pytest/runner.py
@@ -108,8 +108,16 @@
     report = hook.pytest_runtest_makereport(item=item, call=call)
     if log:
         hook.pytest_runtest_logreport(report=report)
+    if check_interactive_exception(call, report):
+        hook.pytest_exception_interact(node=item, call=call, report=report)
     return report
 
+def check_interactive_exception(call, report):
+    return call.excinfo and not (
+                hasattr(report, "wasxfail") or
+                call.excinfo.errisinstance(skip.Exception) or
+                call.excinfo.errisinstance(py.std.bdb.BdbQuit))
+
 def call_runtest_hook(item, when, **kwds):
     hookname = "pytest_runtest_" + when
     ihook = getattr(item.ihook, hookname)
@@ -268,8 +276,11 @@
             if not hasattr(errorinfo, "toterminal"):
                 errorinfo = CollectErrorRepr(errorinfo)
             longrepr = errorinfo
-    return CollectReport(collector.nodeid, outcome, longrepr,
+    rep = CollectReport(collector.nodeid, outcome, longrepr,
         getattr(call, 'result', None))
+    rep.call = call  # see collect_one_node
+    return rep
+
 
 class CollectReport(BaseReport):
     def __init__(self, nodeid, outcome, longrepr, result, sections=(), **extra):
@@ -364,6 +375,16 @@
                 col._prepare_exc = sys.exc_info()
                 raise
 
+def collect_one_node(collector):
+    ihook = collector.ihook
+    ihook.pytest_collectstart(collector=collector)
+    rep = ihook.pytest_make_collect_report(collector=collector)
+    call = rep.__dict__.pop("call", None)
+    if call and check_interactive_exception(call, rep):
+        ihook.pytest_exception_interact(node=collector, call=call, report=rep)
+    return rep
+
+
 # =============================================================
 # Test OutcomeExceptions and helpers for creating them.
 

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b doc/en/plugins.txt
--- a/doc/en/plugins.txt
+++ b/doc/en/plugins.txt
@@ -359,6 +359,17 @@
 
 .. autofunction:: pytest_runtest_logreport
 
+
+Debugging/Interaction hooks
+--------------------------------------
+
+There are few hooks which can be used for special
+reporting or interaction with exceptions:
+
+.. autofunction:: pytest_internalerror
+.. autofunction:: pytest_keyboard_interrupt
+.. autofunction:: pytest_exception_interact
+
 Reference of objects involved in hooks
 ===========================================================
 

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b setup.py
--- a/setup.py
+++ b/setup.py
@@ -11,7 +11,7 @@
         name='pytest',
         description='py.test: simple powerful testing with Python',
         long_description = long_description,
-        version='2.4.0.dev11',
+        version='2.4.0.dev12',
         url='http://pytest.org',
         license='MIT license',
         platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b testing/python/integration.py
--- a/testing/python/integration.py
+++ b/testing/python/integration.py
@@ -1,4 +1,5 @@
 import pytest, py, sys
+from _pytest import runner
 
 class TestOEJSKITSpecials:
     def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage
@@ -18,7 +19,7 @@
                 pass
         """)
         # this hook finds funcarg factories
-        rep = modcol.ihook.pytest_make_collect_report(collector=modcol)
+        rep = runner.collect_one_node(collector=modcol)
         clscol = rep.result[0]
         clscol.obj = lambda arg1: None
         clscol.funcargs = {}
@@ -46,7 +47,7 @@
                 pass
         """)
         # this hook finds funcarg factories
-        rep = modcol.ihook.pytest_make_collect_report(collector=modcol)
+        rep = runner.collect_one_node(modcol)
         clscol = rep.result[0]
         clscol.obj = lambda: None
         clscol.funcargs = {}

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b testing/test_pdb.py
--- a/testing/test_pdb.py
+++ b/testing/test_pdb.py
@@ -1,6 +1,8 @@
 import py, pytest
 import sys
 
+from test_doctest import xfail_if_pdbpp_installed
+
 class TestPDB:
     def pytest_funcarg__pdblist(self, request):
         monkeypatch = request.getfuncargvalue("monkeypatch")
@@ -85,6 +87,32 @@
         if child.isalive():
             child.wait()
 
+    def test_pdb_interaction_on_collection_issue181(self, testdir):
+        p1 = testdir.makepyfile("""
+            import pytest
+            xxx
+        """)
+        child = testdir.spawn_pytest("--pdb %s" % p1)
+        #child.expect(".*import pytest.*")
+        child.expect("(Pdb)")
+        child.sendeof()
+        child.expect("1 error")
+        if child.isalive():
+            child.wait()
+
+    def test_pdb_interaction_on_internal_error(self, testdir):
+        testdir.makeconftest("""
+            def pytest_runtest_protocol():
+                0/0
+        """)
+        p1 = testdir.makepyfile("def test_func(): pass")
+        child = testdir.spawn_pytest("--pdb %s" % p1)
+        #child.expect(".*import pytest.*")
+        child.expect("(Pdb)")
+        child.sendeof()
+        if child.isalive():
+            child.wait()
+
     def test_pdb_interaction_capturing_simple(self, testdir):
         p1 = testdir.makepyfile("""
             import pytest
@@ -122,6 +150,7 @@
         if child.isalive():
             child.wait()
 
+    @xfail_if_pdbpp_installed
     def test_pdb_interaction_doctest(self, testdir):
         p1 = testdir.makepyfile("""
             import pytest

diff -r 4fc42aa2118143e97ec1c67a0151191d4566ec3c -r 1d3ebb313d68d4bcb3f1a2e575febf196689731b testing/test_runner.py
--- a/testing/test_runner.py
+++ b/testing/test_runner.py
@@ -1,5 +1,5 @@
 import pytest, py, sys, os
-from _pytest import runner
+from _pytest import runner, main
 from py._code.code import ReprExceptionInfo
 
 class TestSetupState:
@@ -298,7 +298,7 @@
             class TestClass:
                 pass
         """)
-        rep = runner.pytest_make_collect_report(col)
+        rep = runner.collect_one_node(col)
         assert not rep.failed
         assert not rep.skipped
         assert rep.passed
@@ -318,7 +318,7 @@
             def test_func():
                 pass
         """)
-        rep = runner.pytest_make_collect_report(col)
+        rep = main.collect_one_node(col)
         assert not rep.failed
         assert not rep.passed
         assert rep.skipped

Repository URL: https://bitbucket.org/hpk42/pytest/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.


More information about the pytest-commit mailing list