[pypy-commit] pypy jit-duplicated_short_boxes: hg merge default
hakanardo
noreply at buildbot.pypy.org
Wed Sep 7 12:18:16 CEST 2011
Author: Hakan Ardo <hakan at debian.org>
Branch: jit-duplicated_short_boxes
Changeset: r47128:95355f75d469
Date: 2011-09-07 10:00 +0200
http://bitbucket.org/pypy/pypy/changeset/95355f75d469/
Log: hg merge default
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -359,7 +359,7 @@
RegrTest('test_property.py', core=True),
RegrTest('test_pstats.py'),
RegrTest('test_pty.py', skip="unsupported extension module"),
- RegrTest('test_pwd.py', skip=skip_win32),
+ RegrTest('test_pwd.py', usemodules="pwd", skip=skip_win32),
RegrTest('test_py3kwarn.py'),
RegrTest('test_pyclbr.py'),
RegrTest('test_pydoc.py'),
diff --git a/lib_pypy/_elementtree.py b/lib_pypy/_elementtree.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_elementtree.py
@@ -0,0 +1,6 @@
+# Just use ElementTree.
+
+from xml.etree import ElementTree
+
+globals().update(ElementTree.__dict__)
+del __all__
diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py
--- a/lib_pypy/_pypy_interact.py
+++ b/lib_pypy/_pypy_interact.py
@@ -56,6 +56,10 @@
prompt = getattr(sys, 'ps1', '>>> ')
try:
line = raw_input(prompt)
+ # Can be None if sys.stdin was redefined
+ encoding = getattr(sys.stdin, 'encoding', None)
+ if encoding and not isinstance(line, unicode):
+ line = line.decode(encoding)
except EOFError:
console.write("\n")
break
diff --git a/lib_pypy/distributed/test/test_distributed.py b/lib_pypy/distributed/test/test_distributed.py
--- a/lib_pypy/distributed/test/test_distributed.py
+++ b/lib_pypy/distributed/test/test_distributed.py
@@ -9,7 +9,7 @@
class AppTestDistributed(object):
def setup_class(cls):
cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
- "usemodules":("_stackless",)})
+ "usemodules":("_continuation",)})
def test_init(self):
import distributed
@@ -91,10 +91,8 @@
class AppTestDistributedTasklets(object):
spaceconfig = {"objspace.std.withtproxy": True,
- "objspace.usemodules._stackless": True}
+ "objspace.usemodules._continuation": True}
def setup_class(cls):
- #cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
- # "usemodules":("_stackless",)})
cls.w_test_env = cls.space.appexec([], """():
from distributed import test_env
return test_env
diff --git a/lib_pypy/distributed/test/test_greensock.py b/lib_pypy/distributed/test/test_greensock.py
--- a/lib_pypy/distributed/test/test_greensock.py
+++ b/lib_pypy/distributed/test/test_greensock.py
@@ -10,7 +10,7 @@
if not option.runappdirect:
py.test.skip("Cannot run this on top of py.py because of PopenGateway")
cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
- "usemodules":("_stackless",)})
+ "usemodules":("_continuation",)})
cls.w_remote_side_code = cls.space.appexec([], """():
import sys
sys.path.insert(0, '%s')
diff --git a/lib_pypy/distributed/test/test_socklayer.py b/lib_pypy/distributed/test/test_socklayer.py
--- a/lib_pypy/distributed/test/test_socklayer.py
+++ b/lib_pypy/distributed/test/test_socklayer.py
@@ -9,7 +9,8 @@
class AppTestSocklayer:
def setup_class(cls):
cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
- "usemodules":("_stackless","_socket", "select")})
+ "usemodules":("_continuation",
+ "_socket", "select")})
def test_socklayer(self):
class X(object):
diff --git a/lib_pypy/pypy_test/test_coroutine.py b/lib_pypy/pypy_test/test_coroutine.py
--- a/lib_pypy/pypy_test/test_coroutine.py
+++ b/lib_pypy/pypy_test/test_coroutine.py
@@ -2,7 +2,7 @@
from py.test import skip, raises
try:
- from lib_pypy.stackless import coroutine, CoroutineExit
+ from stackless import coroutine, CoroutineExit
except ImportError, e:
skip('cannot import stackless: %s' % (e,))
@@ -20,10 +20,6 @@
assert not co.is_zombie
def test_is_zombie_del_without_frame(self):
- try:
- import _stackless # are we on pypy with a stackless build?
- except ImportError:
- skip("only works on pypy-c-stackless")
import gc
res = []
class MyCoroutine(coroutine):
@@ -45,10 +41,6 @@
assert res[0], "is_zombie was False in __del__"
def test_is_zombie_del_with_frame(self):
- try:
- import _stackless # are we on pypy with a stackless build?
- except ImportError:
- skip("only works on pypy-c-stackless")
import gc
res = []
class MyCoroutine(coroutine):
diff --git a/lib_pypy/pyrepl/reader.py b/lib_pypy/pyrepl/reader.py
--- a/lib_pypy/pyrepl/reader.py
+++ b/lib_pypy/pyrepl/reader.py
@@ -576,7 +576,7 @@
self.console.push_char(char)
self.handle1(0)
- def readline(self):
+ def readline(self, returns_unicode=False):
"""Read a line. The implementation of this method also shows
how to drive Reader if you want more control over the event
loop."""
@@ -585,6 +585,8 @@
self.refresh()
while not self.finished:
self.handle1()
+ if returns_unicode:
+ return self.get_unicode()
return self.get_buffer()
finally:
self.restore()
diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
--- a/lib_pypy/pyrepl/readline.py
+++ b/lib_pypy/pyrepl/readline.py
@@ -198,7 +198,7 @@
reader.ps1 = prompt
return reader.readline()
- def multiline_input(self, more_lines, ps1, ps2):
+ def multiline_input(self, more_lines, ps1, ps2, returns_unicode=False):
"""Read an input on possibly multiple lines, asking for more
lines as long as 'more_lines(unicodetext)' returns an object whose
boolean value is true.
@@ -209,7 +209,7 @@
reader.more_lines = more_lines
reader.ps1 = reader.ps2 = ps1
reader.ps3 = reader.ps4 = ps2
- return reader.readline()
+ return reader.readline(returns_unicode=returns_unicode)
finally:
reader.more_lines = saved
diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py
--- a/lib_pypy/pyrepl/simple_interact.py
+++ b/lib_pypy/pyrepl/simple_interact.py
@@ -54,7 +54,8 @@
ps1 = getattr(sys, 'ps1', '>>> ')
ps2 = getattr(sys, 'ps2', '... ')
try:
- statement = multiline_input(more_lines, ps1, ps2)
+ statement = multiline_input(more_lines, ps1, ps2,
+ returns_unicode=True)
except EOFError:
break
more = console.push(statement)
diff --git a/lib_pypy/stackless.py b/lib_pypy/stackless.py
--- a/lib_pypy/stackless.py
+++ b/lib_pypy/stackless.py
@@ -4,121 +4,124 @@
Please refer to their documentation.
"""
-DEBUG = True
-
-def dprint(*args):
- for arg in args:
- print arg,
- print
import traceback
-import sys
+import _continuation
+from functools import partial
+
+class TaskletExit(Exception):
+ pass
+
+CoroutineExit = TaskletExit
+
+class GWrap(_continuation.continulet):
+ """This is just a wrapper around continulet to allow
+ to stick additional attributes to a continulet.
+ To be more concrete, we need a backreference to
+ the coroutine object"""
+
+
+class coroutine(object):
+ "we can't have continulet as a base, because continulets can't be rebound"
+
+ def __init__(self):
+ self._frame = None
+ self.is_zombie = False
+
+ def __getattr__(self, attr):
+ return getattr(self._frame, attr)
+
+ def __del__(self):
+ self.is_zombie = True
+ del self._frame
+ self._frame = None
+
+ def bind(self, func, *argl, **argd):
+ """coro.bind(f, *argl, **argd) -> None.
+ binds function f to coro. f will be called with
+ arguments *argl, **argd
+ """
+ if self._frame is None or not self._frame.is_pending():
+
+ def _func(c, *args, **kwargs):
+ return func(*args, **kwargs)
+
+ run = partial(_func, *argl, **argd)
+ self._frame = frame = GWrap(run)
+ else:
+ raise ValueError("cannot bind a bound coroutine")
+
+ def switch(self):
+ """coro.switch() -> returnvalue
+ switches to coroutine coro. If the bound function
+ f finishes, the returnvalue is that of f, otherwise
+ None is returned
+ """
+ current = _getcurrent()
+ current._jump_to(self)
+
+ def _jump_to(self, coroutine):
+ _tls.current_coroutine = coroutine
+ self._frame.switch(to=coroutine._frame)
+
+ def kill(self):
+ """coro.kill() : kill coroutine coro"""
+ _tls.current_coroutine = self
+ self._frame.throw(CoroutineExit)
+
+ def _is_alive(self):
+ if self._frame is None:
+ return False
+ return not self._frame.is_pending()
+ is_alive = property(_is_alive)
+ del _is_alive
+
+ def getcurrent():
+ """coroutine.getcurrent() -> the currently running coroutine"""
+ try:
+ return _getcurrent()
+ except AttributeError:
+ return _maincoro
+ getcurrent = staticmethod(getcurrent)
+
+ def __reduce__(self):
+ raise TypeError, 'pickling is not possible based upon continulets'
+
+
+def _getcurrent():
+ "Returns the current coroutine (i.e. the one which called this function)."
+ try:
+ return _tls.current_coroutine
+ except AttributeError:
+ # first call in this thread: current == main
+ _coroutine_create_main()
+ return _tls.current_coroutine
+
try:
- # If _stackless can be imported then TaskletExit and CoroutineExit are
- # automatically added to the builtins.
- from _stackless import coroutine, greenlet
-except ImportError: # we are running from CPython
- from greenlet import greenlet, GreenletExit
- TaskletExit = CoroutineExit = GreenletExit
- del GreenletExit
- try:
- from functools import partial
- except ImportError: # we are not running python 2.5
- class partial(object):
- # just enough of 'partial' to be usefull
- def __init__(self, func, *argl, **argd):
- self.func = func
- self.argl = argl
- self.argd = argd
+ from thread import _local
+except ImportError:
+ class _local(object): # assume no threads
+ pass
- def __call__(self):
- return self.func(*self.argl, **self.argd)
+_tls = _local()
- class GWrap(greenlet):
- """This is just a wrapper around greenlets to allow
- to stick additional attributes to a greenlet.
- To be more concrete, we need a backreference to
- the coroutine object"""
+def _coroutine_create_main():
+ # create the main coroutine for this thread
+ _tls.current_coroutine = None
+ main_coroutine = coroutine()
+ main_coroutine.bind(lambda x:x)
+ _tls.main_coroutine = main_coroutine
+ _tls.current_coroutine = main_coroutine
+ return main_coroutine
- class MWrap(object):
- def __init__(self,something):
- self.something = something
- def __getattr__(self, attr):
- return getattr(self.something, attr)
+_maincoro = _coroutine_create_main()
- class coroutine(object):
- "we can't have greenlet as a base, because greenlets can't be rebound"
-
- def __init__(self):
- self._frame = None
- self.is_zombie = False
-
- def __getattr__(self, attr):
- return getattr(self._frame, attr)
-
- def __del__(self):
- self.is_zombie = True
- del self._frame
- self._frame = None
-
- def bind(self, func, *argl, **argd):
- """coro.bind(f, *argl, **argd) -> None.
- binds function f to coro. f will be called with
- arguments *argl, **argd
- """
- if self._frame is None or self._frame.dead:
- self._frame = frame = GWrap()
- frame.coro = self
- if hasattr(self._frame, 'run') and self._frame.run:
- raise ValueError("cannot bind a bound coroutine")
- self._frame.run = partial(func, *argl, **argd)
-
- def switch(self):
- """coro.switch() -> returnvalue
- switches to coroutine coro. If the bound function
- f finishes, the returnvalue is that of f, otherwise
- None is returned
- """
- try:
- return greenlet.switch(self._frame)
- except TypeError, exp: # self._frame is the main coroutine
- return greenlet.switch(self._frame.something)
-
- def kill(self):
- """coro.kill() : kill coroutine coro"""
- self._frame.throw()
-
- def _is_alive(self):
- if self._frame is None:
- return False
- return not self._frame.dead
- is_alive = property(_is_alive)
- del _is_alive
-
- def getcurrent():
- """coroutine.getcurrent() -> the currently running coroutine"""
- try:
- return greenlet.getcurrent().coro
- except AttributeError:
- return _maincoro
- getcurrent = staticmethod(getcurrent)
-
- def __reduce__(self):
- raise TypeError, 'pickling is not possible based upon greenlets'
-
- _maincoro = coroutine()
- maingreenlet = greenlet.getcurrent()
- _maincoro._frame = frame = MWrap(maingreenlet)
- frame.coro = _maincoro
- del frame
- del maingreenlet
from collections import deque
import operator
-__all__ = 'run getcurrent getmain schedule tasklet channel coroutine \
- greenlet'.split()
+__all__ = 'run getcurrent getmain schedule tasklet channel coroutine'.split()
_global_task_id = 0
_squeue = None
@@ -131,7 +134,8 @@
def _scheduler_remove(value):
try:
del _squeue[operator.indexOf(_squeue, value)]
- except ValueError:pass
+ except ValueError:
+ pass
def _scheduler_append(value, normal=True):
if normal:
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -27,7 +27,7 @@
# --allworkingmodules
working_modules = default_modules.copy()
working_modules.update(dict.fromkeys(
- ["_socket", "unicodedata", "mmap", "fcntl", "_locale",
+ ["_socket", "unicodedata", "mmap", "fcntl", "_locale", "pwd",
"rctime" , "select", "zipimport", "_lsprof",
"crypt", "signal", "_rawffi", "termios", "zlib", "bz2",
"struct", "_hashlib", "_md5", "_sha", "_minimal_curses", "cStringIO",
@@ -58,6 +58,7 @@
# unix only modules
del working_modules["crypt"]
del working_modules["fcntl"]
+ del working_modules["pwd"]
del working_modules["termios"]
del working_modules["_minimal_curses"]
diff --git a/pypy/config/test/test_config.py b/pypy/config/test/test_config.py
--- a/pypy/config/test/test_config.py
+++ b/pypy/config/test/test_config.py
@@ -281,11 +281,11 @@
def test_underscore_in_option_name():
descr = OptionDescription("opt", "", [
- BoolOption("_stackless", "", default=False),
+ BoolOption("_foobar", "", default=False),
])
config = Config(descr)
parser = to_optparse(config)
- assert parser.has_option("--_stackless")
+ assert parser.has_option("--_foobar")
def test_none():
dummy1 = BoolOption('dummy1', 'doc dummy', default=False, cmdline=None)
diff --git a/pypy/doc/config/objspace.usemodules._stackless.txt b/pypy/doc/config/objspace.usemodules._stackless.txt
deleted file mode 100644
--- a/pypy/doc/config/objspace.usemodules._stackless.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-Deprecated.
diff --git a/pypy/doc/config/objspace.usemodules.pwd.txt b/pypy/doc/config/objspace.usemodules.pwd.txt
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/objspace.usemodules.pwd.txt
@@ -0,0 +1,2 @@
+Use the 'pwd' module.
+This module is expected to be fully working.
diff --git a/pypy/interpreter/miscutils.py b/pypy/interpreter/miscutils.py
--- a/pypy/interpreter/miscutils.py
+++ b/pypy/interpreter/miscutils.py
@@ -167,3 +167,7 @@
def getmainthreadvalue(self):
return self._value
+
+ def getallvalues(self):
+ return {0: self._value}
+
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1523,10 +1523,8 @@
if not isinstance(prog, codetype):
filename = '<string>'
- if not isinstance(prog, str):
- if isinstance(prog, basestring):
- prog = str(prog)
- elif isinstance(prog, file):
+ if not isinstance(prog, basestring):
+ if isinstance(prog, file):
filename = prog.name
prog = prog.read()
else:
diff --git a/pypy/interpreter/test/test_exec.py b/pypy/interpreter/test/test_exec.py
--- a/pypy/interpreter/test/test_exec.py
+++ b/pypy/interpreter/test/test_exec.py
@@ -219,3 +219,30 @@
raise e
assert res == 1
+
+ def test_exec_unicode(self):
+ # 's' is a string
+ s = "x = u'\xd0\xb9\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd'"
+ # 'u' is a unicode
+ u = s.decode('utf-8')
+ exec u
+ assert len(x) == 6
+ assert ord(x[0]) == 0x0439
+ assert ord(x[1]) == 0x0446
+ assert ord(x[2]) == 0x0443
+ assert ord(x[3]) == 0x043a
+ assert ord(x[4]) == 0x0435
+ assert ord(x[5]) == 0x043d
+
+ def test_eval_unicode(self):
+ u = "u'%s'" % unichr(0x1234)
+ v = eval(u)
+ assert v == unichr(0x1234)
+
+ def test_compile_unicode(self):
+ s = "x = u'\xd0\xb9\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd'"
+ u = s.decode('utf-8')
+ c = compile(u, '<input>', 'exec')
+ exec c
+ assert len(x) == 6
+ assert ord(x[0]) == 0x0439
diff --git a/pypy/jit/backend/llsupport/regalloc.py b/pypy/jit/backend/llsupport/regalloc.py
--- a/pypy/jit/backend/llsupport/regalloc.py
+++ b/pypy/jit/backend/llsupport/regalloc.py
@@ -57,11 +57,13 @@
all_regs = []
no_lower_byte_regs = []
save_around_call_regs = []
-
+ frame_reg = None
+
def __init__(self, longevity, frame_manager=None, assembler=None):
self.free_regs = self.all_regs[:]
self.longevity = longevity
self.reg_bindings = {}
+ self.bindings_to_frame_reg = {}
self.position = -1
self.frame_manager = frame_manager
self.assembler = assembler
@@ -218,6 +220,10 @@
self.reg_bindings[v] = loc
return loc
+ def force_allocate_frame_reg(self, v):
+ """ Allocate the new variable v in the frame register."""
+ self.bindings_to_frame_reg[v] = None
+
def force_spill_var(self, var):
self._sync_var(var)
try:
@@ -236,6 +242,8 @@
try:
return self.reg_bindings[box]
except KeyError:
+ if box in self.bindings_to_frame_reg:
+ return self.frame_reg
return self.frame_manager.loc(box)
def return_constant(self, v, forbidden_vars=[], selected_reg=None):
@@ -264,8 +272,9 @@
self._check_type(v)
if isinstance(v, Const):
return self.return_constant(v, forbidden_vars, selected_reg)
-
prev_loc = self.loc(v)
+ if prev_loc is self.frame_reg and selected_reg is None:
+ return prev_loc
loc = self.force_allocate_reg(v, forbidden_vars, selected_reg,
need_lower_byte=need_lower_byte)
if prev_loc is not loc:
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -957,6 +957,7 @@
if (isinstance(from_loc, RegLoc) and from_loc.is_xmm) or (isinstance(to_loc, RegLoc) and to_loc.is_xmm):
self.mc.MOVSD(to_loc, from_loc)
else:
+ assert to_loc is not ebp
self.mc.MOV(to_loc, from_loc)
regalloc_mov = mov # legacy interface
@@ -2510,11 +2511,6 @@
genop_discard_cond_call_gc_wb_array = genop_discard_cond_call_gc_wb
- def genop_force_token(self, op, arglocs, resloc):
- # RegAlloc.consider_force_token ensures this:
- assert isinstance(resloc, RegLoc)
- self.mc.LEA_rb(resloc.value, FORCE_INDEX_OFS)
-
def not_implemented_op_discard(self, op, arglocs):
not_implemented("not implemented operation: %s" % op.getopname())
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -29,6 +29,7 @@
all_regs = [eax, ecx, edx, ebx, esi, edi]
no_lower_byte_regs = [esi, edi]
save_around_call_regs = [eax, edx, ecx]
+ frame_reg = ebp
REGLOC_TO_GCROOTMAP_REG_INDEX = {
ebx: 1,
@@ -312,8 +313,11 @@
self.fm.frame_bindings[arg] = loc
else:
if isinstance(loc, RegLoc):
- self.rm.reg_bindings[arg] = loc
- used[loc] = None
+ if loc is ebp:
+ self.rm.bindings_to_frame_reg[arg] = None
+ else:
+ self.rm.reg_bindings[arg] = loc
+ used[loc] = None
else:
self.fm.frame_bindings[arg] = loc
self.rm.free_regs = []
@@ -1358,8 +1362,8 @@
self.assembler.datablockwrapper)
def consider_force_token(self, op):
- loc = self.rm.force_allocate_reg(op.result)
- self.Perform(op, [], loc)
+ # the FORCE_TOKEN operation returns directly 'ebp'
+ self.rm.force_allocate_frame_reg(op.result)
def not_implemented_op(self, op):
not_implemented("not implemented operation: %s" % op.getopname())
diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -119,7 +119,8 @@
setitem(index, null)
def get_latest_force_token(self):
- return self.assembler.fail_ebp + FORCE_INDEX_OFS
+ # the FORCE_TOKEN operation and this helper both return 'ebp'.
+ return self.assembler.fail_ebp
def execute_token(self, executable_token):
addr = executable_token._x86_bootstrap_code
@@ -153,8 +154,9 @@
flavor='raw', zero=True,
immortal=True)
- def force(self, addr_of_force_index):
+ def force(self, addr_of_force_token):
TP = rffi.CArrayPtr(lltype.Signed)
+ addr_of_force_index = addr_of_force_token + FORCE_INDEX_OFS
fail_index = rffi.cast(TP, addr_of_force_index)[0]
assert fail_index >= 0, "already forced!"
faildescr = self.get_fail_descr_from_number(fail_index)
@@ -164,7 +166,7 @@
# start of "no gc operation!" block
fail_index_2 = self.assembler.grab_frame_values(
bytecode,
- addr_of_force_index - FORCE_INDEX_OFS,
+ addr_of_force_token,
self.all_null_registers)
self.assembler.leave_jitted_hook()
# end of "no gc operation!" block
diff --git a/pypy/jit/metainterp/optimizeopt/heap.py b/pypy/jit/metainterp/optimizeopt/heap.py
--- a/pypy/jit/metainterp/optimizeopt/heap.py
+++ b/pypy/jit/metainterp/optimizeopt/heap.py
@@ -25,7 +25,7 @@
# 'cached_fields'.
#
self._cached_fields = {}
- self._cached_fields_getfield_op = {}
+ self._cached_fields_getfield_op = {}
self._lazy_setfield = None
self._lazy_setfield_registered = False
@@ -81,7 +81,7 @@
def remember_field_value(self, structvalue, fieldvalue, getfield_op=None):
assert self._lazy_setfield is None
self._cached_fields[structvalue] = fieldvalue
- self._cached_fields_getfield_op[structvalue] = getfield_op
+ self._cached_fields_getfield_op[structvalue] = getfield_op
def force_lazy_setfield(self, optheap, can_cache=True):
op = self._lazy_setfield
@@ -167,7 +167,7 @@
def new(self):
return OptHeap()
-
+
def produce_potential_short_preamble_ops(self, sb):
descrkeys = self.cached_fields.keys()
if not we_are_translated():
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -4711,6 +4711,33 @@
"""
self.optimize_loop(ops, expected)
+ def test_forced_virtuals_aliasing(self):
+ ops = """
+ [i0, i1]
+ p0 = new(descr=ssize)
+ p1 = new(descr=ssize)
+ escape(p0)
+ escape(p1)
+ setfield_gc(p0, i0, descr=adescr)
+ setfield_gc(p1, i1, descr=adescr)
+ i2 = getfield_gc(p0, descr=adescr)
+ jump(i2, i2)
+ """
+ expected = """
+ [i0, i1]
+ p0 = new(descr=ssize)
+ escape(p0)
+ p1 = new(descr=ssize)
+ escape(p1)
+ setfield_gc(p0, i0, descr=adescr)
+ setfield_gc(p1, i1, descr=adescr)
+ jump(i0, i0)
+ """
+ py.test.skip("not implemented")
+ # setfields on things that used to be virtual still can't alias each
+ # other
+ self.optimize_loop(ops, expected)
+
class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
pass
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -639,33 +639,6 @@
a1.free()
cb.free()
- def test_another_callback_in_stackless(self):
- try:
- import _stackless
- except ImportError:
- skip("only valid in a stackless pypy-c")
-
- import _rawffi
- lib = _rawffi.CDLL(self.lib_name)
- runcallback = lib.ptr('runcallback', ['P'], 'q')
- def callback():
- co = _stackless.coroutine()
- def f():
- pass
- try:
- co.bind(f)
- co.switch()
- except RuntimeError:
- return 1<<42
- return -5
-
- cb = _rawffi.CallbackPtr(callback, [], 'q')
- a1 = cb.byptr()
- res = runcallback(a1)
- assert res[0] == 1<<42
- a1.free()
- cb.free()
-
def test_raising_callback(self):
import _rawffi, sys
import StringIO
diff --git a/pypy/module/_stackless/__init__.py b/pypy/module/_stackless/__init__.py
deleted file mode 100644
--- a/pypy/module/_stackless/__init__.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Package initialisation
-from pypy.interpreter.mixedmodule import MixedModule
-
-class Module(MixedModule):
- """
- This module implements Stackless for applications.
- """
-
- appleveldefs = {
- 'GreenletExit' : 'app_greenlet.GreenletExit',
- 'GreenletError' : 'app_greenlet.GreenletError',
- }
-
- interpleveldefs = {
- 'tasklet' : 'interp_stackless.tasklet',
- 'coroutine' : 'interp_coroutine.AppCoroutine',
- 'greenlet' : 'interp_greenlet.AppGreenlet',
- 'usercostate': 'interp_composable_coroutine.W_UserCoState',
- '_return_main' : 'interp_coroutine.return_main',
- 'get_stack_depth_limit': 'interp_coroutine.get_stack_depth_limit',
- 'set_stack_depth_limit': 'interp_coroutine.set_stack_depth_limit',
- }
-
- def setup_after_space_initialization(self):
- # post-installing classmethods/staticmethods which
- # are not yet directly supported
- from pypy.module._stackless.interp_coroutine import post_install as post_install_coro
- post_install_coro(self)
- from pypy.module._stackless.interp_greenlet import post_install as post_install_greenlet
- post_install_greenlet(self)
-
- if self.space.config.translation.gc == 'marksweep':
- from pypy.module._stackless.interp_clonable import post_install as post_install_clonable
- self.extra_interpdef('clonable', 'interp_clonable.AppClonableCoroutine')
- self.extra_interpdef('fork', 'interp_clonable.fork')
- post_install_clonable(self)
diff --git a/pypy/module/_stackless/app_greenlet.py b/pypy/module/_stackless/app_greenlet.py
deleted file mode 100644
--- a/pypy/module/_stackless/app_greenlet.py
+++ /dev/null
@@ -1,5 +0,0 @@
-class GreenletExit(Exception):
- pass
-
-class GreenletError(Exception):
- pass
diff --git a/pypy/module/_stackless/interp_clonable.py b/pypy/module/_stackless/interp_clonable.py
deleted file mode 100644
--- a/pypy/module/_stackless/interp_clonable.py
+++ /dev/null
@@ -1,106 +0,0 @@
-from pypy.interpreter.error import OperationError
-from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.gateway import interp2app
-from pypy.module._stackless.interp_coroutine import AppCoroutine, AppCoState
-from pypy.module._stackless.interp_coroutine import makeStaticMethod
-from pypy.module._stackless.rcoroutine import AbstractThunk
-from pypy.module._stackless.rclonable import InterpClonableMixin
-
-
-class AppClonableCoroutine(AppCoroutine, InterpClonableMixin):
-
- def newsubctx(self):
- self.hello_local_pool()
- AppCoroutine.newsubctx(self)
- self.goodbye_local_pool()
-
- def hello(self):
- self.hello_local_pool()
- AppCoroutine.hello(self)
-
- def goodbye(self):
- AppCoroutine.goodbye(self)
- self.goodbye_local_pool()
-
- def descr_method__new__(space, w_subtype):
- co = space.allocate_instance(AppClonableCoroutine, w_subtype)
- costate = AppClonableCoroutine._get_state(space)
- AppClonableCoroutine.__init__(co, space, state=costate)
- return space.wrap(co)
-
- def _get_state(space):
- return space.fromcache(AppClonableCoState)
- _get_state = staticmethod(_get_state)
-
- def w_getcurrent(space):
- return space.wrap(AppClonableCoroutine._get_state(space).current)
- w_getcurrent = staticmethod(w_getcurrent)
-
- def w_clone(self):
- space = self.space
- costate = self.costate
- if costate.current is self:
- raise OperationError(space.w_RuntimeError,
- space.wrap("clone() cannot clone the "
- "current coroutine"
- "; use fork() instead"))
- copy = AppClonableCoroutine(space, state=costate)
- copy.subctx = self.clone_into(copy, self.subctx)
- return space.wrap(copy)
-
- def descr__reduce__(self, space):
- raise OperationError(space.w_TypeError,
- space.wrap("_stackless.clonable instances are "
- "not picklable"))
-
-
-AppClonableCoroutine.typedef = TypeDef("clonable", AppCoroutine.typedef,
- __new__ = interp2app(AppClonableCoroutine.descr_method__new__.im_func),
- getcurrent = interp2app(AppClonableCoroutine.w_getcurrent),
- clone = interp2app(AppClonableCoroutine.w_clone),
- __reduce__ = interp2app(AppClonableCoroutine.descr__reduce__),
-)
-
-class AppClonableCoState(AppCoState):
- def post_install(self):
- self.current = self.main = AppClonableCoroutine(self.space, state=self)
- self.main.subctx.clear_framestack() # wack
-
-def post_install(module):
- makeStaticMethod(module, 'clonable', 'getcurrent')
- space = module.space
- AppClonableCoroutine._get_state(space).post_install()
-
-# ____________________________________________________________
-
-class ForkThunk(AbstractThunk):
- def __init__(self, coroutine):
- self.coroutine = coroutine
- self.newcoroutine = None
- def call(self):
- oldcoro = self.coroutine
- self.coroutine = None
- newcoro = AppClonableCoroutine(oldcoro.space, state=oldcoro.costate)
- newcoro.subctx = oldcoro.clone_into(newcoro, oldcoro.subctx)
- newcoro.parent = oldcoro
- self.newcoroutine = newcoro
-
-def fork(space):
- """Fork, as in the Unix fork(): the call returns twice, and the return
- value of the call is either the new 'child' coroutine object (if returning
- into the parent), or None (if returning into the child). This returns
- into the parent first, which can switch to the child later.
- """
- costate = AppClonableCoroutine._get_state(space)
- current = costate.current
- if current is costate.main:
- raise OperationError(space.w_RuntimeError,
- space.wrap("cannot fork() in the main "
- "clonable coroutine"))
- thunk = ForkThunk(current)
- coro_fork = AppClonableCoroutine(space, state=costate)
- coro_fork.bind(thunk)
- coro_fork.switch()
- # we resume here twice. The following would need explanations about
- # why it returns the correct thing in both the parent and the child...
- return space.wrap(thunk.newcoroutine)
diff --git a/pypy/module/_stackless/interp_composable_coroutine b/pypy/module/_stackless/interp_composable_coroutine
deleted file mode 100644
--- a/pypy/module/_stackless/interp_composable_coroutine
+++ /dev/null
@@ -1,33 +0,0 @@
-from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef, interp2app
-from pypy.module._stackless.coroutine import AppCoState, AppCoroutine
-
-
-class W_UserCoState(Wrappable):
- def __init__(self, space):
- self.costate = AppCoState(space)
- self.costate.post_install()
-
- def descr_method__new__(space, w_subtype):
- costate = space.allocate_instance(W_UserCoState, w_subtype)
- W_UserCoState.__init__(costate, space)
- return space.wrap(costate)
-
- def w_getcurrent(self):
- space = self.costate.space
- return space.wrap(self.costate.current)
-
- def w_spawn(self, w_subtype=None):
- space = self.costate.space
- if space.is_w(w_subtype, space.w_None):
- w_subtype = space.gettypeobject(AppCoroutine.typedef)
- co = space.allocate_instance(AppCoroutine, w_subtype)
- AppCoroutine.__init__(co, space, state=self.costate)
- return space.wrap(co)
-
-W_UserCoState.typedef = TypeDef("usercostate",
- __new__ = interp2app(W_UserCoState.descr_method__new__.im_func),
- __module__ = '_stackless',
- getcurrent = interp2app(W_UserCoState.w_getcurrent),
- spawn = interp2app(W_UserCoState.w_spawn),
-)
diff --git a/pypy/module/_stackless/interp_composable_coroutine.py b/pypy/module/_stackless/interp_composable_coroutine.py
deleted file mode 100644
--- a/pypy/module/_stackless/interp_composable_coroutine.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef, interp2app
-from pypy.module._stackless.interp_coroutine import AppCoState, AppCoroutine
-
-
-class W_UserCoState(Wrappable):
- def __init__(self, space):
- self.costate = AppCoState(space)
- self.costate.post_install()
-
- def descr_method__new__(space, w_subtype):
- costate = space.allocate_instance(W_UserCoState, w_subtype)
- W_UserCoState.__init__(costate, space)
- return space.wrap(costate)
-
- def w_getcurrent(self):
- space = self.costate.space
- return space.wrap(self.costate.current)
-
- def w_spawn(self, w_subtype=None):
- space = self.costate.space
- if space.is_w(w_subtype, space.w_None):
- w_subtype = space.gettypeobject(AppCoroutine.typedef)
- co = space.allocate_instance(AppCoroutine, w_subtype)
- AppCoroutine.__init__(co, space, state=self.costate)
- return space.wrap(co)
-
-W_UserCoState.typedef = TypeDef("usercostate",
- __new__ = interp2app(W_UserCoState.descr_method__new__.im_func),
- __module__ = '_stackless',
- getcurrent = interp2app(W_UserCoState.w_getcurrent),
- spawn = interp2app(W_UserCoState.w_spawn),
-)
-W_UserCoState.acceptable_as_base_class = False
diff --git a/pypy/module/_stackless/interp_coroutine.py b/pypy/module/_stackless/interp_coroutine.py
deleted file mode 100644
--- a/pypy/module/_stackless/interp_coroutine.py
+++ /dev/null
@@ -1,403 +0,0 @@
-"""
-Coroutine implementation for application level on top
-of the internal coroutines.
-This is an extensible concept. Multiple implementations
-of concurrency can exist together, if they follow the
-basic concept of maintaining their own costate.
-
-There is also some diversification possible by using
-multiple costates for the same type. This leads to
-disjoint switchable sets within the same type.
-
-I'm not so sure to what extent the opposite is possible, too.
-I.e., merging the costate of tasklets and greenlets would
-allow them to be parents of each other. Needs a bit more
-experience to decide where to set the limits.
-"""
-
-from pypy.interpreter.argument import Arguments
-from pypy.interpreter.typedef import GetSetProperty, TypeDef
-from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.error import OperationError, operationerrfmt
-
-from pypy.module._stackless.stackless_flags import StacklessFlags
-from pypy.module._stackless.rcoroutine import Coroutine, BaseCoState, AbstractThunk, CoroutineExit
-
-from pypy.module.exceptions.interp_exceptions import W_SystemExit, _new_exception
-
-from pypy.rlib import rstack, jit # for resume points
-from pypy.tool import stdlib_opcode as pythonopcode
-
-class _AppThunk(AbstractThunk):
-
- def __init__(self, space, costate, w_obj, args):
- self.space = space
- self.costate = costate
- if not space.is_true(space.callable(w_obj)):
- raise operationerrfmt(
- space.w_TypeError,
- "'%s' object is not callable",
- space.type(w_obj).getname(space))
- self.w_func = w_obj
- self.args = args
-
- def call(self):
- costate = self.costate
- w_result = self.space.call_args(self.w_func, self.args)
- costate.w_tempval = w_result
-
-class _ResumeThunk(AbstractThunk):
- def __init__(self, space, costate, w_frame):
- self.space = space
- self.costate = costate
- self.w_frame = w_frame
-
- def call(self):
- w_result = resume_frame(self.space, self.w_frame)
- # costate.w_tempval = w_result #XXX?
-
-
-W_CoroutineExit = _new_exception('CoroutineExit', W_SystemExit,
- """Coroutine killed manually.""")
-
-# Should be moved to interp_stackless.py if it's ever implemented... Currently
-# used by pypy/lib/stackless.py.
-W_TaskletExit = _new_exception('TaskletExit', W_SystemExit,
- """Tasklet killed manually.""")
-
-class AppCoroutine(Coroutine): # XXX, StacklessFlags):
-
- def __init__(self, space, state=None):
- self.space = space
- if state is None:
- state = AppCoroutine._get_state(space)
- Coroutine.__init__(self, state)
- self.flags = 0
- self.newsubctx()
-
- def newsubctx(self):
- ec = self.space.getexecutioncontext()
- self.subctx = ec.Subcontext()
-
- def descr_method__new__(space, w_subtype):
- co = space.allocate_instance(AppCoroutine, w_subtype)
- AppCoroutine.__init__(co, space)
- return space.wrap(co)
-
- def _get_state(space):
- return space.fromcache(AppCoState)
- _get_state = staticmethod(_get_state)
-
- def w_bind(self, w_func, __args__):
- space = self.space
- if self.frame is not None:
- raise OperationError(space.w_ValueError, space.wrap(
- "cannot bind a bound Coroutine"))
- state = self.costate
- thunk = _AppThunk(space, state, w_func, __args__)
- self.bind(thunk)
-
- def w_switch(self):
- space = self.space
- if self.frame is None:
- raise OperationError(space.w_ValueError, space.wrap(
- "cannot switch to an unbound Coroutine"))
- state = self.costate
- self.switch()
- w_ret, state.w_tempval = state.w_tempval, space.w_None
- return w_ret
-
- def switch(self):
- space = self.space
- try:
- Coroutine.switch(self)
- except CoroutineExit:
- raise OperationError(self.costate.w_CoroutineExit, space.w_None)
-
- def w_finished(self, w_excinfo):
- pass
-
- def finish(self, operror=None):
- space = self.space
- if isinstance(operror, OperationError):
- w_exctype = operror.w_type
- w_excvalue = operror.get_w_value(space)
- w_exctraceback = operror.get_traceback()
- w_excinfo = space.newtuple([w_exctype, w_excvalue, w_exctraceback])
-
- if w_exctype is self.costate.w_CoroutineExit:
- self.coroutine_exit = True
- else:
- w_N = space.w_None
- w_excinfo = space.newtuple([w_N, w_N, w_N])
-
- return space.call_method(space.wrap(self),'finished', w_excinfo)
-
- def hello(self):
- ec = self.space.getexecutioncontext()
- self.subctx.enter(ec)
-
- def goodbye(self):
- ec = self.space.getexecutioncontext()
- self.subctx.leave(ec)
-
- def w_kill(self):
- self.kill()
-
- def w_throw(self, w_type, w_value=None, w_traceback=None):
- space = self.space
-
- operror = OperationError(w_type, w_value)
- operror.normalize_exception(space)
-
- if not space.is_w(w_traceback, space.w_None):
- from pypy.interpreter import pytraceback
- tb = space.interpclass_w(w_traceback)
- if tb is None or not space.is_true(space.isinstance(tb,
- space.gettypeobject(pytraceback.PyTraceback.typedef))):
- raise OperationError(space.w_TypeError,
- space.wrap("throw: arg 3 must be a traceback or None"))
- operror.set_traceback(tb)
-
- self._kill(operror)
-
- def _userdel(self):
- if self.get_is_zombie():
- return
- self.set_is_zombie(True)
- self.space.userdel(self.space.wrap(self))
-
- def w_getcurrent(space):
- return space.wrap(AppCoroutine._get_state(space).current)
- w_getcurrent = staticmethod(w_getcurrent)
-
- def w_getmain(space):
- return space.wrap(AppCoroutine._get_state(space).main)
- w_getmain = staticmethod(w_getmain)
-
- # pickling interface
- def descr__reduce__(self, space):
- # this is trying to be simplistic at the moment.
- # we neither allow to pickle main (which can become a mess
- # since it has some deep anchestor frames)
- # nor we allow to pickle the current coroutine.
- # rule: switch before pickling.
- # you cannot construct the tree that you are climbing.
- from pypy.interpreter.mixedmodule import MixedModule
- w_mod = space.getbuiltinmodule('_stackless')
- mod = space.interp_w(MixedModule, w_mod)
- w_mod2 = space.getbuiltinmodule('_pickle_support')
- mod2 = space.interp_w(MixedModule, w_mod2)
- w_new_inst = mod.get('coroutine')
- w = space.wrap
- nt = space.newtuple
- ec = self.space.getexecutioncontext()
-
- if self is self.costate.main:
- return nt([mod.get('_return_main'), nt([])])
-
- thunk = self.thunk
- if isinstance(thunk, _AppThunk):
- w_args, w_kwds = thunk.args.topacked()
- w_thunk = nt([thunk.w_func, w_args, w_kwds])
- else:
- w_thunk = space.w_None
-
- tup_base = [
- ]
- tup_state = [
- w(self.flags),
- self.subctx.getstate(space),
- w_thunk,
- w(self.parent),
- ]
-
- return nt([w_new_inst, nt(tup_base), nt(tup_state)])
-
- def descr__setstate__(self, space, w_args):
- w_flags, w_state, w_thunk, w_parent = space.unpackiterable(w_args,
- expected_length=4)
- self.flags = space.int_w(w_flags)
- if space.is_w(w_parent, space.w_None):
- w_parent = self.w_getmain(space)
- self.parent = space.interp_w(AppCoroutine, w_parent)
- ec = self.space.getexecutioncontext()
- self.subctx.setstate(space, w_state)
- if space.is_w(w_thunk, space.w_None):
- if space.is_w(w_state, space.w_None):
- self.thunk = None
- else:
- self.bind(_ResumeThunk(space, self.costate, self.subctx.topframe))
- else:
- w_func, w_args, w_kwds = space.unpackiterable(w_thunk,
- expected_length=3)
- args = Arguments.frompacked(space, w_args, w_kwds)
- self.bind(_AppThunk(space, self.costate, w_func, args))
-
-
-# _mixin_ did not work
-for methname in StacklessFlags.__dict__:
- meth = getattr(StacklessFlags, methname)
- if hasattr(meth, 'im_func'):
- setattr(AppCoroutine, meth.__name__, meth.im_func)
-del meth, methname
-
-def w_get_is_zombie(self, space):
- return space.wrap(self.get_is_zombie())
-AppCoroutine.w_get_is_zombie = w_get_is_zombie
-
-def w_get_is_alive(self, space):
- return space.wrap(self.is_alive())
-AppCoroutine.w_get_is_alive = w_get_is_alive
-
-def w_descr__framestack(self, space):
- assert isinstance(self, AppCoroutine)
- counter = 0
- f = self.subctx.topframe
- while f is not None:
- counter += 1
- f = f.f_backref()
- items = [None] * counter
- f = self.subctx.topframe
- while f is not None:
- counter -= 1
- assert counter >= 0
- items[counter] = space.wrap(f)
- f = f.f_backref()
- assert counter == 0
- return space.newtuple(items)
-
-def makeStaticMethod(module, classname, funcname):
- "NOT_RPYTHON"
- space = module.space
- w_klass = space.getattr(space.wrap(module), space.wrap(classname))
- # HACK HACK HACK
- # make the typeobject mutable for a while
- from pypy.objspace.std.typeobject import W_TypeObject
- assert isinstance(w_klass, W_TypeObject)
- old_flag = w_klass.flag_heaptype
- w_klass.flag_heaptype = True
-
- space.appexec([w_klass, space.wrap(funcname)], """
- (klass, funcname):
- func = getattr(klass, funcname)
- setattr(klass, funcname, staticmethod(func.im_func))
- """)
- w_klass.flag_heaptype = old_flag
-
-def post_install(module):
- makeStaticMethod(module, 'coroutine', 'getcurrent')
- makeStaticMethod(module, 'coroutine', 'getmain')
- space = module.space
- AppCoroutine._get_state(space).post_install()
-
-# space.appexec("""() :
-
-# maybe use __spacebind__ for postprocessing
-
-AppCoroutine.typedef = TypeDef("coroutine",
- __new__ = interp2app(AppCoroutine.descr_method__new__.im_func),
- bind = interp2app(AppCoroutine.w_bind),
- switch = interp2app(AppCoroutine.w_switch),
- kill = interp2app(AppCoroutine.w_kill),
- throw = interp2app(AppCoroutine.w_throw),
- finished = interp2app(AppCoroutine.w_finished),
- is_alive = GetSetProperty(AppCoroutine.w_get_is_alive),
- is_zombie = GetSetProperty(AppCoroutine.w_get_is_zombie,
- doc=AppCoroutine.get_is_zombie.__doc__), #--- this flag is a bit obscure
- # and not useful (it's totally different from Coroutine.is_zombie(), too)
- # but lib/stackless.py uses it
- _framestack = GetSetProperty(w_descr__framestack),
- getcurrent = interp2app(AppCoroutine.w_getcurrent),
- getmain = interp2app(AppCoroutine.w_getmain),
- __reduce__ = interp2app(AppCoroutine.descr__reduce__),
- __setstate__ = interp2app(AppCoroutine.descr__setstate__),
- __module__ = '_stackless',
-)
-
-class AppCoState(BaseCoState):
- def __init__(self, space):
- BaseCoState.__init__(self)
- self.w_tempval = space.w_None
- self.space = space
-
- # XXX Workaround: for now we need to instantiate these classes
- # explicitly for translation to work
- W_CoroutineExit(space)
- W_TaskletExit(space)
-
- # Exporting new exception to space
- self.w_CoroutineExit = space.gettypefor(W_CoroutineExit)
- space.setitem(
- space.exceptions_module.w_dict,
- space.new_interned_str('CoroutineExit'),
- self.w_CoroutineExit)
- space.setitem(space.builtin.w_dict,
- space.new_interned_str('CoroutineExit'),
- self.w_CoroutineExit)
-
- # Should be moved to interp_stackless.py if it's ever implemented...
- self.w_TaskletExit = space.gettypefor(W_TaskletExit)
- space.setitem(
- space.exceptions_module.w_dict,
- space.new_interned_str('TaskletExit'),
- self.w_TaskletExit)
- space.setitem(space.builtin.w_dict,
- space.new_interned_str('TaskletExit'),
- self.w_TaskletExit)
-
- def post_install(self):
- self.current = self.main = AppCoroutine(self.space, state=self)
- self.main.subctx.clear_framestack() # wack
-
-def return_main(space):
- return AppCoroutine._get_state(space).main
-
-def get_stack_depth_limit(space):
- return space.wrap(rstack.get_stack_depth_limit())
-
- at unwrap_spec(limit=int)
-def set_stack_depth_limit(space, limit):
- rstack.set_stack_depth_limit(limit)
-
-
-# ___________________________________________________________________
-# unpickling trampoline
-
-def resume_frame(space, w_frame):
- from pypy.interpreter.pyframe import PyFrame
- frame = space.interp_w(PyFrame, w_frame, can_be_None=True)
- w_result = space.w_None
- operr = None
- executioncontext = frame.space.getexecutioncontext()
- while frame is not None:
- code = frame.pycode.co_code
- instr = frame.last_instr
- opcode = ord(code[instr])
- map = pythonopcode.opmap
- call_ops = [map['CALL_FUNCTION'], map['CALL_FUNCTION_KW'], map['CALL_FUNCTION_VAR'],
- map['CALL_FUNCTION_VAR_KW'], map['CALL_METHOD']]
- assert opcode in call_ops
- instr += 1
- oparg = ord(code[instr]) | ord(code[instr + 1]) << 8
- nargs = oparg & 0xff
- nkwds = (oparg >> 8) & 0xff
- if nkwds == 0: # only positional arguments
- # fast paths leaves things on the stack, pop them
- if space.config.objspace.opcodes.CALL_METHOD and opcode == map['CALL_METHOD']:
- frame.dropvalues(nargs + 2)
- elif opcode == map['CALL_FUNCTION']:
- frame.dropvalues(nargs + 1)
-
- # small hack: unlink frame out of the execution context, because
- # execute_frame will add it there again
- executioncontext.topframeref = jit.non_virtual_ref(frame.f_backref())
- frame.last_instr = instr + 1 # continue after the call
- try:
- w_result = frame.execute_frame(w_result, operr)
- except OperationError, operr:
- pass
- frame = frame.f_backref()
- if operr:
- raise operr
- return w_result
diff --git a/pypy/module/_stackless/interp_greenlet.py b/pypy/module/_stackless/interp_greenlet.py
deleted file mode 100644
--- a/pypy/module/_stackless/interp_greenlet.py
+++ /dev/null
@@ -1,238 +0,0 @@
-from pypy.interpreter.argument import Arguments
-from pypy.interpreter.typedef import GetSetProperty, TypeDef
-from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.gateway import NoneNotWrapped
-from pypy.interpreter.error import OperationError
-
-from pypy.module._stackless.rcoroutine import Coroutine, BaseCoState
-from pypy.module._stackless.rcoroutine import AbstractThunk, syncstate
-from pypy.module._stackless.interp_coroutine import makeStaticMethod
-
-
-class GreenletThunk(AbstractThunk):
-
- def __init__(self, greenlet):
- self.greenlet = greenlet
-
- def call(self):
- greenlet = self.greenlet
- greenlet.active = True
- try:
- space = greenlet.space
- args_w = greenlet.costate.args_w
- __args__ = Arguments(space, args_w)
- try:
- w_run = space.getattr(space.wrap(greenlet), space.wrap('run'))
- greenlet.w_callable = None
- w_result = space.call_args(w_run, __args__)
- except OperationError, operror:
- if not operror.match(space, greenlet.costate.w_GreenletExit):
- raise
- w_result = operror.get_w_value(space)
- finally:
- greenlet.active = False
- greenlet.costate.args_w = [w_result]
-
-class AppGreenletCoState(BaseCoState):
- def __init__(self, space):
- BaseCoState.__init__(self)
- self.args_w = None
- self.space = space
- self.w_GreenletExit = get(space, "GreenletExit")
- self.w_GreenletError = get(space, "GreenletError")
-
- def post_install(self):
- self.current = self.main = AppGreenlet(self.space, is_main=True)
-
-class AppGreenlet(Coroutine):
- def __init__(self, space, w_callable=None, is_main=False):
- Coroutine.__init__(self, self._get_state(space))
- self.space = space
- self.w_callable = w_callable
- self.active = is_main
- self.subctx = space.getexecutioncontext().Subcontext()
- if is_main:
- self.subctx.clear_framestack() # wack
- else:
- self.bind(GreenletThunk(self))
-
- def descr_method__new__(space, w_subtype, __args__):
- co = space.allocate_instance(AppGreenlet, w_subtype)
- AppGreenlet.__init__(co, space)
- return space.wrap(co)
-
- def descr_method__init__(self, w_run=NoneNotWrapped,
- w_parent=NoneNotWrapped):
- if w_run is not None:
- self.set_run(w_run)
- if w_parent is not None:
- self.set_parent(w_parent)
-
- def _get_state(space):
- return space.fromcache(AppGreenletCoState)
- _get_state = staticmethod(_get_state)
-
- def hello(self):
- ec = self.space.getexecutioncontext()
- self.subctx.enter(ec)
-
- def goodbye(self):
- ec = self.space.getexecutioncontext()
- self.subctx.leave(ec)
-
- def w_getcurrent(space):
- return space.wrap(AppGreenlet._get_state(space).current)
- w_getcurrent = staticmethod(w_getcurrent)
-
- def w_switch(self, args_w):
- # Find the switch target - it might be a parent greenlet
- space = self.space
- costate = self.costate
- target = self
- while target.isdead():
- target = target.parent
- assert isinstance(target, AppGreenlet)
- # Switch to it
- costate.args_w = args_w
- if target is not costate.current:
- target.switch()
- else:
- # case not handled in Coroutine.switch()
- syncstate._do_things_to_do()
- result_w = costate.args_w
- costate.args_w = None
- # costate.args_w can be set to None above for throw(), but then
- # switch() should have raised. At this point cosstate.args_w != None.
- assert result_w is not None
- # Return the result of a switch, packaging it in a tuple if
- # there is more than one value.
- if len(result_w) == 1:
- return result_w[0]
- return space.newtuple(result_w)
-
- def w_throw(self, w_type=None, w_value=None, w_traceback=None):
- space = self.space
- if space.is_w(w_type, space.w_None):
- w_type = self.costate.w_GreenletExit
- # Code copied from RAISE_VARARGS but slightly modified. Not too nice.
- operror = OperationError(w_type, w_value)
- operror.normalize_exception(space)
- if not space.is_w(w_traceback, space.w_None):
- from pypy.interpreter import pytraceback
- tb = space.interpclass_w(w_traceback)
- if tb is None or not space.is_true(space.isinstance(tb,
- space.gettypeobject(pytraceback.PyTraceback.typedef))):
- raise OperationError(space.w_TypeError,
- space.wrap("throw: arg 3 must be a traceback or None"))
- operror.set_traceback(tb)
- # Dead greenlet: turn GreenletExit into a regular return
- if self.isdead() and operror.match(space, self.costate.w_GreenletExit):
- args_w = [operror.get_w_value(space)]
- else:
- syncstate.push_exception(operror)
- args_w = None
- return self.w_switch(args_w)
-
- def _userdel(self):
- self.space.userdel(self.space.wrap(self))
-
- def isdead(self):
- return self.thunk is None and not self.active
-
- def w_get_is_dead(self, space):
- return space.newbool(self.isdead())
-
- def descr__nonzero__(self):
- return self.space.newbool(self.active)
-
- def w_get_run(self, space):
- w_run = self.w_callable
- if w_run is None:
- raise OperationError(space.w_AttributeError, space.wrap("run"))
- return w_run
-
- def set_run(self, w_run):
- space = self.space
- if self.thunk is None:
- raise OperationError(space.w_AttributeError,
- space.wrap("run cannot be set "
- "after the start of the greenlet"))
- self.w_callable = w_run
-
- def w_set_run(self, space, w_run):
- self.set_run(w_run)
-
- def w_del_run(self, space):
- if self.w_callable is None:
- raise OperationError(space.w_AttributeError, space.wrap("run"))
- self.w_callable = None
-
- def w_get_parent(self, space):
- return space.wrap(self.parent)
-
- def set_parent(self, w_parent):
- space = self.space
- newparent = space.interp_w(AppGreenlet, w_parent)
- if newparent.costate is not self.costate:
- raise OperationError(self.costate.w_GreenletError,
- space.wrap("invalid foreign parent"))
- curr = newparent
- while curr:
- if curr is self:
- raise OperationError(space.w_ValueError,
- space.wrap("cyclic parent chain"))
- curr = curr.parent
- self.parent = newparent
-
- def w_set_parent(self, space, w_parent):
- self.set_parent(w_parent)
-
- def w_get_frame(self, space):
- if not self.active or self.costate.current is self:
- f = None
- else:
- f = self.subctx.topframe
- return space.wrap(f)
-
-def get(space, name):
- w_module = space.getbuiltinmodule('_stackless')
- return space.getattr(w_module, space.wrap(name))
-
-def post_install(module):
- "NOT_RPYTHON"
- makeStaticMethod(module, 'greenlet', 'getcurrent')
- space = module.space
- state = AppGreenlet._get_state(space)
- state.post_install()
- w_greenlet = get(space, 'greenlet')
- # HACK HACK HACK
- # make the typeobject mutable for a while
- from pypy.objspace.std.typeobject import W_TypeObject
- assert isinstance(w_greenlet, W_TypeObject)
- old_flag = w_greenlet.flag_heaptype
- w_greenlet.flag_heaptype = True
- space.appexec([w_greenlet,
- state.w_GreenletExit,
- state.w_GreenletError], """
- (greenlet, exit, error):
- greenlet.GreenletExit = exit
- greenlet.error = error
- """)
- w_greenlet.flag_heaptype = old_flag
-
-AppGreenlet.typedef = TypeDef("greenlet",
- __new__ = interp2app(AppGreenlet.descr_method__new__.im_func),
- __init__ = interp2app(AppGreenlet.descr_method__init__),
- switch = interp2app(AppGreenlet.w_switch),
- dead = GetSetProperty(AppGreenlet.w_get_is_dead),
- run = GetSetProperty(AppGreenlet.w_get_run,
- AppGreenlet.w_set_run,
- AppGreenlet.w_del_run),
- parent = GetSetProperty(AppGreenlet.w_get_parent,
- AppGreenlet.w_set_parent),
- getcurrent = interp2app(AppGreenlet.w_getcurrent),
- throw = interp2app(AppGreenlet.w_throw),
- gr_frame = GetSetProperty(AppGreenlet.w_get_frame),
- __nonzero__ = interp2app(AppGreenlet.descr__nonzero__),
- __module__ = '_stackless',
-)
diff --git a/pypy/module/_stackless/interp_stackless.py b/pypy/module/_stackless/interp_stackless.py
deleted file mode 100644
--- a/pypy/module/_stackless/interp_stackless.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.gateway import interp2app
-import os
-
-
-class tasklet(Wrappable):
-
- def __init__(self, space):
- self.space = space
- self.flags = 0
- self.state = None
-
- def descr_method__new__(space, w_subtype):
- t = space.allocate_instance(tasklet, w_subtype)
- tasklet.__init__(t, space)
- return space.wrap(t)
-
- def w_demo(self):
- output("42")
-
-tasklet.typedef = TypeDef("tasklet",
- __new__ = interp2app(tasklet.descr_method__new__.im_func),
- demo = interp2app(tasklet.w_demo),
-)
-
-def output(stuff):
- os.write(2, stuff + '\n')
diff --git a/pypy/module/_stackless/rclonable.py b/pypy/module/_stackless/rclonable.py
deleted file mode 100644
--- a/pypy/module/_stackless/rclonable.py
+++ /dev/null
@@ -1,87 +0,0 @@
-from pypy.module._stackless.interp_coroutine import AbstractThunk, Coroutine
-from pypy.rlib.rgc import gc_swap_pool, gc_clone
-from pypy.rlib.objectmodel import we_are_translated
-
-
-class InterpClonableMixin:
- local_pool = None
- _mixin_ = True
-
- def hello_local_pool(self):
- if we_are_translated():
- self.saved_pool = gc_swap_pool(self.local_pool)
-
- def goodbye_local_pool(self):
- if we_are_translated():
- self.local_pool = gc_swap_pool(self.saved_pool)
- self.saved_pool = None
-
- def clone_into(self, copy, extradata=None):
- if not we_are_translated():
- raise NotImplementedError
- # cannot gc_clone() directly self, because it is not in its own
- # local_pool. Moreover, it has a __del__, which cloning doesn't
- # support properly at the moment.
- copy.parent = self.parent
- # the hello/goodbye pair has two purposes: it forces
- # self.local_pool to be computed even if it was None up to now,
- # and it puts the 'data' tuple in the correct pool to be cloned.
- self.hello_local_pool()
- data = (self.frame, extradata)
- self.goodbye_local_pool()
- # clone!
- data, copy.local_pool = gc_clone(data, self.local_pool)
- copy.frame, extradata = data
- copy.thunk = self.thunk # in case we haven't switched to self yet
- return extradata
-
-
-class InterpClonableCoroutine(Coroutine, InterpClonableMixin):
-
- def hello(self):
- self.hello_local_pool()
-
- def goodbye(self):
- self.goodbye_local_pool()
-
- def clone(self):
- # hack, this is overridden in AppClonableCoroutine
- if self.getcurrent() is self:
- raise RuntimeError("clone() cannot clone the current coroutine; "
- "use fork() instead")
- copy = InterpClonableCoroutine(self.costate)
- self.clone_into(copy)
- return copy
-
-
-class ForkThunk(AbstractThunk):
- def __init__(self, coroutine):
- self.coroutine = coroutine
- self.newcoroutine = None
- def call(self):
- oldcoro = self.coroutine
- self.coroutine = None
- newcoro = oldcoro.clone()
- newcoro.parent = oldcoro
- self.newcoroutine = newcoro
-
-def fork():
- """Fork, as in the Unix fork(): the call returns twice, and the return
- value of the call is either the new 'child' coroutine object (if returning
- into the parent), or None (if returning into the child). This returns
- into the parent first, which can switch to the child later.
- """
- current = InterpClonableCoroutine.getcurrent()
- if not isinstance(current, InterpClonableCoroutine):
- raise RuntimeError("fork() in a non-clonable coroutine")
- thunk = ForkThunk(current)
- coro_fork = InterpClonableCoroutine()
- coro_fork.bind(thunk)
- coro_fork.switch()
- # we resume here twice. The following would need explanations about
- # why it returns the correct thing in both the parent and the child...
- return thunk.newcoroutine
-
-## from pypy.rpython.lltypesystem import lltype, lloperation
-## lloperation.llop.debug_view(lltype.Void, current, thunk,
-## lloperation.llop.gc_x_size_header(lltype.Signed))
diff --git a/pypy/module/_stackless/rcoroutine.py b/pypy/module/_stackless/rcoroutine.py
deleted file mode 100644
--- a/pypy/module/_stackless/rcoroutine.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from pypy.rlib.rcoroutine import make_coroutine_classes
-from pypy.interpreter.baseobjspace import Wrappable
-
-d = make_coroutine_classes(Wrappable)
-
-Coroutine = d['Coroutine']
-BaseCoState = d['BaseCoState']
-AbstractThunk = d['AbstractThunk']
-syncstate = d['syncstate']
-CoroutineExit = d['CoroutineExit']
diff --git a/pypy/module/_stackless/stackless_flags.py b/pypy/module/_stackless/stackless_flags.py
deleted file mode 100644
--- a/pypy/module/_stackless/stackless_flags.py
+++ /dev/null
@@ -1,201 +0,0 @@
-"""
-basic definitions for tasklet flags.
-For simplicity and compatibility,
-they are defined the same for coroutines,
-even if they are not used.
-
-taken from tasklet_structs.h
-----------------------------
-
-/***************************************************************************
-
- Tasklet Flag Definition
- -----------------------
-
- blocked: The tasklet is either waiting in a channel for
- writing (1) or reading (-1) or not blocked (0).
- Maintained by the channel logic. Do not change.
-
- atomic: If true, schedulers will never switch. Driven by
- the code object or dynamically, see below.
-
- ignore_nesting: Allows auto-scheduling, even if nesting_level
- is not zero.
-
- autoschedule: The tasklet likes to be auto-scheduled. User driven.
-
- block_trap: Debugging aid. Whenever the tasklet would be
- blocked by a channel, an exception is raised.
-
- is_zombie: This tasklet is almost dead, its deallocation has
- started. The tasklet *must* die at some time, or the
- process can never end.
-
- pending_irq: If set, an interrupt was issued during an atomic
- operation, and should be handled when possible.
-
-
- Policy for atomic/autoschedule and switching:
- ---------------------------------------------
- A tasklet switch can always be done explicitly by calling schedule().
- Atomic and schedule are concerned with automatic features.
-
- atomic autoschedule
-
- 1 any Neither a scheduler nor a watchdog will
- try to switch this tasklet.
-
- 0 0 The tasklet can be stopped on desire, or it
- can be killed by an exception.
-
- 0 1 Like above, plus auto-scheduling is enabled.
-
- Default settings:
- -----------------
- All flags are zero by default.
-
- ***************************************************************************/
-
-typedef struct _tasklet_flags {
- int blocked: 2;
- unsigned int atomic: 1;
- unsigned int ignore_nesting: 1;
- unsigned int autoschedule: 1;
- unsigned int block_trap: 1;
- unsigned int is_zombie: 1;
- unsigned int pending_irq: 1;
-} PyTaskletFlagStruc;
-"""
-
-from pypy.rlib.rarithmetic import LONG_BIT, intmask
-
-class BitSetDef(object):
- __slots__ = "_names __dict__ _attrname".split()
-
- def __init__(self, _attrname):
- self._names = []
- self._attrname = _attrname
-
- def __setattr__(self, key, value):
- if key not in self.__slots__:
- assert key not in self.__dict__
- self._names.append(key)
- object.__setattr__(self, key, value)
-
- def __iter__(self):
- return self._enum_objects()
-
- def _enum_objects(self):
- for name in self._names:
- yield name, getattr(self, name)
-
-# negative values are user-writable
-flags = BitSetDef("flags")
-flags.blocked = 2, """writing (1) or reading (-1) or not blocked (0)"""
-flags.atomic = -1, """If true, schedulers will never switch"""
-flags.ignore_nesting = -1, """allow auto-scheduling in nested interpreters"""
-flags.autoschedule = -1, """enable auto-scheduling"""
-flags.block_trap = -1, """raise an exception instead of blocking"""
-flags.is_zombie = 1, """__del__ is in progress"""
-flags.pending_irq = 1, """an interrupt occured while being atomic"""
-
-def make_get_bits(name, bits, shift):
- """ return a bool for single bits, signed int otherwise """
- signmask = 1 << (bits - 1 + shift)
- lshift = bits + shift
- rshift = bits
- if bits == 1:
- return "bool(%s & 0x%x)" % (name, signmask)
- else:
- return "intmask(%s << (LONG_BIT-%d)) >> (LONG_BIT-%d)" % (name, lshift, rshift)
-
-def make_set_bits(name, bits, shift):
- datamask = int('1' * bits, 2)
- clearmask = datamask << shift
- return "%s & ~0x%x | (value & 0x%x) << %d" % (name, clearmask, datamask, shift)
-
-def gen_code():
- from cStringIO import StringIO
- f = StringIO()
- print >> f, "class StacklessFlags(object):"
- print >> f, " _mixin_ = True"
- shift = 0
- field = "self.%s" % flags._attrname
- for name, (bits, doc) in flags:
- write, bits = bits < 0, abs(bits)
- print >> f
- print >> f, ' def get_%s(self):' % name
- print >> f, ' """%s"""' % doc
- print >> f, ' return %s' % make_get_bits(field, bits, shift)
- print >> f, ' def set_%s(self, value):' % name
- print >> f, ' """%s"""' % doc
- print >> f, ' %s = %s' % (field, make_set_bits(field, bits, shift))
- print >> f, ' set_%s._public = %s' % (name, write)
- shift += bits
- return f.getvalue()
-
-# BEGIN generated code
-class StacklessFlags(object):
- _mixin_ = True
-
- def get_blocked(self):
- """writing (1) or reading (-1) or not blocked (0)"""
- return intmask(self.flags << (LONG_BIT-2)) >> (LONG_BIT-2)
- def set_blocked(self, value):
- """writing (1) or reading (-1) or not blocked (0)"""
- self.flags = self.flags & ~0x3 | (value & 0x3) << 0
- set_blocked._public = False
-
- def get_atomic(self):
- """If true, schedulers will never switch"""
- return bool(self.flags & 0x4)
- def set_atomic(self, value):
- """If true, schedulers will never switch"""
- self.flags = self.flags & ~0x4 | (value & 0x1) << 2
- set_atomic._public = True
-
- def get_ignore_nesting(self):
- """allow auto-scheduling in nested interpreters"""
- return bool(self.flags & 0x8)
- def set_ignore_nesting(self, value):
- """allow auto-scheduling in nested interpreters"""
- self.flags = self.flags & ~0x8 | (value & 0x1) << 3
- set_ignore_nesting._public = True
-
- def get_autoschedule(self):
- """enable auto-scheduling"""
- return bool(self.flags & 0x10)
- def set_autoschedule(self, value):
- """enable auto-scheduling"""
- self.flags = self.flags & ~0x10 | (value & 0x1) << 4
- set_autoschedule._public = True
-
- def get_block_trap(self):
- """raise an exception instead of blocking"""
- return bool(self.flags & 0x20)
- def set_block_trap(self, value):
- """raise an exception instead of blocking"""
- self.flags = self.flags & ~0x20 | (value & 0x1) << 5
- set_block_trap._public = True
-
- def get_is_zombie(self):
- """__del__ is in progress"""
- return bool(self.flags & 0x40)
- def set_is_zombie(self, value):
- """__del__ is in progress"""
- self.flags = self.flags & ~0x40 | (value & 0x1) << 6
- set_is_zombie._public = False
-
- def get_pending_irq(self):
- """an interrupt occured while being atomic"""
- return bool(self.flags & 0x80)
- def set_pending_irq(self, value):
- """an interrupt occured while being atomic"""
- self.flags = self.flags & ~0x80 | (value & 0x1) << 7
- set_pending_irq._public = False
-
-# END generated code
-
-if __name__ == '__main__':
- # paste this into the file
- print gen_code()
diff --git a/pypy/module/_stackless/test/__init__.py b/pypy/module/_stackless/test/__init__.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/__init__.py
+++ /dev/null
@@ -1,1 +0,0 @@
-#
\ No newline at end of file
diff --git a/pypy/module/_stackless/test/conftest.py b/pypy/module/_stackless/test/conftest.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/conftest.py
+++ /dev/null
@@ -1,8 +0,0 @@
-import sys
-import py.test
-
-def pytest_runtest_setup(item):
- py.test.importorskip('greenlet')
- if sys.platform == 'win32':
- py.test.skip("stackless tests segfault on Windows")
-
diff --git a/pypy/module/_stackless/test/slp_test_pickle.py b/pypy/module/_stackless/test/slp_test_pickle.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/slp_test_pickle.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from pypy.conftest import gettestobjspace
-
-# app-level testing of coroutine pickling
-
-class AppTest_Pickle:
-
- def setup_class(cls):
- space = gettestobjspace(usemodules=('_stackless',))
- cls.space = space
-
- def test_simple_ish(self):
-
- output = []
- import _stackless
- def f(coro, n, x):
- if n == 0:
- coro.switch()
- return
- f(coro, n-1, 2*x)
- output.append(x)
-
- def example():
- main_coro = _stackless.coroutine.getcurrent()
- sub_coro = _stackless.coroutine()
- sub_coro.bind(f, main_coro, 5, 1)
- sub_coro.switch()
-
- import pickle
- pckl = pickle.dumps(sub_coro)
- new_coro = pickle.loads(pckl)
-
- new_coro.switch()
-
- example()
- assert output == [16, 8, 4, 2, 1]
diff --git a/pypy/module/_stackless/test/test_choicepoint.py b/pypy/module/_stackless/test/test_choicepoint.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_choicepoint.py
+++ /dev/null
@@ -1,85 +0,0 @@
-import py; py.test.skip("clonable coroutines not really maintained any more")
-
-from pypy.rlib.rcoroutine import AbstractThunk
-from pypy.module._stackless.rclonable import InterpClonableCoroutine as ClonableCoroutine
-
-class ChoicePointHolder(object):
- def __init__(self):
- self.choicepoints = []
- self.clone_me = False
- self.answer = 0
- self.solutions_count = 0
-
- def next_choice(self):
- return self.choicepoints.pop()
-
- def add(self, choice, answer=0):
- self.choicepoints.append((choice, answer))
-
- def more_choices(self):
- return bool(self.choicepoints)
-
- def choice(self):
- #os.write(1, "choice\n")
- self.clone_me = True
- self.g_main.switch()
- #os.write(1, "answer: %d\n" % (self.answer,))
- return self.answer
-
- def fail(self):
- self.g_main.switch()
- assert False
-
-choicepoints = ChoicePointHolder()
-
-# ____________________________________________________________
-
-class SearchTask(AbstractThunk):
- def call(self):
- path = []
- for i in range(10):
- res = choicepoints.choice()
- assert len(path) == i
- path.append(res)
- #os.write(1, "{%x} trying: %s\n" % (id(path), path))
- if i == 3:
- import gc; gc.collect()
- #os.write(1, "{%x} found a solution: %s\n" % (id(path), path))
- choicepoints.solutions_count += 1
-
-# ____________________________________________________________
-
-
-class SearchAllTask(AbstractThunk):
- def call(self):
- search_coro = ClonableCoroutine()
- search_coro.bind(SearchTask())
- choicepoints.add(search_coro)
-
- #os.write(1, "starting\n")
- while choicepoints.more_choices():
- searcher, nextvalue = choicepoints.next_choice()
- choicepoints.clone_me = False
- choicepoints.answer = nextvalue
- #os.write(1, '<<< {%x} %d\n' % (id(searcher), nextvalue))
- searcher.switch()
- #os.write(1, '>>> %d\n' % (choicepoints.clone_me,))
- if choicepoints.clone_me:
- searcher2 = searcher.clone()
- #os.write(1, 'searcher = {%x}, searcher2 = {%x}\n' % (
- # id(searcher), id(searcher2)))
- choicepoints.add(searcher, 5)
- choicepoints.add(searcher2, 4)
-
-def entry_point():
- choicepoints.g_main = ClonableCoroutine()
- choicepoints.g_main.bind(SearchAllTask())
- choicepoints.g_main.switch()
- return choicepoints.solutions_count
-
-def test_choicepoint():
- from pypy.translator.c.test import test_newgc
- tester = test_newgc.TestUsingStacklessFramework()
- fn = tester.getcompiled(entry_point)
- res = fn()
- assert res == 2 ** 10
diff --git a/pypy/module/_stackless/test/test_clonable.py b/pypy/module/_stackless/test/test_clonable.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_clonable.py
+++ /dev/null
@@ -1,187 +0,0 @@
-import py; py.test.skip("clonable coroutines not really maintained any more")
-
-from pypy.conftest import gettestobjspace, option
-import py, sys
-
-# app-level testing of coroutine cloning
-
-class AppTestClonable:
-
- def setup_class(cls):
- if not option.runappdirect:
- py.test.skip('pure appdirect test (run with -A)')
- cls.space = space = gettestobjspace(usemodules=('_stackless',))
- if not space.is_true(space.appexec([], """():
- import _stackless
- return hasattr(_stackless, 'clonable')
- """)):
- py.test.skip('no _stackless.clonable')
-
-
- def test_solver(self):
- import _stackless
-
- class Fail(Exception):
- pass
-
- class Success(Exception):
- pass
-
- def first_solution(func):
- global next_answer
- co = _stackless.clonable()
- co.bind(func)
- pending = [(co, None)]
- while pending:
- co, next_answer = pending.pop()
- try:
- co.switch()
- except Fail:
- pass
- except Success, e:
- return e.args[0]
- else:
- # zero_or_one() called, clone the coroutine
- co2 = co.clone()
- pending.append((co2, 1))
- pending.append((co, 0))
- raise Fail("no solution")
-
- pending = []
- main = _stackless.clonable.getcurrent()
-
- def zero_or_one():
- main.switch()
- return next_answer
-
- # ____________________________________________________________
-
- invalid_prefixes = {
- (0, 0): True,
- (0, 1, 0): True,
- (0, 1, 1): True,
- (1, 0): True,
- (1, 1, 0, 0): True,
- }
-
- def example():
- test = []
- for n in range(5):
- test.append(zero_or_one())
- if tuple(test) in invalid_prefixes:
- raise Fail
- raise Success(test)
-
- res = first_solution(example)
- assert res == [1, 1, 0, 1, 0]
-
-
- def test_myself_may_not_be_me_any_more(self):
- import gc
- from _stackless import clonable
-
- counter = [0]
-
- def runner():
- while 1:
- assert clonable.getcurrent() is coro
- counter[0] += 1
- main.switch()
-
- main = clonable.getcurrent()
- coro = clonable()
- coro.bind(runner)
-
- coro.switch()
- assert counter == [1]
-
- assert clonable.getcurrent() is main
- coro1 = coro.clone()
- assert counter == [1]
- assert clonable.getcurrent() is main
- coro.switch()
- assert counter == [2]
- coro.switch()
- assert counter == [3]
- assert clonable.getcurrent() is main
- del coro1
- gc.collect()
- #print "collected!"
- assert clonable.getcurrent() is main
- assert counter == [3]
- coro.switch()
- assert clonable.getcurrent() is main
- assert counter == [4]
-
-
- def test_fork(self):
- import _stackless
-
- class Fail(Exception):
- pass
-
- class Success(Exception):
- pass
-
- def first_solution(func):
- global next_answer
- co = _stackless.clonable()
- co.bind(func)
- try:
- co.switch()
- except Success, e:
- return e.args[0]
-
- def zero_or_one():
- sub = _stackless.fork()
- if sub is not None:
- # in the parent: run the child first
- try:
- sub.switch()
- except Fail:
- pass
- # then proceed with answer '1'
- return 1
- else:
- # in the child: answer '0'
- return 0
-
- # ____________________________________________________________
-
- invalid_prefixes = {
- (0, 0): True,
- (0, 1, 0): True,
- (0, 1, 1): True,
- (1, 0): True,
- (1, 1, 0, 0): True,
- }
-
- def example():
- test = []
- for n in range(5):
- test.append(zero_or_one())
- if tuple(test) in invalid_prefixes:
- raise Fail
- raise Success(test)
-
- res = first_solution(example)
- assert res == [1, 1, 0, 1, 0]
-
- def test_clone_before_start(self):
- """Tests that a clonable coroutine can be
- cloned before it is started
- (this used to fail with a segmentation fault)
- """
- import _stackless
-
- counter = [0]
- def simple_coro():
- print "hello"
- counter[0] += 1
-
- s = _stackless.clonable()
- s.bind(simple_coro)
- t = s.clone()
- s.switch()
- t.switch()
- assert counter[0] == 2
diff --git a/pypy/module/_stackless/test/test_composable_coroutine.py b/pypy/module/_stackless/test/test_composable_coroutine.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_composable_coroutine.py
+++ /dev/null
@@ -1,133 +0,0 @@
-""" a faith is the connection between past and future that divides the
- application into switch-compatible chunks.
- -- stakkars
-"""
-from pypy.conftest import gettestobjspace
-from py.test import skip
-
-class AppTest_ComposableCoroutine:
-
- def setup_class(cls):
- space = gettestobjspace(usemodules=('_stackless',))
- cls.space = space
-
- cls.w_generator_ = space.appexec([], """():
- import _stackless
-
- generators_costate = _stackless.usercostate()
- main = generators_costate.getcurrent()
-
- class generator_iterator(_stackless.coroutine):
-
- def __iter__(self):
- return self
-
- def next(self):
- if self.gi_answer is not None:
- raise ValueError('stackless-generator'
- ' already executing')
- self.gi_answer = []
- self.gi_caller = generators_costate.getcurrent()
- self.switch()
- answer = self.gi_answer
- self.gi_answer = None
- if answer:
- return answer[0]
- else:
- raise StopIteration
-
- def generator(f):
- def myfunc(*args, **kwds):
- g = generators_costate.spawn(generator_iterator)
- g.gi_answer = None
- g.bind(f, *args, **kwds)
- return g
- return myfunc
-
- def Yield(value):
- g = generators_costate.getcurrent()
- if g is main:
- raise ValueError('Yield() outside any stackless-generator')
- assert isinstance(g, generator_iterator)
- assert g.gi_answer == []
- g.gi_answer.append(value)
- g.gi_caller.switch()
-
- generator.Yield = Yield
- generator._costate = generators_costate
- return (generator,)
- """)
-
- def test_simple_costate(self):
- import _stackless
- costate = _stackless.usercostate()
- main = costate.getcurrent()
-
- result = []
- def f():
- result.append(costate.getcurrent())
- co = costate.spawn()
- co.bind(f)
- co.switch()
- assert result == [co]
-
- def test_generator(self):
- generator, = self.generator_
-
- def squares(n):
- for i in range(n):
- generator.Yield(i*i)
- squares = generator(squares)
-
- lst1 = [i*i for i in range(10)]
- for got in squares(10):
- expected = lst1.pop(0)
- assert got == expected
- assert lst1 == []
-
- def test_multiple_costates(self):
- """Test that two independent costates mix transparently:
-
- - compute_costate, used for a coroutine that fills a list with
- some more items each time it is switched to
-
- - generators_costate, used interally by self.generator (see above)
- """
-
- import _stackless
- generator, = self.generator_
-
- # you can see how it fails if we don't have two different costates
- # by setting compute_costate to generator._costate instead
- compute_costate = _stackless.usercostate()
- compute_main = compute_costate.getcurrent()
- lst = []
-
- def filler(): # -> 0, 1, 2, 100, 101, 102, 200, 201, 202, 300 ...
- for k in range(5):
- for j in range(3):
- lst.append(100 * k + j)
- compute_main.switch()
-
- filler_co = compute_costate.spawn()
- filler_co.bind(filler)
-
- def grab_next_value():
- while not lst:
- #print 'filling more...'
- filler_co.switch()
- #print 'now lst =', lst
- #print 'grabbing', lst[0]
- return lst.pop(0)
-
- def squares(n):
- for i in range(n):
- #print 'square:', i
- generator.Yield(i*grab_next_value())
- squares = generator(squares)
-
- lst1 = [0, 1, 4, 300, 404, 510, 1200, 1407, 1616, 2700]
- for got in squares(10):
- expected = lst1.pop(0)
- assert got == expected
- assert lst1 == []
diff --git a/pypy/module/_stackless/test/test_coroutine.py b/pypy/module/_stackless/test/test_coroutine.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_coroutine.py
+++ /dev/null
@@ -1,168 +0,0 @@
-from pypy.conftest import gettestobjspace, option
-from py.test import skip
-
-
-class AppTest_Coroutine:
-
- def setup_class(cls):
- space = gettestobjspace(usemodules=('_stackless',))
- cls.space = space
-
- def test_raise_propagate(self):
- import _stackless as stackless
- co = stackless.coroutine()
- def f():
- return 1/0
- co.bind(f)
- try:
- co.switch()
- except ZeroDivisionError:
- pass
- else:
- raise AssertionError("exception not propagated")
-
- def test_strange_test(self):
- from _stackless import coroutine
- def f():
- print "in new coro"
- return 42
- def create():
- b = coroutine()
- b.bind(f)
- print "bound"
- b.switch()
- print "switched"
- return b
- a = coroutine()
- a.bind(create)
- b = a.switch()
- # now b.parent = a
- def nothing():
- pass
- a.bind(nothing)
- def kill():
- # this sets a.parent = b
- a.kill()
- b.bind(kill)
- b.switch()
-
- def test_kill(self):
- import _stackless as stackless
- co = stackless.coroutine()
- def f():
- pass
- co.bind(f)
- assert co.is_alive
- co.kill()
- assert not co.is_alive
-
- def test_kill_running(self):
- coroutineexit = []
- import _stackless as stackless
- main = stackless.coroutine.getcurrent()
- result = []
- co = stackless.coroutine()
- def f():
- x = 2
- try:
- result.append(1)
- main.switch()
- x = 3
- except CoroutineExit:
- coroutineexit.append(True)
- raise
- finally:
- result.append(x)
- result.append(4)
- co.bind(f)
- assert co.is_alive
- co.switch()
- assert co.is_alive
- assert result == [1]
- co.kill()
- assert not co.is_alive
- assert result == [1, 2]
- assert coroutineexit == [True]
-
- def test_bogus_bind(self):
- import _stackless as stackless
- co = stackless.coroutine()
- def f():
- pass
- co.bind(f)
- raises(ValueError, co.bind, f)
-
- def test__framestack(self):
- import _stackless as stackless
- main = stackless.coroutine.getmain()
- co = stackless.coroutine()
- def g():
- return co._framestack
- def f():
- return g()
-
- co.bind(f)
- stack = co.switch()
- assert stack == () # running corountine, _framestack is empty
-
- co = stackless.coroutine()
- def g():
- return main.switch()
- def f():
- return g()
-
- co.bind(f)
- co.switch()
- stack = co._framestack
- assert len(stack) == 2
- assert stack[0].f_code is f.func_code
- assert stack[1].f_code is g.func_code
-
- co = stackless.coroutine()
-
-
-
-class AppTestDirect:
- def setup_class(cls):
- if not option.runappdirect:
- skip('pure appdirect test (run with -A)')
- cls.space = gettestobjspace(usemodules=('_stackless',))
-
- def test_stack_depth_limit(self):
- import sys
- import _stackless as stackless
- st = stackless.get_stack_depth_limit()
- try:
- stackless.set_stack_depth_limit(1)
- assert stackless.get_stack_depth_limit() == 1
- try:
- co = stackless.coroutine()
- def f():
- pass
- co.bind(f)
- co.switch()
- except RuntimeError:
- pass
- finally:
- stackless.set_stack_depth_limit(st)
-
-class TestRandomThings:
- def setup_class(cls):
- cls.space = gettestobjspace(usemodules=('_stackless',))
-
- def test___del___handling(self):
- space = self.space
- w_l = space.newlist([])
- coro = space.appexec([w_l], """(l):
- from _stackless import coroutine
- class MyCoroutine(coroutine):
- def __del__(self):
- l.append(self.is_zombie)
- return MyCoroutine()
- """)
- coro.__del__()
- space.user_del_action.perform(space.getexecutioncontext(), None)
- coro._kill_finally()
- assert space.len_w(w_l) == 1
- res = space.is_true(space.getitem(w_l, space.wrap(0)))
- assert res
diff --git a/pypy/module/_stackless/test/test_greenlet.py b/pypy/module/_stackless/test/test_greenlet.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_greenlet.py
+++ /dev/null
@@ -1,643 +0,0 @@
-from pypy.conftest import gettestobjspace, skip_on_missing_buildoption
-
-class AppTest_Greenlet:
-
- def setup_class(cls):
- space = gettestobjspace(usemodules=('_stackless',))
- cls.space = space
-
- def test_very_simple(self):
- from _stackless import greenlet
- lst = []
- def f(x):
- lst.append(x)
- return x + 10
- g = greenlet(f)
- assert not g
- res = g.switch(20)
- assert res == 30
- assert lst == [20]
- assert g.dead
- assert not g
-
- def test_switch_back_to_main(self):
- from _stackless import greenlet
- lst = []
- main = greenlet.getcurrent()
- def f(x):
- lst.append(x)
- x = main.switch(x + 10)
- return 40 + x
- g = greenlet(f)
- res = g.switch(20)
- assert res == 30
- assert lst == [20]
- assert not g.dead
- res = g.switch(2)
- assert res == 42
- assert g.dead
-
- def test_simple(self):
- from _stackless import greenlet
- lst = []
- gs = []
- def f():
- lst.append(1)
- greenlet.getcurrent().parent.switch()
- lst.append(3)
- g = greenlet(f)
- lst.append(0)
- g.switch()
- lst.append(2)
- g.switch()
- lst.append(4)
- assert lst == range(5)
-
- def test_exception_simple(self):
- from _stackless import greenlet
- def f():
- raise ValueError
- g1 = greenlet(f)
- raises(ValueError, g1.switch)
-
- def test_exception_propagate(self):
- from _stackless import greenlet
- def f():
- raise ValueError
- def g():
- return g1.switch()
- g1 = greenlet(f)
- g2 = greenlet(g)
- raises(ValueError, g1.switch)
- g1 = greenlet(f)
- raises(ValueError, g2.switch)
-
-
- def test_exc_info_save_restore(self):
- from _stackless import greenlet
- import sys
- def f():
- try:
- raise ValueError('fun')
- except:
- exc_info = sys.exc_info()
- greenlet(h).switch()
- assert exc_info == sys.exc_info()
-
- def h():
- assert sys.exc_info() == (None, None, None)
-
- greenlet(f).switch()
-
- def test_exception(self):
- from _stackless import greenlet
- import sys
- def fmain(seen):
- try:
- greenlet.getcurrent().parent.switch()
- except:
- seen.append(sys.exc_info()[0])
- raise
- raise ValueError
- seen = []
- g1 = greenlet(fmain)
- g2 = greenlet(fmain)
- g1.switch(seen)
- g2.switch(seen)
- raises(TypeError, "g2.parent = 1")
- g2.parent = g1
- assert seen == []
- raises(ValueError, g2.switch)
- assert seen == [ValueError]
- g2.switch()
- assert seen == [ValueError]
-
- def test_send_exception(self):
- from _stackless import greenlet
- import sys
- def send_exception(g, exc):
- # note: send_exception(g, exc) can be now done with g.throw(exc).
- # the purpose of this test is to explicitely check the propagation rules.
- def crasher(exc):
- raise exc
- g1 = greenlet(crasher)
- g1.parent = g
- g1.switch(exc)
- def fmain(seen):
- try:
- greenlet.getcurrent().parent.switch()
- except:
- seen.append(sys.exc_info()[0])
- raise
- raise ValueError
-
- seen = []
- g1 = greenlet(fmain)
- g1.switch(seen)
- raises(KeyError, "send_exception(g1, KeyError)")
- assert seen == [KeyError]
- seen = []
- g1 = greenlet(fmain)
- g1.switch(seen)
- raises(KeyError, "g1.throw(KeyError)")
- assert seen == [KeyError]
- assert g1.dead
-
- def test_frame(self):
- from _stackless import greenlet
- import sys
- def f1():
- f = sys._getframe(0)
- assert f.f_back is None
- greenlet.getcurrent().parent.switch(f)
- return "meaning of life"
- g = greenlet(f1)
- frame = g.switch()
- assert frame is g.gr_frame
- assert g
- next = g.switch()
- assert not g
- assert next == "meaning of life"
- assert g.gr_frame is None
-
- def test_mixing_greenlet_coroutine(self):
- from _stackless import greenlet, coroutine
- lst = []
- def f():
- lst.append(1)
- greenlet.getcurrent().parent.switch()
- lst.append(3)
- def make_h(c):
- def h():
- g = greenlet(f)
- lst.append(0)
- g.switch()
- c.switch()
- lst.append(2)
- g.switch()
- c.switch()
- lst.append(4)
- c.switch()
- return h
- c1 = coroutine.getcurrent()
- c2 = coroutine()
- c3 = coroutine()
- c2.bind(make_h(c3))
- c3.bind(make_h(c2))
- c2.switch()
- assert lst == [0, 1, 0, 1, 2, 3, 2, 3, 4, 4]
-
- def test_dealloc(self):
- skip("not working yet")
- from _stackless import greenlet
- import sys
- def fmain(seen):
- try:
- greenlet.getcurrent().parent.switch()
- except:
- seen.append(sys.exc_info()[0])
- raise
- raise ValueError
- seen = []
- seen = []
- g1 = greenlet(fmain)
- g2 = greenlet(fmain)
- g1.switch(seen)
- g2.switch(seen)
- assert seen == []
- del g1
- assert seen == [greenlet.GreenletExit]
- del g2
- assert seen == [greenlet.GreenletExit, greenlet.GreenletExit]
-
-
-# ____________________________________________________________
-#
-# The tests from greenlets.
-# For now, without the ones that involve threads
-#
-class AppTest_PyMagicTestGreenlet:
-
- def setup_class(cls):
- space = gettestobjspace(usemodules=('_stackless',))
- cls.space = space
- cls.w_glob = space.appexec([], """():
- import sys
- from _stackless import greenlet
-
- class SomeError(Exception):
- pass
-
- def fmain(seen):
- try:
- greenlet.getcurrent().parent.switch()
- except:
- seen.append(sys.exc_info()[0])
- raise
- raise SomeError
-
- class Glob: pass
- glob = Glob()
- glob.__dict__.update(locals())
- return glob
- """)
-
- def test_simple(self):
- greenlet = self.glob.greenlet
- lst = []
- def f():
- lst.append(1)
- greenlet.getcurrent().parent.switch()
- lst.append(3)
- g = greenlet(f)
- lst.append(0)
- g.switch()
- lst.append(2)
- g.switch()
- lst.append(4)
- assert lst == range(5)
-
- def test_exception(self):
- greenlet = self.glob.greenlet
- fmain = self.glob.fmain
- SomeError = self.glob.SomeError
- seen = []
- g1 = greenlet(fmain)
- g2 = greenlet(fmain)
- g1.switch(seen)
- g2.switch(seen)
- g2.parent = g1
- assert seen == []
- raises(SomeError, g2.switch)
- assert seen == [SomeError]
- g2.switch()
- assert seen == [SomeError]
-
- def test_send_exception(self):
- greenlet = self.glob.greenlet
- fmain = self.glob.fmain
- def send_exception(g, exc):
- # note: send_exception(g, exc) can be now done with g.throw(exc).
- # the purpose of this test is to explicitely check the
- # propagation rules.
- def crasher(exc):
- raise exc
- g1 = greenlet(crasher, parent=g)
- g1.switch(exc)
-
- seen = []
- g1 = greenlet(fmain)
- g1.switch(seen)
- raises(KeyError, "send_exception(g1, KeyError)")
- assert seen == [KeyError]
-
- def test_dealloc(self):
- skip("XXX in-progress: GC handling of greenlets")
- import gc
- greenlet = self.glob.greenlet
- fmain = self.glob.fmain
- seen = []
- g1 = greenlet(fmain)
- g2 = greenlet(fmain)
- g1.switch(seen)
- g2.switch(seen)
- assert seen == []
- del g1
- gc.collect()
- assert seen == [greenlet.GreenletExit]
- del g2
- gc.collect()
- assert seen == [greenlet.GreenletExit, greenlet.GreenletExit]
-
- def test_frame(self):
- import sys
- greenlet = self.glob.greenlet
- def f1():
- f = sys._getframe(0)
- assert f.f_back is None
- greenlet.getcurrent().parent.switch(f)
- return "meaning of life"
- g = greenlet(f1)
- frame = g.switch()
- assert frame is g.gr_frame
- assert g
- next = g.switch()
- assert not g
- assert next == "meaning of life"
- assert g.gr_frame is None
-
-
-class AppTest_PyMagicTestThrow:
-
- def setup_class(cls):
- space = gettestobjspace(usemodules=('_stackless',))
- cls.space = space
-
- def test_class(self):
- from _stackless import greenlet
- def switch(*args):
- return greenlet.getcurrent().parent.switch(*args)
-
- def f():
- try:
- switch("ok")
- except RuntimeError:
- switch("ok")
- return
- switch("fail")
-
- g = greenlet(f)
- res = g.switch()
- assert res == "ok"
- res = g.throw(RuntimeError)
- assert res == "ok"
-
- def test_val(self):
- from _stackless import greenlet
- def switch(*args):
- return greenlet.getcurrent().parent.switch(*args)
-
- def f():
- try:
- switch("ok")
- except RuntimeError, val:
- if str(val) == "ciao":
- switch("ok")
- return
- switch("fail")
-
- g = greenlet(f)
- res = g.switch()
- assert res == "ok"
- res = g.throw(RuntimeError("ciao"))
- assert res == "ok"
-
- g = greenlet(f)
- res = g.switch()
- assert res == "ok"
- res = g.throw(RuntimeError, "ciao")
- assert res == "ok"
-
- def test_kill(self):
- from _stackless import greenlet
- def switch(*args):
- return greenlet.getcurrent().parent.switch(*args)
-
- def f():
- switch("ok")
- switch("fail")
-
- g = greenlet(f)
- res = g.switch()
- assert res == "ok"
- res = g.throw()
- assert isinstance(res, greenlet.GreenletExit)
- assert g.dead
- res = g.throw() # immediately eaten by the already-dead greenlet
- assert isinstance(res, greenlet.GreenletExit)
-
- def test_throw_goes_to_original_parent(self):
- from _stackless import greenlet
- main = greenlet.getcurrent()
- def f1():
- try:
- main.switch("f1 ready to catch")
- except IndexError:
- return "caught"
- else:
- return "normal exit"
- def f2():
- main.switch("from f2")
-
- g1 = greenlet(f1)
- g2 = greenlet(f2, parent=g1)
- raises(IndexError, g2.throw, IndexError)
- assert g2.dead
- assert g1.dead
-
- g1 = greenlet(f1)
- g2 = greenlet(f2, parent=g1)
- res = g1.switch()
- assert res == "f1 ready to catch"
- res = g2.throw(IndexError)
- assert res == "caught"
- assert g2.dead
- assert g1.dead
-
- g1 = greenlet(f1)
- g2 = greenlet(f2, parent=g1)
- res = g1.switch()
- assert res == "f1 ready to catch"
- res = g2.switch()
- assert res == "from f2"
- res = g2.throw(IndexError)
- assert res == "caught"
- assert g2.dead
- assert g1.dead
-
-
-class AppTest_PyMagicTestGenerator:
-
- def setup_class(cls):
- space = gettestobjspace(usemodules=('_stackless',))
- cls.space = space
-
- def test_generator(self):
- from _stackless import greenlet
-
- class genlet(greenlet):
-
- def __init__(self, *args, **kwds):
- self.args = args
- self.kwds = kwds
-
- def run(self):
- fn, = self.fn
- fn(*self.args, **self.kwds)
-
- def __iter__(self):
- return self
-
- def next(self):
- self.parent = greenlet.getcurrent()
- result = self.switch()
- if self:
- return result
- else:
- raise StopIteration
-
- def Yield(value):
- g = greenlet.getcurrent()
- while not isinstance(g, genlet):
- if g is None:
- raise RuntimeError, 'yield outside a genlet'
- g = g.parent
- g.parent.switch(value)
-
- def generator(func):
- class generator(genlet):
- fn = (func,)
- return generator
-
- # ___ test starts here ___
- seen = []
- def g(n):
- for i in range(n):
- seen.append(i)
- Yield(i)
- g = generator(g)
- for k in range(3):
- for j in g(5):
- seen.append(j)
- assert seen == 3 * [0, 0, 1, 1, 2, 2, 3, 3, 4, 4]
-
-
-class AppTest_PyMagicTestGeneratorNested:
-
- def setup_class(cls):
- space = gettestobjspace(usemodules=('_stackless',))
- cls.space = space
- cls.w_glob = space.appexec([], """():
- from _stackless import greenlet
-
- class genlet(greenlet):
-
- def __init__(self, *args, **kwds):
- self.args = args
- self.kwds = kwds
- self.child = None
-
- def run(self):
- fn, = self.fn
- fn(*self.args, **self.kwds)
-
- def __iter__(self):
- return self
-
- def set_child(self, child):
- self.child = child
-
- def next(self):
- if self.child:
- child = self.child
- while child.child:
- tmp = child
- child = child.child
- tmp.child = None
-
- result = child.switch()
- else:
- self.parent = greenlet.getcurrent()
- result = self.switch()
-
- if self:
- return result
- else:
- raise StopIteration
-
- def Yield(value, level = 1):
- g = greenlet.getcurrent()
-
- while level != 0:
- if not isinstance(g, genlet):
- raise RuntimeError, 'yield outside a genlet'
- if level > 1:
- g.parent.set_child(g)
- g = g.parent
- level -= 1
-
- g.switch(value)
-
- def Genlet(func):
- class Genlet(genlet):
- fn = (func,)
- return Genlet
-
- class Glob: pass
- glob = Glob()
- glob.__dict__.update(locals())
- return glob
- """)
-
- def test_genlet_1(self):
- Genlet = self.glob.Genlet
- Yield = self.glob.Yield
-
- def g1(n, seen):
- for i in range(n):
- seen.append(i+1)
- yield i
-
- def g2(n, seen):
- for i in range(n):
- seen.append(i+1)
- Yield(i)
-
- g2 = Genlet(g2)
-
- def nested(i):
- Yield(i)
-
- def g3(n, seen):
- for i in range(n):
- seen.append(i+1)
- nested(i)
- g3 = Genlet(g3)
-
- raises(RuntimeError, Yield, 10)
- for g in [g1, g2, g3]:
- seen = []
- for k in range(3):
- for j in g(5, seen):
- seen.append(j)
- assert seen == 3 * [1, 0, 2, 1, 3, 2, 4, 3, 5, 4]
- raises(RuntimeError, Yield, 10)
-
- def test_nested_genlets(self):
- Genlet = self.glob.Genlet
- Yield = self.glob.Yield
- def a(n):
- if n == 0:
- return
- for ii in ax(n-1):
- Yield(ii)
- Yield(n)
- ax = Genlet(a)
- seen = []
- for ii in ax(5):
- seen.append(ii)
- assert seen == [1, 2, 3, 4, 5]
-
- def test_perms(self):
- Genlet = self.glob.Genlet
- Yield = self.glob.Yield
- def perms(l):
- if len(l) > 1:
- for e in l:
- # No syntactical sugar for generator expressions
- [Yield([e] + p) for p in perms([x for x in l if x!=e])]
- else:
- Yield(l)
- perms = Genlet(perms)
- gen_perms = perms(range(4))
- permutations = list(gen_perms)
- assert len(permutations) == 4*3*2*1
- assert [0,1,2,3] in permutations
- assert [3,2,1,0] in permutations
-
- def test_layered_genlets(self):
- Genlet = self.glob.Genlet
- Yield = self.glob.Yield
- def gr1(n):
- for ii in range(1, n):
- Yield(ii)
- Yield(ii * ii, 2)
- gr1 = Genlet(gr1)
- def gr2(n, seen):
- for ii in gr1(n):
- seen.append(ii)
- gr2 = Genlet(gr2)
- seen = []
- for ii in gr2(5, seen):
- seen.append(ii)
- assert seen == [1, 1, 2, 4, 3, 9, 4, 16]
diff --git a/pypy/module/_stackless/test/test_interp_clonable.py b/pypy/module/_stackless/test/test_interp_clonable.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_interp_clonable.py
+++ /dev/null
@@ -1,118 +0,0 @@
-"""
-testing cloning
-"""
-import py; py.test.skip("clonable coroutines not really maintained any more")
-
-from pypy import conftest; conftest.translation_test_so_skip_if_appdirect()
-from pypy.translator.c import gc
-from pypy.rpython.memory.gctransform import stacklessframework
-from pypy.rpython.memory.test import test_transformed_gc
-from pypy.module._stackless.rclonable import InterpClonableCoroutine as ClonableCoroutine
-from pypy.module._stackless.rclonable import AbstractThunk, fork
-
-class TestClonableCoroutine(test_transformed_gc.GCTest):
-
- gcname = "marksweep"
- stacklessgc = True
- class gcpolicy(gc.StacklessFrameworkGcPolicy):
- class transformerclass(stacklessframework.StacklessFrameworkGCTransformer):
- GC_PARAMS = {'start_heap_size': 4096 }
-
- def test_clone(self):
- class T(AbstractThunk):
- def __init__(self, result):
- self.result = result
- def call(self):
- self.result.append(2)
- ClonableCoroutine.getmain().switch()
- self.result.append(4)
- def f():
- result = []
- coro = ClonableCoroutine()
- coro.bind(T(result))
- result.append(1)
- coro.switch()
- coro2 = coro.clone()
- result.append(3)
- coro2.switch()
- result.append(5)
- coro.switch()
- result.append(6)
- n = 0
- for i in result:
- n = n*10 + i
- return n
-
- run = self.runner(f)
- res = run([])
- assert res == 1234546
-
- def test_clone_local_state(self):
- class T(AbstractThunk):
- def __init__(self, result):
- self.result = result
- def call(self):
- localstate = []
- localstate.append(10)
- self.result.append(2)
- ClonableCoroutine.getmain().switch()
- localstate.append(20)
- if localstate == [10, 20]:
- self.result.append(4)
- else:
- self.result.append(0)
- def f():
- result = []
- coro = ClonableCoroutine()
- coro.bind(T(result))
- result.append(1)
- coro.switch()
- coro2 = coro.clone()
- result.append(3)
- coro2.switch()
- result.append(5)
- coro.switch()
- result.append(6)
- n = 0
- for i in result:
- n = n*10 + i
- return n
-
- run = self.runner(f)
- res = run([])
- assert res == 1234546
-
- def test_fork(self):
- class T(AbstractThunk):
- def __init__(self, result):
- self.result = result
- def call(self):
- localdata = [10]
- self.result.append(2)
- newcoro = fork()
- localdata.append(20)
- if newcoro is not None:
- # in the parent
- self.result.append(3)
- newcoro.switch()
- self.result.append(5)
- else:
- # in the child
- self.result.append(4)
- localdata.append(30)
- self.result.append(localdata != [10, 20, 30])
- def f():
- result = []
- coro = ClonableCoroutine()
- coro.bind(T(result))
- result.append(1)
- coro.switch()
- result.append(6)
- n = 0
- for i in result:
- n = n*10 + i
- return n
-
- run = self.runner(f)
- res = run([])
- assert res == 12340506
diff --git a/pypy/module/_stackless/test/test_pickle.py b/pypy/module/_stackless/test/test_pickle.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_pickle.py
+++ /dev/null
@@ -1,487 +0,0 @@
-from pypy.conftest import gettestobjspace, option
-import py
-
-# app-level testing of coroutine pickling
-
-
-class AppTestBasic:
- def setup_class(cls):
- cls.space = gettestobjspace(usemodules=('_stackless',))
-
- def test_pickle_main(self):
- import _stackless, pickle
- main = _stackless.coroutine.getcurrent()
- s = pickle.dumps(main)
- c = pickle.loads(s)
- assert c is main
-
-
-class AppTestPickle:
-
- def setup_class(cls):
- cls.space = gettestobjspace(usemodules=('_stackless',), CALL_METHOD=True)
-
- def test_pickle_coroutine_empty(self):
- # this test is limited to basic pickling.
- # real stacks can only tested with a stackless pypy build.
- import _stackless as stackless
- co = stackless.coroutine()
- import pickle
- pckl = pickle.dumps(co)
- co2 = pickle.loads(pckl)
- # the empty unpickled coroutine can still be used:
- result = []
- co2.bind(result.append, 42)
- co2.switch()
- assert result == [42]
-
- def test_pickle_coroutine_bound(self):
- import pickle
- import _stackless
- lst = [4]
- co = _stackless.coroutine()
- co.bind(lst.append, 2)
- pckl = pickle.dumps((co, lst))
-
- (co2, lst2) = pickle.loads(pckl)
- assert lst2 == [4]
- co2.switch()
- assert lst2 == [4, 2]
-
-
- def test_simple_ish(self):
-
- import new, sys
-
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-output = []
-import _stackless
-def f(coro, n, x):
- if n == 0:
- coro.switch()
- return
- f(coro, n-1, 2*x)
- output.append(x)
-
-def example():
- main_coro = _stackless.coroutine.getcurrent()
- sub_coro = _stackless.coroutine()
- sub_coro.bind(f, main_coro, 5, 1)
- sub_coro.switch()
-
- import pickle
- pckl = pickle.dumps(sub_coro)
- new_coro = pickle.loads(pckl)
-
- new_coro.switch()
-
-example()
-assert output == [16, 8, 4, 2, 1]
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
-
- def test_pickle_again(self):
-
- import new, sys
-
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-output = []
-import _stackless
-def f(coro, n, x):
- if n == 0:
- coro.switch()
- return
- f(coro, n-1, 2*x)
- output.append(x)
-
-def example():
- main_coro = _stackless.coroutine.getcurrent()
- sub_coro = _stackless.coroutine()
- sub_coro.bind(f, main_coro, 5, 1)
- sub_coro.switch()
-
- import pickle
- pckl = pickle.dumps(sub_coro)
- new_coro = pickle.loads(pckl)
- pckl = pickle.dumps(new_coro)
- newer_coro = pickle.loads(pckl)
-
- newer_coro.switch()
-
-example()
-assert output == [16, 8, 4, 2, 1]
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
-
- def test_kwargs(self):
-
- import new, sys
-
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-output = []
-import _stackless
-def f(coro, n, x, step=4):
- if n == 0:
- coro.switch()
- return
- f(coro, n-1, 2*x, step=1)
- output.append(x)
-
-def example():
- main_coro = _stackless.coroutine.getcurrent()
- sub_coro = _stackless.coroutine()
- sub_coro.bind(f, main_coro, 5, 1, 1)
- sub_coro.switch()
-
- import pickle
- pckl = pickle.dumps(sub_coro)
- new_coro = pickle.loads(pckl)
-
- new_coro.switch()
-
-example()
-assert output == [16, 8, 4, 2, 1]
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
-
- def test_starstarargs(self):
-
- import new, sys
-
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-output = []
-import _stackless
-def f(coro, n, x, step=4):
- if n == 0:
- coro.switch()
- return
- f(coro, n-1, 2*x, **{'step': 1})
- output.append(x)
-
-def example():
- main_coro = _stackless.coroutine.getcurrent()
- sub_coro = _stackless.coroutine()
- sub_coro.bind(f, main_coro, 5, 1, 1)
- sub_coro.switch()
-
- import pickle
- pckl = pickle.dumps(sub_coro)
- new_coro = pickle.loads(pckl)
-
- new_coro.switch()
-
-example()
-assert output == [16, 8, 4, 2, 1]
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
-
- def test_closure(self):
- import new, sys
-
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-output = []
-import _stackless
-def example():
- main_coro = _stackless.coroutine.getcurrent()
- sub_coro = _stackless.coroutine()
- y = 3
- def f(coro, n, x):
- if n == 0:
- coro.switch()
- return
- f(coro, n-1, 2*x)
- output.append(x+y)
-
- sub_coro.bind(f, main_coro, 5, 1)
- sub_coro.switch()
-
- import pickle
- pckl = pickle.dumps(sub_coro)
- new_coro = pickle.loads(pckl)
-
- new_coro.switch()
-
-example()
-assert output == [19, 11, 7, 5, 4]
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
-
- def test_exception(self):
- import new, sys
-
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-output = []
-import _stackless
-def f(coro):
- try:
- raise ValueError
- except:
- coro.switch()
- import sys
- t, v, tb = sys.exc_info()
- output.append(t)
-
-def example():
- main_coro = _stackless.coroutine.getcurrent()
- sub_coro = _stackless.coroutine()
-
- sub_coro.bind(f, main_coro)
- sub_coro.switch()
-
- import pickle
- pckl = pickle.dumps(sub_coro)
- new_coro = pickle.loads(pckl)
-
- new_coro.switch()
-
-example()
-assert output == [ValueError]
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
-
- def test_exception_after_unpickling(self):
-
- import new, sys
-
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-output = []
-import _stackless
-def f(coro, n, x):
- if n == 0:
- coro.switch()
- raise ValueError
- try:
- f(coro, n-1, 2*x)
- finally:
- output.append(x)
-
-def example():
- main_coro = _stackless.coroutine.getcurrent()
- sub_coro = _stackless.coroutine()
- sub_coro.bind(f, main_coro, 5, 1)
- sub_coro.switch()
-
- import pickle
- pckl = pickle.dumps(sub_coro)
- new_coro = pickle.loads(pckl)
-
- try:
- sub_coro.switch()
- except ValueError:
- pass
- else:
- assert 0
- try:
- new_coro.switch()
- except ValueError:
- pass
- else:
- assert 0
-
-example()
-assert output == [16, 8, 4, 2, 1] * 2
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
-
- def test_loop(self):
- import new, sys
-
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-output = []
-import _stackless
-def f(coro):
- for x in (1,2,3):
- coro.switch()
- output.append(x)
-
-def example():
- main_coro = _stackless.coroutine.getcurrent()
- sub_coro = _stackless.coroutine()
-
- sub_coro.bind(f, main_coro)
- sub_coro.switch()
-
- import pickle
- pckl = pickle.dumps(sub_coro)
- new_coro = pickle.loads(pckl)
-
- new_coro.switch()
- new_coro.switch()
- new_coro.switch()
-
-example()
-assert output == [1, 2, 3]
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
-
- def test_valstack(self):
- import new, sys
-
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-output = []
-import _stackless
-def f(coro):
- r = 1+g(coro)+3
- output.append(r)
-
-def g(coro):
- coro.switch()
- return 2
-
-def example():
- main_coro = _stackless.coroutine.getcurrent()
- sub_coro = _stackless.coroutine()
-
- sub_coro.bind(f, main_coro)
- sub_coro.switch()
-
- import pickle
- pckl = pickle.dumps(sub_coro)
- new_coro = pickle.loads(pckl)
-
- new_coro.switch()
-
-
-example()
-assert output == [6]
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
-
-
- def test_exec_and_locals(self):
- import new, sys
-
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-output = []
-import _stackless
-
-def f(coro):
- x = None
- exec "x = 9"
- coro.switch()
- output.append(x)
-
-def example():
- main_coro = _stackless.coroutine.getcurrent()
- sub_coro = _stackless.coroutine()
- sub_coro.bind(f, main_coro)
- sub_coro.switch()
-
- import pickle
- pckl = pickle.dumps(sub_coro)
- new_coro = pickle.loads(pckl)
-
- new_coro.switch()
-
-example()
-assert output == [9]
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
-
-
- def test_solver(self):
- import new, sys
-
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-import _stackless, pickle
-
-class Fail(Exception):
- pass
-
-class Success(Exception):
- pass
-
-def first_solution(func):
- global next_answer
- co = _stackless.coroutine()
- co.bind(func)
- pending = [(co, None)]
- while pending:
- co, next_answer = pending.pop()
- try:
- co.switch()
- except Fail:
- pass
- except Success, e:
- return e.args[0]
- else:
- # zero_or_one() called, clone the coroutine
- # NB. this seems to be quite slow
- co2 = pickle.loads(pickle.dumps(co))
- pending.append((co2, 1))
- pending.append((co, 0))
- raise Fail("no solution")
-
-pending = []
-main = _stackless.coroutine.getcurrent()
-
-def zero_or_one():
- main.switch()
- return next_answer
-
-# ____________________________________________________________
-
-invalid_prefixes = {
- (0, 0): True,
- (0, 1, 0): True,
- (0, 1, 1): True,
- (1, 0): True,
- (1, 1, 0, 0): True,
- }
-
-def example():
- test = []
- for n in range(5):
- test.append(zero_or_one())
- if tuple(test) in invalid_prefixes:
- raise Fail
- raise Success(test)
-
-res = first_solution(example)
-assert res == [1, 1, 0, 1, 0]
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
diff --git a/pypy/module/marshal/interp_marshal.py b/pypy/module/marshal/interp_marshal.py
--- a/pypy/module/marshal/interp_marshal.py
+++ b/pypy/module/marshal/interp_marshal.py
@@ -40,7 +40,7 @@
reader = FileReader(space, w_f)
try:
u = Unmarshaller(space, reader)
- return u.load_w_obj(False)
+ return u.load_w_obj()
finally:
reader.finished()
@@ -49,7 +49,7 @@
ignored."""
space.timer.start("marshal loads")
u = StringUnmarshaller(space, w_str)
- obj = u.load_w_obj(False)
+ obj = u.load_w_obj()
space.timer.stop("marshal loads")
return obj
@@ -424,7 +424,7 @@
lng = self.get_lng()
return self.get(lng)
- def get_w_obj(self, allow_null):
+ def get_w_obj(self, allow_null=False):
space = self.space
w_ret = space.w_None # something not None
tc = self.get1()
@@ -434,9 +434,9 @@
'NULL object in marshal data'))
return w_ret
- def load_w_obj(self, allow_null):
+ def load_w_obj(self):
try:
- return self.get_w_obj(allow_null)
+ return self.get_w_obj()
except rstackovf.StackOverflow:
rstackovf.check_stack_overflow()
self._overflow()
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -26,13 +26,19 @@
("copysign", "copysign"),
("cos", "cos"),
("divide", "divide"),
+ ("equal", "equal"),
("exp", "exp"),
("fabs", "fabs"),
("floor", "floor"),
+ ("greater", "greater"),
+ ("greater_equal", "greater_equal"),
+ ("less", "less"),
+ ("less_equal", "less_equal"),
("maximum", "maximum"),
("minimum", "minimum"),
("multiply", "multiply"),
("negative", "negative"),
+ ("not_equal", "not_equal"),
("reciprocal", "reciprocal"),
("sign", "sign"),
("sin", "sin"),
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -129,6 +129,16 @@
))
return impl
+def raw_binop(func):
+ # Returns the result unwrapped.
+ @functools.wraps(func)
+ def impl(self, v1, v2):
+ return func(self,
+ self.for_computation(self.unbox(v1)),
+ self.for_computation(self.unbox(v2))
+ )
+ return impl
+
def unaryop(func):
@functools.wraps(func)
def impl(self, v):
@@ -170,8 +180,24 @@
def bool(self, v):
return bool(self.for_computation(self.unbox(v)))
+ @raw_binop
+ def eq(self, v1, v2):
+ return v1 == v2
+ @raw_binop
def ne(self, v1, v2):
- return self.for_computation(self.unbox(v1)) != self.for_computation(self.unbox(v2))
+ return v1 != v2
+ @raw_binop
+ def lt(self, v1, v2):
+ return v1 < v2
+ @raw_binop
+ def le(self, v1, v2):
+ return v1 <= v2
+ @raw_binop
+ def gt(self, v1, v2):
+ return v1 > v2
+ @raw_binop
+ def ge(self, v1, v2):
+ return v1 >= v2
class FloatArithmeticDtype(ArithmaticTypeMixin):
@@ -224,7 +250,7 @@
return math.tan(v)
@unaryop
def arcsin(self, v):
- if v < -1.0 or v > 1.0:
+ if v < -1.0 or v > 1.0:
return rfloat.NAN
return math.asin(v)
@unaryop
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -74,6 +74,13 @@
descr_pow = _binop_impl("power")
descr_mod = _binop_impl("mod")
+ descr_eq = _binop_impl("equal")
+ descr_ne = _binop_impl("not_equal")
+ descr_lt = _binop_impl("less")
+ descr_le = _binop_impl("less_equal")
+ descr_gt = _binop_impl("greater")
+ descr_ge = _binop_impl("greater_equal")
+
def _binop_right_impl(ufunc_name):
def impl(self, space, w_other):
w_other = scalar_w(space,
@@ -404,10 +411,11 @@
"""
Intermediate class for performing binary operations.
"""
- def __init__(self, signature, res_dtype, left, right):
+ def __init__(self, signature, calc_dtype, res_dtype, left, right):
VirtualArray.__init__(self, signature, res_dtype)
self.left = left
self.right = right
+ self.calc_dtype = calc_dtype
def _del_sources(self):
self.left = None
@@ -421,14 +429,14 @@
return self.right.find_size()
def _eval(self, i):
- lhs = self.left.eval(i).convert_to(self.res_dtype)
- rhs = self.right.eval(i).convert_to(self.res_dtype)
+ lhs = self.left.eval(i).convert_to(self.calc_dtype)
+ rhs = self.right.eval(i).convert_to(self.calc_dtype)
sig = jit.promote(self.signature)
assert isinstance(sig, signature.Signature)
call_sig = sig.components[0]
assert isinstance(call_sig, signature.Call2)
- return call_sig.func(self.res_dtype, lhs, rhs)
+ return call_sig.func(self.calc_dtype, lhs, rhs)
class ViewArray(BaseArray):
"""
@@ -573,18 +581,28 @@
__pos__ = interp2app(BaseArray.descr_pos),
__neg__ = interp2app(BaseArray.descr_neg),
__abs__ = interp2app(BaseArray.descr_abs),
+
__add__ = interp2app(BaseArray.descr_add),
__sub__ = interp2app(BaseArray.descr_sub),
__mul__ = interp2app(BaseArray.descr_mul),
__div__ = interp2app(BaseArray.descr_div),
__pow__ = interp2app(BaseArray.descr_pow),
__mod__ = interp2app(BaseArray.descr_mod),
+
__radd__ = interp2app(BaseArray.descr_radd),
__rsub__ = interp2app(BaseArray.descr_rsub),
__rmul__ = interp2app(BaseArray.descr_rmul),
__rdiv__ = interp2app(BaseArray.descr_rdiv),
__rpow__ = interp2app(BaseArray.descr_rpow),
__rmod__ = interp2app(BaseArray.descr_rmod),
+
+ __eq__ = interp2app(BaseArray.descr_eq),
+ __ne__ = interp2app(BaseArray.descr_ne),
+ __lt__ = interp2app(BaseArray.descr_lt),
+ __le__ = interp2app(BaseArray.descr_le),
+ __gt__ = interp2app(BaseArray.descr_gt),
+ __ge__ = interp2app(BaseArray.descr_ge),
+
__repr__ = interp2app(BaseArray.descr_repr),
__str__ = interp2app(BaseArray.descr_str),
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -113,10 +113,11 @@
argcount = 2
def __init__(self, func, name, promote_to_float=False, promote_bools=False,
- identity=None):
+ identity=None, comparison_func=False):
W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity)
self.func = func
+ self.comparison_func = comparison_func
self.signature = signature.Call2(func)
self.reduce_signature = signature.BaseSignature()
@@ -127,18 +128,25 @@
[w_lhs, w_rhs] = args_w
w_lhs = convert_to_array(space, w_lhs)
w_rhs = convert_to_array(space, w_rhs)
- res_dtype = find_binop_result_dtype(space,
+ calc_dtype = find_binop_result_dtype(space,
w_lhs.find_dtype(), w_rhs.find_dtype(),
promote_to_float=self.promote_to_float,
promote_bools=self.promote_bools,
)
+ if self.comparison_func:
+ res_dtype = space.fromcache(interp_dtype.W_BoolDtype)
+ else:
+ res_dtype = calc_dtype
if isinstance(w_lhs, Scalar) and isinstance(w_rhs, Scalar):
- return self.func(res_dtype, w_lhs.value, w_rhs.value).wrap(space)
+ return self.func(calc_dtype,
+ w_lhs.value.convert_to(calc_dtype),
+ w_rhs.value.convert_to(calc_dtype)
+ ).wrap(space)
new_sig = signature.Signature.find_sig([
self.signature, w_lhs.signature, w_rhs.signature
])
- w_res = Call2(new_sig, res_dtype, w_lhs, w_rhs)
+ w_res = Call2(new_sig, calc_dtype, res_dtype, w_lhs, w_rhs)
w_lhs.add_invalidates(w_res)
w_rhs.add_invalidates(w_res)
return w_res
@@ -209,13 +217,16 @@
return space.fromcache(interp_dtype.W_Float64Dtype)
-def ufunc_dtype_caller(ufunc_name, op_name, argcount):
+def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func):
if argcount == 1:
def impl(res_dtype, value):
return getattr(res_dtype, op_name)(value)
elif argcount == 2:
def impl(res_dtype, lvalue, rvalue):
- return getattr(res_dtype, op_name)(lvalue, rvalue)
+ res = getattr(res_dtype, op_name)(lvalue, rvalue)
+ if comparison_func:
+ res = space.fromcache(interp_dtype.W_BoolDtype).box(res)
+ return res
return func_with_new_name(impl, ufunc_name)
class UfuncState(object):
@@ -229,6 +240,13 @@
("mod", "mod", 2, {"promote_bools": True}),
("power", "pow", 2, {"promote_bools": True}),
+ ("equal", "eq", 2, {"comparison_func": True}),
+ ("not_equal", "ne", 2, {"comparison_func": True}),
+ ("less", "lt", 2, {"comparison_func": True}),
+ ("less_equal", "le", 2, {"comparison_func": True}),
+ ("greater", "gt", 2, {"comparison_func": True}),
+ ("greater_equal", "ge", 2, {"comparison_func": True}),
+
("maximum", "max", 2),
("minimum", "min", 2),
@@ -262,7 +280,9 @@
identity = space.fromcache(interp_dtype.W_Int64Dtype).adapt_val(identity)
extra_kwargs["identity"] = identity
- func = ufunc_dtype_caller(ufunc_name, op_name, argcount)
+ func = ufunc_dtype_caller(space, ufunc_name, op_name, argcount,
+ comparison_func=extra_kwargs.get("comparison_func", False)
+ )
if argcount == 1:
ufunc = W_Ufunc1(func, ufunc_name, **extra_kwargs)
elif argcount == 2:
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -557,6 +557,26 @@
assert array([1.2, 5]).dtype is dtype(float)
assert array([]).dtype is dtype(float)
+ def test_comparison(self):
+ import operator
+ from numpy import array, dtype
+
+ a = array(range(5))
+ b = array(range(5), float)
+ for func in [
+ operator.eq, operator.ne, operator.lt, operator.le, operator.gt,
+ operator.ge
+ ]:
+ c = func(a, 3)
+ assert c.dtype is dtype(bool)
+ for i in xrange(5):
+ assert c[i] == func(a[i], 3)
+
+ c = func(b, 3)
+ assert c.dtype is dtype(bool)
+ for i in xrange(5):
+ assert c[i] == func(b[i], 3)
+
class AppTestSupport(object):
def setup_class(cls):
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -310,4 +310,30 @@
assert add.reduce([1, 2, 3]) == 6
assert maximum.reduce([1]) == 1
assert maximum.reduce([1, 2, 3]) == 3
- raises(ValueError, maximum.reduce, [])
\ No newline at end of file
+ raises(ValueError, maximum.reduce, [])
+
+ def test_comparisons(self):
+ import operator
+ from numpy import equal, not_equal, less, less_equal, greater, greater_equal
+
+ for ufunc, func in [
+ (equal, operator.eq),
+ (not_equal, operator.ne),
+ (less, operator.lt),
+ (less_equal, operator.le),
+ (greater, operator.gt),
+ (greater_equal, operator.ge),
+ ]:
+ for a, b in [
+ (3, 3),
+ (3, 4),
+ (4, 3),
+ (3.0, 3.0),
+ (3.0, 3.5),
+ (3.5, 3.0),
+ (3.0, 3),
+ (3, 3.0),
+ (3.5, 3),
+ (3, 3.5),
+ ]:
+ assert ufunc(a, b) is func(a, b)
diff --git a/pypy/module/pwd/__init__.py b/pypy/module/pwd/__init__.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pwd/__init__.py
@@ -0,0 +1,25 @@
+from pypy.interpreter.mixedmodule import MixedModule
+
+class Module(MixedModule):
+ """
+ This module provides access to the Unix password database.
+ It is available on all Unix versions.
+
+ Password database entries are reported as 7-tuples containing the following
+ items from the password database (see `<pwd.h>'), in order:
+ pw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir, pw_shell.
+ The uid and gid items are integers, all others are strings. An
+ exception is raised if the entry asked for cannot be found.
+ """
+
+ interpleveldefs = {
+ 'getpwuid': 'interp_pwd.getpwuid',
+ 'getpwnam': 'interp_pwd.getpwnam',
+ 'getpwall': 'interp_pwd.getpwall',
+ }
+
+ appleveldefs = {
+ 'struct_passwd': 'app_pwd.struct_passwd',
+ 'struct_pwent': 'app_pwd.struct_passwd',
+ }
+
diff --git a/pypy/module/pwd/app_pwd.py b/pypy/module/pwd/app_pwd.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pwd/app_pwd.py
@@ -0,0 +1,20 @@
+from _structseq import structseqtype, structseqfield
+
+class struct_passwd:
+ """
+ pwd.struct_passwd: Results from getpw*() routines.
+
+ This object may be accessed either as a tuple of
+ (pw_name,pw_passwd,pw_uid,pw_gid,pw_gecos,pw_dir,pw_shell)
+ or via the object attributes as named in the above tuple.
+ """
+ __metaclass__ = structseqtype
+ name = "pwd.struct_passwd"
+
+ pw_name = structseqfield(0, "user name")
+ pw_passwd = structseqfield(1, "password")
+ pw_uid = structseqfield(2, "user id")
+ pw_gid = structseqfield(3, "group id")
+ pw_gecos = structseqfield(4, "real name")
+ pw_dir = structseqfield(5, "home directory")
+ pw_shell = structseqfield(6, "shell program")
diff --git a/pypy/module/pwd/interp_pwd.py b/pypy/module/pwd/interp_pwd.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pwd/interp_pwd.py
@@ -0,0 +1,95 @@
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.rpython.tool import rffi_platform
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.rlib.rarithmetic import intmask
+
+eci = ExternalCompilationInfo(
+ includes=['pwd.h']
+ )
+
+class CConfig:
+ _compilation_info_ = eci
+
+ uid_t = rffi_platform.SimpleType("uid_t")
+
+ passwd = rffi_platform.Struct(
+ 'struct passwd',
+ [('pw_name', rffi.CCHARP),
+ ('pw_passwd', rffi.CCHARP),
+ ('pw_uid', rffi.INT),
+ ('pw_gid', rffi.INT),
+ ('pw_gecos', rffi.CCHARP),
+ ('pw_dir', rffi.CCHARP),
+ ('pw_shell', rffi.CCHARP),
+ ])
+
+config = rffi_platform.configure(CConfig)
+passwd_p = lltype.Ptr(config['passwd'])
+uid_t = config['uid_t']
+
+def external(name, args, result, **kwargs):
+ return rffi.llexternal(name, args, result, compilation_info=eci, **kwargs)
+
+c_getpwuid = external("getpwuid", [uid_t], passwd_p)
+c_getpwnam = external("getpwnam", [rffi.CCHARP], passwd_p)
+c_setpwent = external("setpwent", [], lltype.Void)
+c_getpwent = external("getpwent", [], passwd_p)
+c_endpwent = external("endpwent", [], lltype.Void)
+
+def make_struct_passwd(space, pw):
+ w_passwd_struct = space.getattr(space.getbuiltinmodule('pwd'),
+ space.wrap('struct_passwd'))
+ w_tuple = space.newtuple([
+ space.wrap(rffi.charp2str(pw.c_pw_name)),
+ space.wrap(rffi.charp2str(pw.c_pw_passwd)),
+ space.wrap(intmask(pw.c_pw_uid)),
+ space.wrap(intmask(pw.c_pw_gid)),
+ space.wrap(rffi.charp2str(pw.c_pw_gecos)),
+ space.wrap(rffi.charp2str(pw.c_pw_dir)),
+ space.wrap(rffi.charp2str(pw.c_pw_shell)),
+ ])
+ return space.call_function(w_passwd_struct, w_tuple)
+
+ at unwrap_spec(uid=int)
+def getpwuid(space, uid):
+ """
+ getpwuid(uid) -> (pw_name,pw_passwd,pw_uid,
+ pw_gid,pw_gecos,pw_dir,pw_shell)
+ Return the password database entry for the given numeric user ID.
+ See pwd.__doc__ for more on password database entries.
+ """
+ pw = c_getpwuid(uid)
+ if not pw:
+ raise operationerrfmt(space.w_KeyError,
+ "getpwuid(): uid not found: %d", uid)
+ return make_struct_passwd(space, pw)
+
+ at unwrap_spec(name=str)
+def getpwnam(space, name):
+ """
+ getpwnam(name) -> (pw_name,pw_passwd,pw_uid,
+ pw_gid,pw_gecos,pw_dir,pw_shell)
+ Return the password database entry for the given user name.
+ See pwd.__doc__ for more on password database entries.
+ """
+ pw = c_getpwnam(name)
+ if not pw:
+ raise operationerrfmt(space.w_KeyError,
+ "getpwnam(): name not found: %s", name)
+ return make_struct_passwd(space, pw)
+
+def getpwall(space):
+ users_w = []
+ c_setpwent()
+ try:
+ while True:
+ pw = c_getpwent()
+ if not pw:
+ break
+ users_w.append(make_struct_passwd(space, pw))
+ finally:
+ c_endpwent()
+ return space.newlist(users_w)
+
diff --git a/pypy/module/pwd/test/test_pwd.py b/pypy/module/pwd/test/test_pwd.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pwd/test/test_pwd.py
@@ -0,0 +1,28 @@
+from pypy.conftest import gettestobjspace
+
+class AppTestPwd:
+ def setup_class(cls):
+ cls.space = gettestobjspace(usemodules=['pwd'])
+
+ def test_getpwuid(self):
+ import pwd
+ raises(KeyError, pwd.getpwuid, -1)
+ pw = pwd.getpwuid(0)
+ assert pw.pw_name == 'root'
+ assert isinstance(pw.pw_passwd, str)
+ assert pw.pw_uid == 0
+ assert pw.pw_gid == 0
+ assert pw.pw_dir == '/root'
+ assert pw.pw_shell.startswith('/')
+ #
+ assert type(pw.pw_uid) is int
+ assert type(pw.pw_gid) is int
+
+ def test_getpwnam(self):
+ import pwd
+ raises(KeyError, pwd.getpwnam, '~invalid~')
+ assert pwd.getpwnam('root').pw_name == 'root'
+
+ def test_getpwall(self):
+ import pwd
+ assert pwd.getpwnam('root') in pwd.getpwall()
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -2,7 +2,10 @@
import sys
import re
import os.path
-from _pytest.assertion import newinterpret
+try:
+ from _pytest.assertion import newinterpret
+except ImportError: # e.g. Python 2.5
+ newinterpret = None
from pypy.tool.jitlogparser.parser import SimpleParser, Function, TraceForOpcode
from pypy.tool.jitlogparser.storage import LoopStorage
@@ -196,7 +199,7 @@
source = str(source.deindent()).strip()
except py.error.ENOENT:
source = None
- if source and source.startswith('self._assert('):
+ if source and source.startswith('self._assert(') and newinterpret:
# transform self._assert(x, 'foo') into assert x, 'foo'
source = source.replace('self._assert(', 'assert ')
source = source[:-1] # remove the trailing ')'
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -1,3 +1,4 @@
+from __future__ import with_statement
import sys, os
import types
import subprocess
diff --git a/pypy/module/pypyjit/test_pypy_c/test_instance.py b/pypy/module/pypyjit/test_pypy_c/test_instance.py
--- a/pypy/module/pypyjit/test_pypy_c/test_instance.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_instance.py
@@ -142,6 +142,7 @@
i = 0
b = B(1)
while i < 100:
+ b.x
v = b.x # ID: loadattr
i += v
return i
@@ -150,8 +151,6 @@
loop, = log.loops_by_filename(self.filepath)
assert loop.match_by_id('loadattr',
'''
- guard_not_invalidated(descr=...)
- i16 = arraylen_gc(p10, descr=<GcPtrArrayDescr>)
i19 = call(ConstClass(ll_dict_lookup), _, _, _, descr=...)
guard_no_exception(descr=...)
i21 = int_and(i19, _)
diff --git a/pypy/module/sys/__init__.py b/pypy/module/sys/__init__.py
--- a/pypy/module/sys/__init__.py
+++ b/pypy/module/sys/__init__.py
@@ -47,6 +47,7 @@
'pypy_initial_path' : 'state.pypy_initial_path',
'_getframe' : 'vm._getframe',
+ '_current_frames' : 'vm._current_frames',
'setrecursionlimit' : 'vm.setrecursionlimit',
'getrecursionlimit' : 'vm.getrecursionlimit',
'setcheckinterval' : 'vm.setcheckinterval',
diff --git a/pypy/module/sys/test/test_sysmodule.py b/pypy/module/sys/test/test_sysmodule.py
--- a/pypy/module/sys/test/test_sysmodule.py
+++ b/pypy/module/sys/test/test_sysmodule.py
@@ -1,6 +1,6 @@
# -*- coding: iso-8859-1 -*-
import autopath
-from pypy.conftest import option
+from pypy.conftest import option, gettestobjspace
from py.test import raises
from pypy.interpreter.gateway import app2interp_temp
import sys
@@ -524,3 +524,51 @@
# If this ever actually becomes a compilation option this test should
# be changed.
assert sys.float_repr_style == "short"
+
+class AppTestCurrentFrames:
+
+ def test_current_frames(self):
+ try:
+ import thread
+ except ImportError:
+ pass
+ else:
+ skip('This test requires an intepreter without threads')
+ import sys
+
+ def f():
+ return sys._current_frames()
+ frames = f()
+ assert frames.keys() == [0]
+ assert frames[0].f_code.co_name == 'f'
+
+class AppTestCurrentFramesWithThread(AppTestCurrentFrames):
+ def setup_class(cls):
+ cls.space = gettestobjspace(usemodules=('thread',))
+
+ def test_current_frames(self):
+ import sys
+ import time
+ import thread
+
+ thread_id = thread.get_ident()
+ self.ready = False
+ def other_thread():
+ self.ready = True
+ print "thread started"
+ time.sleep(5)
+ thread.start_new_thread(other_thread, ())
+
+ def f():
+ for i in range(100):
+ if self.ready: break
+ time.sleep(0.1)
+ return sys._current_frames()
+
+ frames = f()
+ thisframe = frames.pop(thread_id)
+ assert thisframe.f_code.co_name == 'f'
+
+ assert len(frames) == 1
+ _, other_frame = frames.popitem()
+ assert other_frame.f_code.co_name == 'other_thread'
diff --git a/pypy/module/sys/vm.py b/pypy/module/sys/vm.py
--- a/pypy/module/sys/vm.py
+++ b/pypy/module/sys/vm.py
@@ -43,6 +43,23 @@
f.mark_as_escaped()
return space.wrap(f)
+def _current_frames(space):
+ """_current_frames() -> dictionary
+
+ Return a dictionary mapping each current thread T's thread id to T's
+ current stack frame.
+
+ This function should be used for specialized purposes only."""
+ w_result = space.newdict()
+ ecs = space.threadlocals.getallvalues()
+ for thread_ident, ec in ecs.items():
+ f = ec.gettopframe_nohidden()
+ f.mark_as_escaped()
+ space.setitem(w_result,
+ space.wrap(thread_ident),
+ space.wrap(f))
+ return w_result
+
def setrecursionlimit(space, w_new_limit):
"""setrecursionlimit() sets the maximum number of nested calls that
can occur before a RuntimeError is raised. On PyPy the limit is
diff --git a/pypy/module/test_lib_pypy/test_distributed/test_distributed.py b/pypy/module/test_lib_pypy/test_distributed/test_distributed.py
--- a/pypy/module/test_lib_pypy/test_distributed/test_distributed.py
+++ b/pypy/module/test_lib_pypy/test_distributed/test_distributed.py
@@ -1,3 +1,4 @@
+import py; py.test.skip("xxx remove")
""" Controllers tests
"""
@@ -8,7 +9,7 @@
class AppTestDistributed(object):
def setup_class(cls):
cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
- "usemodules":("_stackless",)})
+ "usemodules":("_continuation",)})
def test_init(self):
import distributed
@@ -90,14 +91,12 @@
class AppTestDistributedTasklets(object):
spaceconfig = {"objspace.std.withtproxy": True,
- "objspace.usemodules._stackless": True}
+ "objspace.usemodules._continuation": True}
reclimit = sys.getrecursionlimit()
def setup_class(cls):
import py.test
py.test.importorskip('greenlet')
- #cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
- # "usemodules":("_stackless",)})
cls.w_test_env_ = cls.space.appexec([], """():
from distributed import test_env
return (test_env,)
diff --git a/pypy/module/test_lib_pypy/test_distributed/test_greensock.py b/pypy/module/test_lib_pypy/test_distributed/test_greensock.py
--- a/pypy/module/test_lib_pypy/test_distributed/test_greensock.py
+++ b/pypy/module/test_lib_pypy/test_distributed/test_greensock.py
@@ -1,5 +1,4 @@
-
-import py
+import py; py.test.skip("xxx remove")
from pypy.conftest import gettestobjspace, option
def setup_module(mod):
@@ -10,7 +9,7 @@
if not option.runappdirect:
py.test.skip("Cannot run this on top of py.py because of PopenGateway")
cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
- "usemodules":("_stackless",)})
+ "usemodules":("_continuation",)})
cls.w_remote_side_code = cls.space.appexec([], """():
import sys
sys.path.insert(0, '%s')
diff --git a/pypy/module/test_lib_pypy/test_distributed/test_socklayer.py b/pypy/module/test_lib_pypy/test_distributed/test_socklayer.py
--- a/pypy/module/test_lib_pypy/test_distributed/test_socklayer.py
+++ b/pypy/module/test_lib_pypy/test_distributed/test_socklayer.py
@@ -1,4 +1,4 @@
-import py
+import py; py.test.skip("xxx remove")
from pypy.conftest import gettestobjspace
def setup_module(mod):
@@ -9,7 +9,8 @@
class AppTestSocklayer:
def setup_class(cls):
cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
- "usemodules":("_stackless","_socket", "select")})
+ "usemodules":("_continuation",
+ "_socket", "select")})
def test_socklayer(self):
class X(object):
diff --git a/pypy/module/test_lib_pypy/test_stackless_pickle.py b/pypy/module/test_lib_pypy/test_stackless_pickle.py
--- a/pypy/module/test_lib_pypy/test_stackless_pickle.py
+++ b/pypy/module/test_lib_pypy/test_stackless_pickle.py
@@ -1,3 +1,4 @@
+import py; py.test.skip("XXX port me")
from pypy.conftest import gettestobjspace, option
class AppTest_Stackless:
diff --git a/pypy/module/thread/threadlocals.py b/pypy/module/thread/threadlocals.py
--- a/pypy/module/thread/threadlocals.py
+++ b/pypy/module/thread/threadlocals.py
@@ -43,6 +43,9 @@
ident = self._mainthreadident
return self._valuedict.get(ident, None)
+ def getallvalues(self):
+ return self._valuedict
+
def enter_thread(self, space):
"Notification that the current thread is just starting."
ec = space.getexecutioncontext()
diff --git a/pypy/objspace/std/marshal_impl.py b/pypy/objspace/std/marshal_impl.py
--- a/pypy/objspace/std/marshal_impl.py
+++ b/pypy/objspace/std/marshal_impl.py
@@ -325,10 +325,10 @@
# of building a list of tuples.
w_dic = space.newdict()
while 1:
- w_key = u.get_w_obj(True)
+ w_key = u.get_w_obj(allow_null=True)
if w_key is None:
break
- w_value = u.get_w_obj(False)
+ w_value = u.get_w_obj()
space.setitem(w_dic, w_key, w_value)
return w_dic
register(TYPE_DICT, unmarshal_DictMulti)
@@ -364,7 +364,7 @@
# so we no longer can handle it in interp_marshal.atom_strlist
def unmarshal_str(u):
- w_obj = u.get_w_obj(False)
+ w_obj = u.get_w_obj()
try:
return u.space.str_w(w_obj)
except OperationError, e:
diff --git a/pypy/objspace/std/objecttype.py b/pypy/objspace/std/objecttype.py
--- a/pypy/objspace/std/objecttype.py
+++ b/pypy/objspace/std/objecttype.py
@@ -24,7 +24,12 @@
return w_obj.getrepr(space, '%s object' % (classname,))
def descr__str__(space, w_obj):
- return space.repr(w_obj)
+ w_type = space.type(w_obj)
+ w_impl = w_type.lookup("__repr__")
+ if w_impl is None:
+ raise OperationError(space.w_TypeError, # can it really occur?
+ space.wrap("operand does not support unary str"))
+ return space.get_and_call_function(w_impl, w_obj)
def descr__class__(space, w_obj):
return space.type(w_obj)
diff --git a/pypy/objspace/std/test/test_methodcache.py b/pypy/objspace/std/test/test_methodcache.py
--- a/pypy/objspace/std/test/test_methodcache.py
+++ b/pypy/objspace/std/test/test_methodcache.py
@@ -88,30 +88,37 @@
def test_many_names(self):
import __pypy__
- class A(object):
- foo = 5
- bar = 6
- baz = 7
- xyz = 8
- stuff = 9
- a = 10
- foobar = 11
+ for j in range(20):
+ class A(object):
+ foo = 5
+ bar = 6
+ baz = 7
+ xyz = 8
+ stuff = 9
+ a = 10
+ foobar = 11
- a = A()
- names = [name for name in A.__dict__.keys()
- if not name.startswith('_')]
- names.sort()
- names_repeated = names * 10
- result = []
- __pypy__.reset_method_cache_counter()
- for name in names_repeated:
- result.append(getattr(a, name))
- append_counter = __pypy__.method_cache_counter("append")
- names_counters = [__pypy__.method_cache_counter(name)
- for name in names]
- assert append_counter[0] >= 5 * len(names)
- for name, count in zip(names, names_counters):
- assert count[0] >= 5, str((name, count))
+ a = A()
+ names = [name for name in A.__dict__.keys()
+ if not name.startswith('_')]
+ names.sort()
+ names_repeated = names * 10
+ result = []
+ __pypy__.reset_method_cache_counter()
+ for name in names_repeated:
+ result.append(getattr(a, name))
+ append_counter = __pypy__.method_cache_counter("append")
+ names_counters = [__pypy__.method_cache_counter(name)
+ for name in names]
+ try:
+ assert append_counter[0] >= 10 * len(names) - 1
+ for name, count in zip(names, names_counters):
+ assert count == (9, 1), str((name, count))
+ break
+ except AssertionError:
+ pass
+ else:
+ raise
def test_mutating_bases(self):
class C(object):
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -94,3 +94,11 @@
#assert len(log) == 1
#assert log[0].message.args == ("object.__init__() takes no parameters",)
#assert type(log[0].message) is DeprecationWarning
+
+ def test_object_str(self):
+ # obscure case: __str__() must delegate to __repr__() without adding
+ # type checking on its own
+ class A(object):
+ def __repr__(self):
+ return 123456
+ assert A().__str__() == 123456
diff --git a/pypy/objspace/std/test/test_stringformat.py b/pypy/objspace/std/test/test_stringformat.py
--- a/pypy/objspace/std/test/test_stringformat.py
+++ b/pypy/objspace/std/test/test_stringformat.py
@@ -168,7 +168,7 @@
def test_incomplete_format(self):
raises(ValueError, '%'.__mod__, ((23,),))
- raises(ValueError, '%('.__mod__, ({},))
+ raises((ValueError, TypeError), '%('.__mod__, ({},))
def test_format_char(self):
import sys
diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -780,8 +780,22 @@
assert type(s) is unicode
assert s == u'\u1234'
+ # now the same with a new-style class...
+ class A(object):
+ def __init__(self, num):
+ self.num = num
+ def __str__(self):
+ return unichr(self.num)
+
+ s = '%s' % A(111) # this is ASCII
+ assert type(s) is unicode
+ assert s == chr(111)
+
+ s = '%s' % A(0x1234) # this is not ASCII
+ assert type(s) is unicode
+ assert s == u'\u1234'
+
def test_formatting_unicode__str__2(self):
- skip("this is completely insane")
class A:
def __str__(self):
return u'baz'
@@ -798,9 +812,22 @@
s = '%s %s' % (a, b)
assert s == u'baz bar'
+ skip("but this case here is completely insane")
s = '%s %s' % (b, a)
assert s == u'foo baz'
+ def test_formatting_unicode__str__3(self):
+ # "bah" is all I can say
+ class X(object):
+ def __repr__(self):
+ return u'\u1234'
+ '%s' % X()
+ #
+ class X(object):
+ def __str__(self):
+ return u'\u1234'
+ '%s' % X()
+
def test_str_subclass(self):
class Foo9(str):
def __unicode__(self):
diff --git a/pypy/rlib/rcoroutine.py b/pypy/rlib/rcoroutine.py
deleted file mode 100644
--- a/pypy/rlib/rcoroutine.py
+++ /dev/null
@@ -1,357 +0,0 @@
-"""
-Basic Concept:
---------------
-
-All concurrency is expressed by some means of coroutines.
-This is the lowest possible exposable interface.
-
-A coroutine is a structure that controls a sequence
-of continuations in time. It contains a frame object
-that is a restartable stack chain. This frame object
-is updated on every switch.
-
-The frame can be None. Either the coroutine is not yet
-bound, or it is the current coroutine of some costate.
-See below. XXX rewrite a definition of these terms.
-
-There is always a notation of a "current" and a "last"
-coroutine. Current has no frame and represents the
-running program. last is needed to keep track of the
-coroutine that receives a new frame chain after a switch.
-
-A costate object holds last and current.
-There are different coroutine concepts existing in
-parallel, like plain interp-level coroutines and
-app-level structures like coroutines, greenlets and
-tasklets.
-Every concept is associated with its own costate object.
-This allows for peaceful co-existence of many concepts.
-The type of a switch is determined by the target's costate.
-"""
-
-import py; py.test.skip("fixme: rewrite using rlib.rstacklet")
-# XXX ^^^ the reason it is not done is that pypy.rlib.rcoroutine
-# plus pypy/module/_stackless look like faaaaaar too much code
-# to me :-(
-
-from pypy.rlib.rstack import yield_current_frame_to_caller
-from pypy.rlib.objectmodel import we_are_translated
-
-from pypy.interpreter.error import OperationError
-
-try:
- from greenlet import greenlet
- main_greenlet = greenlet.getcurrent()
-except (ImportError, ValueError):
- def greenlet(*args, **kwargs):
- raise NotImplementedError("need either greenlets or a translated version of pypy")
-
-class FrameChain(object):
- """Greenlet-based emulation of the primitive rstack 'frames' of RPython"""
-
- def __init__(self, thunk=None):
- if thunk:
- self.greenlet = greenlet(thunk)
- else:
- self.greenlet = greenlet.getcurrent()
-
- def switch(self):
- last = FrameChain()
- return self.greenlet.switch(last)
-
-import sys, os
-
-def make_coroutine_classes(baseclass):
- class BaseCoState(object):
- def __init__(self):
- self.current = self.main = None
-
- def __repr__(self):
- "NOT_RPYTHON"
- # for debugging only
- return '<%s current=%r>' % (self.__class__.__name__, self.current)
-
- def update(self, new):
- syncstate.leaving = self.current
- syncstate.entering = new
- self.current = new
- frame, new.frame = new.frame, None
- return frame
-
-
- class CoState(BaseCoState):
- def __init__(self):
- BaseCoState.__init__(self)
- self.current = self.main = Coroutine(self)
-
- class CoroutineDamage(SystemError):
- pass
-
-
- class SyncState(object):
- def __init__(self):
- self.reset()
-
- def reset(self):
- self.default_costate = None
- self.leaving = None
- self.entering = None
- self.things_to_do = False
- self.temp_exc = None
- self.to_delete = []
-
- def switched(self, incoming_frame):
- left = syncstate.leaving
- entered = syncstate.entering
- syncstate.leaving = syncstate.entering = None
- if left is not None: # mostly to work around an annotation problem;
- # should not really be None
- left.frame = incoming_frame
- left.goodbye()
- if entered is not None:
- entered.hello()
- if self.things_to_do:
- self._do_things_to_do()
-
- def push_exception(self, exc):
- self.things_to_do = True
- self.temp_exc = exc
-
- def check_for_zombie(self, obj):
- return obj in self.to_delete
-
- def postpone_deletion(self, obj):
- self.to_delete.append(obj)
- self.things_to_do = True
-
- def _do_things_to_do(self):
- if self.temp_exc is not None:
- # somebody left an unhandled exception and switched to us.
- # this both provides default exception handling and the
- # way to inject an exception, like CoroutineExit.
- e, self.temp_exc = self.temp_exc, None
- self.things_to_do = bool(self.to_delete)
- raise e
- while self.to_delete:
- delete, self.to_delete = self.to_delete, []
- for obj in delete:
- obj.parent = obj.costate.current
- obj._kill_finally()
- else:
- self.things_to_do = False
-
- def _freeze_(self):
- self.reset()
- return False
-
- syncstate = SyncState()
-
-
- class CoroutineExit(SystemExit):
- # XXX SystemExit's __init__ creates problems in bookkeeper.
- def __init__(self):
- pass
-
- class AbstractThunk(object):
- def call(self):
- raise NotImplementedError("abstract base class")
-
-
- class Coroutine(baseclass):
- def __init__(self, state=None):
- self.frame = None
- if state is None:
- state = self._get_default_costate()
- self.costate = state
- self.parent = None
- self.thunk = None
- self.coroutine_exit = False
-
- def __repr__(self):
- 'NOT_RPYTHON'
- # just for debugging
- if hasattr(self, '__name__'):
- return '<Coro %s frame=%r %s>' % (self.__name__, self.frame, self.thunk is not None)
- else:
- return '<coro frame=%r %s>' % (self.frame, self.thunk is not None)
-
- def _get_default_costate():
- state = syncstate.default_costate
- if state is None:
- state = syncstate.default_costate = CoState()
- return state
- _get_default_costate = staticmethod(_get_default_costate)
-
- def _get_default_parent(self):
- return self.costate.current
-
- def bind(self, thunk):
- assert isinstance(thunk, AbstractThunk)
- if self.frame is not None:
- raise CoroutineDamage
- if self.parent is None:
- self.parent = self._get_default_parent()
- assert self.parent is not None
- self.thunk = thunk
- if we_are_translated():
- self.frame = self._bind()
- else:
- self.frame = self._greenlet_bind()
-
- def _greenlet_bind(self):
- weak = [self]
- def _greenlet_execute(incoming_frame):
- try:
- chain2go2next = weak[0]._execute(incoming_frame)
- except:
- # no exception is supposed to get out of _execute()
- # better report it directly into the main greenlet then,
- # and hidden to prevent catching
- main_greenlet.throw(AssertionError(
- "unexpected exception out of Coroutine._execute()",
- *sys.exc_info()))
- assert 0
- del weak[0]
- greenlet.getcurrent().parent = chain2go2next.greenlet
- return None # as the result of the FrameChain.switch()
- chain = FrameChain(_greenlet_execute)
- return chain
-
- def _bind(self):
- state = self.costate
- incoming_frame = yield_current_frame_to_caller()
- self = state.current
- return self._execute(incoming_frame)
-
- def _execute(self, incoming_frame):
- state = self.costate
- try:
- try:
- try:
- exc = None
- thunk = self.thunk
- self.thunk = None
- syncstate.switched(incoming_frame)
- thunk.call()
- except Exception, e:
- exc = e
- raise
- finally:
- # warning! we must reload the 'self' from the costate,
- # because after a clone() the 'self' of both copies
- # point to the original!
- self = state.current
- self.finish(exc)
- except CoroutineExit:
- pass
- except Exception, e:
- if self.coroutine_exit is False:
- # redirect all unhandled exceptions to the parent
- syncstate.push_exception(e)
-
- while self.parent is not None and self.parent.frame is None:
- # greenlet behavior is fine
- self.parent = self.parent.parent
- return state.update(self.parent)
-
- def switch(self):
- if self.frame is None:
- # considered a programming error.
- # greenlets and tasklets have different ideas about this.
- raise CoroutineDamage
- state = self.costate
- incoming_frame = state.update(self).switch()
- syncstate.switched(incoming_frame)
-
- def kill(self):
- self._kill(CoroutineExit())
-
- def _kill(self, exc):
- if self.frame is None:
- return
- state = self.costate
- syncstate.push_exception(exc)
- # careful here - if setting self.parent to state.current would
- # create a loop, break it. The assumption is that 'self'
- # will die, so that state.current's chain of parents can be
- # modified to skip 'self' without too many people noticing.
- p = state.current
- if p is self or self.parent is None:
- pass # killing the current of the main - don't change any parent
- else:
- while p.parent is not None:
- if p.parent is self:
- p.parent = self.parent
- break
- p = p.parent
- self.parent = state.current
- self.switch()
-
- def _kill_finally(self):
- try:
- self._userdel()
- except Exception:
- pass # maybe print a warning?
- self.kill()
-
- __already_postponed = False
-
- def __del__(self):
- # provide the necessary clean-up
- # note that AppCoroutine has to take care about this
- # as well, including a check for user-supplied __del__.
- # Additionally note that in the context of __del__, we are
- # not in the position to issue a switch.
- # we defer it completely.
-
- # it is necessary to check whether syncstate is None because CPython
- # sets it to None when it cleans up the modules, which will lead to
- # very strange effects
-
- if not we_are_translated():
- # we need to make sure that we postpone each coroutine only once on
- # top of CPython, because this resurrects the coroutine and CPython
- # calls __del__ again, thus postponing and resurrecting the
- # coroutine once more :-(
- if self.__already_postponed:
- return
- self.__already_postponed = True
- if syncstate is not None:
- syncstate.postpone_deletion(self)
-
- # coroutines need complete control over their __del__ behaviour. In
- # particular they need to care about calling space.userdel themselves
- handle_del_manually = True
-
- def _userdel(self):
- # override this for exposed coros
- pass
-
- def is_alive(self):
- return self.frame is not None or self is self.costate.current
-
- def is_zombie(self):
- return self.frame is not None and syncstate.check_for_zombie(self)
-
- def getcurrent():
- costate = Coroutine._get_default_costate()
- return costate.current
- getcurrent = staticmethod(getcurrent)
-
- def getmain():
- costate = Coroutine._get_default_costate()
- return costate.main
- getmain = staticmethod(getmain)
-
- def hello(self):
- "Called when execution is transferred into this coroutine."
-
- def goodbye(self):
- "Called just after execution is transferred away from this coroutine."
-
- def finish(self, exc=None):
- "stephan forgot me"
-
- return locals()
-
-# _________________________________________________
diff --git a/pypy/rlib/test/test_rcoroutine.py b/pypy/rlib/test/test_rcoroutine.py
deleted file mode 100644
--- a/pypy/rlib/test/test_rcoroutine.py
+++ /dev/null
@@ -1,348 +0,0 @@
-"""
-testing coroutines at interprepter level
-"""
-import py
-import os
-from pypy import conftest; conftest.translation_test_so_skip_if_appdirect()
-from pypy.rlib.rcoroutine import make_coroutine_classes
-from pypy.translator.c.test.test_stackless import StacklessTest
-from pypy.translator.c import gc
-
-def setup_module(mod):
- py.test.importorskip('greenlet')
-
-d = make_coroutine_classes(object)
-syncstate = d['syncstate']
-Coroutine = d['Coroutine']
-AbstractThunk = d['AbstractThunk']
-
-def output(stuff):
- os.write(2, stuff + '\n')
-
-class _TestCoroutine(StacklessTest):
- backendopt = True
- Coroutine = Coroutine
-
- def setup_method(self, method):
- syncstate.reset()
-
- def _freeze_(self): # for 'self.Coroutine'
- return True
-
- def test_coroutine1(self):
-
- def g(lst, coros):
- coro_f, coro_g, coro_h = coros
- lst.append(2)
- output('g appended 2')
- coro_h.switch()
- lst.append(5)
- output('g appended 5')
-
- def h(lst, coros):
- coro_f, coro_g, coro_h = coros
- lst.append(3)
- output('h appended 3')
- coro_f.switch()
- lst.append(7)
- output('h appended 7')
-
- class T(AbstractThunk):
- def __init__(self, func, arg1, arg2):
- self.func = func
- self.arg1 = arg1
- self.arg2 = arg2
- def call(self):
- self.func(self.arg1, self.arg2)
-
- def f():
- lst = [1]
- coro_f = Coroutine.getcurrent()
- coro_g = self.Coroutine()
- coro_h = self.Coroutine()
- coros = [coro_f, coro_g, coro_h]
- thunk_g = T(g, lst, coros)
- output('binding g after f set 1')
- coro_g.bind(thunk_g)
- thunk_h = T(h, lst, coros)
- output('binding h after f set 1')
- coro_h.bind(thunk_h)
- output('switching to g')
- coro_g.switch()
- lst.append(4)
- output('f appended 4')
- coro_g.switch()
- lst.append(6)
- output('f appended 6')
- coro_h.switch()
- lst.append(8)
- output('f appended 8')
- n = 0
- for i in lst:
- n = n*10 + i
- return n
-
- data = self.wrap_stackless_function(f)
- assert data == 12345678
-
- def test_coroutine2(self):
-
- class TBase(AbstractThunk):
- def call(self):
- pass
-
- class T(TBase):
- def __init__(self, func, arg1, arg2):
- self.func = func
- self.arg1 = arg1
- self.arg2 = arg2
- def call(self):
- self.res = self.func(self.arg1, self.arg2)
-
- class T1(TBase):
- def __init__(self, func, arg1):
- self.func = func
- self.arg1 = arg1
- def call(self):
- self.res = self.func(self.arg1)
-
- def g(lst, coros):
- coro_f1, coro_g, coro_h = coros
- lst.append(2)
- output('g appended 2')
- coro_h.switch()
- lst.append(5)
- output('g appended 5')
- output('exiting g')
-
- def h(lst, coros):
- coro_f1, coro_g, coro_h = coros
- lst.append(3)
- output('h appended 3')
- coro_f1.switch()
- lst.append(7)
- output('h appended 7')
- output('exiting h')
-
- def f1(coro_f1):
- lst = [1]
- coro_g = self.Coroutine()
- coro_g.__name__ = 'coro_g'
- coro_h = self.Coroutine()
- coro_h.__name__ = 'coro_h'
- coros = [coro_f1, coro_g, coro_h]
- thunk_g = T(g, lst, coros)
- output('binding g after f1 set 1')
- coro_g.bind(thunk_g)
- thunk_h = T(h, lst, coros)
- output('binding h after f1 set 1')
- coro_h.bind(thunk_h)
- output('switching to g')
- coro_g.switch()
- lst.append(4)
- output('f1 appended 4')
- coro_g.switch()
- lst.append(6)
- output('f1 appended 6')
- coro_h.switch()
- lst.append(8)
- output('f1 appended 8')
- n = 0
- for i in lst:
- n = n*10 + i
- output('exiting f1')
- return n
-
- def f():
- coro_f = Coroutine.getcurrent()
- coro_f.__name__ = 'coro_f'
- coro_f1 = self.Coroutine()
- coro_f1.__name__ = 'coro_f1'
- thunk_f1 = T1(f1, coro_f1)
- output('binding f1 after f set 1')
- coro_f1.bind(thunk_f1)
- coro_f1.switch()
- output('return to main :-(')
- return thunk_f1.res
-
- data = self.wrap_stackless_function(f)
- assert data == 12345678
-
- def test_kill_raise_del_coro(self):
- class T(AbstractThunk):
- def __init__(self, func, arg):
- self.func = func
- self.arg = arg
- def call(self):
- self.func(self.arg, self)
-
- def g(nrec, t, count=0):
- t.count = count
- if nrec < 0:
- raise ValueError
- if nrec:
- g(nrec-1, t, count+1)
- Coroutine.getmain().switch()
-
- def f():
- assert Coroutine.getmain().frame is None
- coro_g = self.Coroutine()
- coro_g.__name__ = 'coro_g'
- thunk_g = T(g, 42)
- coro_g.bind(thunk_g)
- coro_g.switch()
- res = thunk_g.count
- res *= 10
- res |= coro_g.frame is not None
- # testing kill
- coro_g.kill()
- res *= 10
- res |= coro_g.frame is None
- coro_g = self.Coroutine()
- # see what happens if we __del__
- thunk_g = T(g, -42)
- coro_g.bind(thunk_g)
- try:
- coro_g.switch()
- except ValueError:
- res += 500
- return res
-
- data = self.wrap_stackless_function(f)
- assert data == 4711
-
- def test_tree_compare(self):
- class Node:
- def __init__(self, value, left=None, right=None):
- self.value = value
- self.left = left
- self.right = right
- def __repr__(self):
- return 'Node(%r, %r, %r)'%(self.value, self.left, self.right)
-
- tree1 = Node(1, Node(2, Node(3)))
- tree2 = Node(1, Node(3, Node(2)))
- tree3 = Node(1, Node(2), Node(3))
-
- class Producer(AbstractThunk):
- def __init__(self, tree, objects, consumer):
- self.tree = tree
- self.objects = objects
- self.consumer = consumer
- def produce(self, t):
- if t is None:
- return
- self.objects.append(t.value)
- self.consumer.switch()
- self.produce(t.left)
- self.produce(t.right)
- def call(self):
- self.produce(self.tree)
- while 1:
- self.consumer.switch()
- class Consumer(AbstractThunk):
- def __init__(self, tree, objects, producer):
- self.tree = tree
- self.objects = objects
- self.producer = producer
- def consume(self, t):
- if t is None:
- return True
- self.producer.switch()
- if not self.objects:
- return False
- if self.objects.pop(0) != t.value:
- return False
- if not self.consume(t.left):
- return False
- return self.consume(t.right)
-
- def call(self):
- self.result = self.consume(self.tree)
- Coroutine.getmain().switch()
-
- def pre_order_eq(t1, t2):
- objects = []
- producer = self.Coroutine()
- consumer = self.Coroutine()
-
- producer.bind(Producer(t1, objects, consumer))
- cons = Consumer(t2, objects, producer)
- consumer.bind(cons)
-
- consumer.switch()
-
- return cons.result
-
- def ep():
- return int("%d%d%d%d"%(pre_order_eq(tree1, tree2),
- pre_order_eq(tree1, tree1),
- pre_order_eq(tree1, tree3),
- pre_order_eq(tree2, tree1),
- ))
-
- output = self.wrap_stackless_function(ep)
- assert output == int('0110')
-
- def test_hello_goodbye(self):
-
- class C(Coroutine):
- n = 2
- def __init__(self, n):
- Coroutine.__init__(self)
- self.n = n
- def hello(self):
- costate.hello_goodbye *= 10
- costate.hello_goodbye += self.n
- def goodbye(self):
- costate.hello_goodbye *= 10
- costate.hello_goodbye += self.n + 1
-
- class T(AbstractThunk):
- def call(self):
- pass
-
- costate = Coroutine._get_default_costate()
- costate.current.__class__ = C
- costate.hello_goodbye = 0
-
- def ep():
- syncstate.default_costate = costate
- costate.hello_goodbye = 0
- c1 = C(4)
- c1.bind(T())
- c1.switch()
- return costate.hello_goodbye
-
- output = self.wrap_stackless_function(ep)
- # expected result:
- # goodbye main 3
- # hello c1 4
- # goodbye c1 5
- # hello main 2
- assert output == 3452
-
- def test_raise_propagate(self):
- class T(AbstractThunk):
- def call(self):
- raise ValueError
-
- def ep():
- c = self.Coroutine()
- c.bind(T())
- try:
- c.switch()
- except ValueError:
- return 100
- else:
- return -5
-
- output = self.wrap_stackless_function(ep)
- assert output == 100
-
-
-TestCoroutine = _TestCoroutine # to activate
-class TestCoroutineOnCPython(_TestCoroutine):
- def wrap_stackless_function(self, func):
- return func()
-
diff --git a/pypy/rpython/module/ll_os_stat.py b/pypy/rpython/module/ll_os_stat.py
--- a/pypy/rpython/module/ll_os_stat.py
+++ b/pypy/rpython/module/ll_os_stat.py
@@ -49,19 +49,8 @@
]
N_INDEXABLE_FIELDS = 10
-# for now, check the host Python to know which st_xxx fields exist
-STAT_FIELDS = [(_name, _TYPE) for (_name, _TYPE) in ALL_STAT_FIELDS
- if hasattr(os.stat_result, _name)]
-
-STAT_FIELD_TYPES = dict(STAT_FIELDS) # {'st_xxx': TYPE}
-
-STAT_FIELD_NAMES = [_name for (_name, _TYPE) in ALL_STAT_FIELDS
- if _name in STAT_FIELD_TYPES]
-
-del _name, _TYPE
-
# For OO backends, expose only the portable fields (the first 10).
-PORTABLE_STAT_FIELDS = STAT_FIELDS[:N_INDEXABLE_FIELDS]
+PORTABLE_STAT_FIELDS = ALL_STAT_FIELDS[:N_INDEXABLE_FIELDS]
# ____________________________________________________________
#
@@ -142,17 +131,22 @@
includes = INCLUDES
)
-if sys.platform != 'win32':
+if TIMESPEC is not None:
+ class CConfig_for_timespec:
+ _compilation_info_ = compilation_info
+ TIMESPEC = TIMESPEC
+ TIMESPEC = lltype.Ptr(
+ platform.configure(CConfig_for_timespec)['TIMESPEC'])
+
+
+def posix_declaration(try_to_add=None):
+ global STAT_STRUCT
LL_STAT_FIELDS = STAT_FIELDS[:]
+ if try_to_add:
+ LL_STAT_FIELDS.append(try_to_add)
if TIMESPEC is not None:
- class CConfig_for_timespec:
- _compilation_info_ = compilation_info
- TIMESPEC = TIMESPEC
-
- TIMESPEC = lltype.Ptr(
- platform.configure(CConfig_for_timespec)['TIMESPEC'])
def _expand(lst, originalname, timespecname):
for i, (_name, _TYPE) in enumerate(lst):
@@ -178,9 +172,34 @@
class CConfig:
_compilation_info_ = compilation_info
STAT_STRUCT = platform.Struct('struct %s' % _name_struct_stat, LL_STAT_FIELDS)
- config = platform.configure(CConfig)
+ try:
+ config = platform.configure(CConfig)
+ except platform.CompilationError:
+ if try_to_add:
+ return # failed to add this field, give up
+ raise
STAT_STRUCT = lltype.Ptr(config['STAT_STRUCT'])
+ if try_to_add:
+ STAT_FIELDS.append(try_to_add)
+
+
+# This lists only the fields that have been found on the underlying platform.
+# Initially only the PORTABLE_STAT_FIELDS, but more may be added by the
+# following loop.
+STAT_FIELDS = PORTABLE_STAT_FIELDS[:]
+
+if sys.platform != 'win32':
+ posix_declaration()
+ for _i in range(len(PORTABLE_STAT_FIELDS), len(ALL_STAT_FIELDS)):
+ posix_declaration(ALL_STAT_FIELDS[_i])
+ del _i
+
+# these two global vars only list the fields defined in the underlying platform
+STAT_FIELD_TYPES = dict(STAT_FIELDS) # {'st_xxx': TYPE}
+STAT_FIELD_NAMES = [_name for (_name, _TYPE) in STAT_FIELDS]
+del _name, _TYPE
+
def build_stat_result(st):
# only for LL backends
diff --git a/pypy/rpython/module/test/test_ll_os_stat.py b/pypy/rpython/module/test/test_ll_os_stat.py
--- a/pypy/rpython/module/test/test_ll_os_stat.py
+++ b/pypy/rpython/module/test/test_ll_os_stat.py
@@ -2,6 +2,16 @@
import sys, os
import py
+
+class TestLinuxImplementation:
+ def setup_class(cls):
+ if not sys.platform.startswith('linux'):
+ py.test.skip("linux specific tests")
+
+ def test_has_all_fields(self):
+ assert ll_os_stat.STAT_FIELDS == ll_os_stat.ALL_STAT_FIELDS[:13]
+
+
class TestWin32Implementation:
def setup_class(cls):
if sys.platform != 'win32':
diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -8,6 +8,7 @@
bridge = None
offset = None
asm = None
+ failargs = ()
def __init__(self, name, args, res, descr):
self.name = name
@@ -18,8 +19,8 @@
if self._is_guard:
self.guard_no = int(self.descr[len('<Guard'):-1])
- def setfailargs(self, _):
- pass
+ def setfailargs(self, failargs):
+ self.failargs = failargs
def getarg(self, i):
return self._getvar(self.args[i])
diff --git a/pypy/translator/goal/targetpreimportedpypy.py b/pypy/translator/goal/targetpreimportedpypy.py
deleted file mode 100644
--- a/pypy/translator/goal/targetpreimportedpypy.py
+++ /dev/null
@@ -1,239 +0,0 @@
-import py
-
-import os, sys
-sys.setrecursionlimit(17000)
-
-from pypy.interpreter import gateway
-from pypy.interpreter.error import OperationError
-from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy
-from pypy.config.config import Config, to_optparse, make_dict, SUPPRESS_USAGE
-from pypy.config.config import ConflictConfigError
-from pypy.tool.option import make_objspace
-from pypy.translator.goal.nanos import setup_nanos
-
-EXTRA_MODULES = [
- #"os",
- #"decimal",
- #"difflib",
- #"tarfile",
- #"cookielib",
- #"optparse",
- "inspect",
- "random",
-]
-
-thisdir = py.path.local(__file__).dirpath()
-
-try:
- this_dir = os.path.dirname(__file__)
-except NameError:
- this_dir = os.path.dirname(sys.argv[0])
-
-def debug(msg):
- os.write(2, "debug: " + msg + '\n')
-
-# __________ Entry point __________
-
-def create_entry_point(space, w_dict):
- w_entry_point = space.getitem(w_dict, space.wrap('entry_point'))
- w_run_toplevel = space.getitem(w_dict, space.wrap('run_toplevel'))
- w_call_finish_gateway = space.wrap(gateway.interp2app(call_finish))
- w_call_startup_gateway = space.wrap(gateway.interp2app(call_startup))
- w_os = setup_nanos(space)
-
- def entry_point(argv):
- space.timer.start("Entrypoint")
- #debug("entry point starting")
- #for arg in argv:
- # debug(" argv -> " + arg)
- if len(argv) > 2 and argv[1] == '--heapsize':
- # Undocumented option, handled at interp-level.
- # It has silently no effect with some GCs.
- # It works in Boehm and in the semispace or generational GCs
- # (but see comments in semispace.py:set_max_heap_size()).
- # At the moment this option exists mainly to support sandboxing.
- from pypy.rlib import rgc
- rgc.set_max_heap_size(int(argv[2]))
- argv = argv[:1] + argv[3:]
- try:
- try:
- space.timer.start("space.startup")
- space.call_function(w_run_toplevel, w_call_startup_gateway)
- space.timer.stop("space.startup")
- w_executable = space.wrap(argv[0])
- w_argv = space.newlist([space.wrap(s) for s in argv[1:]])
- space.timer.start("w_entry_point")
- w_exitcode = space.call_function(w_entry_point, w_executable, w_argv, w_os)
- space.timer.stop("w_entry_point")
- exitcode = space.int_w(w_exitcode)
- # try to pull it all in
- ## from pypy.interpreter import main, interactive, error
- ## con = interactive.PyPyConsole(space)
- ## con.interact()
- except OperationError, e:
- debug("OperationError:")
- debug(" operror-type: " + e.w_type.getname(space))
- debug(" operror-value: " + space.str_w(space.str(e.get_w_value(space))))
- return 1
- finally:
- try:
- space.timer.start("space.finish")
- space.call_function(w_run_toplevel, w_call_finish_gateway)
- space.timer.stop("space.finish")
- except OperationError, e:
- debug("OperationError:")
- debug(" operror-type: " + e.w_type.getname(space))
- debug(" operror-value: " + space.str_w(space.str(e.get_w_value(space))))
- return 1
- space.timer.stop("Entrypoint")
- space.timer.dump()
- return exitcode
- return entry_point
-
-def call_finish(space):
- space.finish()
-
-def call_startup(space):
- space.startup()
-
-# _____ Define and setup target ___
-
-# for now this will do for option handling
-
-class PyPyTarget(object):
-
- usage = SUPPRESS_USAGE
-
- take_options = True
-
- def opt_parser(self, config):
- parser = to_optparse(config, useoptions=["objspace.*"],
- parserkwargs={'usage': self.usage})
- return parser
-
- def handle_config(self, config, translateconfig):
- self.translateconfig = translateconfig
- # set up the objspace optimizations based on the --opt argument
- from pypy.config.pypyoption import set_pypy_opt_level
- set_pypy_opt_level(config, translateconfig.opt)
-
- # as of revision 27081, multimethod.py uses the InstallerVersion1 by default
- # because it is much faster both to initialize and run on top of CPython.
- # The InstallerVersion2 is optimized for making a translator-friendly
- # structure for low level backends. However, InstallerVersion1 is still
- # preferable for high level backends, so we patch here.
-
- from pypy.objspace.std import multimethod
- if config.objspace.std.multimethods == 'mrd':
- assert multimethod.InstallerVersion1.instance_counter == 0,\
- 'The wrong Installer version has already been instatiated'
- multimethod.Installer = multimethod.InstallerVersion2
- elif config.objspace.std.multimethods == 'doubledispatch':
- # don't rely on the default, set again here
- assert multimethod.InstallerVersion2.instance_counter == 0,\
- 'The wrong Installer version has already been instatiated'
- multimethod.Installer = multimethod.InstallerVersion1
-
- def print_help(self, config):
- self.opt_parser(config).print_help()
-
- def get_additional_config_options(self):
- from pypy.config.pypyoption import pypy_optiondescription
- return pypy_optiondescription
-
- def target(self, driver, args):
- driver.exe_name = 'pypy-%(backend)s'
-
- config = driver.config
- parser = self.opt_parser(config)
-
- parser.parse_args(args)
-
- # expose the following variables to ease debugging
- global space, entry_point
-
- if config.objspace.allworkingmodules:
- from pypy.config.pypyoption import enable_allworkingmodules
- enable_allworkingmodules(config)
-
- if config.translation.thread:
- config.objspace.usemodules.thread = True
- elif config.objspace.usemodules.thread:
- try:
- config.translation.thread = True
- except ConflictConfigError:
- # If --allworkingmodules is given, we reach this point
- # if threads cannot be enabled (e.g. they conflict with
- # something else). In this case, we can try setting the
- # usemodules.thread option to False again. It will
- # cleanly fail if that option was set to True by the
- # command-line directly instead of via --allworkingmodules.
- config.objspace.usemodules.thread = False
-
- if config.translation.stackless:
- config.objspace.usemodules._stackless = True
- elif config.objspace.usemodules._stackless:
- try:
- config.translation.stackless = True
- except ConflictConfigError:
- raise ConflictConfigError("please use the --stackless option "
- "to translate.py instead of "
- "--withmod-_stackless directly")
-
- if not config.translation.rweakref:
- config.objspace.usemodules._weakref = False
-
- if self.translateconfig.goal_options.jit:
- config.objspace.usemodules.pypyjit = True
- elif config.objspace.usemodules.pypyjit:
- self.translateconfig.goal_options.jit = True
-
- if config.translation.backend == "cli":
- config.objspace.usemodules.clr = True
- # XXX did it ever work?
- #elif config.objspace.usemodules.clr:
- # config.translation.backend == "cli"
-
- config.objspace.nofaking = True
- config.objspace.compiler = "ast"
- config.translating = True
-
- import translate
- translate.log_config(config.objspace, "PyPy config object")
-
- # obscure hack to stuff the translation options into the translated PyPy
- import pypy.module.sys
- options = make_dict(config)
- wrapstr = 'space.wrap(%r)' % (options)
- pypy.module.sys.Module.interpleveldefs['pypy_translation_info'] = wrapstr
-
- return self.get_entry_point(config)
-
- def portal(self, driver):
- from pypy.module.pypyjit.portal import get_portal
- return get_portal(driver)
-
- def get_entry_point(self, config):
- space = make_objspace(config)
-
- # manually imports app_main.py
- filename = os.path.join(this_dir, 'app_main.py')
- w_dict = space.newdict()
- space.exec_(open(filename).read(), w_dict, w_dict)
- for modulename in EXTRA_MODULES:
- print 'pre-importing', modulename
- space.exec_("import " + modulename, w_dict, w_dict)
- print 'phew, ready'
- entry_point = create_entry_point(space, w_dict)
-
- return entry_point, None, PyPyAnnotatorPolicy(single_space = space)
-
- def interface(self, ns):
- for name in ['take_options', 'handle_config', 'print_help', 'target',
- 'portal',
- 'get_additional_config_options']:
- ns[name] = getattr(self, name)
-
-
-PyPyTarget().interface(globals())
-
More information about the pypy-commit
mailing list