[pypy-commit] pypy py3.6: Merged in py3tests (pull request #660)

rlamy pypy.commits at gmail.com
Thu Aug 1 12:38:15 EDT 2019


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.6
Changeset: r97046:62f51af92fd2
Date: 2019-08-01 16:37 +0000
http://bitbucket.org/pypy/pypy/changeset/62f51af92fd2/

Log:	Merged in py3tests (pull request #660)

	New mechanism for app-level testing (py3 edition)

diff too long, truncating to 2000 out of 8781 lines

diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -223,6 +223,10 @@
         BoolOption("newshortcut",
                    "cache and shortcut calling __new__ from builtin types",
                    default=False),
+        BoolOption("reinterpretasserts",
+                   "Perform reinterpretation when an assert fails "
+                   "(only relevant for tests)",
+                   default=False),
 
      ]),
 ])
diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -9,6 +9,8 @@
 PYTHON3 = os.getenv('PYTHON3') or py.path.local.sysfind(LOOK_FOR_PYTHON3)
 if PYTHON3 is not None:
     PYTHON3 = str(PYTHON3)
+HOST_IS_PY3 = sys.version_info[0] > 2
+APPLEVEL_FN = 'apptest_*.py'
 
 # pytest settings
 rsyncdirs = ['.', '../lib-python', '../lib_pypy', '../demo']
@@ -45,35 +47,48 @@
 def pytest_report_header():
     return "pytest-%s from %s" % (pytest.__version__, pytest.__file__)
 
-def pytest_addhooks(pluginmanager):
-    if sys.version_info < (3,):
-        from rpython.conftest import LeakFinder
-        pluginmanager.register(LeakFinder())
+ at pytest.hookimpl(tryfirst=True)
+def pytest_cmdline_preparse(config, args):
+    if not (set(args) & {'-D', '--direct-apptest'}):
+        args.append('--assert=reinterp')
 
 def pytest_configure(config):
+    if HOST_IS_PY3 and not config.getoption('direct_apptest'):
+        raise ValueError(
+            "On top of a Python 3 interpreter, the -D flag is mandatory")
     global option
     option = config.option
+    mode_A = config.getoption('runappdirect')
+    mode_D = config.getoption('direct_apptest')
     def py3k_skip(message):
         py.test.skip('[py3k] %s' % message)
     py.test.py3k_skip = py3k_skip
+    if mode_D or not mode_A:
+        config.addinivalue_line('python_files', APPLEVEL_FN)
+    if not mode_A and not mode_D:  # 'own' tests
+        from rpython.conftest import LeakFinder
+        config.pluginmanager.register(LeakFinder())
 
 def pytest_addoption(parser):
-    from rpython.conftest import pytest_addoption
-    pytest_addoption(parser)
-
     group = parser.getgroup("pypy options")
     group.addoption('-A', '--runappdirect', action="store_true",
            default=False, dest="runappdirect",
-           help="run applevel tests directly on the python interpreter " +
+           help="run legacy applevel tests directly on the python interpreter " +
                 "specified by --python")
     group.addoption('--python', type="string", default=PYTHON3,
            help="python interpreter to run appdirect tests with")
+    group.addoption('-D', '--direct-apptest', action="store_true",
+           default=False, dest="direct_apptest",
+           help="run applevel_XXX.py tests directly on host interpreter")
     group.addoption('--direct', action="store_true",
            default=False, dest="rundirect",
            help="run pexpect tests directly")
     group.addoption('--raise-operr', action="store_true",
             default=False, dest="raise_operr",
             help="Show the interp-level OperationError in app-level tests")
+    group.addoption('--applevel-rewrite', action="store_true",
+            default=False, dest="applevel_rewrite",
+            help="Use assert rewriting in app-level test files (slow)")
 
 @pytest.fixture(scope='function')
 def space(request):
@@ -107,14 +122,21 @@
     ensure_pytest_builtin_helpers()
 
 def pytest_pycollect_makemodule(path, parent):
-    return PyPyModule(path, parent)
+    if path.fnmatch(APPLEVEL_FN):
+        if parent.config.getoption('direct_apptest'):
+            return
+        from pypy.tool.pytest.apptest2 import AppTestModule
+        rewrite = parent.config.getoption('applevel_rewrite')
+        return AppTestModule(path, parent, rewrite_asserts=rewrite)
+    else:
+        return PyPyModule(path, parent)
 
 def is_applevel(item):
     from pypy.tool.pytest.apptest import AppTestFunction
     return isinstance(item, AppTestFunction)
 
 def pytest_collection_modifyitems(config, items):
-    if config.option.runappdirect:
+    if config.getoption('runappdirect') or config.getoption('direct_apptest'):
         return
     for item in items:
         if isinstance(item, py.test.Function):
@@ -123,17 +145,17 @@
             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.
     """
     def accept_regular_test(self):
         if self.config.option.runappdirect:
-            # only collect regular tests if we are in an 'app_test' directory,
-            # or in test_lib_pypy
+            # only collect regular tests if we are in test_lib_pypy
             for name in self.listnames():
-                if "app_test" in name or "test_lib_pypy" in name:
+                if "test_lib_pypy" in name:
                     return True
             return False
         return True
@@ -205,6 +227,8 @@
                 appclass.obj.space = LazyObjSpaceGetter()
             appclass.obj.runappdirect = option.runappdirect
 
-
-def pytest_ignore_collect(path):
+def pytest_ignore_collect(path, config):
+    if (config.getoption('direct_apptest') and not path.isdir()
+            and not path.fnmatch(APPLEVEL_FN)):
+        return True
     return path.check(link=1)
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -342,10 +342,10 @@
         translate.log_config(config.objspace, "PyPy config object")
 
         # obscure hack to stuff the translation options into the translated PyPy
-        import pypy.module.sys
+        from pypy.module.sys.moduledef import Module as SysModule
         options = make_dict(config)
-        wrapstr = 'space.wrap(%r)' % (options) # import time
-        pypy.module.sys.Module.interpleveldefs['pypy_translation_info'] = wrapstr
+        wrapstr = 'space.wrap(%r)' % (options)  # import time
+        SysModule.interpleveldefs['pypy_translation_info'] = wrapstr
         if config.objspace.usemodules._cffi_backend:
             self.hack_for_cffi_modules(driver)
 
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -493,13 +493,14 @@
             return self.__class__.__name__
 
     @not_rpython
-    def setbuiltinmodule(self, importname):
+    def setbuiltinmodule(self, pkgname):
         """load a lazy pypy/module and put it into sys.modules"""
-        if '.' in importname:
-            fullname = importname
-            importname = fullname.rsplit('.', 1)[1]
+        if '.' in pkgname:
+            fullname = "%s.moduledef" % (pkgname,)
+            importname = pkgname.rsplit('.', 1)[1]
         else:
-            fullname = "pypy.module.%s" % importname
+            fullname = "pypy.module.%s.moduledef" % pkgname
+            importname = pkgname
 
         Module = __import__(fullname,
                             None, None, ["Module"]).Module
@@ -578,22 +579,22 @@
     def make_builtins(self):
         "only for initializing the space."
 
-        from pypy.module.exceptions import Module
+        from pypy.module.exceptions.moduledef import Module
         w_name = self.newtext('__exceptions__')
         self.exceptions_module = Module(self, w_name)
         self.exceptions_module.install()
 
-        from pypy.module.imp import Module
+        from pypy.module.imp.moduledef import Module
         w_name = self.newtext('_imp')
         mod = Module(self, w_name)
         mod.install()
 
-        from pypy.module.sys import Module
+        from pypy.module.sys.moduledef import Module
         w_name = self.newtext('sys')
         self.sys = Module(self, w_name)
         self.sys.install()
 
-        from pypy.module.__builtin__ import Module
+        from pypy.module.__builtin__.moduledef import Module
         w_name = self.newtext('builtins')
         self.builtin = Module(self, w_name)
         w_builtin = self.builtin
diff --git a/pypy/interpreter/main.py b/pypy/interpreter/main.py
--- a/pypy/interpreter/main.py
+++ b/pypy/interpreter/main.py
@@ -34,7 +34,7 @@
 
     try:
         if space is None:
-            from pypy.objspace.std import StdObjSpace
+            from pypy.objspace.std.objspace import StdObjSpace
             space = StdObjSpace()
 
         pycode = compilecode(space, source, filename or '<string>', cmd)
@@ -82,7 +82,7 @@
     implementation.
     """
     if space is None:
