Author: Floris Bruynooghe <[email protected]>
Branch: py3tests
Changeset: r94012:6fdcb46e0b2f
Date: 2018-03-19 18:21 +0100
http://bitbucket.org/pypy/pypy/changeset/6fdcb46e0b2f/

Log:    Make untranslated app tests work on a very basic level

        This can collect a module and run test functions inside it, without
        any fixtures or setup.

diff --git a/_pytest/assertion/rewrite.py b/_pytest/assertion/rewrite.py
--- a/_pytest/assertion/rewrite.py
+++ b/_pytest/assertion/rewrite.py
@@ -265,10 +265,10 @@
         if (not source.startswith(BOM_UTF8) and
             cookie_re.match(source[0:end1]) is None and
             cookie_re.match(source[end1 + 1:end2]) is None):
-            if hasattr(state, "_indecode"):
-                # encodings imported us again, so don't rewrite.
-                return None, None
-            state._indecode = True
+            # if hasattr(state, "_indecode"):
+            #     # encodings imported us again, so don't rewrite.
+            #     return None, None
+            # state._indecode = True
             try:
                 try:
                     source.decode("ascii")
@@ -293,10 +293,21 @@
     except SyntaxError:
         # It's possible that this error is from some bug in the
         # assertion rewriting, but I don't know of a fast way to tell.
-        state.trace("failed to compile: %r" % (fn,))
+        # state.trace("failed to compile: %r" % (fn,))
         return None, None
     return stat, co
 
+
+def create_module(co):
+    """Hack to create a module from a code object created by _rewrite_test()"""
+    mod = imp.new_module(co.co_filename.split('/')[-1].split('.')[0])
+    mod.__file__ = co.co_filename
+    # mod.__cached__ = pyc
+    mod.__loader__ = None
+    exec(co, mod.__dict__)
+    return mod
+
+
 def _make_rewritten_pyc(state, source_stat, pyc, co):
     """Try to dump rewritten code to *pyc*."""
     if sys.platform.startswith("win"):
diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -9,6 +9,7 @@
 PYTHON3 = os.getenv('PYTHON3') or py.path.local.sysfind(LOOK_FOR_PYTHON3)
 if PYTHON3 is not None:
     PYTHON3 = str(PYTHON3)
+APPLEVEL_FN = 'apptest_*.py'
 
 # pytest settings
 rsyncdirs = ['.', '../lib-python', '../lib_pypy', '../demo']
@@ -44,7 +45,7 @@
         py.test.skip('[py3k] %s' % message)
     py.test.py3k_skip = py3k_skip
     if config.getoption('runappdirect'):
-        config.addinivalue_line('python_files', 'apptest_*.py')
+        config.addinivalue_line('python_files', APPLEVEL_FN)
 
 def pytest_addoption(parser):
     group = parser.getgroup("pypy options")
@@ -94,7 +95,11 @@
 
 def pytest_pycollect_makemodule(path, parent):
     if not parent.config.getoption('runappdirect'):
-        return PyPyModule(path, parent)
+        if path.fnmatch(APPLEVEL_FN):
+            from pypy.tool.pytest.apptest2 import AppTestModule
+            return AppTestModule(path, parent)
+        else:
+            return PyPyModule(path, parent)
 
 def is_applevel(item):
     from pypy.tool.pytest.apptest import AppTestFunction
@@ -110,7 +115,8 @@
             else:
                 item.add_marker('interplevel')
 
-class PyPyModule(py.test.collect.Module):
+
+class PyPyModule(pytest.Module):
     """ we take care of collecting classes both at app level
         and at interp-level (because we need to stick a space
         at the class) ourselves.
@@ -194,6 +200,6 @@
 
 
 def pytest_ignore_collect(path, config):
-    if config.getoption('runappdirect') and not path.fnmatch('apptest_*.py'):
+    if config.getoption('runappdirect') and not path.fnmatch(APPLEVEL_FN):
         return True
     return path.check(link=1)
diff --git a/pypy/tool/pytest/apptest2.py b/pypy/tool/pytest/apptest2.py
new file mode 100644
--- /dev/null
+++ b/pypy/tool/pytest/apptest2.py
@@ -0,0 +1,72 @@
+import sys
+
+import pytest
+import pypy.interpreter.function
+from pypy.interpreter.error import OperationError
+from pypy.tool.pytest import objspace
+from pypy.tool.pytest import appsupport
+
+
+class AppTestModule(pytest.Module):
+
+    def collect(self):
+        space = objspace.gettestobjspace()
+        w_mod = space.appexec([] ,"""():
+        import sys
+        sys.path.insert(0, '%s')
+        import _pytest.assertion.rewrite, py.path
+
+        stat, co = _pytest.assertion.rewrite._rewrite_test(None, 
py.path.local('%s'))
+        mod = _pytest.assertion.rewrite.create_module(co)
+        return mod
+        """ % (self.config.rootdir, str(self.fspath)))
+        mod_dict = w_mod.getdict(space).unwrap(space)
+        items = []
+        for name, w_obj in mod_dict.items():
+            if not name.startswith('test_'):
+                continue
+            if not isinstance(w_obj, pypy.interpreter.function.Function):
+                continue
+            items.append(AppTestFunction(name, self, w_obj))
+        return items
+
+    def setup(self):
+        pass
+
+
+class AppError(Exception):
+
+    def __init__(self, excinfo):
+        self.excinfo = excinfo
+
+
+class AppTestFunction(pytest.Item):
+
+    def __init__(self, name, parent, w_obj):
+        super(AppTestFunction, self).__init__(name, parent)
+        self.w_obj = w_obj
+
+    def runtest(self):
+        target = self.w_obj
+        space = target.space
+        self.execute_appex(space, target)
+
+    def repr_failure(self, excinfo):
+        if excinfo.errisinstance(AppError):
+            excinfo = excinfo.value.excinfo
+        return super(AppTestFunction, self).repr_failure(excinfo)
+
+    def execute_appex(self, space, w_func):
+        space.getexecutioncontext().set_sys_exc_info(None)
+        try:
+            space.call_function(w_func)
+        except OperationError as e:
+            if self.config.option.raise_operr:
+                raise
+            tb = sys.exc_info()[2]
+            if e.match(space, space.w_KeyboardInterrupt):
+                raise KeyboardInterrupt, KeyboardInterrupt(), tb
+            appexcinfo = appsupport.AppExceptionInfo(space, e)
+            if appexcinfo.traceback:
+                raise AppError, AppError(appexcinfo), tb
+            raise
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to