[pypy-svn] r7988 - in pypy/branch/src-pytest/pypy: . tool tool/pytest tool/test

arigo at codespeak.net arigo at codespeak.net
Fri Dec 24 18:14:27 CET 2004


Author: arigo
Date: Fri Dec 24 18:14:26 2004
New Revision: 7988

Added:
   pypy/branch/src-pytest/pypy/tool/pytestsupport.py
      - copied, changed from r7980, pypy/branch/src-pytest/pypy/tool/pytest/support.py
   pypy/branch/src-pytest/pypy/tool/test/test_pytestsupport.py
      - copied, changed from r7980, pypy/branch/src-pytest/pypy/tool/pytest/support.py
Removed:
   pypy/branch/src-pytest/pypy/tool/pytest/
Modified:
   pypy/branch/src-pytest/pypy/conftest.py
Log:
D    tool/pytest
M    conftest.py

Moved some content of the above files into a new module:

A    tool/pytestsupport.py
A    tool/test/test_pytestsupport.py

This (finally) allows app-level assertions to be displayed with full exprinfo
explanations.  For other app-level exceptions, reinterpretation is entierely
disabled for now.


Modified: pypy/branch/src-pytest/pypy/conftest.py
==============================================================================
--- pypy/branch/src-pytest/pypy/conftest.py	(original)
+++ pypy/branch/src-pytest/pypy/conftest.py	Fri Dec 24 18:14:26 2004
@@ -1,7 +1,8 @@
 import py
 from pypy.interpreter.gateway import app2interp_temp 
 from pypy.interpreter.error import OperationError
-from pypy.objspace.std import StdObjSpace 
+from pypy.objspace.std import StdObjSpace
+from pypy.tool import pytestsupport
 
 #
 # PyPy's command line extra options (these are added 
@@ -30,8 +31,11 @@
         return _spacecache[name]
     except KeyError:
         module = __import__("pypy.objspace.%s" % name, None, None, ["Space"])
-        Space = module.Space
-        return _spacecache.setdefault(name, Space())
+        space = module.Space()
+        _spacecache[name] = space
+        space.setitem(space.w_builtins, space.wrap('AssertionError'), 
+                      pytestsupport.build_pytest_assertion(space))
+        return space
 
 # 
 # Interfacing/Integrating with py.test's collection process 
@@ -69,65 +73,13 @@
     return space
 
 
-class AppFrame(py.code.Frame):
-
-    def __init__(self, pyframe):
-        self.code = py.code.Code(pyframe.code)
-        self.lineno = pyframe.get_last_lineno() - 1
-        self.space = pyframe.space
-        self.w_globals = pyframe.w_globals
-        self.w_locals = pyframe.getdictscope()
-        self.f_locals = self.w_locals   # for py.test's recursion detection
-
-    def eval(self, code, **vars):
-        space = self.space
-        for key, w_value in vars.items():
-            space.setitem(self.w_locals, space.wrap(key), w_value)
-        return space.eval(code, self.w_globals, self.w_locals)
-
-    def exec_(self, code, **vars):
-        space = self.space
-        for key, w_value in vars.items():
-            space.setitem(self.w_locals, space.wrap(key), w_value)
-        space.exec_(code, self.w_globals, self.w_locals)
-
-    def repr(self, w_value):
-        return self.space.unwrap(self.space.repr(w_value))
-
-    def is_true(self, w_value):
-        return self.space.is_true(w_value)
-
-
-class AppExceptionInfo(py.code.ExceptionInfo):
-    """An ExceptionInfo object representing an app-level exception."""
-    exprinfo = None
-
-    def __init__(self, space, operr):
-        self.space = space
-        self.operr = operr
-
-    def __str__(self):
-        return '(app-level) ' + self.operr.errorstr(self.space)
-
-    def __iter__(self):
-        tb = self.operr.application_traceback
-        while tb is not None:
-            yield AppTracebackEntry(tb)
-            tb = tb.next
-
-class AppTracebackEntry(py.code.TracebackEntry):
-    def __init__(self, tb):
-        self.frame = AppFrame(tb.frame)
-        self.lineno = tb.lineno - 1
-
-
 class PyPyItem(py.test.Item):
     # All PyPy test items catch and display OperationErrors specially.
     def execute_in_space(self, space, target, *args):
         try:
             target(*args)
         except OperationError, e:
-            raise self.Failed(excinfo=AppExceptionInfo(space, e))
+            raise self.Failed(excinfo=pytestsupport.AppExceptionInfo(space, e))
 
 class IntTestFunction(PyPyItem):
     def execute(self, target, *args):

Copied: pypy/branch/src-pytest/pypy/tool/pytestsupport.py (from r7980, pypy/branch/src-pytest/pypy/tool/pytest/support.py)
==============================================================================
--- pypy/branch/src-pytest/pypy/tool/pytest/support.py	(original)
+++ pypy/branch/src-pytest/pypy/tool/pytestsupport.py	Fri Dec 24 18:14:26 2004
@@ -1,20 +1,19 @@
 import autopath
 import py
 from py.__impl__.magic import exprinfo
