[pypy-commit] pypy remove-list-smm-2: hg merge remove-dict-smm
Manuel Jacob
noreply at buildbot.pypy.org
Fri May 17 16:24:47 CEST 2013
Author: Manuel Jacob
Branch: remove-list-smm-2
Changeset: r64259:45c2aa4fb0ed
Date: 2013-05-17 15:18 +0200
http://bitbucket.org/pypy/pypy/changeset/45c2aa4fb0ed/
Log: hg merge remove-dict-smm
diff --git a/lib-python/2.7/socket.py b/lib-python/2.7/socket.py
--- a/lib-python/2.7/socket.py
+++ b/lib-python/2.7/socket.py
@@ -324,7 +324,12 @@
if self._close:
self._sock.close()
else:
- self._sock._decref_socketios()
+ try:
+ self._sock._decref_socketios()
+ except AttributeError:
+ pass # bah, someone built a _fileobject manually
+ # with some unexpected replacement of the
+ # _socketobject class
self._sock = None
def __del__(self):
diff --git a/lib-python/2.7/test/test_codecs.py b/lib-python/2.7/test/test_codecs.py
--- a/lib-python/2.7/test/test_codecs.py
+++ b/lib-python/2.7/test/test_codecs.py
@@ -2,7 +2,11 @@
import unittest
import codecs
import locale
-import sys, StringIO, _testcapi
+import sys, StringIO
+try:
+ import _testcapi
+except ImportError:
+ _testcapi = None
class Queue(object):
"""
@@ -1387,8 +1391,7 @@
decodedresult += reader.read()
self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding))
- if (encoding not in broken_incremental_coders and
- hasattr(_testcapi, 'codec_incrementalencoder')):
+ if encoding not in broken_incremental_coders and _testcapi:
# check incremental decoder/encoder (fetched via the Python
# and C API) and iterencode()/iterdecode()
try:
diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py
--- a/lib-python/2.7/test/test_descr.py
+++ b/lib-python/2.7/test/test_descr.py
@@ -2080,9 +2080,8 @@
except ImportError:
pass
else:
- if hasattr(_testcapi, 'test_with_docstring'):
- class X(object):
- p = property(_testcapi.test_with_docstring)
+ class X(object):
+ p = property(_testcapi.test_with_docstring)
def test_properties_plus(self):
class C(object):
diff --git a/lib-python/2.7/test/test_traceback.py b/lib-python/2.7/test/test_traceback.py
--- a/lib-python/2.7/test/test_traceback.py
+++ b/lib-python/2.7/test/test_traceback.py
@@ -180,7 +180,7 @@
def test_traceback_format(self):
if traceback_print is None:
- return
+ raise unittest.SkipTest('Requires _testcapi')
try:
raise KeyError('blah')
except KeyError:
diff --git a/lib-python/2.7/test/test_unicode.py b/lib-python/2.7/test/test_unicode.py
--- a/lib-python/2.7/test/test_unicode.py
+++ b/lib-python/2.7/test/test_unicode.py
@@ -1612,7 +1612,7 @@
try:
from _testcapi import unicode_encodedecimal
except ImportError:
- return
+ raise unittest.SkipTest('Requires _testcapi')
self.assertEqual(unicode_encodedecimal(u'123'),
b'123')
self.assertEqual(unicode_encodedecimal(u'\u0663.\u0661\u0664'),
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -130,7 +130,7 @@
RegrTest('test_bz2.py', usemodules='bz2'),
RegrTest('test_calendar.py'),
RegrTest('test_call.py', core=True),
- RegrTest('test_capi.py'),
+ RegrTest('test_capi.py', usemodules='cpyext'),
RegrTest('test_cd.py'),
RegrTest('test_cfgparser.py'),
RegrTest('test_cgi.py'),
@@ -177,7 +177,7 @@
RegrTest('test_cprofile.py'),
RegrTest('test_crypt.py', usemodules='crypt'),
RegrTest('test_csv.py', usemodules='_csv'),
- RegrTest('test_ctypes.py', usemodules="_rawffi thread"),
+ RegrTest('test_ctypes.py', usemodules="_rawffi thread cpyext"),
RegrTest('test_curses.py'),
RegrTest('test_datetime.py', usemodules='binascii struct'),
RegrTest('test_dbm.py'),
diff --git a/lib_pypy/_testcapi.py b/lib_pypy/_testcapi.py
--- a/lib_pypy/_testcapi.py
+++ b/lib_pypy/_testcapi.py
@@ -57,6 +57,6 @@
try:
import cpyext
except ImportError:
- pass
+ raise ImportError("No module named '_testcapi'")
else:
compile_shared()
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -47,7 +47,7 @@
# The short X.Y version.
version = '2.0'
# The full version, including alpha/beta/rc tags.
-release = '2.0.0'
+release = '2.0.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -22,7 +22,8 @@
will capture the revision number of this change for the release;
some of the next updates may be done before or after branching; make
sure things are ported back to the trunk and to the branch as
- necessary
+ necessary; also update the version number in pypy/doc/conf.py,
+ and in pypy/doc/index.rst
* update pypy/doc/contributor.rst (and possibly LICENSE)
* rename pypy/doc/whatsnew_head.rst to whatsnew_VERSION.rst
and create a fresh whatsnew_head.rst after the release
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -40,7 +40,7 @@
* `FAQ`_: some frequently asked questions.
-* `Release 2.0`_: the latest official release
+* `Release 2.0.1`_: the latest official release
* `PyPy Blog`_: news and status info about PyPy
@@ -110,7 +110,7 @@
.. _`Getting Started`: getting-started.html
.. _`Papers`: extradoc.html
.. _`Videos`: video-index.html
-.. _`Release 2.0`: http://pypy.org/download.html
+.. _`Release 2.0.1`: http://pypy.org/download.html
.. _`speed.pypy.org`: http://speed.pypy.org
.. _`RPython toolchain`: translation.html
.. _`potential project ideas`: project-ideas.html
diff --git a/pypy/doc/release-2.0.1.rst b/pypy/doc/release-2.0.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-2.0.1.rst
@@ -0,0 +1,46 @@
+==============================
+PyPy 2.0.1 - Bohr Smørrebrød
+==============================
+
+We're pleased to announce PyPy 2.0.1. This is a stable bugfix release
+over `2.0`_. You can download it here:
+
+ http://pypy.org/download.html
+
+The fixes are mainly about fatal errors or crashes in our stdlib. See
+below for more details.
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy 2.0 and cpython 2.7.3`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 64 or
+Windows 32. Support for ARM is progressing but not bug-free yet.
+
+.. _`pypy 2.0 and cpython 2.7.3`: http://speed.pypy.org
+
+Highlights
+==========
+
+- fix an occasional crash in the JIT that ends in `RPython Fatal error:
+ NotImplementedError`__.
+
+- `id(x)` is now always a positive number (except on int/float/long/complex).
+ This fixes an issue in ``_sqlite.py`` (mostly for 32-bit Linux).
+
+- fix crashes of callback-from-C-functions (with cffi) when used together
+ with Stackless features, on asmgcc (i.e. Linux only). Now `gevent should
+ work better`__.
+
+- work around an eventlet issue with `socket._decref_socketios()`__.
+
+.. __: https://bugs.pypy.org/issue1482
+.. __: http://mail.python.org/pipermail/pypy-dev/2013-May/011362.html
+.. __: https://bugs.pypy.org/issue1468
+.. _2.0: release-2.0.0.html
+
+Cheers,
+arigo et. al. for the PyPy team
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
@@ -16,3 +16,9 @@
.. branch: remove-set-smm
Remove multi-methods on sets
+
+.. branch: numpy-subarrays
+Implement subarrays for numpy
+
+.. branch: remove-dict-smm
+Remove multi-methods on dict
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -242,6 +242,11 @@
def __spacebind__(self, space):
return self
+ def unwrap(self, space):
+ """NOT_RPYTHON"""
+ # _____ this code is here to support testing only _____
+ return self
+
class W_InterpIterable(W_Root):
def __init__(self, space, w_iterable):
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -920,7 +920,7 @@
import app_main
app_main.setup_bootstrap_path('/tmp/pypy-c') # stdlib not found
assert sys.executable == ''
- assert sys.path == old_sys_path + [self.goal_dir]
+ assert sys.path == old_sys_path
app_main.setup_bootstrap_path(self.fake_exe)
assert sys.executable == self.fake_exe
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -114,8 +114,11 @@
ge = _make_comparison('ge')
def hash(self):
- h = (objectmodel.compute_identity_hash(self.ctype) ^
- rffi.cast(lltype.Signed, self._cdata))
+ h = rffi.cast(lltype.Signed, self._cdata)
+ # To hash pointers in dictionaries. Assumes that h shows some
+ # alignment (to 4, 8, maybe 16 bytes), so we use the following
+ # formula to avoid the trailing bits being always 0.
+ h = h ^ (h >> 4)
return self.space.wrap(h)
def getitem(self, w_index):
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
@@ -365,8 +365,9 @@
BInt = new_primitive_type("int")
BFloat = new_primitive_type("float")
for i in range(1, 20):
- if (hash(cast(BChar, chr(i))) !=
- hash(cast(BInt, i))):
+ x1 = cast(BChar, chr(i))
+ x2 = cast(BInt, i)
+ if hash(x1) != hash(x2):
break
else:
raise AssertionError("hashes are equal")
@@ -2723,6 +2724,14 @@
assert x.__name__ == '<cdata>'
assert hasattr(x, '__doc__')
+def test_different_types_of_ptr_equality():
+ BVoidP = new_pointer_type(new_void_type())
+ BIntP = new_pointer_type(new_primitive_type("int"))
+ x = cast(BVoidP, 12345)
+ assert x == cast(BIntP, 12345)
+ assert x != cast(BIntP, 12344)
+ assert hash(x) == hash(cast(BIntP, 12345))
+
def test_version():
# this test is here mostly for PyPy
assert __version__ == "0.6"
diff --git a/pypy/module/_ffi/test/test_funcptr.py b/pypy/module/_ffi/test/test_funcptr.py
--- a/pypy/module/_ffi/test/test_funcptr.py
+++ b/pypy/module/_ffi/test/test_funcptr.py
@@ -74,9 +74,9 @@
from _ffi import CDLL, types
# this should return *all* loaded libs, dlopen(NULL)
dll = CDLL(None)
- # Assume CPython, or PyPy compiled with cpyext
- res = dll.getfunc('Py_IsInitialized', [], types.slong)()
- assert res == 1
+ # libm should be loaded
+ res = dll.getfunc('sqrt', [types.double], types.double)(1.0)
+ assert res == 1.0
def test_callfunc(self):
from _ffi import CDLL, types
@@ -139,7 +139,7 @@
def test_pointer_args(self):
"""
- extern int dummy; // defined in test_void_result
+ extern int dummy; // defined in test_void_result
DLLEXPORT int* get_dummy_ptr() { return &dummy; }
DLLEXPORT void set_val_to_ptr(int* ptr, int val) { *ptr = val; }
"""
@@ -158,7 +158,7 @@
def test_convert_pointer_args(self):
"""
- extern int dummy; // defined in test_void_result
+ extern int dummy; // defined in test_void_result
DLLEXPORT int* get_dummy_ptr(); // defined in test_pointer_args
DLLEXPORT void set_val_to_ptr(int* ptr, int val); // ditto
"""
@@ -170,7 +170,7 @@
def _as_ffi_pointer_(self, ffitype):
assert ffitype is types.void_p
return self.value
-
+
libfoo = CDLL(self.libfoo_name)
get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
get_dummy_ptr = libfoo.getfunc('get_dummy_ptr', [], types.void_p)
@@ -259,7 +259,7 @@
def test_typed_pointer_args(self):
"""
- extern int dummy; // defined in test_void_result
+ extern int dummy; // defined in test_void_result
DLLEXPORT int* get_dummy_ptr(); // defined in test_pointer_args
DLLEXPORT void set_val_to_ptr(int* ptr, int val); // ditto
"""
@@ -551,7 +551,7 @@
from _ffi import CDLL, types
libfoo = CDLL(self.libfoo_name)
raises(TypeError, "libfoo.getfunc('sum_xy', [types.void], types.sint)")
-
+
def test_OSError_loading(self):
from _ffi import CDLL, types
raises(OSError, "CDLL('I do not exist')")
@@ -606,7 +606,7 @@
from _rawffi import FUNCFLAG_STDCALL
libm = CDLL(self.libm_name)
pow_addr = libm.getaddressindll('pow')
- wrong_pow = FuncPtr.fromaddr(pow_addr, 'pow',
+ wrong_pow = FuncPtr.fromaddr(pow_addr, 'pow',
[types.double, types.double], types.double, FUNCFLAG_STDCALL)
try:
wrong_pow(2, 3) == 8
@@ -622,7 +622,7 @@
from _rawffi import FUNCFLAG_STDCALL
kernel = WinDLL('Kernel32.dll')
sleep_addr = kernel.getaddressindll('Sleep')
- sleep = FuncPtr.fromaddr(sleep_addr, 'sleep', [types.uint],
+ sleep = FuncPtr.fromaddr(sleep_addr, 'sleep', [types.uint],
types.void, FUNCFLAG_STDCALL)
sleep(10)
diff --git a/pypy/module/sys/initpath.py b/pypy/module/sys/initpath.py
--- a/pypy/module/sys/initpath.py
+++ b/pypy/module/sys/initpath.py
@@ -68,7 +68,7 @@
If it cannot be found, return (None, None).
"""
if executable == '':
- return None, None
+ executable = 'pypy-c'
search = executable
while True:
dirname = resolvedirof(search)
diff --git a/pypy/module/sys/system.py b/pypy/module/sys/system.py
--- a/pypy/module/sys/system.py
+++ b/pypy/module/sys/system.py
@@ -1,6 +1,6 @@
"""Information about the current system."""
from pypy.interpreter import gateway
-from rpython.rlib import rfloat, rbigint
+from rpython.rlib import rbigint, rfloat
from rpython.rtyper.lltypesystem import rffi
@@ -47,7 +47,6 @@
return space.call_function(w_float_info, space.newtuple(info_w))
def get_long_info(space):
- #assert rbigint.SHIFT == 31
bits_per_digit = rbigint.SHIFT
sizeof_digit = rffi.sizeof(rbigint.STORE_TYPE)
info_w = [
@@ -58,7 +57,4 @@
return space.call_function(w_long_info, space.newtuple(info_w))
def get_float_repr_style(space):
- if rfloat.USE_SHORT_FLOAT_REPR:
- return space.wrap("short")
- else:
- return space.wrap("legacy")
+ return space.wrap("short" if rfloat.USE_SHORT_FLOAT_REPR else "legacy")
diff --git a/pypy/module/sys/test/test_initpath.py b/pypy/module/sys/test/test_initpath.py
--- a/pypy/module/sys/test/test_initpath.py
+++ b/pypy/module/sys/test/test_initpath.py
@@ -16,9 +16,12 @@
build_hierarchy(tmpdir)
path, prefix = find_stdlib(None, str(pypy))
assert prefix == tmpdir
- # shouldn't find stdlib if executable == '' even if parent dir has a stdlib
- monkeypatch.chdir(tmpdir.join('bin'))
- assert find_stdlib(None, '') == (None, None)
+ # in executable is None look for stdlib based on the working directory
+ # see lib-python/2.7/test/test_sys.py:test_executable
+ _, prefix = find_stdlib(None, '')
+ cwd = os.path.dirname(os.path.realpath(__file__))
+ assert prefix is not None
+ assert cwd.startswith(str(prefix))
@py.test.mark.skipif('not hasattr(os, "symlink")')
def test_find_stdlib_follow_symlink(tmpdir):
diff --git a/pypy/objspace/fake/checkmodule.py b/pypy/objspace/fake/checkmodule.py
--- a/pypy/objspace/fake/checkmodule.py
+++ b/pypy/objspace/fake/checkmodule.py
@@ -5,7 +5,6 @@
def checkmodule(*modnames):
config = get_pypy_config(translating=True)
space = FakeObjSpace(config)
- space.setup()
seeobj_w = []
for modname in modnames:
mod = __import__('pypy.module.%s' % modname, None, None, ['__doc__'])
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -110,6 +110,7 @@
def __init__(self, config=None):
self._seen_extras = []
ObjSpace.__init__(self, config=config)
+ self.setup()
def _freeze_(self):
return True
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
@@ -1,19 +1,19 @@
-import py, sys
-from pypy.objspace.std.model import registerimplementation, W_Object
-from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.setobject import set_typedef as settypedef
-from pypy.objspace.std.setobject import frozenset_typedef as frozensettypedef
+from pypy.interpreter import gateway
+from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.mixedmodule import MixedModule
from pypy.interpreter.signature import Signature
+from pypy.objspace.std.stdtypedef import StdTypeDef
+from rpython.rlib import rerased, jit
+from rpython.rlib.debug import mark_dict_non_null
from rpython.rlib.objectmodel import r_dict, specialize, newlist_hint
-from rpython.rlib.debug import mark_dict_non_null
from rpython.tool.sourcetools import func_with_new_name
-from rpython.rlib import rerased, jit
UNROLL_CUTOFF = 5
+
def _is_str(space, w_key):
return space.is_w(space.type(w_key), space.w_str)
@@ -40,9 +40,20 @@
w_dct.length() <= UNROLL_CUTOFF)
-class W_DictMultiObject(W_Object):
- from pypy.objspace.std.dicttype import dict_typedef as typedef
+def negate(f):
+ def _negator(self, space, w_other):
+ # no need to use space.is_ / space.not_
+ tmp = f(self, space, w_other)
+ if tmp is space.w_NotImplemented:
+ return space.w_NotImplemented
+ elif tmp is space.w_False:
+ return space.w_True
+ else:
+ return space.w_False
+ _negator.func_name = 'negate-%s' % f.func_name
+ return _negator
+class W_DictMultiObject(W_Root):
@staticmethod
def allocate_and_init_instance(space, w_type=None, module=False,
instance=False, strdict=False, kwargs=False):
@@ -108,6 +119,230 @@
def setitem_str(self, key, w_value):
self.strategy.setitem_str(self, key, w_value)
+ @staticmethod
+ def descr_new(space, w_dicttype, __args__):
+ w_obj = W_DictMultiObject.allocate_and_init_instance(space, w_dicttype)
+ return w_obj
+
+ @staticmethod
+ def descr_fromkeys(space, w_type, w_keys, w_fill=None):
+ if w_fill is None:
+ w_fill = space.w_None
+ if space.is_w(w_type, space.w_dict):
+ w_dict = W_DictMultiObject.allocate_and_init_instance(space, w_type)
+
+ strlist = space.listview_str(w_keys)
+ if strlist is not None:
+ for key in strlist:
+ w_dict.setitem_str(key, w_fill)
+ else:
+ for w_key in space.listview(w_keys):
+ w_dict.setitem(w_key, w_fill)
+ else:
+ w_dict = space.call_function(w_type)
+ for w_key in space.listview(w_keys):
+ space.setitem(w_dict, w_key, w_fill)
+ return w_dict
+
+ def descr_init(self, space, __args__):
+ init_or_update(space, self, __args__, 'dict')
+
+ def descr_repr(self, space):
+ ec = space.getexecutioncontext()
+ w_currently_in_repr = ec._py_repr
+ if w_currently_in_repr is None:
+ w_currently_in_repr = ec._py_repr = space.newdict()
+ return dictrepr(space, w_currently_in_repr, self)
+
+ def descr_eq(self, space, w_other):
+ if space.is_w(self, w_other):
+ return space.w_True
+ if not isinstance(w_other, W_DictMultiObject):
+ return space.w_NotImplemented
+
+ if self.length() != w_other.length():
+ return space.w_False
+ iteratorimplementation = self.iteritems()
+ while 1:
+ w_key, w_val = iteratorimplementation.next_item()
+ if w_key is None:
+ break
+ w_rightval = w_other.getitem(w_key)
+ if w_rightval is None:
+ return space.w_False
+ if not space.eq_w(w_val, w_rightval):
+ return space.w_False
+ return space.w_True
+
+ def descr_lt(self, space, w_other):
+ if not isinstance(w_other, W_DictMultiObject):
+ return space.w_NotImplemented
+ return self._compare_lt(space, w_other)
+
+ def descr_gt(self, space, w_other):
+ if not isinstance(w_other, W_DictMultiObject):
+ return space.w_NotImplemented
+ return w_other._compare_lt(space, self)
+
+ def _compare_lt(self, space, w_other):
+ # Different sizes, no problem
+ if self.length() < w_other.length():
+ return space.w_True
+ if self.length() > w_other.length():
+ return space.w_False
+
+ # Same size
+ w_leftdiff, w_leftval = characterize(space, self, w_other)
+ if w_leftdiff is None:
+ return space.w_False
+ w_rightdiff, w_rightval = characterize(space, w_other, self)
+ if w_rightdiff is None:
+ # w_leftdiff is not None, w_rightdiff is None
+ return space.w_True
+ w_res = space.lt(w_leftdiff, w_rightdiff)
+ if (not space.is_true(w_res) and
+ space.eq_w(w_leftdiff, w_rightdiff) and
+ w_rightval is not None):
+ w_res = space.lt(w_leftval, w_rightval)
+ return w_res
+
+ descr_ne = negate(descr_eq)
+ descr_le = negate(descr_gt)
+ descr_ge = negate(descr_lt)
+
+ def descr_len(self, space):
+ return space.wrap(self.length())
+
+ def descr_iter(self, space):
+ return W_DictMultiIterKeysObject(space, self.iterkeys())
+
+ def descr_contains(self, space, w_key):
+ return space.newbool(self.getitem(w_key) is not None)
+
+ def descr_getitem(self, space, w_key):
+ w_value = self.getitem(w_key)
+ if w_value is not None:
+ return w_value
+
+ w_missing_item = self.missing_method(space, w_key)
+ if w_missing_item is not None:
+ return w_missing_item
+
+ space.raise_key_error(w_key)
+
+ def descr_setitem(self, space, w_newkey, w_newvalue):
+ self.setitem(w_newkey, w_newvalue)
+
+ def descr_delitem(self, space, w_key):
+ try:
+ self.delitem(w_key)
+ except KeyError:
+ space.raise_key_error(w_key)
+
+ def descr_reversed(self, space):
+ raise OperationError(space.w_TypeError, space.wrap('argument to reversed() must be a sequence'))
+
+ def descr_copy(self, space):
+ """D.copy() -> a shallow copy of D"""
+ w_new = W_DictMultiObject.allocate_and_init_instance(space)
+ update1_dict_dict(space, w_new, self)
+ return w_new
+
+ def descr_items(self, space):
+ """D.items() -> list of D's (key, value) pairs, as 2-tuples"""
+ return space.newlist(self.items())
+
+ def descr_keys(self, space):
+ """D.keys() -> list of D's keys"""
+ return self.w_keys()
+
+ def descr_values(self, space):
+ """D.values() -> list of D's values"""
+ return space.newlist(self.values())
+
+ def descr_iteritems(self, space):
+ """D.iteritems() -> an iterator over the (key, value) items of D"""
+ return W_DictMultiIterItemsObject(space, self.iteritems())
+
+ def descr_iterkeys(self, space):
+ """D.iterkeys() -> an iterator over the keys of D"""
+ return W_DictMultiIterKeysObject(space, self.iterkeys())
+
+ def descr_itervalues(self, space):
+ """D.itervalues() -> an iterator over the values of D"""
+ return W_DictMultiIterValuesObject(space, self.itervalues())
+
+ def descr_viewitems(self, space):
+ """D.viewitems() -> a set-like object providing a view on D's items"""
+ return W_DictViewItemsObject(space, self)
+
+ def descr_viewkeys(self, space):
+ """D.viewkeys() -> a set-like object providing a view on D's keys"""
+ return W_DictViewKeysObject(space, self)
+
+ def descr_viewvalues(self, space):
+ """D.viewvalues() -> an object providing a view on D's values"""
+ return W_DictViewValuesObject(space, self)
+
+ def descr_has_key(self, space, w_key):
+ """D.has_key(k) -> True if D has a key k, else False"""
+ return space.newbool(self.getitem(w_key) is not None)
+
+ def descr_clear(self, space):
+ """D.clear() -> None. Remove all items from D."""
+ self.clear()
+
+ @gateway.unwrap_spec(w_default=gateway.WrappedDefault(None))
+ def descr_get(self, space, w_key, w_default):
+ """D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None."""
+ w_value = self.getitem(w_key)
+ if w_value is not None:
+ return w_value
+ else:
+ return w_default
+
+ @gateway.unwrap_spec(defaults_w='args_w')
+ def descr_pop(self, space, w_key, defaults_w):
+ """D.pop(k[,d]) -> v, remove specified key and return the
+ corresponding value\nIf key is not found, d is returned if given,
+ otherwise KeyError is raised
+ """
+ len_defaults = len(defaults_w)
+ if len_defaults > 1:
+ raise operationerrfmt(space.w_TypeError,
+ "pop expected at most 2 arguments, got %d",
+ 1 + len_defaults)
+ w_item = self.getitem(w_key)
+ if w_item is None:
+ if len_defaults > 0:
+ return defaults_w[0]
+ else:
+ space.raise_key_error(w_key)
+ else:
+ self.delitem(w_key)
+ return w_item
+
+ def descr_popitem(self, space):
+ """D.popitem() -> (k, v), remove and return some (key, value) pair as
+ a\n2-tuple; but raise KeyError if D is empty"""
+ try:
+ w_key, w_value = self.popitem()
+ except KeyError:
+ raise OperationError(space.w_KeyError,
+ space.wrap("popitem(): dictionary is empty"))
+ return space.newtuple([w_key, w_value])
+
+ @gateway.unwrap_spec(w_default=gateway.WrappedDefault(None))
+ def descr_setdefault(self, space, w_key, w_default):
+ """D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"""
+ return self.setdefault(w_key, w_default)
+
+ def descr_update(self, space, __args__):
+ """D.update(E, **F) -> None. Update D from E and F: for k in E: D[k]
+ = E[k]\n(if E has keys else: for (k, v) in E: D[k] = v) then: for k in
+ F: D[k] = F[k]"""
+ init_or_update(space, self, __args__, 'dict.update')
+
def _add_indirections():
dict_methods = "getitem getitem_str setitem setdefault \
@@ -128,8 +363,87 @@
_add_indirections()
+
+app = gateway.applevel('''
+ def dictrepr(currently_in_repr, d):
+ if len(d) == 0:
+ return "{}"
+ dict_id = id(d)
+ if dict_id in currently_in_repr:
+ return '{...}'
+ currently_in_repr[dict_id] = 1
+ try:
+ items = []
+ # XXX for now, we cannot use iteritems() at app-level because
+ # we want a reasonable result instead of a RuntimeError
+ # even if the dict is mutated by the repr() in the loop.
+ for k, v in dict.items(d):
+ items.append(repr(k) + ": " + repr(v))
+ return "{" + ', '.join(items) + "}"
+ finally:
+ try:
+ del currently_in_repr[dict_id]
+ except:
+ pass
+''', filename=__file__)
+
+dictrepr = app.interphook("dictrepr")
+
+
+W_DictMultiObject.typedef = StdTypeDef("dict",
+ __doc__ = '''dict() -> new empty dictionary.
+dict(mapping) -> new dictionary initialized from a mapping object\'s
+ (key, value) pairs.
+dict(seq) -> new dictionary initialized as if via:
+ d = {}
+ for k, v in seq:
+ d[k] = v
+dict(**kwargs) -> new dictionary initialized with the name=value pairs
+ in the keyword argument list. For example: dict(one=1, two=2)''',
+ __new__ = gateway.interp2app(W_DictMultiObject.descr_new),
+ fromkeys = gateway.interp2app(W_DictMultiObject.descr_fromkeys,
+ as_classmethod=True),
+ __hash__ = None,
+ __repr__ = gateway.interp2app(W_DictMultiObject.descr_repr),
+ __init__ = gateway.interp2app(W_DictMultiObject.descr_init),
+
+ __eq__ = gateway.interp2app(W_DictMultiObject.descr_eq),
+ __ne__ = gateway.interp2app(W_DictMultiObject.descr_ne),
+ __lt__ = gateway.interp2app(W_DictMultiObject.descr_lt),
+ __le__ = gateway.interp2app(W_DictMultiObject.descr_le),
+ __gt__ = gateway.interp2app(W_DictMultiObject.descr_gt),
+ __ge__ = gateway.interp2app(W_DictMultiObject.descr_ge),
+
+ __len__ = gateway.interp2app(W_DictMultiObject.descr_len),
+ __iter__ = gateway.interp2app(W_DictMultiObject.descr_iter),
+ __contains__ = gateway.interp2app(W_DictMultiObject.descr_contains),
+
+ __getitem__ = gateway.interp2app(W_DictMultiObject.descr_getitem),
+ __setitem__ = gateway.interp2app(W_DictMultiObject.descr_setitem),
+ __delitem__ = gateway.interp2app(W_DictMultiObject.descr_delitem),
+
+ __reversed__ = gateway.interp2app(W_DictMultiObject.descr_reversed),
+ copy = gateway.interp2app(W_DictMultiObject.descr_copy),
+ items = gateway.interp2app(W_DictMultiObject.descr_items),
+ keys = gateway.interp2app(W_DictMultiObject.descr_keys),
+ values = gateway.interp2app(W_DictMultiObject.descr_values),
+ iteritems = gateway.interp2app(W_DictMultiObject.descr_iteritems),
+ iterkeys = gateway.interp2app(W_DictMultiObject.descr_iterkeys),
+ itervalues = gateway.interp2app(W_DictMultiObject.descr_itervalues),
+ viewkeys = gateway.interp2app(W_DictMultiObject.descr_viewkeys),
+ viewitems = gateway.interp2app(W_DictMultiObject.descr_viewitems),
+ viewvalues = gateway.interp2app(W_DictMultiObject.descr_viewvalues),
+ has_key = gateway.interp2app(W_DictMultiObject.descr_has_key),
+ clear = gateway.interp2app(W_DictMultiObject.descr_clear),
+ get = gateway.interp2app(W_DictMultiObject.descr_get),
+ pop = gateway.interp2app(W_DictMultiObject.descr_pop),
+ popitem = gateway.interp2app(W_DictMultiObject.descr_popitem),
+ setdefault = gateway.interp2app(W_DictMultiObject.descr_setdefault),
+ update = gateway.interp2app(W_DictMultiObject.descr_update),
+ )
+
+
class DictStrategy(object):
-
def __init__(self, space):
self.space = space
@@ -171,7 +485,6 @@
# it ends up taking n**2 time, because the next() calls below
# will take longer and longer. But all interesting strategies
# provide a better one.
- space = self.space
iterator = self.iteritems(w_dict)
w_key, w_value = iterator.next_item()
self.delitem(w_dict, w_key)
@@ -195,8 +508,8 @@
def view_as_kwargs(self, w_dict):
return (None, None)
+
class EmptyDictStrategy(DictStrategy):
-
erase, unerase = rerased.new_erasing_pair("empty")
erase = staticmethod(erase)
unerase = staticmethod(unerase)
@@ -301,6 +614,7 @@
def getiteritems(self, w_dict):
return iter([(None, None)])
+
# Iterator Implementation base classes
def _new_next(TP):
@@ -308,7 +622,7 @@
EMPTY = None
else:
EMPTY = None, None
-
+
def next(self):
if self.dictimplementation is None:
return EMPTY
@@ -372,7 +686,7 @@
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)
@@ -424,11 +738,6 @@
create_iterator_classes(EmptyDictStrategy)
-registerimplementation(W_DictMultiObject)
-
-# DictImplementation lattice
-# XXX fix me
-
# concrete subclasses of the above
@@ -543,7 +852,6 @@
class ObjectDictStrategy(AbstractTypedStrategy, DictStrategy):
-
erase, unerase = rerased.new_erasing_pair("object")
erase = staticmethod(erase)
unerase = staticmethod(unerase)
@@ -576,8 +884,8 @@
create_iterator_classes(ObjectDictStrategy)
+
class StringDictStrategy(AbstractTypedStrategy, DictStrategy):
-
erase, unerase = rerased.new_erasing_pair("string")
erase = staticmethod(erase)
unerase = staticmethod(unerase)
@@ -642,7 +950,6 @@
class UnicodeDictStrategy(AbstractTypedStrategy, DictStrategy):
-
erase, unerase = rerased.new_erasing_pair("unicode")
erase = staticmethod(erase)
unerase = staticmethod(unerase)
@@ -744,9 +1051,6 @@
create_iterator_classes(IntDictStrategy)
-init_signature = Signature(['seq_or_map'], None, 'kwargs')
-init_defaults = [None]
-
def update1(space, w_dict, w_data):
if space.findattr(w_data, space.wrap("keys")) is None:
@@ -788,6 +1092,9 @@
w_dict.setitem(w_key, w_value)
+init_signature = Signature(['seq_or_map'], None, 'kwargs')
+init_defaults = [None]
+
def init_or_update(space, w_dict, __args__, funcname):
w_src, w_kwds = __args__.parse_obj(
None, funcname,
@@ -798,61 +1105,6 @@
if space.is_true(w_kwds):
update1(space, w_dict, w_kwds)
-def init__DictMulti(space, w_dict, __args__):
- init_or_update(space, w_dict, __args__, 'dict')
-
-def dict_update__DictMulti(space, w_dict, __args__):
- init_or_update(space, w_dict, __args__, 'dict.update')
-
-def getitem__DictMulti_ANY(space, w_dict, w_key):
- w_value = w_dict.getitem(w_key)
- if w_value is not None:
- return w_value
-
- w_missing_item = w_dict.missing_method(space, w_key)
- if w_missing_item is not None:
- return w_missing_item
-
- space.raise_key_error(w_key)
-
-def setitem__DictMulti_ANY_ANY(space, w_dict, w_newkey, w_newvalue):
- w_dict.setitem(w_newkey, w_newvalue)
-
-def delitem__DictMulti_ANY(space, w_dict, w_key):
- try:
- w_dict.delitem(w_key)
- except KeyError:
- space.raise_key_error(w_key)
-
-def len__DictMulti(space, w_dict):
- return space.wrap(w_dict.length())
-
-def contains__DictMulti_ANY(space, w_dict, w_key):
- return space.newbool(w_dict.getitem(w_key) is not None)
-
-dict_has_key__DictMulti_ANY = contains__DictMulti_ANY
-
-def iter__DictMulti(space, w_dict):
- return W_DictMultiIterKeysObject(space, w_dict.iterkeys())
-
-def eq__DictMulti_DictMulti(space, w_left, w_right):
- if space.is_w(w_left, w_right):
- return space.w_True
-
- if w_left.length() != w_right.length():
- return space.w_False
- iteratorimplementation = w_left.iteritems()
- while 1:
- w_key, w_val = iteratorimplementation.next_item()
- if w_key is None:
- break
- w_rightval = w_right.getitem(w_key)
- if w_rightval is None:
- return space.w_False
- if not space.eq_w(w_val, w_rightval):
- return space.w_False
- return space.w_True
-
def characterize(space, w_a, w_b):
""" (similar to CPython)
returns the smallest key in acontent for which b's value is different or absent and this value """
@@ -874,105 +1126,11 @@
w_smallest_diff_a_key = w_key
return w_smallest_diff_a_key, w_its_value
-def lt__DictMulti_DictMulti(space, w_left, w_right):
- # Different sizes, no problem
- if w_left.length() < w_right.length():
- return space.w_True
- if w_left.length() > w_right.length():
- return space.w_False
-
- # Same size
- w_leftdiff, w_leftval = characterize(space, w_left, w_right)
- if w_leftdiff is None:
- return space.w_False
- w_rightdiff, w_rightval = characterize(space, w_right, w_left)
- if w_rightdiff is None:
- # w_leftdiff is not None, w_rightdiff is None
- return space.w_True
- w_res = space.lt(w_leftdiff, w_rightdiff)
- if (not space.is_true(w_res) and
- space.eq_w(w_leftdiff, w_rightdiff) and
- w_rightval is not None):
- w_res = space.lt(w_leftval, w_rightval)
- return w_res
-
-def dict_copy__DictMulti(space, w_self):
- w_new = W_DictMultiObject.allocate_and_init_instance(space)
- update1_dict_dict(space, w_new, w_self)
- return w_new
-
-def dict_items__DictMulti(space, w_self):
- return space.newlist(w_self.items())
-
-def dict_keys__DictMulti(space, w_self):
- return w_self.w_keys()
-
-def dict_values__DictMulti(space, w_self):
- return space.newlist(w_self.values())
-
-def dict_iteritems__DictMulti(space, w_self):
- return W_DictMultiIterItemsObject(space, w_self.iteritems())
-
-def dict_iterkeys__DictMulti(space, w_self):
- return W_DictMultiIterKeysObject(space, w_self.iterkeys())
-
-def dict_itervalues__DictMulti(space, w_self):
- return W_DictMultiIterValuesObject(space, w_self.itervalues())
-
-def dict_viewitems__DictMulti(space, w_self):
- return W_DictViewItemsObject(space, w_self)
-
-def dict_viewkeys__DictMulti(space, w_self):
- return W_DictViewKeysObject(space, w_self)
-
-def dict_viewvalues__DictMulti(space, w_self):
- return W_DictViewValuesObject(space, w_self)
-
-def dict_clear__DictMulti(space, w_self):
- w_self.clear()
-
-def dict_get__DictMulti_ANY_ANY(space, w_dict, w_key, w_default):
- w_value = w_dict.getitem(w_key)
- if w_value is not None:
- return w_value
- else:
- return w_default
-
-def dict_setdefault__DictMulti_ANY_ANY(space, w_dict, w_key, w_default):
- return w_dict.setdefault(w_key, w_default)
-
-def dict_pop__DictMulti_ANY(space, w_dict, w_key, defaults_w):
- len_defaults = len(defaults_w)
- if len_defaults > 1:
- raise operationerrfmt(space.w_TypeError,
- "pop expected at most 2 arguments, got %d",
- 1 + len_defaults)
- w_item = w_dict.getitem(w_key)
- if w_item is None:
- if len_defaults > 0:
- return defaults_w[0]
- else:
- space.raise_key_error(w_key)
- else:
- w_dict.delitem(w_key)
- return w_item
-
-def dict_popitem__DictMulti(space, w_dict):
- try:
- w_key, w_value = w_dict.popitem()
- except KeyError:
- raise OperationError(space.w_KeyError,
- space.wrap("popitem(): dictionary is empty"))
- return space.newtuple([w_key, w_value])
-
# ____________________________________________________________
# Iteration
-
-class W_BaseDictMultiIterObject(W_Object):
- from pypy.objspace.std.dicttype import dictiter_typedef as typedef
-
+class W_BaseDictMultiIterObject(W_Root):
_immutable_fields_ = ["iteratorimplementation"]
ignore_for_isinstance_cache = True
@@ -981,139 +1139,199 @@
w_self.space = space
w_self.iteratorimplementation = iteratorimplementation
+ def descr_iter(self, space):
+ return self
+
+ def descr_length_hint(self, space):
+ return space.wrap(self.iteratorimplementation.length())
+
+ def descr_reduce(self, space):
+ """
+ This is a slightly special case of pickling.
+ Since iteration over a dict is a bit hairy,
+ we do the following:
+ - create a clone of the dict iterator
+ - run it to the original position
+ - collect all remaining elements into a list
+ At unpickling time, we just use that list
+ and create an iterator on it.
+ This is of course not the standard way.
+
+ XXX to do: remove this __reduce__ method and do
+ a registration with copy_reg, instead.
+ """
+ w_mod = space.getbuiltinmodule('_pickle_support')
+ mod = space.interp_w(MixedModule, w_mod)
+ new_inst = mod.get('dictiter_surrogate_new')
+ w_typeobj = space.gettypeobject(W_BaseDictMultiIterObject.typedef)
+
+ raise OperationError(
+ space.w_TypeError,
+ space.wrap("can't pickle dictionary-keyiterator objects"))
+ # XXXXXX get that working again
+
+ # we cannot call __init__ since we don't have the original dict
+ if isinstance(self, W_DictIter_Keys):
+ w_clone = space.allocate_instance(W_DictIter_Keys, w_typeobj)
+ elif isinstance(self, W_DictIter_Values):
+ w_clone = space.allocate_instance(W_DictIter_Values, w_typeobj)
+ elif isinstance(self, W_DictIter_Items):
+ w_clone = space.allocate_instance(W_DictIter_Items, w_typeobj)
+ else:
+ msg = "unsupported dictiter type '%s' during pickling" % (self,)
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ w_clone.space = space
+ w_clone.content = self.content
+ w_clone.len = self.len
+ w_clone.pos = 0
+ w_clone.setup_iterator()
+ # spool until we have the same pos
+ while w_clone.pos < self.pos:
+ w_obj = w_clone.next_entry()
+ w_clone.pos += 1
+ stuff = [w_clone.next_entry() for i in range(w_clone.pos, w_clone.len)]
+ w_res = space.newlist(stuff)
+ tup = [
+ w_res
+ ]
+ w_ret = space.newtuple([new_inst, space.newtuple(tup)])
+ return w_ret
+
+
class W_DictMultiIterKeysObject(W_BaseDictMultiIterObject):
- pass
+ def descr_next(self, space):
+ iteratorimplementation = self.iteratorimplementation
+ w_key = iteratorimplementation.next_key()
+ if w_key is not None:
+ return w_key
+ raise OperationError(space.w_StopIteration, space.w_None)
class W_DictMultiIterValuesObject(W_BaseDictMultiIterObject):
- pass
+ def descr_next(self, space):
+ iteratorimplementation = self.iteratorimplementation
+ w_value = iteratorimplementation.next_value()
+ if w_value is not None:
+ return w_value
+ raise OperationError(space.w_StopIteration, space.w_None)
class W_DictMultiIterItemsObject(W_BaseDictMultiIterObject):
- pass
+ def descr_next(self, space):
+ iteratorimplementation = self.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)
-registerimplementation(W_DictMultiIterKeysObject)
-registerimplementation(W_DictMultiIterValuesObject)
-registerimplementation(W_DictMultiIterItemsObject)
+W_DictMultiIterItemsObject.typedef = StdTypeDef(
+ "dict_iteritems",
+ __iter__ = gateway.interp2app(W_DictMultiIterItemsObject.descr_iter),
+ next = gateway.interp2app(W_DictMultiIterItemsObject.descr_next),
+ __length_hint__ = gateway.interp2app(W_BaseDictMultiIterObject.descr_length_hint)
+ )
-def iter__DictMultiIterKeysObject(space, w_dictiter):
- return w_dictiter
+W_DictMultiIterKeysObject.typedef = StdTypeDef(
+ "dict_iterkeys",
+ __iter__ = gateway.interp2app(W_DictMultiIterKeysObject.descr_iter),
+ next = gateway.interp2app(W_DictMultiIterKeysObject.descr_next),
+ __length_hint__ = gateway.interp2app(W_BaseDictMultiIterObject.descr_length_hint)
+ )
-def next__DictMultiIterKeysObject(space, w_dictiter):
- iteratorimplementation = w_dictiter.iteratorimplementation
- w_key = iteratorimplementation.next_key()
- if w_key is not None:
- return w_key
- raise OperationError(space.w_StopIteration, space.w_None)
+W_DictMultiIterValuesObject.typedef = StdTypeDef(
+ "dict_itervalues",
+ __iter__ = gateway.interp2app(W_DictMultiIterValuesObject.descr_iter),
+ next = gateway.interp2app(W_DictMultiIterValuesObject.descr_next),
+ __length_hint__ = gateway.interp2app(W_BaseDictMultiIterObject.descr_length_hint)
+ )
-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)
# ____________________________________________________________
# Views
-class W_DictViewObject(W_Object):
+class W_DictViewObject(W_Root):
def __init__(w_self, space, w_dict):
w_self.w_dict = w_dict
-class W_DictViewKeysObject(W_DictViewObject):
- from pypy.objspace.std.dicttype import dict_keys_typedef as typedef
-registerimplementation(W_DictViewKeysObject)
+ def descr_repr(self, space):
+ w_seq = space.call_function(space.w_list, self)
+ w_repr = space.repr(w_seq)
+ return space.wrap("%s(%s)" % (space.type(self).getname(space),
+ space.str_w(w_repr)))
+
+ def descr_eq(self, space, w_otherview):
+ if not space.eq_w(space.len(self), space.len(w_otherview)):
+ return space.w_False
+
+ w_iter = space.iter(self)
+ while True:
+ try:
+ w_item = space.next(w_iter)
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ break
+ if not space.is_true(space.contains(w_otherview, w_item)):
+ return space.w_False
+ return space.w_True
+
+ def descr_len(self, space):
+ return space.len(self.w_dict)
+
+ def descr_and(self, space, w_otherview):
+ w_set = space.call_function(space.w_set, self)
+ space.call_method(w_set, "intersection_update", w_otherview)
+ return w_set
+
+ def descr_or(self, space, w_otherview):
+ w_set = space.call_function(space.w_set, self)
+ space.call_method(w_set, "update", w_otherview)
+ return w_set
+
+ def descr_xor(self, space, w_otherview):
+ w_set = space.call_function(space.w_set, self)
+ space.call_method(w_set, "symmetric_difference_update", w_otherview)
+ return w_set
class W_DictViewItemsObject(W_DictViewObject):
- from pypy.objspace.std.dicttype import dict_items_typedef as typedef
-registerimplementation(W_DictViewItemsObject)
+ def descr_iter(self, space):
+ return W_DictMultiIterItemsObject(space, self.w_dict.iteritems())
+
+class W_DictViewKeysObject(W_DictViewObject):
+ def descr_iter(self, space):
+ return W_DictMultiIterKeysObject(space, self.w_dict.iterkeys())
class W_DictViewValuesObject(W_DictViewObject):
- from pypy.objspace.std.dicttype import dict_values_typedef as typedef
-registerimplementation(W_DictViewValuesObject)
+ def descr_iter(self, space):
+ return W_DictMultiIterValuesObject(space, self.w_dict.itervalues())
-def len__DictViewKeys(space, w_dictview):
- return space.len(w_dictview.w_dict)
-len__DictViewItems = len__DictViewValues = len__DictViewKeys
+W_DictViewItemsObject.typedef = StdTypeDef(
+ "dict_items",
+ __repr__ = gateway.interp2app(W_DictViewItemsObject.descr_repr),
+ __eq__ = gateway.interp2app(W_DictViewItemsObject.descr_eq),
+ __len__ = gateway.interp2app(W_DictViewItemsObject.descr_len),
+ __iter__ = gateway.interp2app(W_DictViewItemsObject.descr_iter),
+ __and__ = gateway.interp2app(W_DictViewItemsObject.descr_and),
+ __or__ = gateway.interp2app(W_DictViewItemsObject.descr_or),
+ __xor__ = gateway.interp2app(W_DictViewItemsObject.descr_xor)
+ )
-def iter__DictViewKeys(space, w_dictview):
- return dict_iterkeys__DictMulti(space, w_dictview.w_dict)
-def iter__DictViewItems(space, w_dictview):
- return dict_iteritems__DictMulti(space, w_dictview.w_dict)
-def iter__DictViewValues(space, w_dictview):
- return dict_itervalues__DictMulti(space, w_dictview.w_dict)
+W_DictViewKeysObject.typedef = StdTypeDef(
+ "dict_keys",
+ __repr__ = gateway.interp2app(W_DictViewKeysObject.descr_repr),
+ __eq__ = gateway.interp2app(W_DictViewKeysObject.descr_eq),
+ __len__ = gateway.interp2app(W_DictViewKeysObject.descr_len),
+ __iter__ = gateway.interp2app(W_DictViewKeysObject.descr_iter),
+ __and__ = gateway.interp2app(W_DictViewKeysObject.descr_and),
+ __or__ = gateway.interp2app(W_DictViewKeysObject.descr_or),
+ __xor__ = gateway.interp2app(W_DictViewKeysObject.descr_xor)
+ )
-def all_contained_in(space, w_dictview, w_otherview):
- w_iter = space.iter(w_dictview)
-
- while True:
- try:
- w_item = space.next(w_iter)
- except OperationError, e:
- if not e.match(space, space.w_StopIteration):
- raise
- break
- if not space.is_true(space.contains(w_otherview, w_item)):
- return space.w_False
-
- return space.w_True
-
-def eq__DictViewKeys_DictViewKeys(space, w_dictview, w_otherview):
- if space.eq_w(space.len(w_dictview), space.len(w_otherview)):
- return all_contained_in(space, w_dictview, w_otherview)
- return space.w_False
-eq__DictViewKeys_settypedef = eq__DictViewKeys_DictViewKeys
-eq__DictViewKeys_frozensettypedef = eq__DictViewKeys_DictViewKeys
-
-eq__DictViewKeys_DictViewItems = eq__DictViewKeys_DictViewKeys
-eq__DictViewItems_DictViewItems = eq__DictViewKeys_DictViewKeys
-eq__DictViewItems_settypedef = eq__DictViewItems_DictViewItems
-eq__DictViewItems_frozensettypedef = eq__DictViewItems_DictViewItems
-
-def repr__DictViewKeys(space, w_dictview):
- w_seq = space.call_function(space.w_list, w_dictview)
- w_repr = space.repr(w_seq)
- return space.wrap("%s(%s)" % (space.type(w_dictview).getname(space),
- space.str_w(w_repr)))
-repr__DictViewItems = repr__DictViewKeys
-repr__DictViewValues = repr__DictViewKeys
-
-def and__DictViewKeys_DictViewKeys(space, w_dictview, w_otherview):
- w_set = space.call_function(space.w_set, w_dictview)
- space.call_method(w_set, "intersection_update", w_otherview)
- return w_set
-and__DictViewKeys_settypedef = and__DictViewKeys_DictViewKeys
-and__DictViewItems_DictViewItems = and__DictViewKeys_DictViewKeys
-and__DictViewItems_settypedef = and__DictViewKeys_DictViewKeys
-
-def or__DictViewKeys_DictViewKeys(space, w_dictview, w_otherview):
- w_set = space.call_function(space.w_set, w_dictview)
- space.call_method(w_set, "update", w_otherview)
- return w_set
-or__DictViewKeys_settypedef = or__DictViewKeys_DictViewKeys
-or__DictViewItems_DictViewItems = or__DictViewKeys_DictViewKeys
-or__DictViewItems_settypedef = or__DictViewKeys_DictViewKeys
-
-def xor__DictViewKeys_DictViewKeys(space, w_dictview, w_otherview):
- w_set = space.call_function(space.w_set, w_dictview)
- space.call_method(w_set, "symmetric_difference_update", w_otherview)
- return w_set
-xor__DictViewKeys_settypedef = xor__DictViewKeys_DictViewKeys
-xor__DictViewItems_DictViewItems = xor__DictViewKeys_DictViewKeys
-xor__DictViewItems_settypedef = xor__DictViewKeys_DictViewKeys
-
-# ____________________________________________________________
-
-from pypy.objspace.std import dicttype
-register_all(vars(), dicttype)
+W_DictViewValuesObject.typedef = StdTypeDef(
+ "dict_values",
+ __repr__ = gateway.interp2app(W_DictViewValuesObject.descr_repr),
+ __eq__ = gateway.interp2app(W_DictViewValuesObject.descr_eq),
+ __len__ = gateway.interp2app(W_DictViewValuesObject.descr_len),
+ __iter__ = gateway.interp2app(W_DictViewValuesObject.descr_iter),
+ __and__ = gateway.interp2app(W_DictViewValuesObject.descr_and),
+ __or__ = gateway.interp2app(W_DictViewValuesObject.descr_or),
+ __xor__ = gateway.interp2app(W_DictViewValuesObject.descr_xor)
+ )
diff --git a/pypy/objspace/std/dicttype.py b/pypy/objspace/std/dicttype.py
deleted file mode 100644
--- a/pypy/objspace/std/dicttype.py
+++ /dev/null
@@ -1,221 +0,0 @@
-from pypy.interpreter.error import OperationError
-from pypy.interpreter.mixedmodule import MixedModule
-from pypy.interpreter import gateway
-from pypy.objspace.std.stdtypedef import StdTypeDef, SMM
-from pypy.objspace.std.register_all import register_all
-
-dict_copy = SMM('copy', 1,
- doc='D.copy() -> a shallow copy of D')
-dict_items = SMM('items', 1,
- doc="D.items() -> list of D's (key, value) pairs, as"
- ' 2-tuples')
-dict_keys = SMM('keys', 1,
- doc="D.keys() -> list of D's keys")
-dict_values = SMM('values', 1,
- doc="D.values() -> list of D's values")
-dict_has_key = SMM('has_key', 2,
- doc='D.has_key(k) -> True if D has a key k, else False')
-dict_clear = SMM('clear', 1,
- doc='D.clear() -> None. Remove all items from D.')
-dict_get = SMM('get', 3, defaults=(None,),
- doc='D.get(k[,d]) -> D[k] if k in D, else d. d defaults'
- ' to None.')
-dict_pop = SMM('pop', 2, varargs_w=True,
- doc='D.pop(k[,d]) -> v, remove specified key and return'
- ' the corresponding value\nIf key is not found, d is'
- ' returned if given, otherwise KeyError is raised')
-dict_popitem = SMM('popitem', 1,
- doc='D.popitem() -> (k, v), remove and return some (key,'
- ' value) pair as a\n2-tuple; but raise KeyError if D'
- ' is empty')
-dict_setdefault = SMM('setdefault', 3, defaults=(None,),
- doc='D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d'
- ' if k not in D')
-dict_update = SMM('update', 1, general__args__=True,
- doc='D.update(E, **F) -> None. Update D from E and F:'
- ' for k in E: D[k] = E[k]\n(if E has keys else: for'
- ' (k, v) in E: D[k] = v) then: for k in F: D[k] ='
- ' F[k]')
-dict_iteritems = SMM('iteritems', 1,
- doc='D.iteritems() -> an iterator over the (key, value)'
- ' items of D')
-dict_iterkeys = SMM('iterkeys', 1,
- doc='D.iterkeys() -> an iterator over the keys of D')
-dict_itervalues = SMM('itervalues', 1,
- doc='D.itervalues() -> an iterator over the values of D')
-dict_viewkeys = SMM('viewkeys', 1,
- doc="D.viewkeys() -> a set-like object providing a view on D's keys")
-dict_viewitems = SMM('viewitems', 1,
- doc="D.viewitems() -> a set-like object providing a view on D's items")
-dict_viewvalues = SMM('viewvalues', 1,
- doc="D.viewvalues() -> an object providing a view on D's values")
-dict_reversed = SMM('__reversed__', 1)
-
-def dict_reversed__ANY(space, w_dict):
- raise OperationError(space.w_TypeError, space.wrap('argument to reversed() must be a sequence'))
-
-register_all(vars(), globals())
-
-def descr_fromkeys(space, w_type, w_keys, w_fill=None):
- from pypy.objspace.std.dictmultiobject import W_DictMultiObject
- if w_fill is None:
- w_fill = space.w_None
- if space.is_w(w_type, space.w_dict):
- w_dict = W_DictMultiObject.allocate_and_init_instance(space, w_type)
-
- strlist = space.listview_str(w_keys)
- if strlist is not None:
- for key in strlist:
- w_dict.setitem_str(key, w_fill)
- else:
- for w_key in space.listview(w_keys):
- w_dict.setitem(w_key, w_fill)
- else:
- w_dict = space.call_function(w_type)
- for w_key in space.listview(w_keys):
- space.setitem(w_dict, w_key, w_fill)
- return w_dict
-
-
-app = gateway.applevel('''
- def dictrepr(currently_in_repr, d):
- if len(d) == 0:
- return "{}"
- dict_id = id(d)
- if dict_id in currently_in_repr:
- return '{...}'
- currently_in_repr[dict_id] = 1
- try:
- items = []
- # XXX for now, we cannot use iteritems() at app-level because
- # we want a reasonable result instead of a RuntimeError
- # even if the dict is mutated by the repr() in the loop.
- for k, v in dict.items(d):
- items.append(repr(k) + ": " + repr(v))
- return "{" + ', '.join(items) + "}"
- finally:
- try:
- del currently_in_repr[dict_id]
- except:
- pass
-''', filename=__file__)
-
-dictrepr = app.interphook("dictrepr")
-
-
-def descr_repr(space, w_dict):
- ec = space.getexecutioncontext()
- w_currently_in_repr = ec._py_repr
- if w_currently_in_repr is None:
- w_currently_in_repr = ec._py_repr = space.newdict()
- return dictrepr(space, w_currently_in_repr, w_dict)
-
-
-# ____________________________________________________________
-
-def descr__new__(space, w_dicttype, __args__):
- from pypy.objspace.std.dictmultiobject import W_DictMultiObject
- w_obj = W_DictMultiObject.allocate_and_init_instance(space, w_dicttype)
- return w_obj
-
-# ____________________________________________________________
-
-dict_typedef = StdTypeDef("dict",
- __doc__ = '''dict() -> new empty dictionary.
-dict(mapping) -> new dictionary initialized from a mapping object\'s
- (key, value) pairs.
-dict(seq) -> new dictionary initialized as if via:
- d = {}
- for k, v in seq:
- d[k] = v
-dict(**kwargs) -> new dictionary initialized with the name=value pairs
- in the keyword argument list. For example: dict(one=1, two=2)''',
- __new__ = gateway.interp2app(descr__new__),
- __hash__ = None,
- __repr__ = gateway.interp2app(descr_repr),
- fromkeys = gateway.interp2app(descr_fromkeys, as_classmethod=True),
- )
-dict_typedef.registermethods(globals())
-
-# ____________________________________________________________
-
-def descr_dictiter__length_hint__(space, w_self):
- from pypy.objspace.std.dictmultiobject import W_BaseDictMultiIterObject
- assert isinstance(w_self, W_BaseDictMultiIterObject)
- return space.wrap(w_self.iteratorimplementation.length())
-
-
-def descr_dictiter__reduce__(w_self, space):
- """
- This is a slightly special case of pickling.
- Since iteration over a dict is a bit hairy,
- we do the following:
- - create a clone of the dict iterator
- - run it to the original position
- - collect all remaining elements into a list
- At unpickling time, we just use that list
- and create an iterator on it.
- This is of course not the standard way.
-
- XXX to do: remove this __reduce__ method and do
- a registration with copy_reg, instead.
- """
- w_mod = space.getbuiltinmodule('_pickle_support')
- mod = space.interp_w(MixedModule, w_mod)
- new_inst = mod.get('dictiter_surrogate_new')
- w_typeobj = space.gettypeobject(dictiter_typedef)
-
- raise OperationError(
- space.w_TypeError,
- space.wrap("can't pickle dictionary-keyiterator objects"))
- # XXXXXX get that working again
-
- # we cannot call __init__ since we don't have the original dict
- if isinstance(w_self, W_DictIter_Keys):
- w_clone = space.allocate_instance(W_DictIter_Keys, w_typeobj)
- elif isinstance(w_self, W_DictIter_Values):
- w_clone = space.allocate_instance(W_DictIter_Values, w_typeobj)
- elif isinstance(w_self, W_DictIter_Items):
- w_clone = space.allocate_instance(W_DictIter_Items, w_typeobj)
- else:
- msg = "unsupported dictiter type '%s' during pickling" % (w_self, )
- raise OperationError(space.w_TypeError, space.wrap(msg))
- w_clone.space = space
- w_clone.content = w_self.content
- w_clone.len = w_self.len
- w_clone.pos = 0
- w_clone.setup_iterator()
- # spool until we have the same pos
- while w_clone.pos < w_self.pos:
- w_obj = w_clone.next_entry()
- w_clone.pos += 1
- stuff = [w_clone.next_entry() for i in range(w_clone.pos, w_clone.len)]
- w_res = space.newlist(stuff)
- tup = [
- w_res
- ]
- w_ret = space.newtuple([new_inst, space.newtuple(tup)])
- return w_ret
-
-# ____________________________________________________________
-
-
-dictiter_typedef = StdTypeDef("dictionaryiterator",
- __length_hint__ = gateway.interp2app(descr_dictiter__length_hint__),
- __reduce__ = gateway.interp2app(descr_dictiter__reduce__),
- )
-
-# ____________________________________________________________
-# Dict views
-
-dict_keys_typedef = StdTypeDef(
- "dict_keys",
- )
-
-dict_items_typedef = StdTypeDef(
- "dict_items",
- )
-
-dict_values_typedef = StdTypeDef(
- "dict_values",
- )
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
@@ -12,6 +12,7 @@
from pypy.objspace.std.register_all import register_all
from rpython.rlib.rarithmetic import LONG_BIT, r_longlong, r_uint, intmask
from pypy.objspace.std import model
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject
from pypy.interpreter.special import Ellipsis
from pypy.interpreter.pycode import PyCode
from pypy.interpreter import gateway, unicodehelper
@@ -24,7 +25,6 @@
from pypy.objspace.std.floatobject import W_FloatObject
from pypy.objspace.std.tupleobject import W_TupleObject
from pypy.objspace.std.listobject import W_ListObject
-from pypy.objspace.std.dictmultiobject import W_DictMultiObject
from pypy.objspace.std.stringobject import W_StringObject
from pypy.objspace.std.typeobject import W_TypeObject
from pypy.objspace.std.longobject import W_LongObject, newlong
@@ -309,15 +309,18 @@
return space.newlist(items_w)
register(TYPE_LIST, unmarshal_List)
-def marshal_w__DictMulti(space, w_dict, m):
+def marshal_w_dict(space, w_dict, m):
+ if not isinstance(w_dict, W_DictMultiObject):
+ raise_exception(space, "unmarshallable object")
m.start(TYPE_DICT)
for w_tuple in w_dict.items():
w_key, w_value = space.fixedview(w_tuple, 2)
m.put_w_obj(w_key)
m.put_w_obj(w_value)
m.atom(TYPE_NULL)
+handled_by_any.append(('dict', marshal_w_dict))
-def unmarshal_DictMulti(space, u, tc):
+def unmarshal_dict(space, u, tc):
# since primitive lists are not optimized and we don't know
# the dict size in advance, use the dict's setitem instead
# of building a list of tuples.
@@ -329,7 +332,7 @@
w_value = u.get_w_obj()
space.setitem(w_dic, w_key, w_value)
return w_dic
-register(TYPE_DICT, unmarshal_DictMulti)
+register(TYPE_DICT, unmarshal_dict)
def unmarshal_NULL(self, u, tc):
return None
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
@@ -40,7 +40,6 @@
from pypy.objspace.std.complextype import complex_typedef
from pypy.objspace.std.tupletype import tuple_typedef
from pypy.objspace.std.listobject import list_typedef
- from pypy.objspace.std.dicttype import dict_typedef
from pypy.objspace.std.basestringtype import basestring_typedef
from pypy.objspace.std.stringtype import str_typedef
from pypy.objspace.std.bytearraytype import bytearray_typedef
@@ -81,6 +80,7 @@
# not-multimethod based types
+ self.pythontypes.append(dictmultiobject.W_DictMultiObject.typedef)
self.pythontypes.append(setobject.W_SetObject.typedef)
self.pythontypes.append(setobject.W_FrozensetObject.typedef)
@@ -92,10 +92,6 @@
floatobject.W_FloatObject: [],
tupleobject.W_TupleObject: [],
listobject.W_ListObject: [],
- dictmultiobject.W_DictMultiObject: [],
- dictmultiobject.W_DictMultiIterKeysObject: [],
- dictmultiobject.W_DictMultiIterValuesObject: [],
- dictmultiobject.W_DictMultiIterItemsObject: [],
stringobject.W_StringObject: [],
bytearrayobject.W_BytearrayObject: [],
typeobject.W_TypeObject: [],
@@ -108,9 +104,6 @@
iterobject.W_FastTupleIterObject: [],
iterobject.W_ReverseSeqIterObject: [],
unicodeobject.W_UnicodeObject: [],
- dictmultiobject.W_DictViewKeysObject: [],
- dictmultiobject.W_DictViewItemsObject: [],
- dictmultiobject.W_DictViewValuesObject: [],
pypy.interpreter.pycode.PyCode: [],
pypy.interpreter.special.Ellipsis: [],
}
@@ -333,9 +326,6 @@
s += ' instance of %s' % self.w__class__
return '<%s>' % s
- def unwrap(self, space):
- raise UnwrapError('cannot unwrap %r' % self)
-
class UnwrapError(Exception):
pass
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -253,10 +253,9 @@
def unwrap(self, w_obj):
"""NOT_RPYTHON"""
- if isinstance(w_obj, model.W_Object):
+ # _____ this code is here to support testing only _____
+ if isinstance(w_obj, W_Root):
return w_obj.unwrap(self)
- if isinstance(w_obj, W_Root):
- return w_obj
raise model.UnwrapError("cannot unwrap: %r" % w_obj)
def newint(self, intval):
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
@@ -2,8 +2,7 @@
import py
from pypy.objspace.std.dictmultiobject import (W_DictMultiObject,
- setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, StringDictStrategy,
- ObjectDictStrategy)
+ StringDictStrategy, ObjectDictStrategy)
class TestW_DictObject(object):
@@ -409,6 +408,24 @@
assert {'a': 1 } < { 'b': 1}
assert {'a': 1, 'x': 2 } < { 'b': 1, 'x': 2}
+ def test_other_rich_cmp(self):
+ d1 = {1: 2, 3: 4}
+ d2 = {1: 2, 3: 4}
+ d3 = {1: 2, 3: 5}
+ d4 = {1: 2}
+
+ assert d1 <= d2
+ assert d1 <= d3
+ assert not d1 <= d4
+
+ assert not d1 > d2
+ assert not d1 > d3
+ assert d1 > d4
+
+ assert d1 >= d2
+ assert not d1 >= d3
+ assert d1 >= d4
+
def test_str_repr(self):
assert '{}' == str({})
assert '{1: 2}' == str({1: 2})
@@ -604,6 +621,9 @@
assert d.values() == []
assert d.keys() == []
+ def test_cmp_with_noncmp(self):
+ assert not {} > object()
+
class AppTest_DictMultiObject(AppTest_DictObject):
def test_emptydict_unhashable(self):
@@ -971,10 +991,10 @@
pydict = {}
for i in range(N):
x = randint(-N, N)
- setitem__DictMulti_ANY_ANY(self.space, d, x, i)
+ d.descr_setitem(self.space, x, i)
pydict[x] = i
for key, value in pydict.iteritems():
- assert value == getitem__DictMulti_ANY(self.space, d, key)
+ assert value == d.descr_getitem(self.space, key)
class BaseTestRDictImplementation:
diff --git a/rpython/memory/gctransform/asmgcroot.py b/rpython/memory/gctransform/asmgcroot.py
--- a/rpython/memory/gctransform/asmgcroot.py
+++ b/rpython/memory/gctransform/asmgcroot.py
@@ -331,6 +331,11 @@
[annmodel.SomeInteger(),
annmodel.SomeAddress()],
annmodel.s_None)
+ #
+ # check that the order of the need_*() is correct for us: if we
+ # need both threads and stacklets, need_thread_support() must be
+ # called first, to initialize self.belongs_to_current_thread.
+ assert not hasattr(self, 'gc_detach_callback_pieces_ptr')
def walk_stack_roots(self, collect_stack_root):
gcdata = self.gcdata
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -236,9 +236,10 @@
# thread support
if translator.config.translation.continuation:
root_walker.stacklet_support = True
- root_walker.need_stacklet_support(self, getfn)
if translator.config.translation.thread:
root_walker.need_thread_support(self, getfn)
+ if root_walker.stacklet_support:
+ root_walker.need_stacklet_support(self, getfn)
self.layoutbuilder.encode_type_shapes_now()
diff --git a/rpython/rlib/entrypoint.py b/rpython/rlib/entrypoint.py
--- a/rpython/rlib/entrypoint.py
+++ b/rpython/rlib/entrypoint.py
@@ -57,7 +57,8 @@
# This thing is imported by any target which has any API, so it'll get
# registered
-RPython_StartupCode = rffi.llexternal('RPython_StartupCode', [], lltype.Void)
+RPython_StartupCode = rffi.llexternal('RPython_StartupCode', [], lltype.Void,
+ _nowrapper=True)
@entrypoint('main', [], c_name='rpython_startup_code')
def rpython_startup_code():
diff --git a/rpython/rtyper/rpbc.py b/rpython/rtyper/rpbc.py
--- a/rpython/rtyper/rpbc.py
+++ b/rpython/rtyper/rpbc.py
@@ -529,7 +529,7 @@
im_selves = []
for desc in s_pbc.descriptions:
- assert desc.funcdesc is self.funcdesc
+ assert desc.funcdesc is self.funcdesc, "You can't mix a set of methods on a frozen PBC in RPython that are different underlaying functions"
im_selves.append(desc.frozendesc)
self.s_im_self = annmodel.SomePBC(im_selves)
More information about the pypy-commit
mailing list