From 4337702a6a8486c2f12e5919cd98a67dc1eccd65 Mon Sep 17 00:00:00 2001 From: "hpk@tannit.openend.se" Date: Fri, 23 Apr 2010 12:05:29 +0200 Subject: [PATCH 1/5] fixes for testrun on jython --HG-- branch : trunk --- testing/io_/test_capture.py | 9 +++++++++ testing/io_/test_terminalwriter.py | 9 ++++++--- testing/test_outcome.py | 4 +++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/testing/io_/test_capture.py b/testing/io_/test_capture.py index 03e1b108b..d12e084c2 100644 --- a/testing/io_/test_capture.py +++ b/testing/io_/test_capture.py @@ -1,6 +1,8 @@ import os, sys import py +needsdup = py.test.mark.skipif("not hasattr(os, 'dup')") + from py.builtin import print_ if sys.version_info >= (3,0): @@ -72,6 +74,7 @@ def pytest_funcarg__tmpfile(request): request.addfinalizer(f.close) return f +@needsdup def test_dupfile(tmpfile): somefile = tmpfile flist = [] @@ -91,6 +94,8 @@ def test_dupfile(tmpfile): somefile.close() class TestFDCapture: + pytestmark = needsdup + def test_stdout(self, tmpfile): fd = tmpfile.fileno() cap = py.io.FDCapture(fd) @@ -261,6 +266,8 @@ class TestStdCapture: assert not err class TestStdCaptureFD(TestStdCapture): + pytestmark = needsdup + def getcapture(self, **kw): return py.io.StdCaptureFD(**kw) @@ -289,6 +296,7 @@ class TestStdCaptureFD(TestStdCapture): assert out.startswith("3") assert err.startswith("4") +@needsdup def test_capture_no_sys(): capsys = py.io.StdCapture() try: @@ -303,6 +311,7 @@ def test_capture_no_sys(): finally: capsys.reset() +@needsdup def test_callcapture_nofd(): def func(x, y): oswritebytes(1, "hello") diff --git a/testing/io_/test_terminalwriter.py b/testing/io_/test_terminalwriter.py index 7a5f6c4bb..1710bd3bd 100644 --- a/testing/io_/test_terminalwriter.py +++ b/testing/io_/test_terminalwriter.py @@ -38,9 +38,12 @@ def test_terminalwriter_dumb_term_no_markup(monkeypatch): def isatty(self): return True monkeypatch.setattr(sys, 'stdout', MyFile()) - assert sys.stdout.isatty() - tw = py.io.TerminalWriter() - assert not tw.hasmarkup + try: + assert sys.stdout.isatty() + tw = py.io.TerminalWriter() + assert not tw.hasmarkup + finally: + monkeypatch.undo() def test_unicode_encoding(): msg = py.builtin._totext('b\u00f6y', 'utf8') diff --git a/testing/test_outcome.py b/testing/test_outcome.py index 08c0b9f7a..f415d13c0 100644 --- a/testing/test_outcome.py +++ b/testing/test_outcome.py @@ -68,5 +68,7 @@ def test_pytest_cmdline_main(testdir): py.test.cmdline.main([__file__]) """ % (str(py._pydir.dirpath()))) import subprocess - ret = subprocess.call([sys.executable, str(p)]) + popen = subprocess.Popen([sys.executable, str(p)], stdout=subprocess.PIPE) + s = popen.stdout.read() + ret = popen.wait() assert ret == 0 From 2ee6653ff719ca7fb969a3d512ae0c77fe2aa58c Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 23 Apr 2010 12:31:11 +0200 Subject: [PATCH 2/5] update distribute --HG-- branch : trunk --- CHANGELOG | 1 + distribute_setup.py | 81 ++++++++++++++++++++++++++++----------------- 2 files changed, 52 insertions(+), 30 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 066dff0d7..2f373122b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,7 @@ Changes between 1.2.1 and 1.2.2 (release pending) - (issue87) fix unboundlocal error in assertionold code - (issue86) improve documentation for looponfailing - fix jython/win32 issues +- ship distribute_setup.py version 0.6.10 Changes between 1.2.1 and 1.2.0 diff --git a/distribute_setup.py b/distribute_setup.py index 728533560..002133624 100644 --- a/distribute_setup.py +++ b/distribute_setup.py @@ -46,19 +46,21 @@ except ImportError: args = [quote(arg) for arg in args] return os.spawnl(os.P_WAIT, sys.executable, *args) == 0 -DEFAULT_VERSION = "0.6.6" +DEFAULT_VERSION = "0.6.10" DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/" +SETUPTOOLS_FAKED_VERSION = "0.6c11" + SETUPTOOLS_PKG_INFO = """\ Metadata-Version: 1.0 Name: setuptools -Version: 0.6c9 +Version: %s Summary: xxxx Home-page: xxx Author: xxx Author-email: xxx License: xxx Description: xxx -""" +""" % SETUPTOOLS_FAKED_VERSION def _install(tarball): @@ -79,12 +81,14 @@ def _install(tarball): # installing log.warn('Installing Distribute') - assert _python_cmd('setup.py', 'install') + if not _python_cmd('setup.py', 'install'): + log.warn('Something went wrong during the installation.') + log.warn('See the error message above.') finally: os.chdir(old_wd) -def _build_egg(tarball, to_dir): +def _build_egg(egg, tarball, to_dir): # extracting the tarball tmpdir = tempfile.mkdtemp() log.warn('Extracting in %s', tmpdir) @@ -104,27 +108,28 @@ def _build_egg(tarball, to_dir): log.warn('Building a Distribute egg in %s', to_dir) _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) - # returning the result - for file in os.listdir(to_dir): - if fnmatch.fnmatch(file, 'distribute-%s*.egg' % DEFAULT_VERSION): - return os.path.join(to_dir, file) - - raise IOError('Could not build the egg.') finally: os.chdir(old_wd) + # returning the result + log.warn(egg) + if not os.path.exists(egg): + raise IOError('Could not build the egg.') def _do_download(version, download_base, to_dir, download_delay): - tarball = download_setuptools(version, download_base, - to_dir, download_delay) - egg = _build_egg(tarball, to_dir) + egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg' + % (version, sys.version_info[0], sys.version_info[1])) + if not os.path.exists(egg): + tarball = download_setuptools(version, download_base, + to_dir, download_delay) + _build_egg(egg, tarball, to_dir) sys.path.insert(0, egg) import setuptools setuptools.bootstrap_install_from = egg def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, - to_dir=os.curdir, download_delay=15, no_fake=False): + to_dir=os.curdir, download_delay=15, no_fake=True): # making sure we use the absolute path to_dir = os.path.abspath(to_dir) was_imported = 'pkg_resources' in sys.modules or \ @@ -134,7 +139,7 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, import pkg_resources if not hasattr(pkg_resources, '_distribute'): if not no_fake: - fake_setuptools() + _fake_setuptools() raise ImportError except ImportError: return _do_download(version, download_base, to_dir, download_delay) @@ -159,7 +164,8 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, return _do_download(version, download_base, to_dir, download_delay) finally: - _create_fake_setuptools_pkg_info(to_dir) + if not no_fake: + _create_fake_setuptools_pkg_info(to_dir) def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, delay=15): @@ -218,22 +224,34 @@ def _patch_file(path, content): def _same_content(path, content): return open(path).read() == content +def _no_sandbox(function): + def __no_sandbox(*args, **kw): + try: + from setuptools.sandbox import DirectorySandbox + def violation(*args): + pass + DirectorySandbox._old = DirectorySandbox._violation + DirectorySandbox._violation = violation + patched = True + except ImportError: + patched = False + try: + return function(*args, **kw) + finally: + if patched: + DirectorySandbox._violation = DirectorySandbox._old + del DirectorySandbox._old + + return __no_sandbox + +@_no_sandbox def _rename_path(path): new_name = path + '.OLD.%s' % time.time() log.warn('Renaming %s into %s', path, new_name) - try: - from setuptools.sandbox import DirectorySandbox - def _violation(*args): - pass - DirectorySandbox._violation = _violation - except ImportError: - pass - os.rename(path, new_name) return new_name - def _remove_flat_installation(placeholder): if not os.path.isdir(placeholder): log.warn('Unkown installation at %s', placeholder) @@ -273,22 +291,26 @@ def _after_install(dist): placeholder = dist.get_command_obj('install').install_purelib _create_fake_setuptools_pkg_info(placeholder) +@_no_sandbox def _create_fake_setuptools_pkg_info(placeholder): if not placeholder or not os.path.exists(placeholder): log.warn('Could not find the install location') return pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1]) - setuptools_file = 'setuptools-0.6c9-py%s.egg-info' % pyver + setuptools_file = 'setuptools-%s-py%s.egg-info' % \ + (SETUPTOOLS_FAKED_VERSION, pyver) pkg_info = os.path.join(placeholder, setuptools_file) if os.path.exists(pkg_info): log.warn('%s already exists', pkg_info) return + log.warn('Creating %s', pkg_info) f = open(pkg_info, 'w') try: f.write(SETUPTOOLS_PKG_INFO) finally: f.close() + pth_file = os.path.join(placeholder, 'setuptools.pth') log.warn('Creating %s', pth_file) f = open(pth_file, 'w') @@ -297,7 +319,6 @@ def _create_fake_setuptools_pkg_info(placeholder): finally: f.close() - def _patch_egg_dir(path): # let's check if it's already patched pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') @@ -319,7 +340,7 @@ def _patch_egg_dir(path): def _before_install(): log.warn('Before install bootstrap.') - fake_setuptools() + _fake_setuptools() def _under_prefix(location): @@ -340,7 +361,7 @@ def _under_prefix(location): return True -def fake_setuptools(): +def _fake_setuptools(): log.warn('Scanning installed packages') try: import pkg_resources From 221ac3e46650310a9ac52885e09e8db205a99742 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 23 Apr 2010 13:29:28 +0200 Subject: [PATCH 3/5] a couple of more mostly jython-related fixes --HG-- branch : trunk --- py/_path/svnurl.py | 2 ++ testing/code/test_excinfo.py | 6 +++++- testing/code/test_frame.py | 2 -- testing/code/test_source.py | 10 ++++++++++ testing/log/test_log.py | 2 +- testing/path/common.py | 4 ++-- 6 files changed, 20 insertions(+), 6 deletions(-) delete mode 100644 testing/code/test_frame.py diff --git a/py/_path/svnurl.py b/py/_path/svnurl.py index 93d168a9c..383b01ed4 100644 --- a/py/_path/svnurl.py +++ b/py/_path/svnurl.py @@ -353,6 +353,8 @@ def parse_time_with_missing_year(timestr): day = time.strptime(tparts.pop(0), '%d')[2] last = tparts.pop(0) # year or hour:minute try: + if ":" in last: + raise ValueError() year = time.strptime(last, '%Y')[0] hour = minute = 0 except ValueError: diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 4fbc61aa5..9264026bb 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -3,6 +3,8 @@ import py from py._code.code import FormattedExcinfo, ReprExceptionInfo queue = py.builtin._tryimport('queue', 'Queue') +failsonjython = py.test.mark.xfail("sys.platform.startswith('java')") + class TWMock: def __init__(self): self.lines = [] @@ -82,6 +84,7 @@ class TestTraceback_f_g_h: assert s.startswith("def f():") assert s.endswith("raise ValueError") + @failsonjython def test_traceback_entry_getsource_in_construct(self): source = py.code.Source("""\ def xyz(): @@ -216,7 +219,7 @@ def test_excinfo_repr(): def test_excinfo_str(): excinfo = py.test.raises(ValueError, h) s = str(excinfo) - assert s.startswith(__file__[:-1]) # pyc file + assert s.startswith(__file__[:-9]) # pyc file and $py.class assert s.endswith("ValueError") assert len(s.split(":")) >= 3 # on windows it's 4 @@ -290,6 +293,7 @@ class TestFormattedExcinfo: assert lines[0] == "| def f(x):" assert lines[1] == " pass" + @failsonjython def test_repr_source_excinfo(self): """ check if indentation is right """ pr = FormattedExcinfo() diff --git a/testing/code/test_frame.py b/testing/code/test_frame.py deleted file mode 100644 index 1307de543..000000000 --- a/testing/code/test_frame.py +++ /dev/null @@ -1,2 +0,0 @@ -import sys -import py diff --git a/testing/code/test_source.py b/testing/code/test_source.py index d65b45c64..ef3d805ce 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -2,6 +2,8 @@ from py.code import Source import py import sys +failsonjython = py.test.mark.xfail("sys.platform.startswith('java')") + def test_source_str_function(): x = Source("3") assert str(x) == "3" @@ -78,6 +80,7 @@ def test_source_strip_multiline(): source2 = source.strip() assert source2.lines == [" hello"] +@failsonjython def test_syntaxerror_rerepresentation(): ex = py.test.raises(SyntaxError, py.code.compile, 'x x') assert ex.value.lineno == 1 @@ -129,6 +132,7 @@ class TestSourceParsingAndCompiling: exec (co, d) assert d['x'] == 3 + @failsonjython def test_compile_and_getsource_simple(self): co = py.code.compile("x=3") exec (co) @@ -199,6 +203,7 @@ class TestSourceParsingAndCompiling: assert isinstance(mod, ast.Module) compile(mod, "", "exec") + @failsonjython def test_compile_and_getsource(self): co = self.source.compile() py.builtin.exec_(co, globals()) @@ -255,6 +260,7 @@ def test_getstartingblock_multiline(): l = [i for i in x.source.lines if i.strip()] assert len(l) == 4 +@failsonjython def test_getline_finally(): def c(): pass excinfo = py.test.raises(TypeError, """ @@ -268,6 +274,7 @@ def test_getline_finally(): source = excinfo.traceback[-1].statement assert str(source).strip() == 'c(1)' +@failsonjython def test_getfuncsource_dynamic(): source = """ def f(): @@ -334,6 +341,7 @@ def test_getsource_fallback(): src = getsource(x) assert src == expected +@failsonjython def test_idem_compile_and_getsource(): from py._code.source import getsource expected = "def x(): pass" @@ -347,6 +355,7 @@ def test_findsource_fallback(): assert 'test_findsource_simple' in str(src) assert src[lineno] == ' def x():' +@failsonjython def test_findsource___source__(): from py._code.source import findsource co = py.code.compile("""if 1: @@ -364,6 +373,7 @@ def test_findsource___source__(): assert src[lineno] == " def x():" +@failsonjython def test_getfslineno(): from py.code import getfslineno diff --git a/testing/log/test_log.py b/testing/log/test_log.py index da1f53799..5f84afc11 100644 --- a/testing/log/test_log.py +++ b/testing/log/test_log.py @@ -117,7 +117,7 @@ class TestLogConsumer: def test_log_file(self, tmpdir): customlog = tmpdir.join('log.out') - py.log.setconsumer("default", open(str(customlog), 'w', buffering=1)) + py.log.setconsumer("default", open(str(customlog), 'w', 1)) py.log.Producer("default")("hello world #1") assert customlog.readlines() == ['[default] hello world #1\n'] diff --git a/testing/path/common.py b/testing/path/common.py index 8e83e45f6..3b0d48c19 100644 --- a/testing/path/common.py +++ b/testing/path/common.py @@ -132,7 +132,7 @@ class CommonFSTests(object): assert not l1.relto(l2) assert not l2.relto(l1) - @py.test.mark.xfail("sys.platform.startswith('java')") + #@py.test.mark.xfail("sys.platform.startswith('java')") def test_listdir(self, path1): l = path1.listdir() assert path1.join('sampledir') in l @@ -178,7 +178,7 @@ class CommonFSTests(object): assert "sampledir" in l assert "otherdir" in l - @py.test.mark.xfail("sys.platform.startswith('java')") + #@py.test.mark.xfail("sys.platform.startswith('java')") def test_visit_ignore(self, path1): p = path1.join('nonexisting') assert list(p.visit(ignore=py.error.ENOENT)) == [] From b3a05b545e19556fb314f71fe90fd4ea23133b69 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 23 Apr 2010 19:05:22 +0200 Subject: [PATCH 4/5] another couple of checks on jython, still some problems --HG-- branch : trunk --- py/_cmdline/pyconvert_unittest.py | 6 +++++- py/_code/code.py | 3 ++- testing/cmdline/test_convert_unittest.py | 2 ++ testing/path/common.py | 4 ++-- testing/path/test_svnurl.py | 6 ++++++ testing/plugin/test_pytest__pytest.py | 4 ++-- testing/plugin/test_pytest_terminal.py | 2 +- testing/root/test_oldmagic.py | 5 ++++- testing/root/test_py_imports.py | 2 +- 9 files changed, 25 insertions(+), 9 deletions(-) diff --git a/py/_cmdline/pyconvert_unittest.py b/py/_cmdline/pyconvert_unittest.py index a975a478e..a50233638 100644 --- a/py/_cmdline/pyconvert_unittest.py +++ b/py/_cmdline/pyconvert_unittest.py @@ -1,6 +1,10 @@ import re import sys -import parser + +try: + import parser +except ImportError: + parser = None d={} # d is the dictionary of unittest changes, keyed to the old name diff --git a/py/_code/code.py b/py/_code/code.py index 397398029..ee054fc2e 100644 --- a/py/_code/code.py +++ b/py/_code/code.py @@ -523,7 +523,8 @@ class FormattedExcinfo(object): source = py.code.Source("???") line_index = 0 else: - line_index = entry.lineno - entry.getfirstlinesource() + # entry.getfirstlinesource() can be -1, should be 0 on jython + line_index = entry.lineno - max(entry.getfirstlinesource(), 0) lines = [] if self.style == "long": diff --git a/testing/cmdline/test_convert_unittest.py b/testing/cmdline/test_convert_unittest.py index 48280c7c1..2bfcd9c2b 100644 --- a/testing/cmdline/test_convert_unittest.py +++ b/testing/cmdline/test_convert_unittest.py @@ -1,3 +1,5 @@ +import py +py.test.importorskip("parser") from py._cmdline.pyconvert_unittest import rewrite_utest diff --git a/testing/path/common.py b/testing/path/common.py index 3b0d48c19..8e83e45f6 100644 --- a/testing/path/common.py +++ b/testing/path/common.py @@ -132,7 +132,7 @@ class CommonFSTests(object): assert not l1.relto(l2) assert not l2.relto(l1) - #@py.test.mark.xfail("sys.platform.startswith('java')") + @py.test.mark.xfail("sys.platform.startswith('java')") def test_listdir(self, path1): l = path1.listdir() assert path1.join('sampledir') in l @@ -178,7 +178,7 @@ class CommonFSTests(object): assert "sampledir" in l assert "otherdir" in l - #@py.test.mark.xfail("sys.platform.startswith('java')") + @py.test.mark.xfail("sys.platform.startswith('java')") def test_visit_ignore(self, path1): p = path1.join('nonexisting') assert list(p.visit(ignore=py.error.ENOENT)) == [] diff --git a/testing/path/test_svnurl.py b/testing/path/test_svnurl.py index 82dce22d4..e6e226661 100644 --- a/testing/path/test_svnurl.py +++ b/testing/path/test_svnurl.py @@ -13,6 +13,12 @@ class TestSvnURLCommandPath(CommonSvnTests): def test_load(self, path1): super(TestSvnURLCommandPath, self).test_load(path1) + # the following two work on jython but not in local/svnwc + def test_listdir(self, path1): + super(TestSvnURLCommandPath, self).test_listdir(path1) + def test_visit_ignore(self, path1): + super(TestSvnURLCommandPath, self).test_visit_ignore(path1) + def test_svnurl_needs_arg(self, path1): py.test.raises(TypeError, "py.path.svnurl()") diff --git a/testing/plugin/test_pytest__pytest.py b/testing/plugin/test_pytest__pytest.py index 182efe564..4eb7beac1 100644 --- a/testing/plugin/test_pytest__pytest.py +++ b/testing/plugin/test_pytest__pytest.py @@ -1,5 +1,5 @@ import py -import sys +import os, sys from py._plugin.pytest__pytest import HookRecorder from py._test.pluginmanager import Registry @@ -17,7 +17,7 @@ def test_hookrecorder_basic(): def test_hookrecorder_basic_no_args_hook(): rec = HookRecorder(Registry()) - apimod = type(sys)('api') + apimod = type(os)('api') def xyz(): pass apimod.xyz = xyz diff --git a/testing/plugin/test_pytest_terminal.py b/testing/plugin/test_pytest_terminal.py index 98b367d88..7180927b2 100644 --- a/testing/plugin/test_pytest_terminal.py +++ b/testing/plugin/test_pytest_terminal.py @@ -82,7 +82,7 @@ class TestTerminal: ]) def test_collect_fail(self, testdir, option): - p = testdir.makepyfile("import xyz") + p = testdir.makepyfile("import xyz\n") result = testdir.runpytest(*option._getcmdargs()) result.stdout.fnmatch_lines([ "*test_collect_fail.py E*", diff --git a/testing/root/test_oldmagic.py b/testing/root/test_oldmagic.py index e6f608578..92accc699 100644 --- a/testing/root/test_oldmagic.py +++ b/testing/root/test_oldmagic.py @@ -1,8 +1,10 @@ import py import sys, os +def fass(): + assert 1 == 2 def check_assertion(): - excinfo = py.test.raises(AssertionError, "assert 1 == 2") + excinfo = py.test.raises(AssertionError, fass) s = excinfo.exconly(tryshort=True) if not s == "assert 1 == 2": raise ValueError("assertion not enabled: got %s" % s) @@ -16,6 +18,7 @@ def test_invoke_assertion(recwarn, monkeypatch): py.magic.revoke(assertion=True) recwarn.pop(DeprecationWarning) +@py.test.mark.skipif("sys.platform.startswith('java')") def test_invoke_compile(recwarn, monkeypatch): monkeypatch.setattr(py.builtin.builtins, 'compile', None) py.magic.invoke(compile=True) diff --git a/testing/root/test_py_imports.py b/testing/root/test_py_imports.py index 81b1a1975..901b304bd 100644 --- a/testing/root/test_py_imports.py +++ b/testing/root/test_py_imports.py @@ -9,7 +9,7 @@ def checksubpackage(name): keys = dir(obj) assert len(keys) > 0 print (obj.__map__) - for name in obj.__map__: + for name in list(obj.__map__): assert hasattr(obj, name), (obj, name) def test_dir(): From 0b24a7027990097f6915b605331d89b9461a8906 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 23 Apr 2010 19:28:41 +0200 Subject: [PATCH 5/5] this should test and fix the same issue that was committed in the pypy svn-repo as r72534 --HG-- branch : trunk --- py/_test/outcome.py | 2 +- testing/test_outcome.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/py/_test/outcome.py b/py/_test/outcome.py index 619de1309..f58f396c1 100644 --- a/py/_test/outcome.py +++ b/py/_test/outcome.py @@ -100,7 +100,7 @@ def raises(ExpectedException, *args, **kwargs): k = ", ".join(["%s=%r" % x for x in kwargs.items()]) if k: k = ', ' + k - expr = '%s(%r%s)' %(func.__name__, args, k) + expr = '%s(%r%s)' %(getattr(func, '__name__', func), args, k) raise ExceptionFailure(msg="DID NOT RAISE", expr=args, expected=ExpectedException) diff --git a/testing/test_outcome.py b/testing/test_outcome.py index f415d13c0..a7a782aba 100644 --- a/testing/test_outcome.py +++ b/testing/test_outcome.py @@ -15,6 +15,16 @@ class TestRaises: def test_raises_function(self): py.test.raises(ValueError, int, 'hello') + def test_raises_callable_no_exception(self): + from py._test.outcome import ExceptionFailure + class A: + def __call__(self): + pass + try: + py.test.raises(ValueError, A()) + except ExceptionFailure: + pass + def test_pytest_exit(): try: py.test.exit("hello")