-        from pypy.objspace.std import StdObjSpace
+        from pypy.objspace.std.objspace import StdObjSpace
         space = StdObjSpace()
     argv = [module_name]
     if args is not None:
diff --git a/pypy/interpreter/mixedmodule.py b/pypy/interpreter/mixedmodule.py
--- a/pypy/interpreter/mixedmodule.py
+++ b/pypy/interpreter/mixedmodule.py
@@ -30,17 +30,21 @@
 
     @not_rpython
     def install(self):
-        """install this module, and it's submodules into
+        """Install this module, and its submodules into
         space.builtin_modules"""
         Module.install(self)
         if hasattr(self, "submodules"):
             space = self.space
-            name = space.text_w(self.w_name)
+            pkgname = space.text_w(self.w_name)
             for sub_name, module_cls in self.submodules.iteritems():
                 if module_cls.submodule_name is None:
                     module_cls.submodule_name = sub_name
-                module_name = space.newtext("%s.%s" % (name, sub_name))
-                m = module_cls(space, module_name)
+                else:
+                    assert module_cls.submodule_name == sub_name
+                name = "%s.%s" % (pkgname, sub_name)
+                module_cls.applevel_name = name
+                w_name = space.newtext(name)
+                m = module_cls(space, w_name)
                 m.install()
                 self.submodules_w.append(m)
 
@@ -75,8 +79,7 @@
         if cls.applevel_name is not None:
             return cls.applevel_name
         else:
-            pkgroot = cls.__module__
-            return pkgroot.split('.')[-1]
+            return cls.__module__.split('.')[-2]
 
     def get(self, name):
         space = self.space
@@ -173,10 +176,8 @@
             # build a constant dictionary out of
             # applevel/interplevel definitions
             cls.loaders = loaders = {}
-            pkgroot = cls.__module__
+            pkgroot = cls.__module__.rsplit('.', 1)[0]
             appname = cls.get_applevel_name()
-            if cls.submodule_name is not None:
-                appname += '.%s' % (cls.submodule_name,)
             for name, spec in cls.interpleveldefs.items():
                 loaders[name] = getinterpevalloader(pkgroot, spec)
             for name, spec in cls.appleveldefs.items():
@@ -187,7 +188,7 @@
 
     def extra_interpdef(self, name, spec):
         cls = self.__class__
-        pkgroot = cls.__module__
+        pkgroot = cls.__module__.rsplit('.', 1)[0]
         loader = getinterpevalloader(pkgroot, spec)
         space = self.space
         w_obj = loader(space)
diff --git a/pypy/interpreter/test/apptest_coroutine.py b/pypy/interpreter/test/apptest_coroutine.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/test/apptest_coroutine.py
@@ -0,0 +1,704 @@
+import pytest
+from pytest import raises
+
+
+def test_cannot_iterate():
+    async def f(x):
+        pass
+    pytest.raises(TypeError, "for i in f(5): pass")
+    pytest.raises(TypeError, iter, f(5))
+    pytest.raises(TypeError, next, f(5))
+
+
+def test_async_for():
+    class X:
+        def __aiter__(self):
+            return MyAIter()
+    class MyAIter:
+        async def __anext__(self):
+            return 42
+    async def f(x):
+        sum = 0
+        async for a in x:
+            sum += a
+            if sum > 100:
+                break
+        return sum
+    cr = f(X())
+    try:
+        cr.send(None)
+    except StopIteration as e:
+        assert e.value == 42 * 3
+    else:
+        assert False, "should have raised"
+
+
+def test_StopAsyncIteration():
+    class X:
+        def __aiter__(self):
+            return MyAIter()
+    class MyAIter:
+        count = 0
+        async def __anext__(self):
+            if self.count == 3:
+                raise StopAsyncIteration
+            self.count += 1
+            return 42
+    async def f(x):
+        sum = 0
+        async for a in x:
+            sum += a
+        return sum
+    cr = f(X())
+    try:
+        cr.send(None)
+    except StopIteration as e:
+        assert e.value == 42 * 3
+    else:
+        assert False, "should have raised"
+
+
+def test_async_for_old_style():
+    class X:
+        def __aiter__(self):
+            return MyAIter()
+    class MyAIter:
+        def __await__(self):
+            return iter([20, 30])
+    async def f(x):
+        sum = 0
+        async for a in x:
+            sum += a
+            if sum > 100:
+                break
+        return sum
+    cr = f(X())
+    assert next(cr.__await__()) == 20
+
+
+def test_for_error_cause():
+    class F:
+        def __aiter__(self):
+            return self
+        def __anext__(self):
+            return self
+        def __await__(self):
+            1 / 0
+
+    async def main():
+        async for _ in F():
+            pass
+
+    c = pytest.raises(TypeError, main().send, None)
+    assert 'an invalid object from __anext__' in c.value.args[0], c.value
+    assert isinstance(c.value.__cause__, ZeroDivisionError)
+
+def test_set_coroutine_wrapper():
+    import sys
+    async def f():
+        pass
+    seen = []
+    def my_wrapper(cr):
+        seen.append(cr)
+        return 42
+    assert sys.get_coroutine_wrapper() is None
+    sys.set_coroutine_wrapper(my_wrapper)
+    assert sys.get_coroutine_wrapper() is my_wrapper
+    cr = f()
+    assert cr == 42
+    sys.set_coroutine_wrapper(None)
+    assert sys.get_coroutine_wrapper() is None
+
+
+def test_async_with():
+    seen = []
+    class X:
+        async def __aenter__(self):
+            seen.append('aenter')
+        async def __aexit__(self, *args):
+            seen.append('aexit')
+    async def f(x):
+        async with x:
+            return 42
+    c = f(X())
+    try:
+        c.send(None)
+    except StopIteration as e:
+        assert e.value == 42
+    else:
+        assert False, "should have raised"
+    assert seen == ['aenter', 'aexit']
+
+def test_async_with_exit_True():
+    seen = []
+    class X:
+        async def __aenter__(self):
+            seen.append('aenter')
+        async def __aexit__(self, *args):
+            seen.append('aexit')
+            return True
+    async def f(x):
+        async with x:
+            return 42
+    c = f(X())
+    try:
+        c.send(None)
+    except StopIteration as e:
+        assert e.value == 42
+    else:
+        assert False, "should have raised"
+    assert seen == ['aenter', 'aexit']
+
+def test_await():
+    class X:
+        def __await__(self):
+            i1 = yield 40
+            assert i1 == 82
+            i2 = yield 41
+            assert i2 == 93
+    async def f():
+        await X()
+        await X()
+    c = f()
+    assert c.send(None) == 40
+    assert c.send(82) == 41
+    assert c.send(93) == 40
+    assert c.send(82) == 41
+    pytest.raises(StopIteration, c.send, 93)
+
+
+def test_await_error():
+    async def f():
+        await [42]
+    c = f()
+    try:
+        c.send(None)
+    except TypeError as e:
+        assert str(e) == "object list can't be used in 'await' expression"
+    else:
+        assert False, "should have raised"
+
+
+def test_async_with_exception_context():
+    class CM:
+        async def __aenter__(self):
+            pass
+        async def __aexit__(self, *e):
+            1/0
+    async def f():
+        async with CM():
+            raise ValueError
+    c = f()
+    try:
+        c.send(None)
+    except ZeroDivisionError as e:
+        assert e.__context__ is not None
+        assert isinstance(e.__context__, ValueError)
+    else:
+        assert False, "should have raised"
+
+
+def test_runtime_warning():
+    import gc, warnings  # XXX: importing warnings is expensive untranslated
+    async def foobaz():
+        pass
+    with warnings.catch_warnings(record=True) as l:
+        foobaz()
+        gc.collect()
+        gc.collect()
+        gc.collect()
+
+    assert len(l) == 1, repr(l)
+    w = l[0].message
+    assert isinstance(w, RuntimeWarning)
+    assert str(w).startswith("coroutine ")
+    assert str(w).endswith("foobaz' was never awaited")
+
+
+def test_async_for_with_tuple_subclass():
+    class Done(Exception): pass
+
+    class AIter(tuple):
+        i = 0
+        def __aiter__(self):
+            return self
+        async def __anext__(self):
+            if self.i >= len(self):
+                raise StopAsyncIteration
+            self.i += 1
+            return self[self.i - 1]
+
+    result = []
+    async def foo():
+        async for i in AIter([42]):
+            result.append(i)
+        raise Done
+
+    try:
+        foo().send(None)
+    except Done:
+        pass
+    assert result == [42]
+
+def test_async_yield():
+    class Done(Exception): pass
+
+    async def mygen():
+        yield 5
+
+    result = []
+    async def foo():
+        async for i in mygen():
+            result.append(i)
+        raise Done
+
+    try:
+        foo().send(None)
+    except Done:
+        pass
+    assert result == [5]
+
+def test_async_yield_already_finished():
+    class Done(Exception): pass
+
+    async def mygen():
+        yield 5
+
+    result = []
+    async def foo():
+        g = mygen()
+        async for i in g:
+            result.append(i)
+        async for i in g:
+            assert False   # should not be reached
+        raise Done
+
+    try:
+        foo().send(None)
+    except Done:
+        pass
+    assert result == [5]
+
+def test_async_yield_with_await():
+    class Done(Exception): pass
+
+    class X:
+        def __await__(self):
+            i1 = yield 40
+            assert i1 == 82
+            i2 = yield 41
+            assert i2 == 93
+
+    async def mygen():
+        yield 5
+        await X()
+        yield 6
+
+    result = []
+    async def foo():
+        async for i in mygen():
+            result.append(i)
+        raise Done
+
+    co = foo()
+    x = co.send(None)
+    assert x == 40
+    assert result == [5]
+    x = co.send(82)
+    assert x == 41
+    assert result == [5]
+    raises(Done, co.send, 93)
+    assert result == [5, 6]
+
+def test_async_yield_with_explicit_send():
+    class X:
+        def __await__(self):
+            i1 = yield 40
+            assert i1 == 82
+            i2 = yield 41
+            assert i2 == 93
+
+    async def mygen():
+        x = yield 5
+        assert x == 2189
+        await X()
+        y = yield 6
+        assert y == 319
+
+    result = []
+    async def foo():
+        gen = mygen()
+        result.append(await gen.asend(None))
+        result.append(await gen.asend(2189))
+        try:
+            await gen.asend(319)
+        except StopAsyncIteration:
+            return 42
+        else:
+            raise AssertionError
+
+    co = foo()
+    x = co.send(None)
+    assert x == 40
+    assert result == [5]
+    x = co.send(82)
+    assert x == 41
+    assert result == [5]
+    e = raises(StopIteration, co.send, 93)
+    assert e.value.args == (42,)
+    assert result == [5, 6]
+
+def test_async_yield_explicit_asend_and_next():
+    async def mygen(y):
+        assert y == 4983
+        x = yield 5
+        assert x == 2189
+        yield "ok"
+
+    g = mygen(4983)
+    raises(TypeError, g.asend(42).__next__)
+    e = raises(StopIteration, g.asend(None).__next__)
+    assert e.value.args == (5,)
+    e = raises(StopIteration, g.asend(2189).__next__)
+    assert e.value.args == ("ok",)
+
+def test_async_yield_explicit_asend_and_send():
+    async def mygen(y):
+        assert y == 4983
+        x = yield 5
+        assert x == 2189
+        yield "ok"
+
+    g = mygen(4983)
+    e = raises(TypeError, g.asend(None).send, 42)
+    assert str(e.value) == ("can't send non-None value to a just-started "
+                            "async generator")
+    e = raises(StopIteration, g.asend(None).send, None)
+    assert e.value.args == (5,)
+    e = raises(StopIteration, g.asend("IGNORED").send, 2189)  # xxx
+    assert e.value.args == ("ok",)
+
+def test_async_yield_explicit_asend_used_several_times():
+    class X:
+        def __await__(self):
+            r = yield -2
+            assert r == "cont1"
+            r = yield -3
+            assert r == "cont2"
+            return -4
+    async def mygen(y):
+        x = await X()
+        assert x == -4
+        r = yield -5
+        assert r == "foo"
+        r = yield -6
+        assert r == "bar"
+
+    g = mygen(4983)
+    gs = g.asend(None)
+    r = gs.send(None)
+    assert r == -2
+    r = gs.send("cont1")
+    assert r == -3
+    e = raises(StopIteration, gs.send, "cont2")
+    assert e.value.args == (-5,)
+    e = raises(StopIteration, gs.send, None)
+    assert e.value.args == ()
+    e = raises(StopIteration, gs.send, None)
+    assert e.value.args == ()
+    #
+    gs = g.asend("foo")
+    e = raises(StopIteration, gs.send, None)
+    assert e.value.args == (-6,)
+    e = raises(StopIteration, gs.send, "bar")
+    assert e.value.args == ()
+
+def test_async_yield_asend_notnone_throw():
+    async def f():
+        yield 123
+
+    raises(ValueError, f().asend(42).throw, ValueError)
+
+def test_async_yield_asend_none_throw():
+    async def f():
+        yield 123
+
+    raises(ValueError, f().asend(None).throw, ValueError)
+
+def test_async_yield_athrow_send_none():
+    async def ag():
+        yield 42
+
+    raises(ValueError, ag().athrow(ValueError).send, None)
+
+def test_async_yield_athrow_send_notnone():
+    async def ag():
+        yield 42
+
+    ex = raises(RuntimeError, ag().athrow(ValueError).send, 42)
+    expected = ("can't send non-None value to a just-started coroutine", )
+    assert ex.value.args == expected
+
+def test_async_yield_athrow_send_after_exception():
+    async def ag():
+        yield 42
+
+    athrow_coro = ag().athrow(ValueError)
+    raises(ValueError, athrow_coro.send, None)
+    raises(StopIteration, athrow_coro.send, None)
+
+def test_async_yield_athrow_throw():
+    async def ag():
+        yield 42
+
+    raises(RuntimeError, ag().athrow(ValueError).throw, LookupError)
+    # CPython's message makes little sense; PyPy's message is different
+
+def test_async_yield_athrow_while_running():
+    values = []
+    async def ag():
+        try:
+            received = yield 1
+        except ValueError:
+            values.append(42)
+            return
+        yield 2
+
+
+    async def run():
+        running = ag()
+        x = await running.asend(None)
+        assert x == 1
+        try:
+            await running.athrow(ValueError)
+        except StopAsyncIteration:
+            pass
+
+
+    try:
+        run().send(None)
+    except StopIteration:
+        assert values == [42]
+
+def test_async_aclose():
+    raises_generator_exit = False
+    async def ag():
+        nonlocal raises_generator_exit
+        try:
+            yield
+        except GeneratorExit:
+            raises_generator_exit = True
+            raise
+
+    async def run():
+        a = ag()
+        async for i in a:
+            break
+        await a.aclose()
+    try:
+        run().send(None)
+    except StopIteration:
+        pass
+    assert raises_generator_exit
+
+def test_async_aclose_ignore_generator_exit():
+    async def ag():
+        try:
+            yield
+        except GeneratorExit:
+            yield
+
+    async def run():
+        a = ag()
+        async for i in a:
+            break
+        await a.aclose()
+    raises(RuntimeError, run().send, None)
+
+def test_async_aclose_await_in_finally():
+    import types
+
+    @types.coroutine
+    def coro():
+        yield 'coro'
+
+    state = 0
+    async def ag():
+        nonlocal state
+        try:
+            yield
+        finally:
+            state = 1
+            await coro()
+            state = 2
+
+    async def run():
+        a = ag()
+        async for i in a:
+            break
+        await a.aclose()
+    a = run()
+    assert state == 0
+    assert a.send(None) == 'coro'
+    assert state == 1
+    try:
+        a.send(None)
+    except StopIteration:
+        pass
+    assert state == 2
+
+def test_async_aclose_await_in_finally_with_exception():
+    import types
+
+    @types.coroutine
+    def coro():
+        yield 'coro'
+
+    state = 0
+    async def ag():
+        nonlocal state
+        try:
+            yield
+        finally:
+            state = 1
+            try:
+                await coro()
+            except Exception as exc:
+                state = exc
+
+    async def run():
+        a = ag()
+        async for i in a:
+            break
+        await a.aclose()
+    a = run()
+    assert state == 0
+    assert a.send(None) == 'coro'
+    assert state == 1
+    exc = RuntimeError()
+    try:
+        a.throw(exc)
+    except StopIteration:
+        pass
+    assert state == exc
+
+def test_async_aclose_in_finalize_hook_await_in_finally():
+    import gc
+    import sys
+    import types
+
+    @types.coroutine
+    def coro():
+        yield 'coro'
+
+    state = 0
+    async def ag():
+        nonlocal state
+        try:
+            yield
+        finally:
+            state = 1
+            await coro()
+            state = 2
+
+    async def run():
+        a = ag()
+        async for i in a:
+            break
+        del a
+        gc.collect()
+        gc.collect()
+        gc.collect()
+    a = run()
+
+    a2 = None
+    assert sys.get_asyncgen_hooks() == (None, None)
+    def _finalize(g):
+        nonlocal a2
+        a2 = g.aclose()
+    sys.set_asyncgen_hooks(finalizer=_finalize)
+    assert state == 0
+    try:
+        a.send(None)
+    except StopIteration:
+        pass
+    assert a2.send(None) == 'coro'
+    assert state == 1
+    try:
+        a2.send(None)
+    except StopIteration:
+        pass
+    assert state == 2
+    sys.set_asyncgen_hooks(None, None)
+
+def test_async_anext_close():
+    async def ag():
+        yield 42
+
+    an = ag().__anext__()
+    an.close()
+    try:
+        next(an)
+    except StopIteration as e:
+        assert e.value is None
+    else:
+        assert False, "didn't raise"
+
+def run_async(coro):
+    buffer = []
+    result = None
+    while True:
+        try:
+            buffer.append(coro.send(None))
+        except StopIteration as ex:
+            result = ex.args[0] if ex.args else None
+            break
+    return buffer, result
+
+def test_async_generator():
+    async def f(i):
+        return i
+
+    async def run_list():
+        return [await c for c in [f(1), f(41)]]
+
+    assert run_async(run_list()) == ([], [1, 41])
+
+def test_async_genexpr():
+    async def f(it):
+        for i in it:
+            yield i
+
+    async def run_gen():
+        gen = (i + 1 async for i in f([10, 20]))
+        return [g + 100 async for g in gen]
+
+    assert run_async(run_gen()) == ([], [111, 121])
+
+def test_anext_tuple():
+    async def foo():
+        try:
+            yield (1,)
+        except ZeroDivisionError:
+            yield (2,)
+
+    async def run():
+        it = foo().__aiter__()
+        return await it.__anext__()
+
+    assert run_async(run()) == ([], (1,))
+
+def test_asyncgen_yield_stopiteration():
+    async def foo():
+        yield 1
+        yield StopIteration(2)
+
+    async def run():
+        it = foo().__aiter__()
+        val1 = await it.__anext__()
+        assert val1 == 1
+        val2 = await it.__anext__()
+        assert isinstance(val2, StopIteration)
+        assert val2.value == 2
+
+    run_async(run())
diff --git a/pypy/interpreter/test/apptest_pyframe.py b/pypy/interpreter/test/apptest_pyframe.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/test/apptest_pyframe.py
@@ -0,0 +1,787 @@
+import pytest
+
+ at pytest.fixture
+def tempfile(tmpdir):
+    return str(tmpdir / 'tempfile1')
+
+def test_f_locals():
+    import sys
+    f = sys._getframe()
+    assert f.f_locals is locals()
+
+def test_f_globals():
+    import sys
+    f = sys._getframe()
+    assert f.f_globals is globals()
+    pytest.raises(AttributeError, "f.f_globals = globals()")
+
+def test_f_builtins():
+    import sys, builtins
+    f = sys._getframe()
+    assert f.f_builtins is builtins.__dict__
+
+def test_f_code():
+    def g():
+        import sys
+        f = sys._getframe()
+        return f.f_code
+    assert g() is g.__code__
+
+def test_f_trace_del():
+    import sys
+    f = sys._getframe()
+    del f.f_trace
+    assert f.f_trace is None
+
+def test_f_lineno():
+    def g():
+        import sys
+        f = sys._getframe()
+        x = f.f_lineno
+        y = f.f_lineno
+        z = f.f_lineno
+        return [x, y, z]
+    origin = g.__code__.co_firstlineno
+    assert g() == [origin+3, origin+4, origin+5]
+
+def test_f_lineno_huge_jump():
+    code = """def g():
+        import sys
+        f = sys._getframe()
+        x = f.f_lineno
+        %s
+        y = f.f_lineno
+        %s
+        z = f.f_lineno
+        return [x, y, z]""" % ("\n" * 127, "\n" * 1000)
+    d = {}
+    exec(code, d)
+    g = d['g']
+    origin = g.__code__.co_firstlineno
+    print(repr(g.__code__.co_lnotab))
+    assert g() == [origin+3, origin+5+127, origin+7+127+1000]
+
+def test_f_lineno_set(tempfile):
+    def tracer(f, *args):
+        def y(f, *args):
+            return y
+        def x(f, *args):
+            f.f_lineno += 1
+            return y  # "return None" should have the same effect, but see
+                        # test_local_trace_function_returning_None_ignored
+        return x
+
+    # obscure: call open beforehand, py3k's open invokes some app
+    # level code that confuses our tracing (likely due to the
+    # testing env, otherwise it's not a problem)
+    f = open(tempfile, 'w')
+    def function(f=f):
+        xyz
+        with f as f:
+            pass
+        return 3
+
+    import sys
+    sys.settrace(tracer)
+    function()
+    sys.settrace(None)
+    # assert did not crash
+
+def test_f_lineno_set_2(tempfile):
+    counter = [0]
+    errors = []
+
+    def tracer(f, event, *args):
+        if event == 'line':
+            counter[0] += 1
+            if counter[0] == 2:
+                try:
+                    f.f_lineno += 2
+                except ValueError as e:
+                    errors.append(e)
+        return tracer
+
+    # obscure: call open beforehand, py3k's open invokes some app
+    # level code that confuses our tracing (likely due to the
+    # testing env, otherwise it's not a problem)
+    f = open(tempfile, 'w')
+    def function():
+        try:
+            raise ValueError
+        except ValueError:
+            x = 42
+        return x
+
+    import sys
+    sys.settrace(tracer)
+    x = function()
+    sys.settrace(None)
+    assert x == 42
+    assert len(errors) == 1
+    assert str(errors[0]).startswith(
+        "can't jump into or out of an 'expect' or 'finally' block")
+
+def test_f_lineno_set_3():
+    def jump_in_nested_finally(output):
+        try:
+            output.append(2)
+        finally:
+            output.append(4)
+            try:
+                output.append(6)
+            finally:
+                output.append(8)
+            output.append(9)
+    output = []
+
+    def tracer(f, event, *args):
+        if event == 'line' and len(output) == 1:
+            f.f_lineno += 5
+        return tracer
+
+    import sys
+    sys.settrace(tracer)
+    jump_in_nested_finally(output)
+    sys.settrace(None)
+    assert output == [2, 9]
+
+def test_f_lineno_set_firstline():
+    seen = []
+    def tracer(f, event, *args):
+        if f.f_code.co_name == "decode":
+            return tracer
+        seen.append((event, f.f_lineno))
+        if len(seen) == 5:
+            f.f_lineno = 1       # bug shown only when setting lineno to 1
+        return tracer
+
+    def g():
+        import sys
+        source = "x=1\ny=x+1\nz=y+1\nt=z+1\ns=t+1\n"
+        # compile first to ensure that no spurious events appear in the trace
+        code = compile(source, '<string>', 'exec')
+        sys.settrace(tracer)
+        exec(code, {})
+        sys.settrace(None)
+
+    g()
+    assert seen == [('call', 1),
+                    ('line', 1),
+                    ('line', 2),
+                    ('line', 3),
+                    ('line', 4),
+                    ('line', 2),
+                    ('line', 3),
+                    ('line', 4),
+                    ('line', 5),
+                    ('return', 5)]
+
+def test_f_back():
+    import sys
+    def f():
+        assert sys._getframe().f_code.co_name == g()
+    def g():
+        return sys._getframe().f_back.f_code.co_name
+    f()
+
+def test_f_back_virtualref():
+    import sys
+    def f():
+        return g()
+    def g():
+        return sys._getframe()
+    frame = f()
+    assert frame.f_back.f_code.co_name == 'f'
+
+def test_virtualref_through_traceback():
+    import sys
+    def g():
+        try:
+            raise ValueError
+        except:
+            _, _, tb = sys.exc_info()
+        return tb
+    def f():
+        return g()
+    #
+    tb = f()
+    assert tb.tb_frame.f_code.co_name == 'g'
+    assert tb.tb_frame.f_back.f_code.co_name == 'f'
+
+def test_trace_basic():
+    import sys
+    l = []
+    class Tracer:
+        def __init__(self, i):
+            self.i = i
+        def trace(self, frame, event, arg):
+            l.append((self.i, frame.f_code.co_name, event, arg))
+            if frame.f_code.co_name == 'g2':
+                return None    # don't trace g2
+            return Tracer(self.i+1).trace
+    def g3(n):
+        n -= 5
+        return n
+    def g2(n):
+        n += g3(2)
+        n += g3(7)
+        return n
+    def g(n):
+        n += g2(3)
+        return n
+    def f(n):
+        n = g(n)
+        return n * 7
+    sys.settrace(Tracer(0).trace)
+    x = f(4)
+    sys.settrace(None)
+    assert x == 42
+    print(l)
+    assert l == [(0, 'f', 'call', None),
+                    (1, 'f', 'line', None),
+                        (0, 'g', 'call', None),
+                        (1, 'g', 'line', None),
+                            (0, 'g2', 'call', None),
+                                (0, 'g3', 'call', None),
+                                (1, 'g3', 'line', None),
+                                (2, 'g3', 'line', None),
+                                (3, 'g3', 'return', -3),
+                                (0, 'g3', 'call', None),
+                                (1, 'g3', 'line', None),
+                                (2, 'g3', 'line', None),
+                                (3, 'g3', 'return', 2),
+                        (2, 'g', 'line', None),
+                        (3, 'g', 'return', 6),
+                    (2, 'f', 'line', None),
+                    (3, 'f', 'return', 42)]
+
+def test_trace_exc():
+    import sys
+    l = []
+    def ltrace(a,b,c):
+        if b == 'exception':
+            l.append(c)
+        return ltrace
+    def trace(a,b,c): return ltrace
+    def f():
+        try:
+            raise Exception
+        except:
+            pass
+    sys.settrace(trace)
+    f()
+    sys.settrace(None)
+    assert len(l) == 1
+    assert isinstance(l[0][1], Exception)
+
+def test_trace_ignore_hidden():
+    import sys
+    import _testing
+
+    l = []
+    def trace(a,b,c):
+        if a.f_code.co_name != "decode":
+            l.append((a,b,c))
+
+    def f():
+        h = _testing.Hidden()
+        r = h.meth()
+        return r
+
+    sys.settrace(trace)
+    res = f()
+    sys.settrace(None)
+    assert len(l) == 1
+    assert l[0][1] == 'call'
+    assert res == 'hidden' # sanity
+
+def test_trace_hidden_applevel_builtins():
+    import sys
+
+    l = []
+    def trace(a,b,c):
+        l.append((a,b,c))
+        return trace
+
+    def f():
+        sum([])
+        sum([])
+        sum([])
+        return "that's the return value"
+
+    sys.settrace(trace)
+    f()
+    sys.settrace(None)
+    # should get 1 "call", 3 "line" and 1 "return" events, and no call
+    # or return for the internal app-level implementation of sum
+    assert len(l) == 6
+    assert [what for (frame, what, arg) in l] == [
+        'call', 'line', 'line', 'line', 'line', 'return']
+    assert l[-1][2] == "that's the return value"
+
+def test_trace_return_exc():
+    import sys
+    l = []
+    def trace(a,b,c):
+        if b in ('exception', 'return'):
+            l.append((b, c))
+        return trace
+
+    def g():
+        raise Exception
+    def f():
+        try:
+            g()
+        except:
+            pass
+    sys.settrace(trace)
+    f()
+    sys.settrace(None)
+    assert len(l) == 4
+    assert l[0][0] == 'exception'
+    assert isinstance(l[0][1][1], Exception)
+    assert l[1] == ('return', None)
+    assert l[2][0] == 'exception'
+    assert isinstance(l[2][1][1], Exception)
+    assert l[3] == ('return', None)
+
+def test_trace_raises_on_return():
+    import sys
+    def trace(frame, event, arg):
+        if event == 'return':
+            raise ValueError
+        else:
+            return trace
+
+    def f(): return 1
+
+    for i in range(sys.getrecursionlimit() + 1):
+        sys.settrace(trace)
+        try:
+            f()
+        except ValueError:
+            pass
+
+def test_trace_try_finally():
+    import sys
+    l = []
+    def trace(frame, event, arg):
+        if event == 'exception':
+            l.append(arg)
+        return trace
+
+    def g():
+        try:
+            raise Exception
+        finally:
+            pass
+
+    def f():
+        try:
+            g()
+        except:
+            pass
+
+    sys.settrace(trace)
+    f()
+    sys.settrace(None)
+    assert len(l) == 2
+    assert issubclass(l[0][0], Exception)
+    assert issubclass(l[1][0], Exception)
+
+def test_trace_generator_finalisation():
+    import sys
+    l = []
+    got_exc = []
+    def trace(frame, event, arg):
+        l.append((frame.f_lineno, event))
+        if event == 'exception':
+            got_exc.append(arg)
+        return trace
+
+    d = {}
+    exec("""if 1:
+    def g():
+        try:
+            yield True
+        finally:
+            pass
+
+    def f():
+        try:
+            gen = g()
+            next(gen)
+            gen.close()
+        except:
+            pass
+    """, d)
+    f = d['f']
+
+    sys.settrace(trace)
+    f()
+    sys.settrace(None)
+    assert len(got_exc) == 1
+    assert issubclass(got_exc[0][0], GeneratorExit)
+    assert l == [(8, 'call'),
+                    (9, 'line'),
+                    (10, 'line'),
+                    (11, 'line'),
+                    (2, 'call'),
+                    (3, 'line'),
+                    (4, 'line'),
+                    (4, 'return'),
+                    (12, 'line'),
+                    (4, 'call'),
+                    (4, 'exception'),
+                    (6, 'line'),
+                    (6, 'return'),
+                    (12, 'return')]
+
+def test_dont_trace_on_reraise():
+    import sys
+    l = []
+    def ltrace(a,b,c):
+        if b == 'exception':
+            l.append(c)
+        return ltrace
+    def trace(a,b,c): return ltrace
+    def f():
+        try:
+            1/0
+        except:
+            try:
+                raise
+            except:
+                pass
+    sys.settrace(trace)
+    f()
+    sys.settrace(None)
+    assert len(l) == 1
+    assert issubclass(l[0][0], Exception)
+
+def test_trace_changes_locals():
+    import sys
+    def trace(frame, what, arg):
+        frame.f_locals['x'] = 42
+        return trace
+    def f(x):
+        return x
+    sys.settrace(trace)
+    res = f(1)
+    sys.settrace(None)
+    assert res == 42
+
+def test_trace_onliner_if():
+    import sys
+    l = []
+    def trace(frame, event, arg):
+        l.append((frame.f_lineno, event))
+        return trace
+    def onliners():
+        if True: False
+        else: True
+        return 0
+    sys.settrace(trace)
+    onliners()
+    sys.settrace(None)
+    firstlineno = onliners.__code__.co_firstlineno
+    assert l == [(firstlineno + 0, 'call'),
+                    (firstlineno + 1, 'line'),
+                    (firstlineno + 3, 'line'),
+                    (firstlineno + 3, 'return')]
+
+def test_set_unset_f_trace():
+    import sys
+    seen = []
+    def trace1(frame, what, arg):
+        seen.append((1, frame, frame.f_lineno, what, arg))
+        return trace1
+    def trace2(frame, what, arg):
+        seen.append((2, frame, frame.f_lineno, what, arg))
+        return trace2
+    def set_the_trace(f):
+        f.f_trace = trace1
+        sys.settrace(trace2)
+        len(seen)     # take one line: should not be traced
+    f = sys._getframe()
+    set_the_trace(f)
+    len(seen)     # take one line: should not be traced
+    len(seen)     # take one line: should not be traced
+    sys.settrace(None)   # and this line should be the last line traced
+    len(seen)     # take one line
+    del f.f_trace
+    len(seen)     # take one line
+    firstline = set_the_trace.__code__.co_firstlineno
+    assert seen == [(1, f, firstline + 6, 'line', None),
+                    (1, f, firstline + 7, 'line', None),
+                    (1, f, firstline + 8, 'line', None)]
+
+def test_locals2fast_freevar_bug():
+    import sys
+    def f(n):
+        class A(object):
+            def g(self):
+                return n
+            n = 42
+        return A()
+    res = f(10).g()
+    assert res == 10
+    #
+    def trace(*args):
+        return trace
+    sys.settrace(trace)
+    res = f(10).g()
+    sys.settrace(None)
+    assert res == 10
+
+def test_preserve_exc_state_in_generators():
+    import sys
+    def yield_raise():
+        try:
+            raise KeyError("caught")
+        except KeyError:
+            yield sys.exc_info()[0]
+            yield sys.exc_info()[0]
+
+    it = yield_raise()
+    assert next(it) is KeyError
+    assert next(it) is KeyError
+
+def test_frame_clear():
+    import sys, gc, weakref
+    #
+    raises(RuntimeError, sys._getframe().clear)
+    def g():
+        yield 5
+        raises(RuntimeError, sys._getframe().clear)
+        yield 6
+    assert list(g()) == [5, 6]
+    #
+    class A:
+        pass
+    a1 = A(); a1ref = weakref.ref(a1)
+    a2 = A(); a2ref = weakref.ref(a2)
+    seen = []
+    def f():
+        local_a1 = a1
+        for loc in [5, 6, a2]:
+            try:
+                yield sys._getframe()
+            finally:
+                seen.append(42)
+            seen.append(43)
+    gen = f()
+    frame = next(gen)
+    a1 = a2 = None
+    gc.collect(); gc.collect()
+    assert a1ref() is not None
+    assert a2ref() is not None
+    assert seen == []
+    frame.clear()
+    assert seen == [42]
+    gc.collect(); gc.collect()
+    assert a1ref() is None, "locals not cleared"
+    assert a2ref() is None, "stack not cleared"
+    #
+    raises(StopIteration, next, gen)
+
+def test_frame_clear_really():
+    import sys
+    def f(x):
+        return sys._getframe()
+    frame = f(42)
+    assert frame.f_locals['x'] == 42
+    frame.clear()
+    assert frame.f_locals == {}
+
+def test_throw_trace_bug():
+    import sys
+    def f():
+        yield 5
+    gen = f()
+    assert next(gen) == 5
+    seen = []
+    def trace_func(frame, event, *args):
+        seen.append(event)
+        return trace_func
+    sys.settrace(trace_func)
+    try:
+        gen.throw(ValueError)
+    except ValueError:
+        pass
+    sys.settrace(None)
+    assert seen == ['call', 'exception', 'return']
+
+def test_generator_trace_stopiteration():
+    import sys
+    def f():
+        yield 5
+    gen = f()
+    assert next(gen) == 5
+    seen = []
+    frames = []
+    def trace_func(frame, event, *args):
+        print('TRACE:', frame, event, args)
+        seen.append(event)
+        frames.append(frame)
+        return trace_func
+    def g():
+        for x in gen:
+            never_entered
+    sys.settrace(trace_func)
+    g()
+    sys.settrace(None)
+    print('seen:', seen)
+    # on Python 3 we get an extra 'exception' when 'for' catches
+    # StopIteration (but not always! mess)
+    assert seen == ['call', 'line', 'call', 'return', 'exception', 'return']
+    assert frames[-2].f_code.co_name == 'g'
+
+def test_nongenerator_trace_stopiteration():
+    import sys
+    gen = iter([5])
+    assert next(gen) == 5
+    seen = []
+    frames = []
+    def trace_func(frame, event, *args):
+        print('TRACE:', frame, event, args)
+        seen.append(event)
+        frames.append(frame)
+        return trace_func
+    def g():
+        for x in gen:
+            never_entered
+    sys.settrace(trace_func)
+    g()
+    sys.settrace(None)
+    print('seen:', seen)
+    # hack: don't report the StopIteration for some "simple"
+    # iterators.
+    assert seen == ['call', 'line', 'return']
+    assert frames[-2].f_code.co_name == 'g'
+
+def test_yieldfrom_trace_stopiteration():
+    import sys
+    def f2():
+        yield 5
+    def f():
+        yield from f2()
+    gen = f()
+    assert next(gen) == 5
+    seen = []
+    frames = []
+    def trace_func(frame, event, *args):
+        print('TRACE:', frame, event, args)
+        seen.append(event)
+        frames.append(frame)
+        return trace_func
+    def g():
+        for x in gen:
+            never_entered
+    sys.settrace(trace_func)
+    g()      # invokes next_yield_from() from resume_execute_frame()
+    sys.settrace(None)
+    print('seen:', seen)
+    assert seen == ['call', 'line', 'call', 'call', 'return',
+                    'exception', 'return', 'exception', 'return']
+    assert frames[-4].f_code.co_name == 'f'
+    assert frames[-2].f_code.co_name == 'g'
+
+def test_yieldfrom_trace_stopiteration_2():
+    import sys
+    def f2():
+        if False:
+            yield 5
+    def f():
+        yield from f2()
+    gen = f()
+    seen = []
+    frames = []
+    def trace_func(frame, event, *args):
+        print('TRACE:', frame, event, args)
+        seen.append(event)
+        frames.append(frame)
+        return trace_func
+    def g():
+        for x in gen:
+            never_entered
+    sys.settrace(trace_func)
+    g()      # invokes next_yield_from() from YIELD_FROM()
+    sys.settrace(None)
+    print('seen:', seen)
+    assert seen == ['call', 'line', 'call', 'line', 'call', 'line',
+                    'return', 'exception', 'return', 'exception', 'return']
+    assert frames[-4].f_code.co_name == 'f'
+    assert frames[-2].f_code.co_name == 'g'
+
+def test_yieldfrom_trace_stopiteration_3():
+    import sys
+    def f():
+        yield from []
+    gen = f()
+    seen = []
+    frames = []
+    def trace_func(frame, event, *args):
+        print('TRACE:', frame, event, args)
+        seen.append(event)
+        frames.append(frame)
+        return trace_func
+    def g():
+        for x in gen:
+            never_entered
+    sys.settrace(trace_func)
+    g()      # invokes next_yield_from() from YIELD_FROM()
+    sys.settrace(None)
+    print('seen:', seen)
+    assert seen == ['call', 'line', 'call', 'line',
+                    'return', 'exception', 'return']
+    assert frames[-4].f_code.co_name == 'f'
+
+def test_local_trace_function_returning_None_ignored():
+    # behave the same as CPython does, and in contradiction with
+    # the documentation.
+    def tracer(f, event, arg):
+        assert event == 'call'
+        return local_tracer
+
+    seen = []
+    def local_tracer(f, event, arg):
+        seen.append(event)
+        return None     # but 'local_tracer' will be called again
+
+    def function():
+        a = 1
+        a = 2
+        a = 3
+
+    import sys
+    sys.settrace(tracer)
+    function()
+    sys.settrace(None)
+    assert seen == ["line", "line", "line", "return"]
+
+def test_clear_locals():
+    def make_frames():
+        def outer():
+            x = 5
+            y = 6
+            def inner():
+                z = x + 2
+                1/0
+                t = 9
+            return inner()
+        try:
+            outer()
+        except ZeroDivisionError as e:
+            tb = e.__traceback__
+            frames = []
+            while tb:
+                frames.append(tb.tb_frame)
+                tb = tb.tb_next
+        return frames
+
+    f, outer, inner = make_frames()
+    outer.clear()
+    inner.clear()
+    assert not outer.f_locals
+    assert not inner.f_locals
diff --git a/pypy/interpreter/test/demomixedmod/__init__.py b/pypy/interpreter/test/demomixedmod/__init__.py
--- a/pypy/interpreter/test/demomixedmod/__init__.py
+++ b/pypy/interpreter/test/demomixedmod/__init__.py
@@ -1,15 +0,0 @@
-from pypy.interpreter.mixedmodule import MixedModule 
-
-class Module(MixedModule): 
-    interpleveldefs = {
-        '__name__' : '(space.wrap("mixedmodule"))',
-        '__doc__'  : '(space.wrap("mixedmodule doc"))',
-        'somefunc' : 'file1.somefunc', 
-        'value'    : '(space.w_None)', 
-        'path'     :   'file1.initpath(space)', 
-        'cpypath'  : 'space.wrap(sys.path)'
-    }
-
-    appleveldefs = {
-        'someappfunc' : 'file2_app.someappfunc', 
-    }
diff --git a/pypy/interpreter/test/demomixedmod/__init__.py b/pypy/interpreter/test/demomixedmod/moduledef.py
copy from pypy/interpreter/test/demomixedmod/__init__.py
copy to pypy/interpreter/test/demomixedmod/moduledef.py
diff --git a/pypy/interpreter/test/fixtures.py b/pypy/interpreter/test/fixtures.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/test/fixtures.py
@@ -0,0 +1,5 @@
+from _pytest.tmpdir import TempdirFactory
+
+def tempfile(space, config):
+        tmpdir = TempdirFactory(config).getbasetemp()
+        return space.newtext(str(tmpdir / 'tempfile1'))
diff --git a/pypy/interpreter/test/test_appinterp.py b/pypy/interpreter/test/test_appinterp.py
--- a/pypy/interpreter/test/test_appinterp.py
+++ b/pypy/interpreter/test/test_appinterp.py
@@ -3,32 +3,32 @@
 from pypy.interpreter.gateway import appdef, ApplevelClass, applevel_temp
 from pypy.interpreter.error import OperationError
 
-def test_execwith_novars(space): 
-    val = space.appexec([], """ 
-    (): 
-        return 42 
-    """) 
+def test_execwith_novars(space):
+    val = space.appexec([], """
+    ():
+        return 42
+    """)
     assert space.eq_w(val, space.wrap(42))
 
-def test_execwith_withvars(space): 
+def test_execwith_withvars(space):
     val = space.appexec([space.wrap(7)], """