-from py.code import InspectableFrame
-from pypy.objspace.std import StdObjSpace
-from pypy.interpreter.gateway import app2interp_temp, interp2app_temp
-from pypy.interpreter.argument import Arguments
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import interp2app_temp
 
-class AppRunnerFrame(InspectableFrame):
+# ____________________________________________________________
+
+class AppFrame(py.code.Frame):
 
     def __init__(self, pyframe):
-        lineno = pyframe.get_last_lineno() - 1
-        super(AppRunnerFrame, self).__init__(pyframe.code, lineno)
+        self.code = py.code.Code(pyframe.code)
+        self.lineno = pyframe.get_last_lineno() - 1
         self.space = pyframe.space
         self.w_globals = pyframe.w_globals
         self.w_locals = pyframe.getdictscope()
+        self.f_locals = self.w_locals   # for py.test's recursion detection
 
     def eval(self, code, **vars):
         space = self.space
@@ -34,6 +33,41 @@
     def is_true(self, w_value):
         return self.space.is_true(w_value)
 
+
+class AppExceptionInfo(py.code.ExceptionInfo):
+    """An ExceptionInfo object representing an app-level exception."""
+
+    def __init__(self, space, operr):
+        self.space = space
+        self.operr = operr
+        self.exprinfo = None
+
+    def __str__(self):
+        return '(app-level) ' + self.operr.errorstr(self.space)
+
+    def reinterpret(self):
+        # XXX we need to solve a general problem: how to prevent
+        #     reinterpretation from generating a different exception?
+        #     This problem includes the fact that exprinfo will generate
+        #     its own long message that looks like
+        #        OperationError:   << [<W_TypeObject(NameError)>: W_StringObj...
+        #     which is much less nice than the one produced by str(self).
+        # XXX this reinterpret() is only here to prevent reinterpretation.
+        return self.exprinfo
+
+    def __iter__(self):
+        tb = self.operr.application_traceback
+        while tb is not None:
+            yield AppTracebackEntry(tb)
+            tb = tb.next
+
+class AppTracebackEntry(py.code.TracebackEntry):
+    def __init__(self, tb):
+        self.frame = AppFrame(tb.frame)
+        self.lineno = tb.lineno - 1
+
+# ____________________________________________________________
+
 def build_pytest_assertion(space):
     def my_init(space, w_self, __args__):
         "Our new AssertionError.__init__()."
@@ -47,15 +81,20 @@
         assert frame.code.co_name == 'app_normalize_exception'
         frame = framestack.top(1)
         
-        runner = AppRunnerFrame(frame)
-        # XXX what if the source is not available?
-        msg = exprinfo.interpret(str(runner.statement.deindent()), runner)
-        if msg is None:
-            msg = "(inconsistenty failed then succeeded)"
-        elif msg.startswith('AssertionError: '):
-            msg = msg[16:]
-        space.setattr(w_self, space.wrap('args'),
-                      space.newtuple([space.wrap(msg)]))
+        runner = AppFrame(frame)
+        try:
+            source = runner.statement
+            source = str(source).strip()
+        except py.path.NotFound:
+            source = None
+        if source:
+            msg = exprinfo.interpret(source, runner, should_fail=True)
+            space.setattr(w_self, space.wrap('args'),
+                          space.newtuple([space.wrap(msg)]))
+            w_msg = space.wrap(msg)
+        else:
+            w_msg = space.w_None
+        space.setattr(w_self, space.wrap('msg'), w_msg)
 
     # build a new AssertionError class to replace the original one.
     w_BuiltinAssertionError = space.getitem(space.w_builtins,
@@ -68,38 +107,3 @@
                                space.wrap('AssertionError'),
                                space.newtuple([w_BuiltinAssertionError]),
                                w_dict)
-
-def setup_module(mod):
-    mod.space = StdObjSpace()
-
-def somefunc(x):
-    print x
-
-def test_AppRunnerFrame():
-    from pypy.interpreter.pycode import PyCode
-    from pypy.interpreter.pyframe import PyFrame
-    import sys
-    co = PyCode()._from_code(somefunc.func_code)
-    pyframe = PyFrame(space, co, space.newdict([]), None)
-    runner = AppRunnerFrame(pyframe)
-    exprinfo.run("f = lambda x: x+1", runner)
-    msg = exprinfo.interpret("assert isinstance(f(2), float)", runner)
-    assert msg.startswith("AssertionError: assert isinstance(3, float)\n"
-                          " +  where 3 = ")
-
-
-def test_myexception():
-    def app_test_func():
-        x = 6*7
-        assert x == 43
-    t = app2interp_temp(app_test_func)
-    f = t.get_function(space)
-    space.setitem(space.w_builtins, space.wrap('AssertionError'), 
-                  build_pytest_assertion(space))
-    try:
-        f.call_args(Arguments([]))
-    except OperationError, e:
-        assert e.match(space, space.w_AssertionError)
-        assert space.unwrap(space.str(e.w_value)) == 'assert 42 == 43'
-    else:
-        assert False, "got no exception!"

