[pypy-svn] r74676 - in pypy/trunk: . lib-python py py/_cmdline py/_code py/_io py/_plugin py/_test pypy pypy/interpreter pypy/interpreter/test pypy/jit/metainterp/test pypy/tool/pytest pypy/tool/pytest/test
hpk at codespeak.net
hpk at codespeak.net
Sat May 22 13:29:15 CEST 2010
Author: hpk
Date: Sat May 22 13:29:12 2010
New Revision: 74676
Removed:
pypy/trunk/py/__init__.py.orig
pypy/trunk/py/_plugin/pytest_pytester.py.orig
pypy/trunk/py/_plugin/pytest_terminal.py.orig
Modified:
pypy/trunk/ (props changed)
pypy/trunk/lib-python/conftest.py
pypy/trunk/py/__init__.py
pypy/trunk/py/_builtin.py
pypy/trunk/py/_cmdline/pytest.py
pypy/trunk/py/_code/code.py
pypy/trunk/py/_code/source.py
pypy/trunk/py/_io/capture.py
pypy/trunk/py/_plugin/pytest__pytest.py
pypy/trunk/py/_plugin/pytest_capture.py
pypy/trunk/py/_plugin/pytest_genscript.py
pypy/trunk/py/_plugin/pytest_junitxml.py
pypy/trunk/py/_plugin/pytest_mark.py
pypy/trunk/py/_plugin/pytest_pytester.py
pypy/trunk/py/_plugin/pytest_resultlog.py
pypy/trunk/py/_plugin/pytest_runner.py
pypy/trunk/py/_plugin/pytest_skipping.py
pypy/trunk/py/_plugin/pytest_terminal.py
pypy/trunk/py/_test/cmdline.py
pypy/trunk/py/_test/pycollect.py
pypy/trunk/pypy/conftest.py
pypy/trunk/pypy/interpreter/gateway.py
pypy/trunk/pypy/interpreter/test/test_code.py
pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py
pypy/trunk/pypy/tool/pytest/appsupport.py
pypy/trunk/pypy/tool/pytest/test/test_appsupport.py
Log:
merge py131 branch (which merges py1.3.1a1 - release pending) relevant news:
* fixes keyboardinterrupt issues - hopefully strange internal TBs
when doing ctrl-c are a thing of the past now
* be more robust against bogus source code and fix/improve
reporting of failing applevel tests
* fix some xfail/skipping issues and introduce a new
imperative way to xfail a test by
py.test.xfail() # or py.test.xfail("reasonstring")
I strongly recommend to use this instead of py.test.skip("xxx") because
it more clearly communicates that not just some platform/dependency
problem but an implementation issue is present. Note that it is also
possible to do:
@py.test.mark.xfail
def test_function()
and with Python2.6 it can also be applied to a test class like this:
@py.test.mark.xfail(reason="xyz needs improvement/refactoring")
class TestClass:
def test_...
And btw, you can issue "py.test --runxfail" to still run those tests and see
tracebacks. And finally,
@py.test.mark.xfail(run=False)
def test_function()
will not try to run the function at all.
Modified: pypy/trunk/lib-python/conftest.py
==============================================================================
--- pypy/trunk/lib-python/conftest.py (original)
+++ pypy/trunk/lib-python/conftest.py Sat May 22 13:29:12 2010
@@ -14,7 +14,6 @@
# the following adds command line options as a side effect!
from pypy.conftest import gettestobjspace, option as pypy_option
-from test import pystone
from pypy.tool.pytest import appsupport
from pypy.tool.pytest.confpath import pypydir, libpythondir, \
@@ -40,6 +39,7 @@
option = py.test.config.option
def gettimeout():
+ from test import pystone
timeout = option.timeout.lower()
if timeout.endswith('mp'):
megapystone = float(timeout[:-2])
Modified: pypy/trunk/py/__init__.py
==============================================================================
--- pypy/trunk/py/__init__.py (original)
+++ pypy/trunk/py/__init__.py Sat May 22 13:29:12 2010
@@ -8,7 +8,7 @@
(c) Holger Krekel and others, 2004-2010
"""
-__version__ = version = "1.3.0"
+__version__ = version = "1.3.1a1"
import py.apipkg
@@ -25,7 +25,6 @@
'pytest': '._cmdline.pytest:main',
'pylookup': '._cmdline.pylookup:main',
'pycountloc': '._cmdline.pycountlog:main',
- 'pytest': '._test.cmdline:main',
'pylookup': '._cmdline.pylookup:main',
'pycountloc': '._cmdline.pycountloc:main',
'pycleanup': '._cmdline.pycleanup:main',
Modified: pypy/trunk/py/_builtin.py
==============================================================================
--- pypy/trunk/py/_builtin.py (original)
+++ pypy/trunk/py/_builtin.py Sat May 22 13:29:12 2010
@@ -151,7 +151,10 @@
return getattr(function, "__dict__", None)
def _getcode(function):
- return getattr(function, "func_code", None)
+ try:
+ return getattr(function, "__code__")
+ except AttributeError:
+ return getattr(function, "func_code", None)
def print_(*args, **kwargs):
""" minimal backport of py3k print statement. """
@@ -175,6 +178,7 @@
def exec_(obj, globals=None, locals=None):
""" minimal backport of py3k exec statement. """
+ __tracebackhide__ = True
if globals is None:
frame = sys._getframe(1)
globals = frame.f_globals
@@ -187,14 +191,17 @@
if sys.version_info >= (3,0):
exec ("""
def _reraise(cls, val, tb):
+ __tracebackhide__ = True
assert hasattr(val, '__traceback__')
raise val
""")
else:
exec ("""
def _reraise(cls, val, tb):
+ __tracebackhide__ = True
raise cls, val, tb
def exec2(obj, globals, locals):
+ __tracebackhide__ = True
exec obj in globals, locals
""")
Modified: pypy/trunk/py/_cmdline/pytest.py
==============================================================================
--- pypy/trunk/py/_cmdline/pytest.py (original)
+++ pypy/trunk/py/_cmdline/pytest.py Sat May 22 13:29:12 2010
@@ -1,5 +1,5 @@
#!/usr/bin/env python
import py
-def main(args):
- py.test.cmdline.main(args)
+def main(args=None):
+ raise SystemExit(py.test.cmdline.main(args))
Modified: pypy/trunk/py/_code/code.py
==============================================================================
--- pypy/trunk/py/_code/code.py (original)
+++ pypy/trunk/py/_code/code.py Sat May 22 13:29:12 2010
@@ -23,64 +23,14 @@
def __ne__(self, other):
return not self == other
- def new(self, rec=False, **kwargs):
- """ return new code object with modified attributes.
- if rec-cursive is true then dive into code
- objects contained in co_consts.
- """
- if sys.platform.startswith("java"):
- # XXX jython does not support the below co_filename hack
- return self.raw
- names = [x for x in dir(self.raw) if x[:3] == 'co_']
- for name in kwargs:
- if name not in names:
- raise TypeError("unknown code attribute: %r" %(name, ))
- if rec and hasattr(self.raw, 'co_consts'): # jython
- newconstlist = []
- co = self.raw
- cotype = type(co)
- for c in co.co_consts:
- if isinstance(c, cotype):
- c = self.__class__(c).new(rec=True, **kwargs)
- newconstlist.append(c)
- return self.new(rec=False, co_consts=tuple(newconstlist), **kwargs)
- for name in names:
- if name not in kwargs:
- kwargs[name] = getattr(self.raw, name)
- arglist = [
- kwargs['co_argcount'],
- kwargs['co_nlocals'],
- kwargs.get('co_stacksize', 0), # jython
- kwargs.get('co_flags', 0), # jython
- kwargs.get('co_code', ''), # jython
- kwargs.get('co_consts', ()), # jython
- kwargs.get('co_names', []), #
- kwargs['co_varnames'],
- kwargs['co_filename'],
- kwargs['co_name'],
- kwargs['co_firstlineno'],
- kwargs.get('co_lnotab', ''), #jython
- kwargs.get('co_freevars', None), #jython
- kwargs.get('co_cellvars', None), # jython
- ]
- if sys.version_info >= (3,0):
- arglist.insert(1, kwargs['co_kwonlyargcount'])
- return self.raw.__class__(*arglist)
- else:
- return py.std.new.code(*arglist)
-
def path(self):
""" return a path object pointing to source code"""
- fn = self.raw.co_filename
- try:
- return fn.__path__
- except AttributeError:
- p = py.path.local(self.raw.co_filename)
- if not p.check():
- # XXX maybe try harder like the weird logic
- # in the standard lib [linecache.updatecache] does?
- p = self.raw.co_filename
- return p
+ p = py.path.local(self.raw.co_filename)
+ if not p.check():
+ # XXX maybe try harder like the weird logic
+ # in the standard lib [linecache.updatecache] does?
+ p = self.raw.co_filename
+ return p
path = property(path, None, None, "path of this code object")
Modified: pypy/trunk/py/_code/source.py
==============================================================================
--- pypy/trunk/py/_code/source.py (original)
+++ pypy/trunk/py/_code/source.py Sat May 22 13:29:12 2010
@@ -2,6 +2,7 @@
import sys
import inspect, tokenize
import py
+from types import ModuleType
cpy_compile = compile
try:
@@ -25,6 +26,8 @@
partlines = []
if isinstance(part, Source):
partlines = part.lines
+ elif isinstance(part, (tuple, list)):
+ partlines = [x.rstrip("\n") for x in part]
elif isinstance(part, py.builtin._basestring):
partlines = part.split('\n')
if rstrip:
@@ -171,7 +174,9 @@
try:
#compile(source+'\n', "x", "exec")
syntax_checker(source+'\n')
- except SyntaxError:
+ except KeyboardInterrupt:
+ raise
+ except Exception:
return False
else:
return True
@@ -212,10 +217,17 @@
else:
if flag & _AST_FLAG:
return co
- co_filename = MyStr(filename)
- co_filename.__source__ = self
- return py.code.Code(co).new(rec=1, co_filename=co_filename)
- #return newcode_withfilename(co, co_filename)
+ lines = [(x + "\n") for x in self.lines]
+ if sys.version_info[0] >= 3:
+ # XXX py3's inspect.getsourcefile() checks for a module
+ # and a pep302 __loader__ ... we don't have a module
+ # at code compile-time so we need to fake it here
+ m = ModuleType("_pycodecompile_pseudo_module")
+ py.std.inspect.modulesbyfile[filename] = None
+ py.std.sys.modules[None] = m
+ m.__loader__ = 1
+ py.std.linecache.cache[filename] = (1, None, lines, filename)
+ return co
#
# public API shortcut functions
@@ -224,11 +236,9 @@
def compile_(source, filename=None, mode='exec', flags=
generators.compiler_flag, dont_inherit=0):
""" compile the given source to a raw code object,
- which points back to the source code through
- "co_filename.__source__". All code objects
- contained in the code object will recursively
- also have this special subclass-of-string
- filename.
+ and maintain an internal cache which allows later
+ retrieval of the source code for the code object
+ and any recursively created code objects.
"""
if _ast is not None and isinstance(source, _ast.AST):
# XXX should Source support having AST?
@@ -262,44 +272,26 @@
#
# helper functions
#
-class MyStr(str):
- """ custom string which allows to add attributes. """
def findsource(obj):
- obj = py.code.getrawcode(obj)
try:
- fullsource = obj.co_filename.__source__
- except AttributeError:
- try:
- sourcelines, lineno = py.std.inspect.findsource(obj)
- except (KeyboardInterrupt, SystemExit):
- raise
- except:
- return None, None
- source = Source()
- source.lines = [line.rstrip() for line in sourcelines]
- return source, lineno
- else:
- lineno = obj.co_firstlineno - 1
- return fullsource, lineno
-
+ sourcelines, lineno = py.std.inspect.findsource(obj)
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except:
+ return None, None
+ source = Source()
+ source.lines = [line.rstrip() for line in sourcelines]
+ return source, lineno
def getsource(obj, **kwargs):
obj = py.code.getrawcode(obj)
try:
- fullsource = obj.co_filename.__source__
- except AttributeError:
- try:
- strsrc = inspect.getsource(obj)
- except IndentationError:
- strsrc = "\"Buggy python version consider upgrading, cannot get source\""
- assert isinstance(strsrc, str)
- return Source(strsrc, **kwargs)
- else:
- lineno = obj.co_firstlineno - 1
- end = fullsource.getblockend(lineno)
- return Source(fullsource[lineno:end+1], deident=True)
-
+ strsrc = inspect.getsource(obj)
+ except IndentationError:
+ strsrc = "\"Buggy python version consider upgrading, cannot get source\""
+ assert isinstance(strsrc, str)
+ return Source(strsrc, **kwargs)
def deindent(lines, offset=None):
if offset is None:
Modified: pypy/trunk/py/_io/capture.py
==============================================================================
--- pypy/trunk/py/_io/capture.py (original)
+++ pypy/trunk/py/_io/capture.py Sat May 22 13:29:12 2010
@@ -26,46 +26,56 @@
raise TypeError("not a byte value: %r" %(data,))
StringIO.write(self, data)
+patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'}
+
class FDCapture:
""" Capture IO to/from a given os-level filedescriptor. """
- def __init__(self, targetfd, tmpfile=None):
+ def __init__(self, targetfd, tmpfile=None, now=True, patchsys=False):
""" save targetfd descriptor, and open a new
temporary file there. If no tmpfile is
specified a tempfile.Tempfile() will be opened
in text mode.
"""
self.targetfd = targetfd
- if tmpfile is None:
+ if tmpfile is None and targetfd != 0:
f = tempfile.TemporaryFile('wb+')
tmpfile = dupfile(f, encoding="UTF-8")
f.close()
self.tmpfile = tmpfile
- self._savefd = os.dup(targetfd)
- os.dup2(self.tmpfile.fileno(), targetfd)
- self._patched = []
-
- def setasfile(self, name, module=sys):
- """ patch <module>.<name> to self.tmpfile
- """
- key = (module, name)
- self._patched.append((key, getattr(module, name)))
- setattr(module, name, self.tmpfile)
+ self._savefd = os.dup(self.targetfd)
+ if patchsys:
+ self._oldsys = getattr(sys, patchsysdict[targetfd])
+ if now:
+ self.start()
- def unsetfiles(self):
- """ unpatch all patched items
- """
- while self._patched:
- (module, name), value = self._patched.pop()
- setattr(module, name, value)
+ def start(self):
+ try:
+ os.fstat(self._savefd)
+ except OSError:
+ raise ValueError("saved filedescriptor not valid, "
+ "did you call start() twice?")
+ if self.targetfd == 0 and not self.tmpfile:
+ fd = os.open(devnullpath, os.O_RDONLY)
+ os.dup2(fd, 0)
+ os.close(fd)
+ if hasattr(self, '_oldsys'):
+ setattr(sys, patchsysdict[self.targetfd], DontReadFromInput())
+ else:
+ fd = self.tmpfile.fileno()
+ os.dup2(self.tmpfile.fileno(), self.targetfd)
+ if hasattr(self, '_oldsys'):
+ setattr(sys, patchsysdict[self.targetfd], self.tmpfile)
def done(self):
""" unpatch and clean up, returns the self.tmpfile (file object)
"""
os.dup2(self._savefd, self.targetfd)
- self.unsetfiles()
os.close(self._savefd)
- self.tmpfile.seek(0)
+ if self.targetfd != 0:
+ self.tmpfile.seek(0)
+ if hasattr(self, '_oldsys'):
+ setattr(sys, patchsysdict[self.targetfd], self._oldsys)
return self.tmpfile
def writeorg(self, data):
@@ -100,7 +110,7 @@
if encoding is not None:
mode = mode.replace("b", "")
buffering = True
- return os.fdopen(newfd, mode, buffering, encoding, closefd=False)
+ return os.fdopen(newfd, mode, buffering, encoding, closefd=True)
else:
f = os.fdopen(newfd, mode, buffering)
if encoding is not None:
@@ -146,90 +156,94 @@
def reset(self):
""" reset sys.stdout/stderr and return captured output as strings. """
- if hasattr(self, '_suspended'):
- outfile = self._kwargs['out']
- errfile = self._kwargs['err']
- del self._kwargs
- else:
- outfile, errfile = self.done()
+ outfile, errfile = self.done()
out, err = "", ""
- if outfile:
+ if outfile and not outfile.closed:
out = outfile.read()
outfile.close()
- if errfile and errfile != outfile:
+ if errfile and errfile != outfile and not errfile.closed:
err = errfile.read()
errfile.close()
return out, err
def suspend(self):
""" return current snapshot captures, memorize tempfiles. """
- assert not hasattr(self, '_suspended')
- self._suspended = True
outerr = self.readouterr()
outfile, errfile = self.done()
- self._kwargs['out'] = outfile
- self._kwargs['err'] = errfile
return outerr
- def resume(self):
- """ resume capturing with original temp files. """
- assert self._suspended
- self._initialize(**self._kwargs)
- del self._suspended
-
class StdCaptureFD(Capture):
""" This class allows to capture writes to FD1 and FD2
and may connect a NULL file to FD0 (and prevent
- reads from sys.stdin)
+ reads from sys.stdin). If any of the 0,1,2 file descriptors
+ is invalid it will not be captured.
"""
- def __init__(self, out=True, err=True,
- mixed=False, in_=True, patchsys=True):
- self._kwargs = locals().copy()
- del self._kwargs['self']
- self._initialize(**self._kwargs)
-
- def _initialize(self, out=True, err=True,
- mixed=False, in_=True, patchsys=True):
+ def __init__(self, out=True, err=True, mixed=False,
+ in_=True, patchsys=True, now=True):
+ self._options = locals()
+ self._save()
+ if now:
+ self.startall()
+
+ def _save(self):
+ in_ = self._options['in_']
+ out = self._options['out']
+ err = self._options['err']
+ mixed = self._options['mixed']
+ patchsys = self._options['patchsys']
if in_:
- self._oldin = (sys.stdin, os.dup(0))
- sys.stdin = DontReadFromInput()
- fd = os.open(devnullpath, os.O_RDONLY)
- os.dup2(fd, 0)
- os.close(fd)
- if out:
+ try:
+ self.in_ = FDCapture(0, tmpfile=None, now=False,
+ patchsys=patchsys)
+ except OSError:
+ pass
+ if out:
tmpfile = None
if hasattr(out, 'write'):
tmpfile = out
- self.out = py.io.FDCapture(1, tmpfile=tmpfile)
- if patchsys:
- self.out.setasfile('stdout')
- if err:
- if mixed and out:
+ try:
+ self.out = FDCapture(1, tmpfile=tmpfile,
+ now=False, patchsys=patchsys)
+ self._options['out'] = self.out.tmpfile
+ except OSError:
+ pass
+ if err:
+ if out and mixed:
tmpfile = self.out.tmpfile
elif hasattr(err, 'write'):
tmpfile = err
else:
tmpfile = None
- self.err = py.io.FDCapture(2, tmpfile=tmpfile)
- if patchsys:
- self.err.setasfile('stderr')
+ try:
+ self.err = FDCapture(2, tmpfile=tmpfile,
+ now=False, patchsys=patchsys)
+ self._options['err'] = self.err.tmpfile
+ except OSError:
+ pass
+
+ def startall(self):
+ if hasattr(self, 'in_'):
+ self.in_.start()
+ if hasattr(self, 'out'):
+ self.out.start()
+ if hasattr(self, 'err'):
+ self.err.start()
+
+ def resume(self):
+ """ resume capturing with original temp files. """
+ self.startall()
def done(self):
""" return (outfile, errfile) and stop capturing. """
- if hasattr(self, 'out'):
+ outfile = errfile = None
+ if hasattr(self, 'out') and not self.out.tmpfile.closed:
outfile = self.out.done()
- else:
- outfile = None
- if hasattr(self, 'err'):
+ if hasattr(self, 'err') and not self.err.tmpfile.closed:
errfile = self.err.done()
- else:
- errfile = None
- if hasattr(self, '_oldin'):
- oldsys, oldfd = self._oldin
- os.dup2(oldfd, 0)
- os.close(oldfd)
- sys.stdin = oldsys
+ if hasattr(self, 'in_'):
+ tmpfile = self.in_.done()
+ self._save()
return outfile, errfile
def readouterr(self):
@@ -252,69 +266,61 @@
modifies sys.stdout|stderr|stdin attributes and does not
touch underlying File Descriptors (use StdCaptureFD for that).
"""
- def __init__(self, out=True, err=True, in_=True, mixed=False):
- self._kwargs = locals().copy()
- del self._kwargs['self']
- self._initialize(**self._kwargs)
-
- def _initialize(self, out, err, in_, mixed):
- self._out = out
- self._err = err
- self._in = in_
- if out:
- self._oldout = sys.stdout
- if not hasattr(out, 'write'):
- out = TextIO()
- sys.stdout = self.out = out
- if err:
- self._olderr = sys.stderr
- if out and mixed:
- err = self.out
+ def __init__(self, out=True, err=True, in_=True, mixed=False, now=True):
+ self._oldout = sys.stdout
+ self._olderr = sys.stderr
+ self._oldin = sys.stdin
+ if out and not hasattr(out, 'file'):
+ out = TextIO()
+ self.out = out
+ if err:
+ if mixed:
+ err = out
elif not hasattr(err, 'write'):
err = TextIO()
- sys.stderr = self.err = err
- if in_:
- self._oldin = sys.stdin
- sys.stdin = self.newin = DontReadFromInput()
+ self.err = err
+ self.in_ = in_
+ if now:
+ self.startall()
+
+ def startall(self):
+ if self.out:
+ sys.stdout = self.out
+ if self.err:
+ sys.stderr = self.err
+ if self.in_:
+ sys.stdin = self.in_ = DontReadFromInput()
def done(self):
""" return (outfile, errfile) and stop capturing. """
- o,e = sys.stdout, sys.stderr
- if self._out:
- try:
- sys.stdout = self._oldout
- except AttributeError:
- raise IOError("stdout capturing already reset")
- del self._oldout
+ outfile = errfile = None
+ if self.out and not self.out.closed:
+ sys.stdout = self._oldout
outfile = self.out
outfile.seek(0)
- else:
- outfile = None
- if self._err:
- try:
- sys.stderr = self._olderr
- except AttributeError:
- raise IOError("stderr capturing already reset")
- del self._olderr
+ if self.err and not self.err.closed:
+ sys.stderr = self._olderr
errfile = self.err
errfile.seek(0)
- else:
- errfile = None
- if self._in:
+ if self.in_:
sys.stdin = self._oldin
return outfile, errfile
+ def resume(self):
+ """ resume capturing with original temp files. """
+ self.startall()
+
def readouterr(self):
""" return snapshot value of stdout/stderr capturings. """
out = err = ""
- if self._out:
- out = sys.stdout.getvalue()
- sys.stdout.truncate(0)
- sys.stdout.seek(0)
- if self._err:
- err = sys.stderr.getvalue()
- sys.stderr.truncate(0)
- sys.stderr.seek(0)
+ if self.out:
+ out = self.out.getvalue()
+ self.out.truncate(0)
+ self.out.seek(0)
+ if self.err:
+ err = self.err.getvalue()
+ self.err.truncate(0)
+ self.err.seek(0)
return out, err
class DontReadFromInput:
@@ -344,5 +350,3 @@
devnullpath = 'NUL'
else:
devnullpath = '/dev/null'
-
-
Modified: pypy/trunk/py/_plugin/pytest__pytest.py
==============================================================================
--- pypy/trunk/py/_plugin/pytest__pytest.py (original)
+++ pypy/trunk/py/_plugin/pytest__pytest.py Sat May 22 13:29:12 2010
@@ -46,7 +46,8 @@
recorder = RecordCalls()
self._recorders[hookspec] = recorder
self._registry.register(recorder)
- self.hook = HookRelay(hookspecs, registry=self._registry)
+ self.hook = HookRelay(hookspecs, registry=self._registry,
+ prefix="pytest_")
def finish_recording(self):
for recorder in self._recorders.values():
Modified: pypy/trunk/py/_plugin/pytest_capture.py
==============================================================================
--- pypy/trunk/py/_plugin/pytest_capture.py (original)
+++ pypy/trunk/py/_plugin/pytest_capture.py Sat May 22 13:29:12 2010
@@ -106,6 +106,14 @@
def pytest_configure(config):
config.pluginmanager.register(CaptureManager(), 'capturemanager')
+class NoCapture:
+ def startall(self):
+ pass
+ def resume(self):
+ pass
+ def suspend(self):
+ return "", ""
+
class CaptureManager:
def __init__(self):
self._method2capture = {}
@@ -118,15 +126,17 @@
def _makestringio(self):
return py.io.TextIO()
- def _startcapture(self, method):
+ def _getcapture(self, method):
if method == "fd":
- return py.io.StdCaptureFD(
+ return py.io.StdCaptureFD(now=False,
out=self._maketempfile(), err=self._maketempfile()
)
elif method == "sys":
- return py.io.StdCapture(
+ return py.io.StdCapture(now=False,
out=self._makestringio(), err=self._makestringio()
)
+ elif method == "no":
+ return NoCapture()
else:
raise ValueError("unknown capturing method: %r" % method)
@@ -152,27 +162,25 @@
if hasattr(self, '_capturing'):
raise ValueError("cannot resume, already capturing with %r" %
(self._capturing,))
- if method != "no":
- cap = self._method2capture.get(method)
- if cap is None:
- cap = self._startcapture(method)
- self._method2capture[method] = cap
- else:
- cap.resume()
+ cap = self._method2capture.get(method)
self._capturing = method
+ if cap is None:
+ self._method2capture[method] = cap = self._getcapture(method)
+ cap.startall()
+ else:
+ cap.resume()
def suspendcapture(self, item=None):
self.deactivate_funcargs()
if hasattr(self, '_capturing'):
method = self._capturing
- if method != "no":
- cap = self._method2capture[method]
+ cap = self._method2capture.get(method)
+ if cap is not None:
outerr = cap.suspend()
- else:
- outerr = "", ""
del self._capturing
if item:
- outerr = (item.outerr[0] + outerr[0], item.outerr[1] + outerr[1])
+ outerr = (item.outerr[0] + outerr[0],
+ item.outerr[1] + outerr[1])
return outerr
return "", ""
@@ -180,19 +188,17 @@
if not hasattr(pyfuncitem, 'funcargs'):
return
assert not hasattr(self, '_capturing_funcargs')
- l = []
- for name, obj in pyfuncitem.funcargs.items():
- if name == 'capfd' and not hasattr(os, 'dup'):
- py.test.skip("capfd funcarg needs os.dup")
+ self._capturing_funcargs = capturing_funcargs = []
+ for name, capfuncarg in pyfuncitem.funcargs.items():
if name in ('capsys', 'capfd'):
- obj._start()
- l.append(obj)
- if l:
- self._capturing_funcargs = l
+ capturing_funcargs.append(capfuncarg)
+ capfuncarg._start()
def deactivate_funcargs(self):
- if hasattr(self, '_capturing_funcargs'):
- for capfuncarg in self._capturing_funcargs:
+ capturing_funcargs = getattr(self, '_capturing_funcargs', None)
+ if capturing_funcargs is not None:
+ while capturing_funcargs:
+ capfuncarg = capturing_funcargs.pop()
capfuncarg._finalize()
del self._capturing_funcargs
@@ -256,16 +262,19 @@
platform does not have ``os.dup`` (e.g. Jython) tests using
this funcarg will automatically skip.
"""
+ if not hasattr(os, 'dup'):
+ py.test.skip("capfd funcarg needs os.dup")
return CaptureFuncarg(request, py.io.StdCaptureFD)
class CaptureFuncarg:
def __init__(self, request, captureclass):
self._cclass = captureclass
+ self.capture = self._cclass(now=False)
#request.addfinalizer(self._finalize)
def _start(self):
- self.capture = self._cclass()
+ self.capture.startall()
def _finalize(self):
if hasattr(self, 'capture'):
@@ -276,6 +285,4 @@
return self.capture.readouterr()
def close(self):
- self.capture.reset()
- del self.capture
-
+ self._finalize()
Modified: pypy/trunk/py/_plugin/pytest_genscript.py
==============================================================================
--- pypy/trunk/py/_plugin/pytest_genscript.py (original)
+++ pypy/trunk/py/_plugin/pytest_genscript.py Sat May 22 13:29:12 2010
@@ -4,14 +4,7 @@
"""
import os
-import zlib
-import base64
import sys
-try:
- import pickle
-except Importerror:
- import cPickle as pickle
-
def pytest_addoption(parser):
group = parser.getgroup("debugconfig")
group.addoption("--genscript", action="store", default=None,
@@ -30,6 +23,13 @@
raise SystemExit(0)
def main(pybasedir, outfile, infile):
+ import base64
+ import zlib
+ try:
+ import pickle
+ except Importerror:
+ import cPickle as pickle
+
outfile = str(outfile)
infile = str(infile)
assert os.path.isabs(outfile)
Modified: pypy/trunk/py/_plugin/pytest_junitxml.py
==============================================================================
--- pypy/trunk/py/_plugin/pytest_junitxml.py (original)
+++ pypy/trunk/py/_plugin/pytest_junitxml.py Sat May 22 13:29:12 2010
@@ -56,10 +56,15 @@
def append_failure(self, report):
self._opentestcase(report)
#msg = str(report.longrepr.reprtraceback.extraline)
- self.appendlog('<failure message="test failure">%s</failure>',
- report.longrepr)
+ if "xfail" in report.keywords:
+ self.appendlog(
+ '<skipped message="xfail-marked test passes unexpectedly"/>')
+ self.skipped += 1
+ else:
+ self.appendlog('<failure message="test failure">%s</failure>',
+ report.longrepr)
+ self.failed += 1
self._closetestcase()
- self.failed += 1
def _opentestcase_collectfailure(self, report):
node = report.collector
@@ -95,7 +100,12 @@
def append_skipped(self, report):
self._opentestcase(report)
- self.appendlog("<skipped/>")
+ if "xfail" in report.keywords:
+ self.appendlog(
+ '<skipped message="expected test failure">%s</skipped>',
+ report.keywords['xfail'])
+ else:
+ self.appendlog("<skipped/>")
self._closetestcase()
self.skipped += 1
Modified: pypy/trunk/py/_plugin/pytest_mark.py
==============================================================================
--- pypy/trunk/py/_plugin/pytest_mark.py (original)
+++ pypy/trunk/py/_plugin/pytest_mark.py Sat May 22 13:29:12 2010
@@ -34,38 +34,43 @@
.. _`scoped-marking`:
-Marking classes or modules
+Marking whole classes or modules
----------------------------------------------------
-To mark all methods of a class set a ``pytestmark`` attribute like this::
+If you are programming with Python2.6 you may use ``py.test.mark`` decorators
+with classes to apply markers to all its test methods::
+
+ @py.test.mark.webtest
+ class TestClass:
+ def test_startup(self):
+ ...
+
+This is equivalent to directly applying the decorator to the
+``test_startup`` function.
+
+To remain compatible with Python2.5 you can instead set a
+``pytestmark`` attribute on a TestClass like this::
import py
class TestClass:
pytestmark = py.test.mark.webtest
-You can re-use the same markers that you would use for decorating
-a function - in fact this marker decorator will be applied
-to all test methods of the class.
+or if you need to use multiple markers::
+
+ import py
+
+ class TestClass:
+ pytestmark = [py.test.mark.webtest, pytest.mark.slowtest]
You can also set a module level marker::
import py
pytestmark = py.test.mark.webtest
-in which case then the marker decorator will be applied to all functions and
+in which case then it will be applied to all functions and
methods defined in the module.
-The order in which marker functions are called is this::
-
- per-function (upon import of module already)
- per-class
- per-module
-
-Later called markers may overwrite previous key-value settings.
-Positional arguments are all appended to the same 'args' list
-of the Marker object.
-
Using "-k MARKNAME" to select tests
----------------------------------------------------
@@ -105,15 +110,23 @@
""" if passed a single callable argument: decorate it with mark info.
otherwise add *args/**kwargs in-place to mark information. """
if args:
- if len(args) == 1 and hasattr(args[0], '__call__'):
- func = args[0]
- holder = getattr(func, self.markname, None)
- if holder is None:
- holder = MarkInfo(self.markname, self.args, self.kwargs)
- setattr(func, self.markname, holder)
+ func = args[0]
+ if len(args) == 1 and hasattr(func, '__call__') or \
+ hasattr(func, '__bases__'):
+ if hasattr(func, '__bases__'):
+ l = func.__dict__.setdefault("pytestmark", [])
+ if not isinstance(l, list):
+ func.pytestmark = [l, self]
+ else:
+ l.append(self)
else:
- holder.kwargs.update(self.kwargs)
- holder.args.extend(self.args)
+ holder = getattr(func, self.markname, None)
+ if holder is None:
+ holder = MarkInfo(self.markname, self.args, self.kwargs)
+ setattr(func, self.markname, holder)
+ else:
+ holder.kwargs.update(self.kwargs)
+ holder.args.extend(self.args)
return func
else:
self.args.extend(args)
@@ -147,6 +160,10 @@
func = getattr(func, 'im_func', func) # py2
for parent in [x for x in (mod, cls) if x]:
marker = getattr(parent.obj, 'pytestmark', None)
- if isinstance(marker, MarkDecorator):
- marker(func)
+ if marker is not None:
+ if not isinstance(marker, list):
+ marker = [marker]
+ for mark in marker:
+ if isinstance(mark, MarkDecorator):
+ mark(func)
return item
Modified: pypy/trunk/py/_plugin/pytest_pytester.py
==============================================================================
--- pypy/trunk/py/_plugin/pytest_pytester.py (original)
+++ pypy/trunk/py/_plugin/pytest_pytester.py Sat May 22 13:29:12 2010
@@ -110,7 +110,7 @@
def _makefile(self, ext, args, kwargs):
items = list(kwargs.items())
if args:
- source = "\n".join(map(str, args))
+ source = "\n".join(map(str, args)) + "\n"
basename = self.request.function.__name__
items.insert(0, (basename, source))
ret = None
@@ -294,8 +294,10 @@
ret = popen.wait()
f1.close()
f2.close()
- out = p1.read("rb").decode("utf-8").splitlines()
- err = p2.read("rb").decode("utf-8").splitlines()
+ out = p1.read("rb")
+ out = getdecoded(out).splitlines()
+ err = p2.read("rb")
+ err = getdecoded(err).splitlines()
def dump_lines(lines, fp):
try:
for line in lines:
@@ -360,6 +362,13 @@
child.timeout = expect_timeout
return child
+def getdecoded(out):
+ try:
+ return out.decode("utf-8")
+ except UnicodeDecodeError:
+ return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % (
+ py.io.saferepr(out),)
+
class PseudoPlugin:
def __init__(self, vars):
self.__dict__.update(vars)
Modified: pypy/trunk/py/_plugin/pytest_resultlog.py
==============================================================================
--- pypy/trunk/py/_plugin/pytest_resultlog.py (original)
+++ pypy/trunk/py/_plugin/pytest_resultlog.py Sat May 22 13:29:12 2010
@@ -73,7 +73,7 @@
code = report.shortrepr
if code == 'x':
longrepr = str(report.longrepr)
- elif code == 'P':
+ elif code == 'X':
longrepr = ''
elif report.passed:
longrepr = ""
Modified: pypy/trunk/py/_plugin/pytest_runner.py
==============================================================================
--- pypy/trunk/py/_plugin/pytest_runner.py (original)
+++ pypy/trunk/py/_plugin/pytest_runner.py Sat May 22 13:29:12 2010
@@ -10,6 +10,7 @@
'skip' : skip,
'importorskip' : importorskip,
'fail' : fail,
+ 'xfail' : xfail,
'exit' : exit,
}
@@ -295,6 +296,10 @@
""" raised from an explicit call to py.test.fail() """
__module__ = 'builtins'
+class XFailed(OutcomeException):
+ """ raised from an explicit call to py.test.xfail() """
+ __module__ = 'builtins'
+
class ExceptionFailure(Failed):
""" raised by py.test.raises on an exception-assertion mismatch. """
def __init__(self, expr, expected, msg=None, excinfo=None):
@@ -335,6 +340,14 @@
fail.Exception = Failed
+def xfail(reason=""):
+ """ xfail an executing test or setup functions, taking an optional
+ reason string.
+ """
+ __tracebackhide__ = True
+ raise XFailed(reason)
+xfail.Exception = XFailed
+
def raises(ExpectedException, *args, **kwargs):
""" if args[0] is callable: raise AssertionError if calling it with
the remaining arguments does not raise the expected exception.
Modified: pypy/trunk/py/_plugin/pytest_skipping.py
==============================================================================
--- pypy/trunk/py/_plugin/pytest_skipping.py (original)
+++ pypy/trunk/py/_plugin/pytest_skipping.py Sat May 22 13:29:12 2010
@@ -60,6 +60,19 @@
#
The ``pytestmark`` decorator will be applied to each test function.
+If your code targets python2.6 or above you can equivalently use
+the skipif decorator on classes::
+
+ @py.test.mark.skipif("sys.platform == 'win32'")
+ class TestPosixCalls:
+
+ def test_function(self):
+ # will not be setup or run under 'win32' platform
+ #
+
+It is fine in general to apply multiple "skipif" decorators
+on a single function - this means that if any of the conditions
+apply the function will be skipped.
.. _`whole class- or module level`: mark.html#scoped-marking
@@ -82,10 +95,17 @@
depending on platform::
@py.test.mark.xfail("sys.version_info >= (3,0)")
-
def test_function():
...
+To not run a test and still regard it as "xfailed"::
+
+ @py.test.mark.xfail(..., run=False)
+
+To specify an explicit reason to be shown with xfailure detail::
+
+ @py.test.mark.xfail(..., reason="my reason")
+
skipping on a missing import dependency
--------------------------------------------------
@@ -115,11 +135,14 @@
py.test.skip("unsuppored configuration")
"""
-# XXX py.test.skip, .importorskip and the Skipped class
-# should also be defined in this plugin, requires thought/changes
import py
+def pytest_addoption(parser):
+ group = parser.getgroup("general")
+ group.addoption('--runxfail',
+ action="store_true", dest="runxfail", default=False,
+ help="run tests even if they are marked xfail")
class MarkEvaluator:
def __init__(self, item, name):
@@ -134,17 +157,20 @@
def istrue(self):
if self.holder:
d = {'os': py.std.os, 'sys': py.std.sys, 'config': self.item.config}
- self.result = True
- for expr in self.holder.args:
- self.expr = expr
- if isinstance(expr, str):
- result = cached_eval(self.item.config, expr, d)
- else:
- result = expr
- if not result:
- self.result = False
+ if self.holder.args:
+ self.result = False
+ for expr in self.holder.args:
self.expr = expr
- break
+ if isinstance(expr, str):
+ result = cached_eval(self.item.config, expr, d)
+ else:
+ result = expr
+ if result:
+ self.result = True
+ self.expr = expr
+ break
+ else:
+ self.result = True
return getattr(self, 'result', False)
def get(self, attr, default=None):
@@ -161,27 +187,53 @@
def pytest_runtest_setup(item):
- expr, result = evalexpression(item, 'skipif')
- if result:
- py.test.skip(expr)
+ if not isinstance(item, py.test.collect.Function):
+ return
+ evalskip = MarkEvaluator(item, 'skipif')
+ if evalskip.istrue():
+ py.test.skip(evalskip.getexplanation())
+ item._evalxfail = MarkEvaluator(item, 'xfail')
+ if not item.config.getvalue("runxfail"):
+ if item._evalxfail.istrue():
+ if not item._evalxfail.get('run', True):
+ py.test.skip("xfail")
def pytest_runtest_makereport(__multicall__, item, call):
- if call.when != "call":
+ if not isinstance(item, py.test.collect.Function):
return
- expr, result = evalexpression(item, 'xfail')
- rep = __multicall__.execute()
- if result:
- if call.excinfo:
- rep.skipped = True
- rep.failed = rep.passed = False
+ if not (call.excinfo and
+ call.excinfo.errisinstance(py.test.xfail.Exception)):
+ evalxfail = getattr(item, '_evalxfail', None)
+ if not evalxfail:
+ return
+ if call.excinfo and call.excinfo.errisinstance(py.test.xfail.Exception):
+ rep = __multicall__.execute()
+ rep.keywords['xfail'] = "reason: " + call.excinfo.value.msg
+ rep.skipped = True
+ rep.failed = False
+ return rep
+ if call.when == "setup":
+ rep = __multicall__.execute()
+ if rep.skipped and evalxfail.istrue():
+ expl = evalxfail.getexplanation()
+ if not evalxfail.get("run", True):
+ expl = "[NOTRUN] " + expl
+ rep.keywords['xfail'] = expl
+ return rep
+ elif call.when == "call":
+ rep = __multicall__.execute()
+ if not item.config.getvalue("runxfail") and evalxfail.istrue():
+ if call.excinfo:
+ rep.skipped = True
+ rep.failed = rep.passed = False
+ else:
+ rep.skipped = rep.passed = False
+ rep.failed = True
+ rep.keywords['xfail'] = evalxfail.getexplanation()
else:
- rep.skipped = rep.passed = False
- rep.failed = True
- rep.keywords['xfail'] = expr
- else:
- if 'xfail' in rep.keywords:
- del rep.keywords['xfail']
- return rep
+ if 'xfail' in rep.keywords:
+ del rep.keywords['xfail']
+ return rep
# called by terminalreporter progress reporting
def pytest_report_teststatus(report):
@@ -189,7 +241,7 @@
if report.skipped:
return "xfailed", "x", "xfail"
elif report.failed:
- return "xpassed", "P", "xpass"
+ return "xpassed", "X", "XPASS"
# called by the terminalreporter instance/plugin
def pytest_terminal_summary(terminalreporter):
@@ -229,13 +281,8 @@
xfailed = terminalreporter.stats.get("xfailed")
if xfailed:
for rep in xfailed:
- entry = rep.longrepr.reprcrash
- modpath = rep.item.getmodpath(includemodule=True)
- pos = "%s %s:%d: " %(modpath, entry.path, entry.lineno)
- reason = rep.longrepr.reprcrash.message
- i = reason.find("\n")
- if i != -1:
- reason = reason[:i]
+ pos = terminalreporter.gettestid(rep.item)
+ reason = rep.keywords['xfail']
lines.append("XFAIL %s %s" %(pos, reason))
def show_xpassed(terminalreporter, lines):
@@ -246,24 +293,6 @@
reason = rep.keywords['xfail']
lines.append("XPASS %s %s" %(pos, reason))
-
-def evalexpression(item, keyword):
- if isinstance(item, py.test.collect.Function):
- markholder = getattr(item.obj, keyword, None)
- result = False
- if markholder:
- d = {'os': py.std.os, 'sys': py.std.sys, 'config': item.config}
- expr, result = None, True
- for expr in markholder.args:
- if isinstance(expr, str):
- result = cached_eval(item.config, expr, d)
- else:
- result = expr
- if not result:
- break
- return expr, result
- return None, False
-
def cached_eval(config, expr, d):
if not hasattr(config, '_evalcache'):
config._evalcache = {}
Modified: pypy/trunk/py/_plugin/pytest_terminal.py
==============================================================================
--- pypy/trunk/py/_plugin/pytest_terminal.py (original)
+++ pypy/trunk/py/_plugin/pytest_terminal.py Sat May 22 13:29:12 2010
@@ -141,6 +141,20 @@
else:
return "???", dict(red=True)
+ def gettestid(self, item, relative=True):
+ fspath = item.fspath
+ chain = [x for x in item.listchain() if x.fspath == fspath]
+ chain = chain[1:]
+ names = [x.name for x in chain if x.name != "()"]
+ path = item.fspath
+ if relative:
+ relpath = path.relto(self.curdir)
+ if relpath:
+ path = relpath
+ names.insert(0, str(path))
+ return "::".join(names)
+
+
def pytest_internalerror(self, excrepr):
for line in str(excrepr).split("\n"):
self.write_line("INTERNALERROR> " + line)
Modified: pypy/trunk/py/_test/cmdline.py
==============================================================================
--- pypy/trunk/py/_test/cmdline.py (original)
+++ pypy/trunk/py/_test/cmdline.py Sat May 22 13:29:12 2010
@@ -16,8 +16,9 @@
colitems = config.getinitialnodes()
exitstatus = session.main(colitems)
config.pluginmanager.do_unconfigure(config)
- raise SystemExit(exitstatus)
except config.Error:
e = sys.exc_info()[1]
sys.stderr.write("ERROR: %s\n" %(e.args[0],))
- raise SystemExit(3)
+ exitstatus = 3
+ py.test.config = py.test.config.__class__()
+ return exitstatus
Modified: pypy/trunk/py/_test/pycollect.py
==============================================================================
--- pypy/trunk/py/_test/pycollect.py (original)
+++ pypy/trunk/py/_test/pycollect.py Sat May 22 13:29:12 2010
@@ -393,5 +393,5 @@
def hasinit(obj):
init = getattr(obj, '__init__', None)
if init:
- if not isinstance(init, type(object.__init__)):
+ if init != object.__init__:
return True
Modified: pypy/trunk/pypy/conftest.py
==============================================================================
--- pypy/trunk/pypy/conftest.py (original)
+++ pypy/trunk/pypy/conftest.py Sat May 22 13:29:12 2010
@@ -383,10 +383,15 @@
if option.runappdirect:
return target()
space = gettestobjspace()
- func = app2interp_temp(target)
+ filename = self._getdynfilename(target)
+ func = app2interp_temp(target, filename=filename)
print "executing", func
self.execute_appex(space, func, space)
+ def _getdynfilename(self, func):
+ code = getattr(func, 'im_func', func).func_code
+ return "[%s:%s]" % (code.co_filename, code.co_firstlineno)
+
class AppTestMethod(AppTestFunction):
def setup(self):
@@ -410,7 +415,8 @@
if option.runappdirect:
return target()
space = target.im_self.space
- func = app2interp_temp(target.im_func)
+ filename = self._getdynfilename(target)
+ func = app2interp_temp(target.im_func, filename=filename)
w_instance = self.parent.w_instance
self.execute_appex(space, func, space, w_instance)
Modified: pypy/trunk/pypy/interpreter/gateway.py
==============================================================================
--- pypy/trunk/pypy/interpreter/gateway.py (original)
+++ pypy/trunk/pypy/interpreter/gateway.py Sat May 22 13:29:12 2010
@@ -821,9 +821,6 @@
# and now for something completely different ...
#
-class MyStr(str):
- pass
-
class ApplevelClass:
"""NOT_RPYTHON
A container for app-level source code that should be executed
@@ -837,8 +834,7 @@
# HAAACK (but a good one)
if filename is None:
f = sys._getframe(1)
- filename = MyStr('<%s:%d>' % (f.f_code.co_filename, f.f_lineno))
- filename.__source__ = py.code.Source(source)
+ filename = '<%s:%d>' % (f.f_code.co_filename, f.f_lineno)
self.filename = filename
self.source = str(py.code.Source(source).deindent())
self.modname = modname
@@ -848,6 +844,9 @@
self.can_use_geninterp = False
else:
self.can_use_geninterp = True
+ # make source code available for tracebacks
+ lines = [x + "\n" for x in source.split("\n")]
+ py.std.linecache.cache[filename] = (1, None, lines, filename)
def __repr__(self):
return "<ApplevelClass filename=%r can_use_geninterp=%r>" % (self.filename, self.can_use_geninterp)
@@ -1081,14 +1080,14 @@
# ____________________________________________________________
-def appdef(source, applevel=ApplevelClass):
+def appdef(source, applevel=ApplevelClass, filename=None):
""" NOT_RPYTHON: build an app-level helper function, like for example:
myfunc = appdef('''myfunc(x, y):
return x+y
''')
"""
if not isinstance(source, str):
- source = str(py.code.Source(source).strip())
+ source = py.std.inspect.getsource(source).lstrip()
while source.startswith('@py.test.mark.'):
# these decorators are known to return the same function
# object, we may ignore them
@@ -1100,7 +1099,11 @@
assert p >= 0
funcname = source[:p].strip()
source = source[p:]
- return applevel("def %s%s\n" % (funcname, source)).interphook(funcname)
+ assert source.strip()
+ funcsource = "def %s%s\n" % (funcname, source)
+ #for debugging of wrong source code: py.std.parser.suite(funcsource)
+ a = applevel(funcsource, filename=filename)
+ return a.interphook(funcname)
applevel = ApplevelClass # backward compatibility
app2interp = appdef # backward compatibility
@@ -1118,6 +1121,6 @@
return PyPyCacheDir.build_applevelinterp_dict(self, space)
# app2interp_temp is used for testing mainly
-def app2interp_temp(func, applevel_temp=applevel_temp):
+def app2interp_temp(func, applevel_temp=applevel_temp, filename=None):
""" NOT_RPYTHON """
- return appdef(func, applevel_temp)
+ return appdef(func, applevel_temp, filename=filename)
Modified: pypy/trunk/pypy/interpreter/test/test_code.py
==============================================================================
--- pypy/trunk/pypy/interpreter/test/test_code.py (original)
+++ pypy/trunk/pypy/interpreter/test/test_code.py Sat May 22 13:29:12 2010
@@ -6,11 +6,7 @@
def setup_class(cls):
space = gettestobjspace()
cls.space = space
- if py.test.config.option.runappdirect:
- filename = __file__
- else:
- filename = gateway.__file__
-
+ filename = __file__
if filename[-3:] != '.py':
filename = filename[:-1]
Modified: pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py (original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py Sat May 22 13:29:12 2010
@@ -131,7 +131,7 @@
assert warmrunnerdescr.state.optimize_loop is optimize.optimize_loop
assert warmrunnerdescr.state.optimize_bridge is optimize.optimize_bridge
- def test_static_debug_level(self):
+ def test_static_debug_level(self, capfd):
py.test.skip("debug_level is being deprecated")
from pypy.rlib.jit import DEBUG_PROFILE, DEBUG_OFF, DEBUG_STEPS
from pypy.jit.metainterp.jitprof import EmptyProfiler, Profiler
@@ -144,36 +144,31 @@
n -= 1
return n
- outerr = py.io.StdCaptureFD()
+ capfd.readouterr()
self.meta_interp(f, [10], debug_level=DEBUG_OFF,
ProfilerClass=Profiler)
- out, errf = outerr.done()
- err = errf.read()
+ out, err = capfd.readouterr()
assert not 'ENTER' in err
assert not 'LEAVE' in err
assert not "Running asm" in err
- outerr = py.io.StdCaptureFD()
self.meta_interp(f, [10], debug_level=DEBUG_PROFILE,
ProfilerClass=Profiler)
- out, errf = outerr.done()
- err = errf.read()
+ out, err = capfd.readouterr()
assert not 'ENTER' in err
assert not 'LEAVE' in err
assert not 'compiled new' in err
assert "Running asm" in err
- outerr = py.io.StdCaptureFD()
+
self.meta_interp(f, [10], debug_level=DEBUG_STEPS,
ProfilerClass=Profiler)
- out, errf = outerr.done()
- err = errf.read()
+ out, err = capfd.readouterr()
assert 'ENTER' in err
assert 'LEAVE' in err
assert "Running asm" in err
- outerr = py.io.StdCaptureFD()
+
self.meta_interp(f, [10], debug_level=DEBUG_STEPS,
ProfilerClass=EmptyProfiler)
- out, errf = outerr.done()
- err = errf.read()
+ out, err = capfd.readouterr()
assert 'ENTER' in err
assert 'LEAVE' in err
assert not "Running asm" in err
Modified: pypy/trunk/pypy/tool/pytest/appsupport.py
==============================================================================
--- pypy/trunk/pypy/tool/pytest/appsupport.py (original)
+++ pypy/trunk/pypy/tool/pytest/appsupport.py Sat May 22 13:29:12 2010
@@ -11,7 +11,8 @@
self.raw = pycode
self.w_file = space.getattr(pycode, space.wrap('co_filename'))
self.name = space.getattr(pycode, space.wrap('co_name'))
- self.firstlineno = space.unwrap(space.getattr(pycode, space.wrap('co_firstlineno')))
+ self.firstlineno = space.unwrap(
+ space.getattr(pycode, space.wrap('co_firstlineno'))) - 1
#try:
# self.path = space.unwrap(space.getattr(self.w_file, space.wrap('__path__')))
#except OperationError:
@@ -20,13 +21,14 @@
self.space = space
def fullsource(self):
+ filename = self.space.str_w(self.w_file)
+ source = py.code.Source(py.std.linecache.getlines(filename))
+ if source.lines:
+ return source
try:
- return self.space.str_w(self.w_file).__source__
- except AttributeError:
- try:
- return py.code.Source(self.path.read(mode="rU"))
- except py.error.Error:
- return None
+ return py.code.Source(self.path.read(mode="rU"))
+ except py.error.Error:
+ return None
fullsource = property(fullsource, None, None, "Full source of AppCode")
def getargs(self):
@@ -211,12 +213,19 @@
source = py.code.Source(expr)
frame = space.getexecutioncontext().gettopframe()
w_locals = frame.getdictscope()
+ pycode = frame.pycode
+ filename = "<%s:%s>" %(pycode.co_filename, frame.f_lineno)
+ lines = [x + "\n" for x in expr.split("\n")]
+ py.std.linecache.cache[filename] = (1, None, lines, filename)
w_locals = space.call_method(w_locals, 'copy')
for key, w_value in kwds_w.items():
space.setitem(w_locals, space.wrap(key), w_value)
+ #filename = __file__
+ #if filename.endswith("pyc"):
+ # filename = filename[:-1]
try:
space.exec_(str(source), frame.w_globals, w_locals,
- filename=__file__)
+ filename=filename)
except OperationError, e:
if e.match(space, w_ExpectedException):
return _exc_info(space, e)
Modified: pypy/trunk/pypy/tool/pytest/test/test_appsupport.py
==============================================================================
--- pypy/trunk/pypy/tool/pytest/test/test_appsupport.py (original)
+++ pypy/trunk/pypy/tool/pytest/test/test_appsupport.py Sat May 22 13:29:12 2010
@@ -70,6 +70,49 @@
assert result.ret == 0
result.stdout.fnmatch_lines(["*2 passed*"])
+def test_applevel_raises_simple_display(testdir):
+ setpypyconftest(testdir)
+ p = testdir.makepyfile("""
+ def app_test_raises():
+ raises(ValueError, x)
+ class AppTestRaises:
+ def test_func(self):
+ raises (ValueError, x)
+ #
+ """)
+ result = testdir.runpytest(p, "-s")
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*E*application-level*NameError*x*not defined",
+ "*test_func(self)*",
+ ">*raises*ValueError*",
+ "*E*application-level*NameError*x*not defined",
+ "*test_applevel_raises_simple_display*",
+ ])
+ result = testdir.runpytest(p) # this time we may run the pyc file
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*E*application-level*NameError*x*not defined",
+ ])
+
+def test_applevel_raises_display(testdir):
+ setpypyconftest(testdir)
+ p = testdir.makepyfile("""
+ def app_test_raises():
+ raises(ValueError, "x")
+ pass
+ """)
+ result = testdir.runpytest(p, "-s")
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*E*application-level*NameError*x*not defined",
+ ])
+ result = testdir.runpytest(p) # this time we may run the pyc file
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*E*application-level*NameError*x*not defined",
+ ])
+
def app_test_raises():
info = raises(TypeError, id)
assert info.type is TypeError
More information about the Pypy-commit
mailing list