[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