[pypy-commit] pypy py3k: hg merge default
antocuni
noreply at buildbot.pypy.org
Fri Aug 31 10:28:26 CEST 2012
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: py3k
Changeset: r57048:58ee064bc777
Date: 2012-08-31 10:28 +0200
http://bitbucket.org/pypy/pypy/changeset/58ee064bc777/
Log: hg merge default
diff --git a/lib_pypy/_ctypes/__init__.py b/lib_pypy/_ctypes/__init__.py
--- a/lib_pypy/_ctypes/__init__.py
+++ b/lib_pypy/_ctypes/__init__.py
@@ -19,6 +19,10 @@
from _rawffi import FormatError
from _rawffi import check_HRESULT as _check_HRESULT
+ try: from __pypy__ import builtinify
+ except ImportError: builtinify = lambda f: f
+
+ @builtinify
def CopyComPointer(src, dst):
from ctypes import c_void_p, cast
if src:
@@ -28,6 +32,8 @@
dst[0] = cast(src, c_void_p).value
return 0
+ del builtinify
+
LoadLibrary = dlopen
from _rawffi import FUNCFLAG_STDCALL, FUNCFLAG_CDECL, FUNCFLAG_PYTHONAPI
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -3,6 +3,9 @@
import _ffi
import sys
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
keepalive_key = str # XXX fix this when provided with test
def ensure_objects(where):
@@ -145,6 +148,7 @@
_b_base_ = property(_get_b_base)
_b_needsfree_ = False
+ at builtinify
def sizeof(tp):
if not isinstance(tp, _CDataMeta):
if isinstance(tp, _CData):
@@ -154,6 +158,7 @@
type(tp).__name__,))
return tp._sizeofinstances()
+ at builtinify
def alignment(tp):
if not isinstance(tp, _CDataMeta):
if isinstance(tp, _CData):
@@ -163,6 +168,7 @@
type(tp).__name__,))
return tp._alignmentofinstances()
+ at builtinify
def byref(cdata):
# "pointer" is imported at the end of this module to avoid circular
# imports
@@ -176,6 +182,7 @@
instance._buffer = self._ffiarray.fromaddress(address, lgt)
return instance
+ at builtinify
def addressof(tp):
return tp._buffer.buffer
diff --git a/lib_pypy/_ctypes/dll.py b/lib_pypy/_ctypes/dll.py
--- a/lib_pypy/_ctypes/dll.py
+++ b/lib_pypy/_ctypes/dll.py
@@ -1,5 +1,9 @@
import _rawffi
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+ at builtinify
def dlopen(name, mode):
# XXX mode is ignored
return _rawffi.CDLL(name)
diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
--- a/lib_pypy/_ctypes/function.py
+++ b/lib_pypy/_ctypes/function.py
@@ -10,6 +10,8 @@
import traceback
import warnings
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
# XXX this file needs huge refactoring I fear
@@ -34,6 +36,7 @@
from _ctypes import COMError
return COMError(errcode, None, None)
+ at builtinify
def call_function(func, args):
"Only for debugging so far: So that we can call CFunction instances"
funcptr = CFuncPtr(func)
diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -7,6 +7,9 @@
from _ctypes.array import Array, array_get_slice_params, array_slice_getitem,\
array_slice_setitem
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
# This cache maps types to pointers to them.
_pointer_type_cache = {}
@@ -154,6 +157,7 @@
return result
+ at builtinify
def POINTER(cls):
try:
return _pointer_type_cache[cls]
@@ -173,6 +177,7 @@
_pointer_type_cache[cls] = klass
return klass
+ at builtinify
def pointer(inst):
return POINTER(type(inst))(inst)
diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -531,7 +531,7 @@
if not s_enc.is_constant():
raise TypeError("Non-constant encoding not supported")
enc = s_enc.const
- if enc not in ('ascii', 'latin-1'):
+ if enc not in ('ascii', 'latin-1', 'utf-8'):
raise TypeError("Encoding %s not supported for unicode" % (enc,))
return SomeString()
method_encode.can_only_throw = [UnicodeEncodeError]
@@ -554,7 +554,7 @@
if not s_enc.is_constant():
raise TypeError("Non-constant encoding not supported")
enc = s_enc.const
- if enc not in ('ascii', 'latin-1'):
+ if enc not in ('ascii', 'latin-1', 'utf-8'):
raise TypeError("Encoding %s not supported for strings" % (enc,))
return SomeUnicodeString()
method_decode.can_only_throw = [UnicodeDecodeError]
diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -23,6 +23,17 @@
#
option = None
+
+def braindead_deindent(self):
+ """monkeypatch that wont end up doing stupid in the python tokenizer"""
+ text = '\n'.join(self.lines)
+ short = py.std.textwrap.dedent(text)
+ newsource = py.code.Source()
+ newsource.lines[:] = short.splitlines()
+ return newsource
+
+py.code.Source.deindent = braindead_deindent
+
def pytest_report_header():
return "pytest-%s from %s" % (pytest.__version__, pytest.__file__)
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -23,6 +23,12 @@
.. branch: improve-rbigint
Introduce __int128 on systems where it's supported and improve the speed of
rlib/rbigint.py greatly.
+.. branch: translation-cleanup
+Start to clean up a bit the flow object space.
+.. branch: ffi-backend
+Support CFFI. http://morepypy.blogspot.ch/2012/08/cffi-release-03.html
+.. branch: speedup-unpackiterable
+
.. "uninteresting" branches that we should just ignore for the whatsnew:
.. branch: slightly-shorter-c
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -314,10 +314,7 @@
if num_kwds:
# kwds_mapping maps target indexes in the scope (minus input_argcount)
# to positions in the keywords_w list
- cnt = (co_argcount + co_kwonlyargcount - input_argcount)
- if cnt < 0:
- cnt = 0
- kwds_mapping = [0] * cnt
+ kwds_mapping = [0] * (co_argcount + co_kwonlyargcount - input_argcount)
# initialize manually, for the JIT :-(
for i in range(len(kwds_mapping)):
kwds_mapping[i] = -1
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -20,6 +20,9 @@
UINT_MAX_32_BITS = r_uint(4294967295)
+unpackiterable_driver = jit.JitDriver(name = 'unpackiterable',
+ greens = ['tp'],
+ reds = ['items', 'w_iterator'])
class W_Root(object):
"""This is the abstract root class of all wrapped objects that live
@@ -224,6 +227,23 @@
def __spacebind__(self, space):
return self
+class W_InterpIterable(W_Root):
+ def __init__(self, space, w_iterable):
+ self.w_iter = space.iter(w_iterable)
+ self.space = space
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ space = self.space
+ try:
+ return space.next(self.w_iter)
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ raise StopIteration
+
class InternalSpaceCache(Cache):
"""A generic cache for an object space. Arbitrary information can
be attached to the space by defining a function or class 'f' which
@@ -837,6 +857,9 @@
expected_length)
return lst_w[:] # make the resulting list resizable
+ def iteriterable(self, w_iterable):
+ return W_InterpIterable(self, w_iterable)
+
@jit.dont_look_inside
def _unpackiterable_unknown_length(self, w_iterator, w_iterable):
# Unpack a variable-size list of unknown length.
@@ -857,7 +880,11 @@
except MemoryError:
items = [] # it might have lied
#
+ tp = self.type(w_iterator)
while True:
+ unpackiterable_driver.jit_merge_point(tp=tp,
+ w_iterator=w_iterator,
+ items=items)
try:
w_item = self.next(w_iterator)
except OperationError, e:
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -365,7 +365,8 @@
from pypy.jit.backend.llsupport.ffisupport import UnsupportedKind
arg_types = []
try:
- for arg in cif_description.atypes:
+ for itp in range(cif_description.nargs):
+ arg = cif_description.atypes[itp]
kind = get_ffi_type_kind(self, arg)
if kind != history.VOID:
arg_types.append(kind)
diff --git a/pypy/jit/backend/test/calling_convention_test.py b/pypy/jit/backend/test/calling_convention_test.py
--- a/pypy/jit/backend/test/calling_convention_test.py
+++ b/pypy/jit/backend/test/calling_convention_test.py
@@ -310,9 +310,9 @@
F = lltype.Float
S = lltype.SingleFloat
I = lltype.Signed
- floats = [random.random() - 0.5 for i in range(8)]
- singlefloats = [r_singlefloat(random.random() - 0.5) for i in range(8)]
- ints = [random.randrange(-99, 99) for i in range(8)]
+ floats = [random.random() - 0.5 for i in range(20)]
+ singlefloats = [r_singlefloat(random.random() - 0.5) for i in range(20)]
+ ints = [random.randrange(-99, 99) for i in range(20)]
for repeat in range(100):
args = []
argvalues = []
@@ -320,20 +320,23 @@
local_floats = list(floats)
local_singlefloats = list(singlefloats)
local_ints = list(ints)
- for i in range(8):
- case = random.randrange(0, 3)
- if case == 0:
+ for i in range(random.randrange(4, 20)):
+ case = random.randrange(0, 6)
+ if case & 1: boxme = BoxInt
+ else: boxme = ConstInt
+ if case < 2:
args.append(F)
- arg = local_floats.pop()
- argslist.append(boxfloat(arg))
- elif case == 1:
+ arg = arg1 = local_floats.pop()
+ if case & 1: boxme = boxfloat
+ else: boxme = constfloat
+ elif case < 4:
args.append(S)
arg = local_singlefloats.pop()
- argslist.append(BoxInt(longlong.singlefloat2int(arg)))
+ arg1 = longlong.singlefloat2int(arg)
else:
args.append(I)
- arg = local_ints.pop()
- argslist.append(BoxInt(arg))
+ arg = arg1 = local_ints.pop()
+ argslist.append(boxme(arg1))
argvalues.append(arg)
FUNC = self.FuncType(args, F)
FPTR = self.Ptr(FUNC)
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
@@ -1171,11 +1171,13 @@
xmm_dst_locs.append(unused_xmm.pop())
else:
pass_on_stack.append(loc)
- elif (argtypes is not None and argtypes[i-start] == 'S' and
- len(unused_xmm) > 0):
+ elif argtypes is not None and argtypes[i-start] == 'S':
# Singlefloat argument
- if singlefloats is None: singlefloats = []
- singlefloats.append((loc, unused_xmm.pop()))
+ if len(unused_xmm) > 0:
+ if singlefloats is None: singlefloats = []
+ singlefloats.append((loc, unused_xmm.pop()))
+ else:
+ pass_on_stack.append(loc)
else:
if len(unused_gpr) > 0:
src_locs.append(loc)
@@ -1209,6 +1211,9 @@
# Load the singlefloat arguments from main regs or stack to xmm regs
if singlefloats is not None:
for src, dst in singlefloats:
+ if isinstance(src, ImmedLoc):
+ self.mc.MOV(X86_64_SCRATCH_REG, src)
+ src = X86_64_SCRATCH_REG
self.mc.MOVD(dst, src)
# Finally remap the arguments in the main regs
# If x is a register and is in dst_locs, then oups, it needs to
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -14,6 +14,7 @@
from pypy.rlib.debug import fatalerror
from pypy.rlib.rstackovf import StackOverflow
from pypy.translator.simplify import get_functype
+from pypy.translator.backendopt import removenoops
from pypy.translator.unsimplify import call_final_function
from pypy.jit.metainterp import history, pyjitpl, gc, memmgr
@@ -260,6 +261,10 @@
graph = copygraph(graph)
[jmpp] = find_jit_merge_points([graph])
graph.startblock = support.split_before_jit_merge_point(*jmpp)
+ # XXX this is incredibly obscure, but this is sometiems necessary
+ # so we don't explode in checkgraph. for reasons unknown this
+ # is not contanied within simplify_graph
+ removenoops.remove_same_as(graph)
# a crash in the following checkgraph() means that you forgot
# to list some variable in greens=[] or reds=[] in JitDriver,
# or that a jit_merge_point() takes a constant as an argument.
diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -229,7 +229,7 @@
W_CTypePrimitiveFloat._get_ffi_type = _primfloat_ffi_type
W_CTypePrimitiveLongDouble._get_ffi_type = _primlongdouble_ffi_type
W_CTypePtrBase._get_ffi_type = _ptr_ffi_type
-W_CTypeVoid._get_ffi_type = _void_ffi_type
+#W_CTypeVoid._get_ffi_type = _void_ffi_type -- special-cased
# ----------
@@ -251,7 +251,9 @@
return result
- def fb_fill_type(self, ctype):
+ def fb_fill_type(self, ctype, is_result_type):
+ if is_result_type and isinstance(ctype, W_CTypeVoid):
+ return clibffi.ffi_type_void
return ctype._get_ffi_type(self)
def fb_struct_ffi_type(self, ctype):
@@ -262,6 +264,11 @@
# But on 64-bit UNIX, these two structs are passed by value
# differently: e.g. on x86-64, "b" ends up in register "rsi" in
# the first case and "rdi" in the second case.
+ #
+ # Another reason for 'custom_field_pos' would be anonymous
+ # nested structures: we lost the information about having it
+ # here, so better safe (and forbid it) than sorry (and maybe
+ # crash).
space = self.space
if ctype.custom_field_pos:
raise OperationError(space.w_TypeError,
@@ -281,7 +288,7 @@
raise OperationError(space.w_NotImplementedError,
space.wrap("cannot pass as argument a struct "
"with bit fields"))
- ffi_subtype = self.fb_fill_type(cf.ctype)
+ ffi_subtype = self.fb_fill_type(cf.ctype, False)
if elements:
elements[i] = ffi_subtype
@@ -322,11 +329,11 @@
self.atypes = rffi.cast(FFI_TYPE_PP, atypes)
# next comes the result type data
- self.rtype = self.fb_fill_type(self.fresult)
+ self.rtype = self.fb_fill_type(self.fresult, True)
# next comes each argument's type data
for i, farg in enumerate(self.fargs):
- atype = self.fb_fill_type(farg)
+ atype = self.fb_fill_type(farg, False)
if self.atypes:
self.atypes[i] = atype
diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -162,6 +162,10 @@
def is_bitfield(self):
return self.bitshift >= 0
+ def make_shifted(self, offset):
+ return W_CField(self.ctype, offset + self.offset,
+ self.bitshift, self.bitsize)
+
def read(self, cdata):
cdata = rffi.ptradd(cdata, self.offset)
if self.bitshift == self.BS_REGULAR:
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -182,9 +182,26 @@
if not is_union:
prev_bit_position += fbitsize
#
- fld = ctypestruct.W_CField(ftype, offset, bitshift, fbitsize)
- fields_list.append(fld)
- fields_dict[fname] = fld
+ if (len(fname) == 0 and
+ isinstance(ftype, ctypestruct.W_CTypeStructOrUnion)):
+ # a nested anonymous struct or union
+ srcfield2names = {}
+ for name, srcfld in ftype.fields_dict.items():
+ srcfield2names[srcfld] = name
+ for srcfld in ftype.fields_list:
+ fld = srcfld.make_shifted(offset)
+ fields_list.append(fld)
+ try:
+ fields_dict[srcfield2names[srcfld]] = fld
+ except KeyError:
+ pass
+ # always forbid such structures from being passed by value
+ custom_field_pos = True
+ else:
+ # a regular field
+ fld = ctypestruct.W_CField(ftype, offset, bitshift, fbitsize)
+ fields_list.append(fld)
+ fields_dict[fname] = fld
#
if maxsize < ftype.size:
maxsize = ftype.size
@@ -194,13 +211,13 @@
if is_union:
assert offset == 0
offset = maxsize
- else:
- if offset == 0:
- offset = 1
- offset = (offset + alignment - 1) & ~(alignment-1)
+ offset = (offset + alignment - 1) & ~(alignment-1)
+ # Like C, if the size of this structure would be zero, we compute it
+ # as 1 instead. But for ctypes support, we allow the manually-
+ # specified totalsize to be zero in this case.
if totalsize < 0:
- totalsize = offset
+ totalsize = offset or 1
elif totalsize < offset:
raise operationerrfmt(space.w_TypeError,
"%s cannot be of size %d: there are fields at least "
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -8,6 +8,11 @@
readbuf = str
bufchar = lambda x: x
bytechr = chr
+ class U(object):
+ def __add__(self, other):
+ return eval('u'+repr(other).replace(r'\\u', r'\u')
+ .replace(r'\\U', r'\U'))
+ u = U()
else:
type_or_class = "class"
long = int
@@ -18,6 +23,7 @@
readbuf = lambda buf: buf.tobytes()
bufchar = ord
bytechr = lambda n: bytes([n])
+ u = ""
def size_of_int():
BInt = new_primitive_type("int")
@@ -92,7 +98,7 @@
py.test.raises(TypeError, cast, p, None)
assert long(cast(p, min - 1)) == max
assert int(cast(p, b'\x08')) == 8
- assert int(cast(p, u'\x08')) == 8
+ assert int(cast(p, u+'\x08')) == 8
for name in ['char', 'short', 'int', 'long', 'long long']:
p = new_primitive_type('unsigned ' + name)
size = sizeof(p)
@@ -103,7 +109,7 @@
assert int(cast(p, max + 1)) == 0
assert long(cast(p, -1)) == max
assert int(cast(p, b'\xFE')) == 254
- assert int(cast(p, u'\xFE')) == 254
+ assert int(cast(p, u+'\xFE')) == 254
def test_no_float_on_int_types():
p = new_primitive_type('long')
@@ -136,7 +142,7 @@
assert cast(p, -1.1) != cast(p, -1.1)
assert repr(float(cast(p, -0.0))) == '-0.0'
assert float(cast(p, b'\x09')) == 9.0
- assert float(cast(p, u'\x09')) == 9.0
+ assert float(cast(p, u+'\x09')) == 9.0
assert float(cast(p, True)) == 1.0
py.test.raises(TypeError, cast, p, None)
@@ -286,12 +292,12 @@
assert p[0] == b'A'
py.test.raises(TypeError, newp, BPtr, 65)
py.test.raises(TypeError, newp, BPtr, b"foo")
- py.test.raises(TypeError, newp, BPtr, u"foo")
+ py.test.raises(TypeError, newp, BPtr, u+"foo")
c = cast(BChar, b'A')
assert str(c) == repr(c)
assert int(c) == ord(b'A')
py.test.raises(TypeError, cast, BChar, b'foo')
- py.test.raises(TypeError, cast, BChar, u'foo')
+ py.test.raises(TypeError, cast, BChar, u+'foo')
def test_reading_pointer_to_pointer():
BVoidP = new_pointer_type(new_void_type())
@@ -763,6 +769,11 @@
BFunc = new_function_type((BInt, BInt), BVoid, False)
assert repr(BFunc) == "<ctype 'void(*)(int, int)'>"
+def test_function_void_arg():
+ BVoid = new_void_type()
+ BInt = new_primitive_type("int")
+ py.test.raises(TypeError, new_function_type, (BVoid,), BInt, False)
+
def test_call_function_0():
BSignedChar = new_primitive_type("signed char")
BFunc0 = new_function_type((BSignedChar, BSignedChar), BSignedChar, False)
@@ -846,7 +857,7 @@
#
py.test.raises(TypeError, f, 123456)
py.test.raises(TypeError, f, "foo")
- py.test.raises(TypeError, f, u"bar")
+ py.test.raises(TypeError, f, u+"bar")
def test_call_function_7():
BChar = new_primitive_type("char")
@@ -871,8 +882,8 @@
BStructPtr = new_pointer_type(BStruct)
complete_struct_or_union(BStruct, [('a1', BChar, -1),
('a2', BShort, -1)])
- BFunc18 = new_function_type((BStructPtr,), BShort, False)
- f = cast(BFunc18, _testfunc(20))
+ BFunc20 = new_function_type((BStructPtr,), BShort, False)
+ f = cast(BFunc20, _testfunc(20))
x = newp(BStructPtr, {'a1': b'A', 'a2': -4042})
# test the exception that allows us to pass a 'struct foo' where the
# function really expects a 'struct foo *'.
@@ -880,6 +891,25 @@
assert res == -4042 + ord(b'A')
assert res == f(x)
+def test_call_function_21():
+ BInt = new_primitive_type("int")
+ BStruct = new_struct_type("foo")
+ complete_struct_or_union(BStruct, [('a', BInt, -1),
+ ('b', BInt, -1),
+ ('c', BInt, -1),
+ ('d', BInt, -1),
+ ('e', BInt, -1),
+ ('f', BInt, -1),
+ ('g', BInt, -1),
+ ('h', BInt, -1),
+ ('i', BInt, -1),
+ ('j', BInt, -1)])
+ BFunc21 = new_function_type((BStruct,), BInt, False)
+ f = cast(BFunc21, _testfunc(21))
+ res = f(range(13, 3, -1))
+ lst = [(n << i) for (i, n) in enumerate(range(13, 3, -1))]
+ assert res == sum(lst)
+
def test_call_function_9():
BInt = new_primitive_type("int")
BFunc9 = new_function_type((BInt,), BInt, True) # vararg
@@ -1031,6 +1061,31 @@
assert s.a == -10
assert s.b == 1E-42
+def test_callback_returning_big_struct():
+ BInt = new_primitive_type("int")
+ BStruct = new_struct_type("foo")
+ BStructPtr = new_pointer_type(BStruct)
+ complete_struct_or_union(BStruct, [('a', BInt, -1),
+ ('b', BInt, -1),
+ ('c', BInt, -1),
+ ('d', BInt, -1),
+ ('e', BInt, -1),
+ ('f', BInt, -1),
+ ('g', BInt, -1),
+ ('h', BInt, -1),
+ ('i', BInt, -1),
+ ('j', BInt, -1)])
+ def cb():
+ return newp(BStructPtr, range(13, 3, -1))[0]
+ BFunc = new_function_type((), BStruct)
+ f = callback(BFunc, cb)
+ s = f()
+ assert typeof(s) is BStruct
+ assert repr(s) in ["<cdata 'struct foo' owning 40 bytes>",
+ "<cdata 'struct foo' owning 80 bytes>"]
+ for i, name in enumerate("abcdefghij"):
+ assert getattr(s, name) == 13 - i
+
def test_callback_returning_void():
BVoid = new_void_type()
BFunc = new_function_type((), BVoid, False)
@@ -1106,7 +1161,7 @@
assert f(255) == b'\xFF'
def _hacked_pypy_uni4():
- pyuni4 = {1: True, 2: False}[len(u'\U00012345')]
+ pyuni4 = {1: True, 2: False}[len(u+'\U00012345')]
return 'PY_DOT_PY' in globals() and not pyuni4
def test_callback_returning_wchar_t():
@@ -1114,7 +1169,7 @@
BWChar = new_primitive_type("wchar_t")
def cb(n):
if n == -1:
- return u'\U00012345'
+ return u+'\U00012345'
if n == -2:
raise ValueError
return unichr(n)
@@ -1122,10 +1177,10 @@
f = callback(BFunc, cb)
assert f(0) == unichr(0)
assert f(255) == unichr(255)
- assert f(0x1234) == u'\u1234'
+ assert f(0x1234) == u+'\u1234'
if sizeof(BWChar) == 4 and not _hacked_pypy_uni4():
- assert f(-1) == u'\U00012345'
- assert f(-2) == u'\x00' # and an exception printed to stderr
+ assert f(-1) == u+'\U00012345'
+ assert f(-2) == u+'\x00' # and an exception printed to stderr
def test_struct_with_bitfields():
BLong = new_primitive_type("long")
@@ -1358,14 +1413,14 @@
def test_string_wchar():
BWChar = new_primitive_type("wchar_t")
- assert string(cast(BWChar, 42)) == u'*'
- assert string(cast(BWChar, 0x4253)) == u'\u4253'
- assert string(cast(BWChar, 0)) == u'\x00'
+ assert string(cast(BWChar, 42)) == u+'*'
+ assert string(cast(BWChar, 0x4253)) == u+'\u4253'
+ assert string(cast(BWChar, 0)) == u+'\x00'
BArray = new_array_type(new_pointer_type(BWChar), None)
- a = newp(BArray, [u'A', u'B', u'C'])
- assert type(string(a)) is unicode and string(a) == u'ABC'
+ a = newp(BArray, [u+'A', u+'B', u+'C'])
+ assert type(string(a)) is unicode and string(a) == u+'ABC'
if 'PY_DOT_PY' not in globals() and sys.version_info < (3,):
- assert string(a, 8).startswith(u'ABC') # may contain additional garbage
+ assert string(a, 8).startswith(u+'ABC') # may contain additional garbage
def test_string_typeerror():
BShort = new_primitive_type("short")
@@ -1516,7 +1571,7 @@
def test_wchar():
BWChar = new_primitive_type("wchar_t")
BInt = new_primitive_type("int")
- pyuni4 = {1: True, 2: False}[len(u'\U00012345')]
+ pyuni4 = {1: True, 2: False}[len(u+'\U00012345')]
wchar4 = {2: False, 4: True}[sizeof(BWChar)]
assert str(cast(BWChar, 0x45)) == "<cdata 'wchar_t' %s'E'>" % (
mandatory_u_prefix,)
@@ -1537,44 +1592,44 @@
complete_struct_or_union(BStruct, [('a1', BWChar, -1),
('a2', BWCharP, -1)])
s = newp(BStructPtr)
- s.a1 = u'\x00'
- assert s.a1 == u'\x00'
+ s.a1 = u+'\x00'
+ assert s.a1 == u+'\x00'
py.test.raises(TypeError, "s.a1 = b'a'")
py.test.raises(TypeError, "s.a1 = bytechr(0xFF)")
- s.a1 = u'\u1234'
- assert s.a1 == u'\u1234'
+ s.a1 = u+'\u1234'
+ assert s.a1 == u+'\u1234'
if pyuni4:
assert wchar4
- s.a1 = u'\U00012345'
- assert s.a1 == u'\U00012345'
+ s.a1 = u+'\U00012345'
+ assert s.a1 == u+'\U00012345'
elif wchar4:
if not _hacked_pypy_uni4():
s.a1 = cast(BWChar, 0x12345)
- assert s.a1 == u'\ud808\udf45'
- s.a1 = u'\ud807\udf44'
- assert s.a1 == u'\U00011f44'
+ assert s.a1 == u+'\ud808\udf45'
+ s.a1 = u+'\ud807\udf44'
+ assert s.a1 == u+'\U00011f44'
else:
- py.test.raises(TypeError, "s.a1 = u'\U00012345'")
+ py.test.raises(TypeError, "s.a1 = u+'\U00012345'")
#
BWCharArray = new_array_type(BWCharP, None)
- a = newp(BWCharArray, u'hello \u1234 world')
+ a = newp(BWCharArray, u+'hello \u1234 world')
assert len(a) == 14 # including the final null
- assert string(a) == u'hello \u1234 world'
- a[13] = u'!'
- assert string(a) == u'hello \u1234 world!'
+ assert string(a) == u+'hello \u1234 world'
+ a[13] = u+'!'
+ assert string(a) == u+'hello \u1234 world!'
assert str(a) == repr(a)
- assert a[6] == u'\u1234'
- a[6] = u'-'
- assert string(a) == u'hello - world!'
+ assert a[6] == u+'\u1234'
+ a[6] = u+'-'
+ assert string(a) == u+'hello - world!'
assert str(a) == repr(a)
#
if wchar4 and not _hacked_pypy_uni4():
- u = u'\U00012345\U00012346\U00012347'
- a = newp(BWCharArray, u)
+ u1 = u+'\U00012345\U00012346\U00012347'
+ a = newp(BWCharArray, u1)
assert len(a) == 4
- assert string(a) == u
+ assert string(a) == u1
assert len(list(a)) == 4
- expected = [u'\U00012345', u'\U00012346', u'\U00012347', unichr(0)]
+ expected = [u+'\U00012345', u+'\U00012346', u+'\U00012347', unichr(0)]
assert list(a) == expected
got = [a[i] for i in range(4)]
assert got == expected
@@ -1583,44 +1638,44 @@
w = cast(BWChar, 'a')
assert repr(w) == "<cdata 'wchar_t' %s'a'>" % mandatory_u_prefix
assert str(w) == repr(w)
- assert string(w) == u'a'
+ assert string(w) == u+'a'
assert int(w) == ord('a')
w = cast(BWChar, 0x1234)
assert repr(w) == "<cdata 'wchar_t' %s'\u1234'>" % mandatory_u_prefix
assert str(w) == repr(w)
- assert string(w) == u'\u1234'
+ assert string(w) == u+'\u1234'
assert int(w) == 0x1234
- w = cast(BWChar, u'\u8234')
+ w = cast(BWChar, u+'\u8234')
assert repr(w) == "<cdata 'wchar_t' %s'\u8234'>" % mandatory_u_prefix
assert str(w) == repr(w)
- assert string(w) == u'\u8234'
+ assert string(w) == u+'\u8234'
assert int(w) == 0x8234
- w = cast(BInt, u'\u1234')
+ w = cast(BInt, u+'\u1234')
assert repr(w) == "<cdata 'int' 4660>"
if wchar4 and not _hacked_pypy_uni4():
- w = cast(BWChar, u'\U00012345')
+ w = cast(BWChar, u+'\U00012345')
assert repr(w) == "<cdata 'wchar_t' %s'\U00012345'>" % (
mandatory_u_prefix,)
assert str(w) == repr(w)
- assert string(w) == u'\U00012345'
+ assert string(w) == u+'\U00012345'
assert int(w) == 0x12345
- w = cast(BInt, u'\U00012345')
+ w = cast(BInt, u+'\U00012345')
assert repr(w) == "<cdata 'int' 74565>"
- py.test.raises(TypeError, cast, BInt, u'')
- py.test.raises(TypeError, cast, BInt, u'XX')
- assert int(cast(BInt, u'a')) == ord('a')
+ py.test.raises(TypeError, cast, BInt, u+'')
+ py.test.raises(TypeError, cast, BInt, u+'XX')
+ assert int(cast(BInt, u+'a')) == ord('a')
#
- a = newp(BWCharArray, u'hello - world')
+ a = newp(BWCharArray, u+'hello - world')
p = cast(BWCharP, a)
- assert string(p) == u'hello - world'
- p[6] = u'\u2345'
- assert string(p) == u'hello \u2345 world'
+ assert string(p) == u+'hello - world'
+ p[6] = u+'\u2345'
+ assert string(p) == u+'hello \u2345 world'
#
- s = newp(BStructPtr, [u'\u1234', p])
- assert s.a1 == u'\u1234'
+ s = newp(BStructPtr, [u+'\u1234', p])
+ assert s.a1 == u+'\u1234'
assert s.a2 == p
assert str(s.a2) == repr(s.a2)
- assert string(s.a2) == u'hello \u2345 world'
+ assert string(s.a2) == u+'hello \u2345 world'
#
q = cast(BWCharP, 0)
assert str(q) == repr(q)
@@ -1631,7 +1686,7 @@
return len(string(p))
BFunc = new_function_type((BWCharP,), BInt, False)
f = callback(BFunc, cb, -42)
- assert f(u'a\u1234b') == 3
+ assert f(u+'a\u1234b') == 3
#
if wchar4 and not pyuni4 and not _hacked_pypy_uni4():
# try out-of-range wchar_t values
@@ -1951,3 +2006,50 @@
assert repr(p.a1).startswith("<cdata 'long *' 0x")
else:
assert repr(p.a1).startswith("<cdata 'long[%d]' 0x" % length)
+
+def test_nested_anonymous_struct():
+ BInt = new_primitive_type("int")
+ BChar = new_primitive_type("char")
+ BStruct = new_struct_type("foo")
+ BInnerStruct = new_struct_type("foo")
+ complete_struct_or_union(BInnerStruct, [('a1', BInt, -1),
+ ('a2', BChar, -1)])
+ complete_struct_or_union(BStruct, [('', BInnerStruct, -1),
+ ('a3', BChar, -1)])
+ assert sizeof(BInnerStruct) == sizeof(BInt) * 2 # with alignment
+ assert sizeof(BStruct) == sizeof(BInt) * 3 # 'a3' is placed after
+ d = _getfields(BStruct)
+ assert len(d) == 3
+ assert d[0][0] == 'a1'
+ assert d[0][1].type is BInt
+ assert d[0][1].offset == 0
+ assert d[0][1].bitshift == -1
+ assert d[0][1].bitsize == -1
+ assert d[1][0] == 'a2'
+ assert d[1][1].type is BChar
+ assert d[1][1].offset == sizeof(BInt)
+ assert d[1][1].bitshift == -1
+ assert d[1][1].bitsize == -1
+ assert d[2][0] == 'a3'
+ assert d[2][1].type is BChar
+ assert d[2][1].offset == sizeof(BInt) * 2
+ assert d[2][1].bitshift == -1
+ assert d[2][1].bitsize == -1
+
+def test_sizeof_union():
+ # a union has the largest alignment of its members, and a total size
+ # that is the largest of its items *possibly further aligned* if
+ # another smaller item has a larger alignment...
+ BChar = new_primitive_type("char")
+ BShort = new_primitive_type("short")
+ assert sizeof(BShort) == alignof(BShort) == 2
+ BStruct = new_struct_type("foo")
+ complete_struct_or_union(BStruct, [('a1', BChar),
+ ('a2', BChar),
+ ('a3', BChar)])
+ assert sizeof(BStruct) == 3 and alignof(BStruct) == 1
+ BUnion = new_union_type("u")
+ complete_struct_or_union(BUnion, [('s', BStruct),
+ ('i', BShort)])
+ assert sizeof(BUnion) == 4
+ assert alignof(BUnion) == 2
diff --git a/pypy/module/_cffi_backend/test/_test_lib.c b/pypy/module/_cffi_backend/test/_test_lib.c
--- a/pypy/module/_cffi_backend/test/_test_lib.c
+++ b/pypy/module/_cffi_backend/test/_test_lib.c
@@ -146,6 +146,21 @@
return ptr->a1 + ptr->a2;
}
+struct _testfunc21_s { int a, b, c, d, e, f, g, h, i, j; };
+static int _testfunc21(struct _testfunc21_s inlined)
+{
+ return ((inlined.a << 0) +
+ (inlined.b << 1) +
+ (inlined.c << 2) +
+ (inlined.d << 3) +
+ (inlined.e << 4) +
+ (inlined.f << 5) +
+ (inlined.g << 6) +
+ (inlined.h << 7) +
+ (inlined.i << 8) +
+ (inlined.j << 9));
+}
+
DLLEXPORT void *gettestfunc(int num)
{
void *f;
@@ -171,6 +186,7 @@
case 18: f = &_testfunc18; break;
case 19: f = &_testfunc19; break;
case 20: f = &_testfunc20; break;
+ case 21: f = &_testfunc21; break;
default:
return NULL;
}
diff --git a/pypy/module/_cffi_backend/test/test_c.py b/pypy/module/_cffi_backend/test/test_c.py
--- a/pypy/module/_cffi_backend/test/test_c.py
+++ b/pypy/module/_cffi_backend/test/test_c.py
@@ -1,7 +1,19 @@
from __future__ import with_statement
"""
This file is OBSCURE. Really. The purpose is to avoid copying and changing
-'test_c.py' from cffi/c/.
+'test_c.py' from cffi/c/ in the original CFFI repository:
+ https://bitbucket.org/cffi/cffi
+
+Adding a test here involves:
+1. add a test to cffi/c/test.py
+ - if you need a C function to call, add it into _cffi_backend.c
+ as a testfuncNN().
+2. have it pass when you run 'py.test test_c.py' in cffi
+3. check in and (if you can) push the changes
+4. copy test_c.py into _backend_test.py here, killing the few lines of header
+ - if you added a C function, it goes into _test_lib.c here
+ - if you could complete step 3, try running 'py.test test_file.py' here
+5. make the test pass in pypy ('py.test test_c.py')
"""
import py, sys, ctypes
if sys.version_info < (2, 6):
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -330,13 +330,11 @@
try:
space.call_method(w_iobase, 'flush')
except OperationError, e:
- # if it's an IOError or ValueError, ignore it (ValueError is
- # raised if by chance we are trying to flush a file which has
- # already been closed)
- if not (e.match(space, space.w_IOError) or
- e.match(space, space.w_ValueError)):
- raise
-
+ # Silencing all errors is bad, but getting randomly
+ # interrupted here is equally as bad, and potentially
+ # more frequent (because of shutdown issues).
+ pass
+
class AutoFlusher(object):
diff --git a/pypy/module/_multiprocessing/test/test_semaphore.py b/pypy/module/_multiprocessing/test/test_semaphore.py
--- a/pypy/module/_multiprocessing/test/test_semaphore.py
+++ b/pypy/module/_multiprocessing/test/test_semaphore.py
@@ -18,6 +18,8 @@
kind = self.SEMAPHORE
value = 1
maxvalue = 1
+ # the following line gets OSError: [Errno 38] Function not implemented
+ # if /dev/shm is not mounted on Linux
sem = SemLock(kind, value, maxvalue)
assert sem.kind == kind
assert sem.maxvalue == maxvalue
@@ -49,6 +51,8 @@
kind = self.RECURSIVE
value = 1
maxvalue = 1
+ # the following line gets OSError: [Errno 38] Function not implemented
+ # if /dev/shm is not mounted on Linux
sem = SemLock(kind, value, maxvalue)
sem.acquire()
diff --git a/pypy/module/itertools/test/test_itertools.py b/pypy/module/itertools/test/test_itertools.py
--- a/pypy/module/itertools/test/test_itertools.py
+++ b/pypy/module/itertools/test/test_itertools.py
@@ -88,6 +88,13 @@
list(it)
assert repr(it) == "repeat('foobar', 0)"
+ def test_repeat_len(self):
+ import itertools
+
+ r = itertools.repeat('a', 15)
+ r.next()
+ raises(TypeError, "len(itertools.repeat('xkcd'))")
+
def test_takewhile(self):
import itertools
diff --git a/pypy/module/micronumpy/strides.py b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -48,9 +48,12 @@
return rstrides, rbackstrides
def is_single_elem(space, w_elem, is_rec_type):
+ from pypy.module.micronumpy.interp_numarray import BaseArray
if (is_rec_type and space.isinstance_w(w_elem, space.w_tuple)):
return True
- if space.issequence_w(w_elem):
+ if (space.isinstance_w(w_elem, space.w_tuple) or
+ isinstance(w_elem, BaseArray) or
+ space.isinstance_w(w_elem, space.w_list)):
return False
return True
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
@@ -193,6 +193,19 @@
assert _to_coords(5, 'F') == [1, 2, 0]
assert _to_coords(13, 'F') == [1, 0, 2]
+ def test_find_shape(self):
+ from pypy.module.micronumpy.strides import find_shape_and_elems
+
+ space = self.space
+ shape, elems = find_shape_and_elems(space,
+ space.newlist([space.wrap("a"),
+ space.wrap("b")]),
+ None)
+ assert shape == [2]
+ assert space.str_w(elems[0]) == "a"
+ assert space.str_w(elems[1]) == "b"
+
+
class AppTestNumArray(BaseNumpyAppTest):
def w_CustomIndexObject(self, index):
class CustomIndexObject(object):
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py b/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py
@@ -253,3 +253,8 @@
TwoOutArgs(a, byref(b), c, byref(d))
assert b.value == 7
assert d.value == 11
+
+ def test_byref_cannot_be_bound(self):
+ class A(object):
+ _byref = byref
+ A._byref(c_int(5))
diff --git a/pypy/objspace/flow/operation.py b/pypy/objspace/flow/operation.py
--- a/pypy/objspace/flow/operation.py
+++ b/pypy/objspace/flow/operation.py
@@ -218,7 +218,6 @@
('inplace_xor', inplace_xor),
('iter', iter),
('next', next),
- ('next', __builtin__.next),
('get', get),
('set', set),
('delete', delete),
@@ -237,7 +236,9 @@
('div_ovf', div_ovf),
('mod_ovf', mod_ovf),
('lshift_ovf', lshift_ovf),
- ]
+]
+if hasattr(__builtin__, 'next'):
+ Table.append(('next', __builtin__.next))
def setup():
# insert all operators
diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py
--- a/pypy/objspace/std/celldict.py
+++ b/pypy/objspace/std/celldict.py
@@ -4,7 +4,7 @@
"""
from pypy.interpreter.baseobjspace import W_Root
-from pypy.objspace.std.dictmultiobject import IteratorImplementation
+from pypy.objspace.std.dictmultiobject import create_iterator_classes
from pypy.objspace.std.dictmultiobject import DictStrategy, _never_equal_to_string
from pypy.objspace.std.dictmultiobject import ObjectDictStrategy
from pypy.rlib import jit, rerased
@@ -124,9 +124,6 @@
w_res = self.getdictvalue_no_unwrapping(w_dict, key)
return unwrap_cell(w_res)
- def iter(self, w_dict):
- return ModuleDictIteratorImplementation(self.space, self, w_dict)
-
def w_keys(self, w_dict):
space = self.space
l = self.unerase(w_dict.dstorage).keys()
@@ -161,15 +158,15 @@
w_dict.strategy = strategy
w_dict.dstorage = strategy.erase(d_new)
-class ModuleDictIteratorImplementation(IteratorImplementation):
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(
- self, space, strategy, dictimplementation)
- dict_w = strategy.unerase(dictimplementation.dstorage)
- self.iterator = dict_w.iteritems()
+ def getiterkeys(self, w_dict):
+ return self.unerase(w_dict.dstorage).iterkeys()
+ def getitervalues(self, w_dict):
+ return self.unerase(w_dict.dstorage).itervalues()
+ def getiteritems(self, w_dict):
+ return self.unerase(w_dict.dstorage).iteritems()
+ def wrapkey(space, key):
+ return space.wrap(key)
+ def wrapvalue(space, value):
+ return unwrap_cell(value)
- def next_entry(self):
- for key, cell in self.iterator:
- return (self.space.wrap(key), unwrap_cell(cell))
- else:
- return None, None
+create_iterator_classes(ModuleDictStrategy)
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -7,8 +7,10 @@
from pypy.interpreter.argument import Signature
from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.rlib.objectmodel import r_dict, we_are_translated, specialize
+from pypy.rlib.objectmodel import r_dict, we_are_translated, specialize,\
+ newlist_hint
from pypy.rlib.debug import mark_dict_non_null
+from pypy.tool.sourcetools import func_with_new_name
from pypy.rlib import rerased
from pypy.rlib import jit
@@ -111,7 +113,7 @@
dict_methods = "setitem setitem_str getitem \
getitem_str delitem length \
clear w_keys values \
- items iter setdefault \
+ items iterkeys itervalues iteritems setdefault \
popitem listview_str listview_int".split()
def make_method(method):
@@ -120,6 +122,9 @@
f.func_name = method
return f
+ def view_as_kwargs(self):
+ return self.strategy.view_as_kwargs(self)
+
for method in dict_methods:
setattr(W_DictMultiObject, method, make_method(method))
@@ -134,30 +139,30 @@
raise NotImplementedError
def w_keys(self, w_dict):
- iterator = self.iter(w_dict)
- result = []
+ iterator = self.iterkeys(w_dict)
+ result = newlist_hint(self.length(w_dict))
while 1:
- w_key, w_value = iterator.next()
+ w_key = iterator.next_key()
if w_key is not None:
result.append(w_key)
else:
return self.space.newlist(result)
def values(self, w_dict):
- iterator = self.iter(w_dict)
- result = []
+ iterator = self.itervalues(w_dict)
+ result = newlist_hint(self.length(w_dict))
while 1:
- w_key, w_value = iterator.next()
+ w_value = iterator.next_value()
if w_value is not None:
result.append(w_value)
else:
return result
def items(self, w_dict):
- iterator = self.iter(w_dict)
- result = []
+ iterator = self.iteritems(w_dict)
+ result = newlist_hint(self.length(w_dict))
while 1:
- w_key, w_value = iterator.next()
+ w_key, w_value = iterator.next_item()
if w_key is not None:
result.append(self.space.newtuple([w_key, w_value]))
else:
@@ -169,8 +174,8 @@
# will take longer and longer. But all interesting strategies
# provide a better one.
space = self.space
- iterator = self.iter(w_dict)
- w_key, w_value = iterator.next()
+ iterator = self.iteritems(w_dict)
+ w_key, w_value = iterator.next_item()
self.delitem(w_dict, w_key)
return (w_key, w_value)
@@ -271,9 +276,6 @@
def length(self, w_dict):
return 0
- def iter(self, w_dict):
- return EmptyIteratorImplementation(self.space, self, w_dict)
-
def clear(self, w_dict):
return
@@ -283,31 +285,32 @@
def view_as_kwargs(self, w_dict):
return ([], [])
-registerimplementation(W_DictMultiObject)
+ # ---------- iterator interface ----------------
-# DictImplementation lattice
-# XXX fix me
+ def getiterkeys(self, w_dict):
+ return iter([None])
+ getitervalues = getiterkeys
+ def getiteritems(self, w_dict):
+ return iter([(None, None)])
# Iterator Implementation base classes
-class IteratorImplementation(object):
- def __init__(self, space, strategy, implementation):
- self.space = space
- self.strategy = strategy
- self.dictimplementation = implementation
- self.len = implementation.length()
- self.pos = 0
-
+def _new_next(TP):
+ if TP == 'key' or TP == 'value':
+ EMPTY = None
+ else:
+ EMPTY = None, None
+
def next(self):
if self.dictimplementation is None:
- return None, None
+ return EMPTY
if self.len != self.dictimplementation.length():
self.len = -1 # Make this error state sticky
raise OperationError(self.space.w_RuntimeError,
self.space.wrap("dictionary changed size during iteration"))
# look for the next entry
if self.pos < self.len:
- result = self.next_entry()
+ result = getattr(self, 'next_' + TP + '_entry')()
self.pos += 1
if self.strategy is self.dictimplementation.strategy:
return result # common case
@@ -316,6 +319,8 @@
# length of the dict. The (key, value) pair in 'result'
# might be out-of-date. We try to explicitly look up
# the key in the dict.
+ if TP == 'key' or TP == 'value':
+ return result
w_key = result[0]
w_value = self.dictimplementation.getitem(w_key)
if w_value is None:
@@ -325,22 +330,96 @@
return (w_key, w_value)
# no more entries
self.dictimplementation = None
- return None, None
+ return EMPTY
+ return func_with_new_name(next, 'next_' + TP)
- def next_entry(self):
- """ Purely abstract method
- """
- raise NotImplementedError
+class BaseIteratorImplementation(object):
+ def __init__(self, space, strategy, implementation):
+ self.space = space
+ self.strategy = strategy
+ self.dictimplementation = implementation
+ self.len = implementation.length()
+ self.pos = 0
def length(self):
if self.dictimplementation is not None:
return self.len - self.pos
return 0
-class EmptyIteratorImplementation(IteratorImplementation):
- def next(self):
- return (None, None)
+class BaseKeyIterator(BaseIteratorImplementation):
+ next_key = _new_next('key')
+class BaseValueIterator(BaseIteratorImplementation):
+ next_value = _new_next('value')
+
+class BaseItemIterator(BaseIteratorImplementation):
+ next_item = _new_next('item')
+
+def create_iterator_classes(dictimpl, override_next_item=None):
+ if not hasattr(dictimpl, 'wrapkey'):
+ wrapkey = lambda space, key : key
+ else:
+ wrapkey = dictimpl.wrapkey.im_func
+ if not hasattr(dictimpl, 'wrapvalue'):
+ wrapvalue = lambda space, key : key
+ else:
+ wrapvalue = dictimpl.wrapvalue.im_func
+
+ class IterClassKeys(BaseKeyIterator):
+ def __init__(self, space, strategy, impl):
+ self.iterator = strategy.getiterkeys(impl)
+ BaseIteratorImplementation.__init__(self, space, strategy, impl)
+
+ def next_key_entry(self):
+ for key in self.iterator:
+ return wrapkey(self.space, key)
+ else:
+ return None
+
+ class IterClassValues(BaseValueIterator):
+ def __init__(self, space, strategy, impl):
+ self.iterator = strategy.getitervalues(impl)
+ BaseIteratorImplementation.__init__(self, space, strategy, impl)
+
+ def next_value_entry(self):
+ for value in self.iterator:
+ return wrapvalue(self.space, value)
+ else:
+ return None
+
+ class IterClassItems(BaseItemIterator):
+ def __init__(self, space, strategy, impl):
+ self.iterator = strategy.getiteritems(impl)
+ BaseIteratorImplementation.__init__(self, space, strategy, impl)
+
+ if override_next_item is not None:
+ next_item_entry = override_next_item
+ else:
+ def next_item_entry(self):
+ for key, value in self.iterator:
+ return (wrapkey(self.space, key),
+ wrapvalue(self.space, value))
+ else:
+ return None, None
+
+ def iterkeys(self, w_dict):
+ return IterClassKeys(self.space, self, w_dict)
+
+ def itervalues(self, w_dict):
+ return IterClassValues(self.space, self, w_dict)
+
+ def iteritems(self, w_dict):
+ return IterClassItems(self.space, self, w_dict)
+ dictimpl.iterkeys = iterkeys
+ dictimpl.itervalues = itervalues
+ dictimpl.iteritems = iteritems
+
+create_iterator_classes(EmptyDictStrategy)
+
+registerimplementation(W_DictMultiObject)
+
+# DictImplementation lattice
+# XXX fix me
# concrete subclasses of the above
@@ -447,6 +526,15 @@
w_dict.strategy = strategy
w_dict.dstorage = strategy.erase(d_new)
+ # --------------- iterator interface -----------------
+
+ def getiterkeys(self, w_dict):
+ return self.unerase(w_dict.dstorage).iterkeys()
+ def getitervalues(self, w_dict):
+ return self.unerase(w_dict.dstorage).itervalues()
+ def getiteritems(self, w_dict):
+ return self.unerase(w_dict.dstorage).iteritems()
+
class ObjectDictStrategy(AbstractTypedStrategy, DictStrategy):
erase, unerase = rerased.new_erasing_pair("object")
@@ -470,12 +558,10 @@
def _never_equal_to(self, w_lookup_type):
return False
- def iter(self, w_dict):
- return ObjectIteratorImplementation(self.space, self, w_dict)
-
def w_keys(self, w_dict):
return self.space.newlist(self.unerase(w_dict.dstorage).keys())
+create_iterator_classes(ObjectDictStrategy)
class StringDictStrategy(AbstractTypedStrategy, DictStrategy):
@@ -520,12 +606,12 @@
def listview_str(self, w_dict):
return self.unerase(w_dict.dstorage).keys()
- def iter(self, w_dict):
- return StrIteratorImplementation(self.space, self, w_dict)
-
def w_keys(self, w_dict):
return self.space.newlist_str(self.listview_str(w_dict))
+ def wrapkey(space, key):
+ return space.wrap(key)
+
@jit.look_inside_iff(lambda self, w_dict:
w_dict_unrolling_heuristic(w_dict))
def view_as_kwargs(self, w_dict):
@@ -540,37 +626,8 @@
i += 1
return keys, values
-class _WrappedIteratorMixin(object):
- _mixin_ = True
+create_iterator_classes(StringDictStrategy)
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(self, space, strategy, dictimplementation)
- self.iterator = strategy.unerase(dictimplementation.dstorage).iteritems()
-
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for key, w_value in self.iterator:
- return self.space.wrap(key), w_value
- else:
- return None, None
-
-class _UnwrappedIteratorMixin:
- _mixin_ = True
-
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(self, space, strategy, dictimplementation)
- self.iterator = strategy.unerase(dictimplementation.dstorage).iteritems()
-
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for w_key, w_value in self.iterator:
- return w_key, w_value
- else:
- return None, None
-
-
-class StrIteratorImplementation(_WrappedIteratorMixin, IteratorImplementation):
- pass
class IntDictStrategy(AbstractTypedStrategy, DictStrategy):
erase, unerase = rerased.new_erasing_pair("int")
@@ -598,19 +655,15 @@
space.is_w(w_lookup_type, space.w_unicode)
)
- def iter(self, w_dict):
- return IntIteratorImplementation(self.space, self, w_dict)
-
def listview_int(self, w_dict):
return self.unerase(w_dict.dstorage).keys()
+ def wrapkey(space, key):
+ return space.wrap(key)
+
# XXX there is no space.newlist_int yet to implement w_keys more efficiently
-class IntIteratorImplementation(_WrappedIteratorMixin, IteratorImplementation):
- pass
-
-class ObjectIteratorImplementation(_UnwrappedIteratorMixin, IteratorImplementation):
- pass
+create_iterator_classes(IntDictStrategy)
init_signature = Signature(['seq_or_map'], None, 'kwargs')
init_defaults = [None]
@@ -636,9 +689,9 @@
w_dict.setitem(w_key, w_value)
def update1_dict_dict(space, w_dict, w_data):
- iterator = w_data.iter()
+ iterator = w_data.iteritems()
while 1:
- w_key, w_value = iterator.next()
+ w_key, w_value = iterator.next_item()
if w_key is None:
break
w_dict.setitem(w_key, w_value)
@@ -686,7 +739,7 @@
return space.newbool(w_dict.getitem(w_key) is not None)
def iter__DictMulti(space, w_dict):
- return W_DictMultiIterObject(space, w_dict.iter(), KEYSITER)
+ return W_DictMultiIterKeysObject(space, w_dict.iterkeys())
def eq__DictMulti_DictMulti(space, w_left, w_right):
if space.is_w(w_left, w_right):
@@ -694,9 +747,9 @@
if w_left.length() != w_right.length():
return space.w_False
- iteratorimplementation = w_left.iter()
+ iteratorimplementation = w_left.iteritems()
while 1:
- w_key, w_val = iteratorimplementation.next()
+ w_key, w_val = iteratorimplementation.next_item()
if w_key is None:
break
w_rightval = w_right.getitem(w_key)
@@ -711,9 +764,9 @@
returns the smallest key in acontent for which b's value is different or absent and this value """
w_smallest_diff_a_key = None
w_its_value = None
- iteratorimplementation = w_a.iter()
+ iteratorimplementation = w_a.iteritems()
while 1:
- w_key, w_val = iteratorimplementation.next()
+ w_key, w_val = iteratorimplementation.next_item()
if w_key is None:
break
if w_smallest_diff_a_key is None or space.is_true(space.lt(w_key, w_smallest_diff_a_key)):
@@ -768,13 +821,13 @@
return W_DictViewValuesObject(space, w_self)
def dict_iteritems__DictMulti(space, w_self):
- return W_DictMultiIterObject(space, w_self.iter(), ITEMSITER)
+ return W_DictMultiIterItemsObject(space, w_self.iteritems())
def dict_iterkeys__DictMulti(space, w_self):
- return W_DictMultiIterObject(space, w_self.iter(), KEYSITER)
+ return W_DictMultiIterKeysObject(space, w_self.iterkeys())
def dict_itervalues__DictMulti(space, w_self):
- return W_DictMultiIterObject(space, w_self.iter(), VALUESITER)
+ return W_DictMultiIterValuesObject(space, w_self.itervalues())
def dict_clear__DictMulti(space, w_self):
w_self.clear()
@@ -818,38 +871,73 @@
# Iteration
-KEYSITER = 0
-ITEMSITER = 1
-VALUESITER = 2
-
-class W_DictMultiIterObject(W_Object):
+class W_DictMultiIterKeysObject(W_Object):
from pypy.objspace.std.dicttype import dictiter_typedef as typedef
- _immutable_fields_ = ["iteratorimplementation", "itertype"]
+ _immutable_fields_ = ["iteratorimplementation"]
- def __init__(w_self, space, iteratorimplementation, itertype):
+ ignore_for_isinstance_cache = True
+
+ def __init__(w_self, space, iteratorimplementation):
w_self.space = space
w_self.iteratorimplementation = iteratorimplementation
- w_self.itertype = itertype
-registerimplementation(W_DictMultiIterObject)
+registerimplementation(W_DictMultiIterKeysObject)
-def iter__DictMultiIterObject(space, w_dictiter):
+class W_DictMultiIterValuesObject(W_Object):
+ from pypy.objspace.std.dicttype import dictiter_typedef as typedef
+
+ _immutable_fields_ = ["iteratorimplementation"]
+
+ ignore_for_isinstance_cache = True
+
+ def __init__(w_self, space, iteratorimplementation):
+ w_self.space = space
+ w_self.iteratorimplementation = iteratorimplementation
+
+registerimplementation(W_DictMultiIterValuesObject)
+
+class W_DictMultiIterItemsObject(W_Object):
+ from pypy.objspace.std.dicttype import dictiter_typedef as typedef
+
+ _immutable_fields_ = ["iteratorimplementation"]
+
+ ignore_for_isinstance_cache = True
+
+ def __init__(w_self, space, iteratorimplementation):
+ w_self.space = space
+ w_self.iteratorimplementation = iteratorimplementation
+
+registerimplementation(W_DictMultiIterItemsObject)
+
+def iter__DictMultiIterKeysObject(space, w_dictiter):
return w_dictiter
-def next__DictMultiIterObject(space, w_dictiter):
+def next__DictMultiIterKeysObject(space, w_dictiter):
iteratorimplementation = w_dictiter.iteratorimplementation
- w_key, w_value = iteratorimplementation.next()
+ w_key = iteratorimplementation.next_key()
if w_key is not None:
- itertype = w_dictiter.itertype
- if itertype == KEYSITER:
- return w_key
- elif itertype == VALUESITER:
- return w_value
- elif itertype == ITEMSITER:
- return space.newtuple([w_key, w_value])
- else:
- assert 0, "should be unreachable"
+ return w_key
+ raise OperationError(space.w_StopIteration, space.w_None)
+
+def iter__DictMultiIterValuesObject(space, w_dictiter):
+ return w_dictiter
+
+def next__DictMultiIterValuesObject(space, w_dictiter):
+ iteratorimplementation = w_dictiter.iteratorimplementation
+ w_value = iteratorimplementation.next_value()
+ if w_value is not None:
+ return w_value
+ raise OperationError(space.w_StopIteration, space.w_None)
+
+def iter__DictMultiIterItemsObject(space, w_dictiter):
+ return w_dictiter
+
+def next__DictMultiIterItemsObject(space, w_dictiter):
+ iteratorimplementation = w_dictiter.iteratorimplementation
+ w_key, w_value = iteratorimplementation.next_item()
+ if w_key is not None:
+ return space.newtuple([w_key, w_value])
raise OperationError(space.w_StopIteration, space.w_None)
# ____________________________________________________________
@@ -884,7 +972,6 @@
def all_contained_in(space, w_dictview, w_otherview):
w_iter = space.iter(w_dictview)
- assert isinstance(w_iter, W_DictMultiIterObject)
while True:
try:
diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py
--- a/pypy/objspace/std/dictproxyobject.py
+++ b/pypy/objspace/std/dictproxyobject.py
@@ -1,6 +1,6 @@
from pypy.objspace.std.model import registerimplementation, W_Object
from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.dictmultiobject import W_DictMultiObject, IteratorImplementation
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject, create_iterator_classes
from pypy.objspace.std.dictmultiobject import DictStrategy
from pypy.objspace.std.typeobject import unwrap_cell
from pypy.interpreter.error import OperationError, operationerrfmt
@@ -71,9 +71,6 @@
def length(self, w_dict):
return len(self.unerase(w_dict.dstorage).dict_w)
- def iter(self, w_dict):
- return DictProxyIteratorImplementation(self.space, self, w_dict)
-
def keys(self, w_dict):
space = self.space
return space.newlist_str(self.unerase(w_dict.dstorage).dict_w.keys())
@@ -96,15 +93,15 @@
w_type.dict_w.clear()
w_type.mutated(None)
-class DictProxyIteratorImplementation(IteratorImplementation):
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(
- self, space, strategy, dictimplementation)
- w_type = strategy.unerase(dictimplementation.dstorage)
- self.iterator = w_type.dict_w.iteritems()
+ def getiterkeys(self, w_dict):
+ return self.unerase(w_dict.dstorage).dict_w.iterkeys()
+ def getitervalues(self, w_dict):
+ return self.unerase(w_dict.dstorage).dict_w.itervalues()
+ def getiteritems(self, w_dict):
+ return self.unerase(w_dict.dstorage).dict_w.iteritems()
+ def wrapkey(space, key):
+ return space.wrap(key)
+ def wrapvalue(space, value):
+ return unwrap_cell(space, value)
- def next_entry(self):
- for key, w_value in self.iterator:
- return (self.space.wrap(key), unwrap_cell(self.space, w_value))
- else:
- return (None, None)
+create_iterator_classes(DictProxyStrategy)
diff --git a/pypy/objspace/std/identitydict.py b/pypy/objspace/std/identitydict.py
--- a/pypy/objspace/std/identitydict.py
+++ b/pypy/objspace/std/identitydict.py
@@ -5,8 +5,7 @@
from pypy.rlib.debug import mark_dict_non_null
from pypy.objspace.std.dictmultiobject import (AbstractTypedStrategy,
DictStrategy,
- IteratorImplementation,
- _UnwrappedIteratorMixin)
+ create_iterator_classes)
# this strategy is selected by EmptyDictStrategy.switch_to_correct_strategy
@@ -77,12 +76,7 @@
def _never_equal_to(self, w_lookup_type):
return False
- def iter(self, w_dict):
- return IdentityDictIteratorImplementation(self.space, self, w_dict)
-
def w_keys(self, w_dict):
return self.space.newlist(self.unerase(w_dict.dstorage).keys())
-
-class IdentityDictIteratorImplementation(_UnwrappedIteratorMixin, IteratorImplementation):
- pass
+create_iterator_classes(IdentityDictStrategy)
diff --git a/pypy/objspace/std/kwargsdict.py b/pypy/objspace/std/kwargsdict.py
--- a/pypy/objspace/std/kwargsdict.py
+++ b/pypy/objspace/std/kwargsdict.py
@@ -3,8 +3,8 @@
from pypy.rlib import rerased, jit
from pypy.objspace.std.dictmultiobject import (DictStrategy,
+ create_iterator_classes,
EmptyDictStrategy,
- IteratorImplementation,
ObjectDictStrategy,
StringDictStrategy)
@@ -39,9 +39,6 @@
def _never_equal_to(self, w_lookup_type):
return False
- def iter(self, w_dict):
- return KwargsDictIterator(self.space, self, w_dict)
-
def w_keys(self, w_dict):
return self.space.newlist([self.space.wrap(key) for key in self.unerase(w_dict.dstorage)[0]])
@@ -157,19 +154,24 @@
keys, values_w = self.unerase(w_dict.dstorage)
return keys[:], values_w[:] # copy to make non-resizable
+ def getiterkeys(self, w_dict):
+ return iter(self.unerase(w_dict.dstorage)[0])
+ def getitervalues(self, w_dict):
+ return iter(self.unerase(w_dict.dstorage)[1])
+ def getiteritems(self, w_dict):
+ keys = self.unerase(w_dict.dstorage)[0]
+ return iter(range(len(keys)))
+ def wrapkey(space, key):
+ return space.wrap(key)
-class KwargsDictIterator(IteratorImplementation):
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(self, space, strategy, dictimplementation)
- keys, values_w = strategy.unerase(self.dictimplementation.dstorage)
- self.iterator = iter(range(len(keys)))
- # XXX this potentially leaks
- self.keys = keys
- self.values_w = values_w
+def next_item(self):
+ strategy = self.strategy
+ assert isinstance(strategy, KwargsDictStrategy)
+ for i in self.iterator:
+ keys, values_w = strategy.unerase(
+ self.dictimplementation.dstorage)
+ return self.space.wrap(keys[i]), values_w[i]
+ else:
+ return None, None
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for i in self.iterator:
- return self.space.wrap(self.keys[i]), self.values_w[i]
- else:
- return None, None
+create_iterator_classes(KwargsDictStrategy, override_next_item=next_item)
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -5,7 +5,7 @@
from pypy.interpreter.baseobjspace import W_Root
from pypy.objspace.std.dictmultiobject import W_DictMultiObject, DictStrategy, ObjectDictStrategy
-from pypy.objspace.std.dictmultiobject import IteratorImplementation
+from pypy.objspace.std.dictmultiobject import BaseKeyIterator, BaseValueIterator, BaseItemIterator
from pypy.objspace.std.dictmultiobject import _never_equal_to_string
from pypy.objspace.std.objectobject import W_ObjectObject
from pypy.objspace.std.typeobject import TypeCell
@@ -674,9 +674,6 @@
res += 1
return res
- def iter(self, w_dict):
- return MapDictIteratorImplementation(self.space, self, w_dict)
-
def clear(self, w_dict):
w_obj = self.unerase(w_dict.dstorage)
new_obj = w_obj._get_mapdict_map().remove_dict_entries(w_obj)
@@ -694,32 +691,83 @@
# XXX could implement a more efficient w_keys based on space.newlist_str
+ def iterkeys(self, w_dict):
+ return MapDictIteratorKeys(self.space, self, w_dict)
+ def itervalues(self, w_dict):
+ return MapDictIteratorValues(self.space, self, w_dict)
+ def iteritems(self, w_dict):
+ return MapDictIteratorItems(self.space, self, w_dict)
+
+
def materialize_r_dict(space, obj, dict_w):
map = obj._get_mapdict_map()
new_obj = map.materialize_r_dict(space, obj, dict_w)
_become(obj, new_obj)
-class MapDictIteratorImplementation(IteratorImplementation):
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(
- self, space, strategy, dictimplementation)
- w_obj = strategy.unerase(dictimplementation.dstorage)
- self.w_obj = w_obj
- self.orig_map = self.curr_map = w_obj._get_mapdict_map()
+class MapDictIteratorKeys(BaseKeyIterator):
+ def __init__(self, space, strategy, dictimplementation):
+ BaseKeyIterator.__init__(
+ self, space, strategy, dictimplementation)
+ w_obj = strategy.unerase(dictimplementation.dstorage)
+ self.w_obj = w_obj
+ self.orig_map = self.curr_map = w_obj._get_mapdict_map()
- def next_entry(self):
- implementation = self.dictimplementation
- assert isinstance(implementation.strategy, MapDictStrategy)
- if self.orig_map is not self.w_obj._get_mapdict_map():
- return None, None
- if self.curr_map:
- curr_map = self.curr_map.search(DICT)
- if curr_map:
- self.curr_map = curr_map.back
- attr = curr_map.selector[0]
- w_attr = self.space.wrap(attr)
- return w_attr, self.w_obj.getdictvalue(self.space, attr)
- return None, None
+ def next_key_entry(self):
+ implementation = self.dictimplementation
+ assert isinstance(implementation.strategy, MapDictStrategy)
+ if self.orig_map is not self.w_obj._get_mapdict_map():
+ return None
+ if self.curr_map:
+ curr_map = self.curr_map.search(DICT)
+ if curr_map:
+ self.curr_map = curr_map.back
+ attr = curr_map.selector[0]
+ w_attr = self.space.wrap(attr)
+ return w_attr
+ return None
+
+class MapDictIteratorValues(BaseValueIterator):
+ def __init__(self, space, strategy, dictimplementation):
+ BaseValueIterator.__init__(
+ self, space, strategy, dictimplementation)
+ w_obj = strategy.unerase(dictimplementation.dstorage)
+ self.w_obj = w_obj
+ self.orig_map = self.curr_map = w_obj._get_mapdict_map()
+
+ def next_value_entry(self):
+ implementation = self.dictimplementation
+ assert isinstance(implementation.strategy, MapDictStrategy)
+ if self.orig_map is not self.w_obj._get_mapdict_map():
+ return None
+ if self.curr_map:
+ curr_map = self.curr_map.search(DICT)
+ if curr_map:
+ self.curr_map = curr_map.back
+ attr = curr_map.selector[0]
+ return self.w_obj.getdictvalue(self.space, attr)
+ return None
+
+class MapDictIteratorItems(BaseItemIterator):
+ def __init__(self, space, strategy, dictimplementation):
+ BaseItemIterator.__init__(
+ self, space, strategy, dictimplementation)
+ w_obj = strategy.unerase(dictimplementation.dstorage)
+ self.w_obj = w_obj
+ self.orig_map = self.curr_map = w_obj._get_mapdict_map()
+
+ def next_item_entry(self):
+ implementation = self.dictimplementation
+ assert isinstance(implementation.strategy, MapDictStrategy)
+ if self.orig_map is not self.w_obj._get_mapdict_map():
+ return None, None
+ if self.curr_map:
+ curr_map = self.curr_map.search(DICT)
+ if curr_map:
+ self.curr_map = curr_map.back
+ attr = curr_map.selector[0]
+ w_attr = self.space.wrap(attr)
+ return w_attr, self.w_obj.getdictvalue(self.space, attr)
+ return None, None
# ____________________________________________________________
# Magic caching
diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py
--- a/pypy/objspace/std/model.py
+++ b/pypy/objspace/std/model.py
@@ -101,7 +101,9 @@
tupleobject.W_TupleObject: [],
listobject.W_ListObject: [],
dictmultiobject.W_DictMultiObject: [],
- dictmultiobject.W_DictMultiIterObject: [],
+ dictmultiobject.W_DictMultiIterKeysObject: [],
+ dictmultiobject.W_DictMultiIterValuesObject: [],
+ dictmultiobject.W_DictMultiIterItemsObject: [],
stringobject.W_StringObject: [],
bytearrayobject.W_BytearrayObject: [],
typeobject.W_TypeObject: [],
@@ -127,7 +129,9 @@
self.imported_but_not_registered = {
dictmultiobject.W_DictMultiObject: True, # XXXXXX
- dictmultiobject.W_DictMultiIterObject: True,
+ dictmultiobject.W_DictMultiIterKeysObject: True,
+ dictmultiobject.W_DictMultiIterValuesObject: True,
+ dictmultiobject.W_DictMultiIterItemsObject: True,
listobject.W_ListObject: True,
stringobject.W_StringObject: True,
tupleobject.W_TupleObject: True,
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -453,6 +453,8 @@
class E(dict):
pass
assert isinstance(D.fromkeys([1, 2]), E)
+ assert dict.fromkeys({"a": 2, "b": 3}) == {"a": None, "b": None}
+ assert dict.fromkeys({"a": 2, 1: 3}) == {"a": None, 1: None}
def test_str_uses_repr(self):
class D(dict):
@@ -1046,10 +1048,10 @@
def test_iter(self):
self.fill_impl()
- iteratorimplementation = self.impl.iter()
+ iteratorimplementation = self.impl.iteritems()
items = []
while 1:
- item = iteratorimplementation.next()
+ item = iteratorimplementation.next_item()
if item == (None, None):
break
items.append(item)
diff --git a/pypy/objspace/std/test/test_kwargsdict.py b/pypy/objspace/std/test/test_kwargsdict.py
--- a/pypy/objspace/std/test/test_kwargsdict.py
+++ b/pypy/objspace/std/test/test_kwargsdict.py
@@ -142,3 +142,9 @@
d = f()
assert "EmptyKwargsDictStrategy" in self.get_strategy(d)
+ def test_iterator(self):
+ def f(**args):
+ return args
+
+ assert dict.fromkeys(f(a=2, b=3)) == {"a": None, "b": None}
+ assert sorted(f(a=2, b=3).itervalues()) == [2, 3]
diff --git a/pypy/rlib/runicode.py b/pypy/rlib/runicode.py
--- a/pypy/rlib/runicode.py
+++ b/pypy/rlib/runicode.py
@@ -47,12 +47,10 @@
def raise_unicode_exception_decode(errors, encoding, msg, s,
startingpos, endingpos):
- assert isinstance(s, str)
raise UnicodeDecodeError(encoding, s, startingpos, endingpos, msg)
def raise_unicode_exception_encode(errors, encoding, msg, u,
startingpos, endingpos):
- assert isinstance(u, unicode)
raise UnicodeEncodeError(encoding, u, startingpos, endingpos, msg)
# ____________________________________________________________
diff --git a/pypy/rlib/test/test_objectmodel.py b/pypy/rlib/test/test_objectmodel.py
--- a/pypy/rlib/test/test_objectmodel.py
+++ b/pypy/rlib/test/test_objectmodel.py
@@ -427,7 +427,7 @@
assert f.foo == 'foo'
assert f(1, 'hello', 42) == (1, 'hello', 42)
exc = py.test.raises(TypeError, "f(1, 2, 3)")
- assert exc.value.message == "f argument number 2 must be of type <type 'str'>"
+ assert exc.value.message == "f argument 'b' must be of type <type 'str'>"
py.test.raises(TypeError, "f('hello', 'world', 3)")
diff --git a/pypy/rpython/lltypesystem/rbuilder.py b/pypy/rpython/lltypesystem/rbuilder.py
--- a/pypy/rpython/lltypesystem/rbuilder.py
+++ b/pypy/rpython/lltypesystem/rbuilder.py
@@ -59,7 +59,7 @@
@classmethod
def ll_new(cls, init_size):
- if init_size < 0 or init_size > MAX:
+ if init_size < 0:
init_size = MAX
ll_builder = lltype.malloc(cls.lowleveltype.TO)
ll_builder.allocated = init_size
diff --git a/pypy/rpython/lltypesystem/rstr.py b/pypy/rpython/lltypesystem/rstr.py
--- a/pypy/rpython/lltypesystem/rstr.py
+++ b/pypy/rpython/lltypesystem/rstr.py
@@ -143,6 +143,13 @@
s.chars[i] = cast_primitive(UniChar, value.chars[i])
return s
+ def ll_decode_utf8(self, llvalue):
+ from pypy.rpython.annlowlevel import hlstr, llunicode
+ from pypy.rlib.runicode import str_decode_utf_8
+ value = hlstr(llvalue)
+ univalue, _ = str_decode_utf_8(value, len(value), 'strict')
+ return llunicode(univalue)
+
class UnicodeRepr(BaseLLStringRepr, AbstractUnicodeRepr):
lowleveltype = Ptr(UNICODE)
basetype = basestring
@@ -187,6 +194,14 @@
result.chars[i] = cast_primitive(Char, c)
return result
+ @jit.elidable
+ def ll_encode_utf8(self, ll_s):
+ from pypy.rpython.annlowlevel import hlunicode, llstr
+ from pypy.rlib.runicode import unicode_encode_utf_8
+ s = hlunicode(ll_s)
+ bytes = unicode_encode_utf_8(s, len(s), 'strict')
+ return llstr(bytes)
+
class CharRepr(AbstractCharRepr, StringRepr):
lowleveltype = Char
diff --git a/pypy/rpython/ootypesystem/rstr.py b/pypy/rpython/ootypesystem/rstr.py
--- a/pypy/rpython/ootypesystem/rstr.py
+++ b/pypy/rpython/ootypesystem/rstr.py
@@ -60,6 +60,13 @@
sb.ll_append_char(cast_primitive(UniChar, c))
return sb.ll_build()
+ def ll_decode_utf8(self, llvalue):
+ from pypy.rpython.annlowlevel import hlstr, oounicode
+ from pypy.rlib.runicode import str_decode_utf_8
+ value = hlstr(llvalue)
+ univalue, _ = str_decode_utf_8(value, len(value), 'strict')
+ return oounicode(univalue)
+
class UnicodeRepr(BaseOOStringRepr, AbstractUnicodeRepr):
lowleveltype = ootype.Unicode
@@ -98,6 +105,13 @@
sb.ll_append_char(cast_primitive(Char, c))
return sb.ll_build()
+ def ll_encode_utf8(self, ll_s):
+ from pypy.rpython.annlowlevel import hlunicode, oostr
+ from pypy.rlib.runicode import unicode_encode_utf_8
+ s = hlunicode(ll_s)
+ bytes = unicode_encode_utf_8(s, len(s), 'strict')
+ return oostr(bytes)
+
class CharRepr(AbstractCharRepr, StringRepr):
lowleveltype = Char
diff --git a/pypy/rpython/rstr.py b/pypy/rpython/rstr.py
--- a/pypy/rpython/rstr.py
+++ b/pypy/rpython/rstr.py
@@ -309,6 +309,8 @@
return hop.gendirectcall(self.ll.ll_str2unicode, v_self)
elif encoding == 'latin-1':
return hop.gendirectcall(self.ll_decode_latin1, v_self)
+ elif encoding == 'utf-8':
+ return hop.gendirectcall(self.ll_decode_utf8, v_self)
else:
raise TyperError("encoding %s not implemented" % (encoding, ))
@@ -340,6 +342,8 @@
return hop.gendirectcall(self.ll_str, v_self)
elif encoding == "latin-1":
return hop.gendirectcall(self.ll_encode_latin1, v_self)
+ elif encoding == 'utf-8':
+ return hop.gendirectcall(self.ll_encode_utf8, v_self)
else:
raise TyperError("encoding %s not implemented" % (encoding, ))
diff --git a/pypy/rpython/test/test_runicode.py b/pypy/rpython/test/test_runicode.py
--- a/pypy/rpython/test/test_runicode.py
+++ b/pypy/rpython/test/test_runicode.py
@@ -98,9 +98,11 @@
self.interpret_raises(UnicodeEncodeError, f, [1234])
def test_unicode_encode(self):
- def f(x):
- y = u'xxx'
- return (y + unichr(x)).encode('ascii') + y.encode('latin-1')
+ def f(n):
+ x = u'xxx' + unichr(n)
+ y = u'àèì' + unichr(n)
+ z = u'美' + unichr(n)
+ return x.encode('ascii') + y.encode('latin-1') + z.encode('utf-8')
assert self.ll_to_string(self.interpret(f, [38])) == f(38)
@@ -128,11 +130,14 @@
assert self.interpret(f, [300, False]) == f(300, False)
def test_unicode_decode(self):
- def f(x):
- y = 'xxx'
- return (y + chr(x)).decode('ascii') + chr(x).decode("latin-1")
+ strings = ['xxx', u'àèì'.encode('latin-1'), u'美'.encode('utf-8')]
+ def f(n):
+ x = strings[n]
+ y = strings[n+1]
+ z = strings[n+2]
+ return x.decode('ascii') + y.decode('latin-1') + z.decode('utf-8')
- assert self.ll_to_string(self.interpret(f, [38])) == f(38)
+ assert self.ll_to_string(self.interpret(f, [0])) == f(0)
def test_unicode_decode_error(self):
def f(x):
diff --git a/pypy/translator/sandbox/test/test_sandlib.py b/pypy/translator/sandbox/test/test_sandlib.py
--- a/pypy/translator/sandbox/test/test_sandlib.py
+++ b/pypy/translator/sandbox/test/test_sandlib.py
@@ -106,7 +106,7 @@
pass
def entry_point(argv):
- fd = os.open("tcp://codespeak.net:80", os.O_RDONLY, 0777)
+ fd = os.open("tcp://pypy.org:80", os.O_RDONLY, 0777)
os.write(fd, 'GET /\n')
print os.read(fd, 30)
return 0
More information about the pypy-commit
mailing list