Copied: pypy/branch/src-pytest/pypy/tool/test/test_pytestsupport.py (from r7980, pypy/branch/src-pytest/pypy/tool/pytest/support.py)
==============================================================================
--- pypy/branch/src-pytest/pypy/tool/pytest/support.py	(original)
+++ pypy/branch/src-pytest/pypy/tool/test/test_pytestsupport.py	Fri Dec 24 18:14:26 2004
@@ -1,94 +1,28 @@
 import autopath
-import py
 from py.__impl__.magic import exprinfo
-from py.code import InspectableFrame
-from pypy.objspace.std import StdObjSpace
-from pypy.interpreter.gateway import app2interp_temp, interp2app_temp
-from pypy.interpreter.argument import Arguments
 from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import app2interp_temp
+from pypy.interpreter.argument import Arguments
+from pypy.interpreter.pycode import PyCode
+from pypy.interpreter.pyframe import PyFrame
+from pypy.tool.pytestsupport import AppFrame, build_pytest_assertion
 
-class AppRunnerFrame(InspectableFrame):
-
-    def __init__(self, pyframe):
-        lineno = pyframe.get_last_lineno() - 1
-        super(AppRunnerFrame, self).__init__(pyframe.code, lineno)
-        self.space = pyframe.space
-        self.w_globals = pyframe.w_globals
-        self.w_locals = pyframe.getdictscope()
-
-    def eval(self, code, **vars):
-        space = self.space
-        for key, w_value in vars.items():
-            space.setitem(self.w_locals, space.wrap(key), w_value)
-        return space.eval(code, self.w_globals, self.w_locals)
-
-    def exec_(self, code, **vars):
-        space = self.space
-        for key, w_value in vars.items():
-            space.setitem(self.w_locals, space.wrap(key), w_value)
-        space.exec_(code, self.w_globals, self.w_locals)
-
-    def repr(self, w_value):
-        return self.space.unwrap(self.space.repr(w_value))
-
-    def is_true(self, w_value):
-        return self.space.is_true(w_value)
-
-def build_pytest_assertion(space):
-    def my_init(space, w_self, __args__):
-        "Our new AssertionError.__init__()."
-        w_parent_init = space.getattr(w_BuiltinAssertionError,
-                                      space.wrap('__init__'))
-        space.call_args(w_parent_init, __args__.prepend(w_self))
-        framestack = space.getexecutioncontext().framestack
-        frame = framestack.top(0)
-        # Argh! we see app-level helpers in the frame stack!
-        #       that's very probably very bad...
-        assert frame.code.co_name == 'app_normalize_exception'
-        frame = framestack.top(1)
-        
-        runner = AppRunnerFrame(frame)
-        # XXX what if the source is not available?
-        msg = exprinfo.interpret(str(runner.statement.deindent()), runner)
-        if msg is None:
-            msg = "(inconsistenty failed then succeeded)"
-        elif msg.startswith('AssertionError: '):
-            msg = msg[16:]
-        space.setattr(w_self, space.wrap('args'),
-                      space.newtuple([space.wrap(msg)]))
-
-    # build a new AssertionError class to replace the original one.
-    w_BuiltinAssertionError = space.getitem(space.w_builtins,
-                                            space.wrap('AssertionError'))
-    w_metaclass = space.type(w_BuiltinAssertionError)
-    w_init = space.wrap(interp2app_temp(my_init))
-    w_dict = space.newdict([])
-    space.setitem(w_dict, space.wrap('__init__'), w_init)
-    return space.call_function(w_metaclass,
-                               space.wrap('AssertionError'),
-                               space.newtuple([w_BuiltinAssertionError]),
-                               w_dict)
-
-def setup_module(mod):
-    mod.space = StdObjSpace()
 
 def somefunc(x):
     print x
 
-def test_AppRunnerFrame():
-    from pypy.interpreter.pycode import PyCode
-    from pypy.interpreter.pyframe import PyFrame
+def test_AppFrame(space):
     import sys
     co = PyCode()._from_code(somefunc.func_code)
     pyframe = PyFrame(space, co, space.newdict([]), None)
-    runner = AppRunnerFrame(pyframe)
+    runner = AppFrame(pyframe)
     exprinfo.run("f = lambda x: x+1", runner)
     msg = exprinfo.interpret("assert isinstance(f(2), float)", runner)
-    assert msg.startswith("AssertionError: assert isinstance(3, float)\n"
+    assert msg.startswith("assert isinstance(3, float)\n"
                           " +  where 3 = ")
 
 
-def test_myexception():
+def test_myexception(space):
     def app_test_func():
         x = 6*7
         assert x == 43



More information about the Pypy-commit mailing list