[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