-    (x): 
-        y = 6 * x 
-        return y 
-    """) 
+    (x):
+        y = 6 * x
+        return y
+    """)
     assert space.eq_w(val, space.wrap(42))
 
-def test_execwith_compile_error(space): 
+def test_execwith_compile_error(space):
     excinfo = py.test.raises(OperationError, space.appexec, [], """
-    (): 
-        y y 
+    ():
+        y y
     """)
     # NOTE: the following test only works because excinfo.value is not
     # normalized so far
-    assert str(excinfo.value.get_w_value(space)).find('y y') != -1 
+    assert str(excinfo.value.get_w_value(space)).find('y y') != -1
 
 def test_simple_applevel(space):
-    app = appdef("""app(x,y): 
+    app = appdef("""app(x,y):
         return x + y
     """)
     assert app.__name__ == 'app'
@@ -36,15 +36,15 @@
     assert space.eq_w(w_result, space.wrap(42))
 
 def test_applevel_with_one_default(space):
-    app = appdef("""app(x,y=1): 
+    app = appdef("""app(x,y=1):
         return x + y
     """)
     assert app.__name__ == 'app'
-    w_result = app(space, space.wrap(41)) 
+    w_result = app(space, space.wrap(41))
     assert space.eq_w(w_result, space.wrap(42))
 
 def test_applevel_with_two_defaults(space):
-    app = appdef("""app(x=1,y=2): 
+    app = appdef("""app(x=1,y=2):
         return x + y
     """)
     w_result = app(space, space.wrap(41), space.wrap(1))
@@ -58,19 +58,19 @@
 
 
 def test_applevel_noargs(space):
-    app = appdef("""app(): 
-        return 42 
+    app = appdef("""app():
+        return 42
     """)
     assert app.__name__ == 'app'
-    w_result = app(space) 
+    w_result = app(space)
     assert space.eq_w(w_result, space.wrap(42))
 
-def somefunc(arg2=42): 
-    return arg2 
+def somefunc(arg2=42):
+    return arg2
 
-def test_app2interp_somefunc(space): 
-    app = appdef(somefunc) 
-    w_result = app(space) 
+def test_app2interp_somefunc(space):
+    app = appdef(somefunc)
+    w_result = app(space)
     assert space.eq_w(w_result, space.wrap(42))
 
 def test_applevel_functions(space, applevel_temp = applevel_temp):
@@ -87,48 +87,49 @@
 def test_applevel_class(space, applevel_temp = applevel_temp):
     app = applevel_temp('''
         class C(object):
-            clsattr = 42 
-            def __init__(self, x=13): 
-                self.attr = x 
+            clsattr = 42
+            def __init__(self, x=13):
+                self.attr = x
     ''')
     C = app.interphook('C')
-    c = C(space, space.wrap(17)) 
+    c = C(space, space.wrap(17))
     w_attr = space.getattr(c, space.wrap('clsattr'))
     assert space.eq_w(w_attr, space.wrap(42))
     w_clsattr = space.getattr(c, space.wrap('attr'))
     assert space.eq_w(w_clsattr, space.wrap(17))
 
-def app_test_something_at_app_level(): 
+def app_test_something_at_app_level():
     x = 2
     assert x/2 == 1
 
-class AppTestMethods: 
-    def test_some_app_test_method(self): 
+class AppTestMethods:
+    def test_some_app_test_method(self):
         assert 2 == 2
 
-class TestMixedModule: 
-    def test_accesses(self): 
+class TestMixedModule:
+    def test_accesses(self):
         space = self.space
-        import demomixedmod 
-        w_module = demomixedmod.Module(space, space.wrap('mixedmodule'))
+        from .demomixedmod.moduledef import Module
+        w_module = Module(space, space.wrap('mixedmodule'))
         space.appexec([w_module], """
-            (module): 
-                assert module.value is None 
+            (module):
+                assert module.value is None
                 assert module.__doc__ == 'mixedmodule doc'
 
-                assert module.somefunc is module.somefunc 
-                result = module.somefunc() 
-                assert result == True 
+                assert module.somefunc is module.somefunc
+                result = module.somefunc()
+                assert result == True
 
-                assert module.someappfunc is module.someappfunc 
-                appresult = module.someappfunc(41) 
-                assert appresult == 42 
+                assert module.someappfunc is module.someappfunc
+                appresult = module.someappfunc(41)
+                assert appresult == 42
 
                 assert module.__dict__ is module.__dict__
-                for name in ('somefunc', 'someappfunc', '__doc__', '__name__'): 
+                for name in ('somefunc', 'someappfunc', '__doc__', '__name__'):
                     assert name in module.__dict__
         """)
         assert space.is_true(w_module.call('somefunc'))
+        assert Module.get_applevel_name() == 'demomixedmod'
 
     def test_whacking_at_loaders(self):
         """Some MixedModules change 'self.loaders' in __init__(), but doing
diff --git a/pypy/interpreter/test/test_extmodules.py b/pypy/interpreter/test/test_extmodules.py
--- a/pypy/interpreter/test/test_extmodules.py
+++ b/pypy/interpreter/test/test_extmodules.py
@@ -2,10 +2,10 @@
 import pytest
 
 from pypy.config.pypyoption import get_pypy_config
-from pypy.objspace.std import StdObjSpace
+from pypy.objspace.std.objspace import StdObjSpace
 from rpython.tool.udir import udir
 


More information about the pypy-commit mailing list