[pypy-commit] pypy py3.5-async: merged py3k changes, generatorentry_driver was used twice, that is now allowed
plan_rich
pypy.commits at gmail.com
Thu Aug 11 10:18:54 EDT 2016
Author: Richard Plangger <planrichi at gmail.com>
Branch: py3.5-async
Changeset: r86141:ce8bb88f9458
Date: 2016-08-11 16:18 +0200
http://bitbucket.org/pypy/pypy/changeset/ce8bb88f9458/
Log: merged py3k changes, generatorentry_driver was used twice, that is
now allowed
diff --git a/lib-python/3/test/test_hash.py b/lib-python/3/test/test_hash.py
--- a/lib-python/3/test/test_hash.py
+++ b/lib-python/3/test/test_hash.py
@@ -198,7 +198,7 @@
class StringlikeHashRandomizationTests(HashRandomizationTests):
if check_impl_detail(pypy=True):
- EMPTY_STRING_HASH = -1
+ EMPTY_STRING_HASH = -2
else:
EMPTY_STRING_HASH = 0
repr_ = None
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -326,6 +326,12 @@
"of type '%T'", res)
return res
+def get_printable_coroutine_location_genentry(bytecode):
+ return '%s <coroutine>' % (bytecode.get_repr(),)
+coroutineentry_driver = jit.JitDriver(greens=['pycode'],
+ reds=['gen', 'w_arg', 'operr'],
+ get_printable_location = get_printable_coroutine_location_genentry,
+ name='coroutineentry')
class Coroutine(W_Root):
"A coroutine object."
@@ -511,8 +517,8 @@
pycode = self.pycode
if pycode is not None:
if jit.we_are_jitted() and should_not_inline(pycode):
- generatorentry_driver.jit_merge_point(gen=self, w_arg=w_arg,
- operr=operr, pycode=pycode)
+ coroutineentry_driver.jit_merge_point(gen=self, w_arg=w_arg,
+ operr=operr, pycode=pycode)
return self._send_ex(w_arg, operr)
def _send_ex(self, w_arg, operr):
diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py
--- a/pypy/module/cppyy/pythonify.py
+++ b/pypy/module/cppyy/pythonify.py
@@ -175,7 +175,7 @@
"__new__" : make_new(class_name),
}
pycppclass = metacpp(class_name, _drop_cycles(bases), d)
-
+
# cache result early so that the class methods can find the class itself
setattr(scope, final_class_name, pycppclass)
@@ -192,13 +192,10 @@
for dm_name in cppclass.get_datamember_names():
cppdm = cppclass.get_datamember(dm_name)
- # here, setattr() can not be used, because a data member can shadow one in
- # its base class, resulting in the __set__() of its base class being called
- # by setattr(); so, store directly on the dictionary
- pycppclass.__dict__[dm_name] = cppdm
+ setattr(pycppclass, dm_name, cppdm)
import cppyy
if cppyy._is_static(cppdm): # TODO: make this a method of cppdm
- metacpp.__dict__[dm_name] = cppdm
+ setattr(metacpp, dm_name, cppdm)
# the call to register will add back-end specific pythonizations and thus
# needs to run first, so that the generic pythonizations can use them
@@ -413,7 +410,7 @@
lib = cppyy._load_dictionary(name)
_loaded_dictionaries[name] = lib
return lib
-
+
def _init_pythonify():
# cppyy should not be loaded at the module level, as that will trigger a
# call to space.getbuiltinmodule(), which will cause cppyy to be loaded
diff --git a/pypy/module/cpyext/dictproxyobject.py b/pypy/module/cpyext/dictproxyobject.py
--- a/pypy/module/cpyext/dictproxyobject.py
+++ b/pypy/module/cpyext/dictproxyobject.py
@@ -1,67 +1,7 @@
-# Read-only proxy for mappings. PyPy does not have a separate type for
-# type.__dict__, so PyDictProxy_New has to use a custom read-only mapping.
-
-from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
-from pypy.interpreter.typedef import TypeDef, interp2app
+from pypy.objspace.std.dictproxyobject import W_DictProxyObject
from pypy.module.cpyext.api import cpython_api, build_type_checkers
from pypy.module.cpyext.pyobject import PyObject
-class W_DictProxyObject(W_Root):
- "Read-only proxy for mappings."
-
- def __init__(self, w_mapping):
- self.w_mapping = w_mapping
-
- def descr_len(self, space):
- return space.len(self.w_mapping)
-
- def descr_getitem(self, space, w_key):
- return space.getitem(self.w_mapping, w_key)
-
- def descr_contains(self, space, w_key):
- return space.contains(self.w_mapping, w_key)
-
- def descr_iter(self, space):
- return space.iter(self.w_mapping)
-
- def descr_str(self, space):
- return space.str(self.w_mapping)
-
- def descr_repr(self, space):
- return space.repr(self.w_mapping)
-
- @unwrap_spec(w_default=WrappedDefault(None))
- def get_w(self, space, w_key, w_default):
- return space.call_method(self.w_mapping, "get", w_key, w_default)
-
- def keys_w(self, space):
- return space.call_method(self.w_mapping, "keys")
-
- def values_w(self, space):
- return space.call_method(self.w_mapping, "values")
-
- def items_w(self, space):
- return space.call_method(self.w_mapping, "items")
-
- def copy_w(self, space):
- return space.call_method(self.w_mapping, "copy")
-
-W_DictProxyObject.typedef = TypeDef(
- 'mappingproxy',
- __len__=interp2app(W_DictProxyObject.descr_len),
- __getitem__=interp2app(W_DictProxyObject.descr_getitem),
- __contains__=interp2app(W_DictProxyObject.descr_contains),
- __iter__=interp2app(W_DictProxyObject.descr_iter),
- __str__=interp2app(W_DictProxyObject.descr_str),
- __repr__=interp2app(W_DictProxyObject.descr_repr),
- get=interp2app(W_DictProxyObject.get_w),
- keys=interp2app(W_DictProxyObject.keys_w),
- values=interp2app(W_DictProxyObject.values_w),
- items=interp2app(W_DictProxyObject.items_w),
- copy=interp2app(W_DictProxyObject.copy_w)
-)
-
PyDictProxy_Check, PyDictProxy_CheckExact = build_type_checkers(
"DictProxy", W_DictProxyObject)
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -417,8 +417,7 @@
init = """PyObject *mod = PyModule_Create(&moduledef);"""
if more_init:
init += more_init
- else:
- init += "\nreturn mod;"
+ init += "\nreturn mod;"
return import_module(space, name=modname, init=init, body=body,
w_include_dirs=w_include_dirs,
PY_SSIZE_T_CLEAN=PY_SSIZE_T_CLEAN)
diff --git a/pypy/module/cpyext/test/test_import_module.c b/pypy/module/cpyext/test/test_import_module.c
--- a/pypy/module/cpyext/test/test_import_module.c
+++ b/pypy/module/cpyext/test/test_import_module.c
@@ -1,17 +1,20 @@
#include "Python.h"
/* Initialize this module. */
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "test_import_module",
+ NULL,
+ -1,
+ NULL, NULL, NULL, NULL, NULL
+};
+
PyMODINIT_FUNC
-inittest_import_module(void)
+PyInit_test_import_module(void)
{
- PyObject *m, *d;
-
- m = Py_InitModule("test_import_module", NULL);
- if (m == NULL)
- return;
- d = PyModule_GetDict(m);
- if (d) {
- PyDict_SetItemString(d, "TEST", (PyObject *) Py_None);
- }
- /* No need to check the error here, the caller will do that */
+ PyObject* m = PyModule_Create(&moduledef);
+ if (m == NULL)
+ return NULL;
+ PyModule_AddObject(m, "TEST", (PyObject *) Py_None);
+ return m;
}
diff --git a/pypy/module/cpyext/test/test_number.py b/pypy/module/cpyext/test/test_number.py
--- a/pypy/module/cpyext/test/test_number.py
+++ b/pypy/module/cpyext/test/test_number.py
@@ -1,5 +1,6 @@
from rpython.rtyper.lltypesystem import lltype
from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
class TestIterator(BaseApiTest):
def test_check(self, space, api):
@@ -63,7 +64,9 @@
assert 9 == space.unwrap(
api.PyNumber_InPlacePower(space.wrap(3), space.wrap(2), space.w_None))
- def test_PyNumber_Check(self):
+
+class AppTestCNumber(AppTestCpythonExtensionBase):
+ def test_PyNumber_Check(self):
mod = self.import_extension('foo', [
("test_PyNumber_Check", "METH_VARARGS",
'''
diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -277,9 +277,41 @@
args->ob_type->tp_dict, "copy");
Py_INCREF(method);
return method;
- ''')])
+ '''),
+ ("get_type_dict", "METH_O",
+ '''
+ PyObject* value = args->ob_type->tp_dict;
+ if (value == NULL) value = Py_None;
+ Py_INCREF(value);
+ return value;
+ '''),
+ ])
obj = foo.new()
assert module.read_tp_dict(obj) == foo.fooType.copy
+ d = module.get_type_dict(obj)
+ assert type(d) is dict
+ d["_some_attribute"] = 1
+ assert type(obj)._some_attribute == 1
+ del d["_some_attribute"]
+
+ class A(object):
+ pass
+ obj = A()
+ d = module.get_type_dict(obj)
+ assert type(d) is dict
+ d["_some_attribute"] = 1
+ assert type(obj)._some_attribute == 1
+ del d["_some_attribute"]
+
+ d = module.get_type_dict(1)
+ assert type(d) is dict
+ try:
+ d["_some_attribute"] = 1
+ except TypeError: # on PyPy, int.__dict__ is really immutable
+ pass
+ else:
+ assert int._some_attribute == 1
+ del d["_some_attribute"]
def test_custom_allocation(self):
foo = self.import_module("foo")
@@ -348,6 +380,21 @@
api.Py_DecRef(ref)
+ def test_type_dict(self, space, api):
+ w_class = space.appexec([], """():
+ class A(object):
+ pass
+ return A
+ """)
+ ref = make_ref(space, w_class)
+
+ py_type = rffi.cast(PyTypeObjectPtr, ref)
+ w_dict = from_ref(space, py_type.c_tp_dict)
+ w_name = space.newunicode(u'a')
+ space.setitem(w_dict, w_name, space.wrap(1))
+ assert space.int_w(space.getattr(w_class, w_name)) == 1
+ space.delitem(w_dict, w_name)
+
def test_multiple_inheritance(self, space, api):
w_class = space.appexec([], """():
class A(object):
@@ -779,7 +826,7 @@
""", more_init="""
IntLike_Type.tp_flags |= Py_TPFLAGS_DEFAULT;
IntLike_Type.tp_as_number = &intlike_as_number;
- intlike_as_number.nb_bool = intlike_nb_nonzero;
+ intlike_as_number.nb_bool = intlike_nb_bool;
intlike_as_number.nb_int = intlike_nb_int;
PyType_Ready(&IntLike_Type);
""")
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -192,7 +192,7 @@
py_methoddescr.c_d_method = w_obj.ml
def classmethoddescr_realize(space, obj):
- # XXX NOT TESTED When is this ever called?
+ # XXX NOT TESTED When is this ever called?
method = rffi.cast(lltype.Ptr(PyMethodDef), obj)
w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
w_obj = space.allocate_instance(W_PyCClassMethodObject, w_type)
@@ -201,7 +201,7 @@
return w_obj
def methoddescr_realize(space, obj):
- # XXX NOT TESTED When is this ever called?
+ # XXX NOT TESTED When is this ever called?
method = rffi.cast(lltype.Ptr(PyMethodDef), obj)
w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
w_obj = space.allocate_instance(W_PyCMethodObject, w_type)
@@ -272,12 +272,12 @@
if len(slot_names) == 1:
if not getattr(pto, slot_names[0]):
setattr(pto, slot_names[0], slot_func_helper)
- elif (w_type.getname(space) in ('list', 'tuple') and
+ elif (w_type.getname(space) in ('list', 'tuple') and
slot_names[0] == 'c_tp_as_number'):
# XXX hack - hwo can we generalize this? The problem is method
# names like __mul__ map to more than one slot, and we have no
# convenient way to indicate which slots CPython have filled
- #
+ #
# We need at least this special case since Numpy checks that
# (list, tuple) do __not__ fill tp_as_number
pass
@@ -767,8 +767,8 @@
if w_obj.is_cpytype():
Py_DecRef(space, pto.c_tp_dict)
- w_dict = w_obj.getdict(space)
- pto.c_tp_dict = make_ref(space, w_dict)
+ w_dict = w_obj.getdict(space)
+ pto.c_tp_dict = make_ref(space, w_dict)
@cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, error=CANNOT_FAIL)
def PyType_IsSubtype(space, a, b):
diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py
--- a/pypy/module/time/interp_time.py
+++ b/pypy/module/time/interp_time.py
@@ -541,6 +541,8 @@
t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw')
t_ref[0] = tt
pbuf = c_localtime(t_ref)
+ rffi.setintfield(pbuf, "c_tm_year",
+ rffi.getintfield(pbuf, "c_tm_year") + 1900)
lltype.free(t_ref, flavor='raw')
if not pbuf:
raise OperationError(space.w_ValueError,
@@ -584,7 +586,7 @@
if rffi.getintfield(glob_buf, 'c_tm_wday') < -1:
raise oefmt(space.w_ValueError, "day of week out of range")
- rffi.setintfield(glob_buf, 'c_tm_year', y - 1900)
+ rffi.setintfield(glob_buf, 'c_tm_year', y)
rffi.setintfield(glob_buf, 'c_tm_mon',
rffi.getintfield(glob_buf, 'c_tm_mon') - 1)
rffi.setintfield(glob_buf, 'c_tm_wday',
@@ -648,7 +650,8 @@
t_ref[0] = seconds
p = c_localtime(t_ref)
if not p:
- raise oefmt(space.w_ValueError, "unconvertible time")
+ raise oefmt(space.w_OSError, "unconvertible time")
+ rffi.setintfield(p, "c_tm_year", rffi.getintfield(p, "c_tm_year") + 1900)
return _asctime(space, p)
# by now w_tup is an optional argument (and not *args)
@@ -677,7 +680,7 @@
w(getif(t_ref, 'c_tm_hour')),
w(getif(t_ref, 'c_tm_min')),
w(getif(t_ref, 'c_tm_sec')),
- w(getif(t_ref, 'c_tm_year') + 1900)]
+ w(getif(t_ref, 'c_tm_year'))]
return space.mod(w("%.3s %.3s%3d %.2d:%.2d:%.2d %d"),
space.newtuple(args))
@@ -715,7 +718,7 @@
lltype.free(t_ref, flavor='raw')
if not p:
- raise OperationError(space.w_ValueError, space.wrap(_get_error_msg()))
+ raise OperationError(space.w_OSError, space.wrap(_get_error_msg()))
return _tm_to_tuple(space, p)
def mktime(space, w_tup):
@@ -725,6 +728,7 @@
buf = _gettmarg(space, w_tup, allowNone=False)
rffi.setintfield(buf, "c_tm_wday", -1)
+ rffi.setintfield(buf, "c_tm_year", rffi.getintfield(buf, "c_tm_year") - 1900)
tt = c_mktime(buf)
# A return value of -1 does not necessarily mean an error, but tm_wday
# cannot remain set to -1 if mktime succeeds.
@@ -801,6 +805,8 @@
rffi.setintfield(buf_value, 'c_tm_isdst', -1)
elif rffi.getintfield(buf_value, 'c_tm_isdst') > 1:
rffi.setintfield(buf_value, 'c_tm_isdst', 1)
+ rffi.setintfield(buf_value, "c_tm_year",
+ rffi.getintfield(buf_value, "c_tm_year") - 1900)
if _WIN:
# check that the format string contains only valid directives
diff --git a/pypy/objspace/std/classdict.py b/pypy/objspace/std/classdict.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/classdict.py
@@ -0,0 +1,119 @@
+from rpython.rlib import rerased
+from rpython.rlib.objectmodel import iteritems_with_hash
+
+from pypy.interpreter.error import OperationError, oefmt
+from pypy.objspace.std.dictmultiobject import (
+ DictStrategy, create_iterator_classes)
+from pypy.objspace.std.typeobject import unwrap_cell
+
+
+class ClassDictStrategy(DictStrategy):
+ """Exposes a W_TypeObject.dict_w at app-level.
+
+ Uses getdictvalue() and setdictvalue() to access items.
+ """
+ erase, unerase = rerased.new_erasing_pair("dictproxy")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def getitem(self, w_dict, w_key):
+ space = self.space
+ w_lookup_type = space.type(w_key)
+ if space.issubtype_w(w_lookup_type, space.w_unicode):
+ return self.getitem_str(w_dict, space.str_w(w_key))
+ else:
+ return None
+
+ def getitem_str(self, w_dict, key):
+ return self.unerase(w_dict.dstorage).getdictvalue(self.space, key)
+
+ def setitem(self, w_dict, w_key, w_value):
+ space = self.space
+ if space.is_w(space.type(w_key), space.w_unicode):
+ self.setitem_str(w_dict, self.space.str_w(w_key), w_value)
+ else:
+ raise oefmt(space.w_TypeError,
+ "cannot add non-string keys to dict of a type")
+
+ def setitem_str(self, w_dict, key, w_value):
+ w_type = self.unerase(w_dict.dstorage)
+ try:
+ w_type.setdictvalue(self.space, key, w_value)
+ except OperationError as e:
+ if not e.match(self.space, self.space.w_TypeError):
+ raise
+ if not w_type.is_cpytype():
+ raise
+ # Allow cpyext to write to type->tp_dict even in the case
+ # of a builtin type.
+ # Like CPython, we assume that this is only done early
+ # after the type is created, and we don't invalidate any
+ # cache. User code shoud call PyType_Modified().
+ w_type.dict_w[key] = w_value
+
+ def setdefault(self, w_dict, w_key, w_default):
+ w_result = self.getitem(w_dict, w_key)
+ if w_result is not None:
+ return w_result
+ self.setitem(w_dict, w_key, w_default)
+ return w_default
+
+ def delitem(self, w_dict, w_key):
+ space = self.space
+ w_key_type = space.type(w_key)
+ if space.is_w(w_key_type, space.w_unicode):
+ key = self.space.str_w(w_key)
+ if not self.unerase(w_dict.dstorage).deldictvalue(space, key):
+ raise KeyError
+ else:
+ raise KeyError
+
+ def length(self, w_dict):
+ return len(self.unerase(w_dict.dstorage).dict_w)
+
+ def w_keys(self, w_dict):
+ space = self.space
+ w_type = self.unerase(w_dict.dstorage)
+ return space.newlist([_wrapkey(space, key)
+ for key in w_type.dict_w.iterkeys()])
+
+ def values(self, w_dict):
+ return [unwrap_cell(self.space, w_value) for w_value in
+ self.unerase(w_dict.dstorage).dict_w.itervalues()]
+
+ def items(self, w_dict):
+ space = self.space
+ w_type = self.unerase(w_dict.dstorage)
+ return [space.newtuple([_wrapkey(space, key),
+ unwrap_cell(space, w_value)])
+ for (key, w_value) in w_type.dict_w.iteritems()]
+
+ def clear(self, w_dict):
+ space = self.space
+ w_type = self.unerase(w_dict.dstorage)
+ if not w_type.is_heaptype():
+ raise oefmt(space.w_TypeError,
+ "can't clear dictionary of type '%N'", w_type)
+ w_type.dict_w.clear()
+ w_type.mutated(None)
+
+ 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_with_hash(self, w_dict):
+ return iteritems_with_hash(self.unerase(w_dict.dstorage).dict_w)
+
+ def wrapkey(space, key):
+ return _wrapkey(space, key)
+
+ def wrapvalue(space, value):
+ return unwrap_cell(space, value)
+
+def _wrapkey(space, key):
+ # keys are utf-8 encoded identifiers from type's dict_w
+ return space.wrap(key.decode('utf-8'))
+
+create_iterator_classes(ClassDictStrategy)
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,212 +1,95 @@
-from rpython.rlib import rerased
-from rpython.rlib.objectmodel import iteritems_with_hash
+"""
+Read-only proxy for mappings.
-from pypy.interpreter.error import OperationError, oefmt
-from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.typedef import TypeDef
-from pypy.objspace.std.dictmultiobject import (
- DictStrategy, W_DictObject, create_iterator_classes)
-from pypy.objspace.std.typeobject import unwrap_cell
+Its main use is as the return type of cls.__dict__.
+"""
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter.error import oefmt
+from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
+from pypy.interpreter.typedef import TypeDef, interp2app
-class W_DictProxyObject(W_DictObject):
+class W_DictProxyObject(W_Root):
+ "Read-only proxy for mappings."
+
+ def __init__(self, w_mapping):
+ self.w_mapping = w_mapping
+
@staticmethod
def descr_new(space, w_type, w_mapping):
if (not space.lookup(w_mapping, "__getitem__") or
- space.isinstance_w(w_mapping, space.w_list) or
- space.isinstance_w(w_mapping, space.w_tuple)):
+ space.isinstance_w(w_mapping, space.w_list) or
+ space.isinstance_w(w_mapping, space.w_tuple)):
raise oefmt(space.w_TypeError,
- "mappingproxy() argument must be a mapping, not %T", w_mapping)
- strategy = space.fromcache(MappingProxyStrategy)
- storage = strategy.erase(w_mapping)
- w_obj = space.allocate_instance(W_DictProxyObject, w_type)
- W_DictProxyObject.__init__(w_obj, space, strategy, storage)
- return w_obj
+ "mappingproxy() argument must be a mapping, not %T",
+ w_mapping)
+ return W_DictProxyObject(w_mapping)
def descr_init(self, space, __args__):
pass
+ def descr_len(self, space):
+ return space.len(self.w_mapping)
+
+ def descr_getitem(self, space, w_key):
+ return space.getitem(self.w_mapping, w_key)
+
+ def descr_contains(self, space, w_key):
+ return space.contains(self.w_mapping, w_key)
+
+ def descr_iter(self, space):
+ return space.iter(self.w_mapping)
+
+ def descr_str(self, space):
+ return space.str(self.w_mapping)
+
def descr_repr(self, space):
- return space.wrap(u"mappingproxy(%s)" % (
- space.unicode_w(W_DictObject.descr_repr(self, space))))
+ return space.newunicode(u"mappingproxy(%s)" %
+ (space.unicode_w(space.repr(self.w_mapping)),))
+
+ @unwrap_spec(w_default=WrappedDefault(None))
+ def get_w(self, space, w_key, w_default):
+ return space.call_method(self.w_mapping, "get", w_key, w_default)
+
+ def keys_w(self, space):
+ return space.call_method(self.w_mapping, "keys")
+
+ def values_w(self, space):
+ return space.call_method(self.w_mapping, "values")
+
+ def items_w(self, space):
+ return space.call_method(self.w_mapping, "items")
+
+ def copy_w(self, space):
+ return space.call_method(self.w_mapping, "copy")
+
+cmp_methods = {}
+def make_cmp_method(op):
+ def descr_op(self, space, w_other):
+ return getattr(space, op)(self.w_mapping, w_other)
+ descr_name = 'descr_' + op
+ descr_op.__name__ = descr_name
+ setattr(W_DictProxyObject, descr_name, descr_op)
+ cmp_methods['__%s__' % op] = interp2app(getattr(W_DictProxyObject, descr_name))
+
+for op in ['eq', 'ne', 'gt', 'ge', 'lt', 'le']:
+ make_cmp_method(op)
+
W_DictProxyObject.typedef = TypeDef(
- "mappingproxy", W_DictObject.typedef,
- __new__ = interp2app(W_DictProxyObject.descr_new),
- __init__ = interp2app(W_DictProxyObject.descr_init),
- __repr__ = interp2app(W_DictProxyObject.descr_repr),
+ 'mappingproxy',
+ __new__=interp2app(W_DictProxyObject.descr_new),
+ __init__=interp2app(W_DictProxyObject.descr_init),
+ __len__=interp2app(W_DictProxyObject.descr_len),
+ __getitem__=interp2app(W_DictProxyObject.descr_getitem),
+ __contains__=interp2app(W_DictProxyObject.descr_contains),
+ __iter__=interp2app(W_DictProxyObject.descr_iter),
+ __str__=interp2app(W_DictProxyObject.descr_str),
+ __repr__=interp2app(W_DictProxyObject.descr_repr),
+ get=interp2app(W_DictProxyObject.get_w),
+ keys=interp2app(W_DictProxyObject.keys_w),
+ values=interp2app(W_DictProxyObject.values_w),
+ items=interp2app(W_DictProxyObject.items_w),
+ copy=interp2app(W_DictProxyObject.copy_w),
+ **cmp_methods
)
-
-
-class DictProxyStrategy(DictStrategy):
- """Exposes a W_TypeObject.dict_w at app-level.
-
- Uses getdictvalue() and setdictvalue() to access items.
- """
- erase, unerase = rerased.new_erasing_pair("dictproxy")
- erase = staticmethod(erase)
- unerase = staticmethod(unerase)
-
- def getitem(self, w_dict, w_key):
- space = self.space
- w_lookup_type = space.type(w_key)
- if space.issubtype_w(w_lookup_type, space.w_unicode):
- return self.getitem_str(w_dict, space.str_w(w_key))
- else:
- return None
-
- def getitem_str(self, w_dict, key):
- return self.unerase(w_dict.dstorage).getdictvalue(self.space, key)
-
- def setitem(self, w_dict, w_key, w_value):
- space = self.space
- if space.is_w(space.type(w_key), space.w_unicode):
- self.setitem_str(w_dict, self.space.str_w(w_key), w_value)
- else:
- raise oefmt(space.w_TypeError,
- "cannot add non-string keys to dict of a type")
-
- def setitem_str(self, w_dict, key, w_value):
- w_type = self.unerase(w_dict.dstorage)
- try:
- w_type.setdictvalue(self.space, key, w_value)
- except OperationError as e:
- if not e.match(self.space, self.space.w_TypeError):
- raise
- if not w_type.is_cpytype():
- raise
- # Allow cpyext to write to type->tp_dict even in the case
- # of a builtin type.
- # Like CPython, we assume that this is only done early
- # after the type is created, and we don't invalidate any
- # cache. User code shoud call PyType_Modified().
- w_type.dict_w[key] = w_value
-
- def setdefault(self, w_dict, w_key, w_default):
- w_result = self.getitem(w_dict, w_key)
- if w_result is not None:
- return w_result
- self.setitem(w_dict, w_key, w_default)
- return w_default
-
- def delitem(self, w_dict, w_key):
- space = self.space
- w_key_type = space.type(w_key)
- if space.is_w(w_key_type, space.w_unicode):
- key = self.space.str_w(w_key)
- if not self.unerase(w_dict.dstorage).deldictvalue(space, key):
- raise KeyError
- else:
- raise KeyError
-
- def length(self, w_dict):
- return len(self.unerase(w_dict.dstorage).dict_w)
-
- def w_keys(self, w_dict):
- space = self.space
- w_type = self.unerase(w_dict.dstorage)
- return space.newlist([_wrapkey(space, key)
- for key in w_type.dict_w.iterkeys()])
-
- def values(self, w_dict):
- return [unwrap_cell(self.space, w_value) for w_value in self.unerase(w_dict.dstorage).dict_w.itervalues()]
-
- def items(self, w_dict):
- space = self.space
- w_type = self.unerase(w_dict.dstorage)
- return [space.newtuple([_wrapkey(space, key),
- unwrap_cell(space, w_value)])
- for (key, w_value) in w_type.dict_w.iteritems()]
-
- def clear(self, w_dict):
- space = self.space
- w_type = self.unerase(w_dict.dstorage)
- if not w_type.is_heaptype():
- raise oefmt(space.w_TypeError,
- "can't clear dictionary of type '%N'", w_type)
- w_type.dict_w.clear()
- w_type.mutated(None)
-
- 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_with_hash(self, w_dict):
- return iteritems_with_hash(self.unerase(w_dict.dstorage).dict_w)
- def wrapkey(space, key):
- return _wrapkey(space, key)
- def wrapvalue(space, value):
- return unwrap_cell(space, value)
-
-def _wrapkey(space, key):
- # keys are utf-8 encoded identifiers from type's dict_w
- return space.wrap(key.decode('utf-8'))
-
-create_iterator_classes(DictProxyStrategy)
-
-
-class MappingProxyStrategy(DictStrategy):
- """Wraps an applevel mapping in a read-only dictionary."""
- erase, unerase = rerased.new_erasing_pair("mappingproxy")
- erase = staticmethod(erase)
- unerase = staticmethod(unerase)
-
- def getitem(self, w_dict, w_key):
- try:
- return self.space.getitem(self.unerase(w_dict.dstorage), w_key)
- except OperationError as e:
- if not e.match(self.space, self.space.w_KeyError):
- raise
- return None
-
- def setitem(self, w_dict, w_key, w_value):
- raise oefmt(self.space.w_TypeError,
- "'%T' object does not support item assignment", w_dict)
-
- def delitem(self, w_dict, w_key):
- raise oefmt(self.space.w_TypeError,
- "'%T' object does not support item deletion", w_dict)
-
- def length(self, w_dict):
- return self.space.len_w(self.unerase(w_dict.dstorage))
-
- def getiterkeys(self, w_dict):
- return self.space.iter(
- self.space.call_method(self.unerase(w_dict.dstorage), "keys"))
-
- def getitervalues(self, w_dict):
- return self.space.iter(
- self.space.call_method(self.unerase(w_dict.dstorage), "values"))
-
- def getiteritems_with_hash(self, w_dict):
- return self.space.iter(
- self.space.call_method(self.unerase(w_dict.dstorage), "items"))
-
- @staticmethod
- def override_next_key(iterkeys):
- w_keys = iterkeys.iterator
- return iterkeys.space.next(w_keys)
-
- @staticmethod
- def override_next_value(itervalues):
- w_values = itervalues.iterator
- return itervalues.space.next(w_values)
-
- @staticmethod
- def override_next_item(iteritems):
- w_items = iteritems.iterator
- w_item = iteritems.space.next(w_items)
- w_key, w_value = iteritems.space.unpackiterable(w_item, 2)
- return w_key, w_value
-
- def clear(self, w_dict):
- raise oefmt(self.space.w_AttributeError, "clear")
-
- def copy(self, w_dict):
- return self.space.call_method(self.unerase(w_dict.dstorage), "copy")
-
-create_iterator_classes(
- MappingProxyStrategy,
- override_next_key=MappingProxyStrategy.override_next_key,
- override_next_value=MappingProxyStrategy.override_next_value,
- override_next_item=MappingProxyStrategy.override_next_item)
diff --git a/pypy/objspace/std/test/test_dictproxy.py b/pypy/objspace/std/test/test_dictproxy.py
--- a/pypy/objspace/std/test/test_dictproxy.py
+++ b/pypy/objspace/std/test/test_dictproxy.py
@@ -9,42 +9,20 @@
assert 'a' in NotEmpty.__dict__
assert 'a' in NotEmpty.__dict__.keys()
assert 'b' not in NotEmpty.__dict__
- NotEmpty.__dict__['b'] = 4
- assert NotEmpty.b == 4
- del NotEmpty.__dict__['b']
assert NotEmpty.__dict__.get("b") is None
+ raises(TypeError, "NotEmpty.__dict__['b'] = 4")
raises(TypeError, 'NotEmpty.__dict__[15] = "y"')
- raises(KeyError, 'del NotEmpty.__dict__[15]')
+ raises(TypeError, 'del NotEmpty.__dict__[15]')
- assert NotEmpty.__dict__.setdefault("string", 1) == 1
- assert NotEmpty.__dict__.setdefault("string", 2) == 1
- assert NotEmpty.string == 1
- raises(TypeError, 'NotEmpty.__dict__.setdefault(15, 1)')
-
- def test_dictproxy_popitem(self):
- class A(object):
- a = 42
- seen = 0
- try:
- while True:
- key, value = A.__dict__.popitem()
- if key == 'a':
- assert value == 42
- seen += 1
- except KeyError:
- pass
- assert seen == 1
+ raises(AttributeError, 'NotEmpty.__dict__.setdefault')
def test_dictproxy_getitem(self):
class NotEmpty(object):
a = 1
assert 'a' in NotEmpty.__dict__
- class substr(str): pass
+ class substr(str):
+ pass
assert substr('a') in NotEmpty.__dict__
- # the following are only for py2
- ## assert u'a' in NotEmpty.__dict__
- ## assert NotEmpty.__dict__[u'a'] == 1
- ## assert u'\xe9' not in NotEmpty.__dict__
def test_dictproxyeq(self):
class a(object):
@@ -63,9 +41,9 @@
class a(object):
pass
s1 = repr(a.__dict__)
+ assert s1.startswith('mappingproxy({') and s1.endswith('})')
s2 = str(a.__dict__)
- assert s1 == s2
- assert s1.startswith('mappingproxy({') and s1.endswith('})')
+ assert s1 == 'mappingproxy(%s)' % s2
def test_immutable_dict_on_builtin_type(self):
raises(TypeError, "int.__dict__['a'] = 1")
@@ -100,4 +78,3 @@
class AppTestUserObjectMethodCache(AppTestUserObject):
spaceconfig = {"objspace.std.withmethodcachecounter": True}
-
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -185,12 +185,12 @@
skip("cannot run this test as apptest")
for u in [u"", u"a", u"aa"]:
assert id(self.unwrap_wrap_unicode(u)) == id(u)
- s = str(u)
- assert id(self.unwrap_wrap_str(s)) == id(s)
+ s = u.encode()
+ assert id(self.unwrap_wrap_bytes(s)) == id(s)
#
- assert id('') == (256 << 4) | 11 # always
+ assert id(b'') == (256 << 4) | 11 # always
assert id(u'') == (257 << 4) | 11
- assert id('a') == (ord('a') << 4) | 11
+ assert id(b'a') == (ord('a') << 4) | 11
assert id(u'\u1234') == ((~0x1234) << 4) | 11
def test_id_of_tuples(self):
@@ -243,13 +243,13 @@
l = []
def add(s, u):
l.append(s)
- l.append(self.unwrap_wrap_str(s))
+ l.append(self.unwrap_wrap_bytes(s))
l.append(s[:1] + s[1:])
l.append(u)
l.append(self.unwrap_wrap_unicode(u))
l.append(u[:1] + u[1:])
for i in range(3, 18):
- add(str(i), unicode(i))
+ add(str(i).encode(), str(i))
add(b"s", u"s")
add(b"", u"")
diff --git a/pypy/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -970,7 +970,6 @@
raises(TypeError, setattr, list, 'foobar', 42)
raises(TypeError, delattr, dict, 'keys')
raises(TypeError, 'int.__dict__["a"] = 1')
- raises(TypeError, 'int.__dict__.clear()')
def test_nontype_in_mro(self):
class OldStyle:
@@ -1028,10 +1027,9 @@
pass
a = A()
+ d = A.__dict__
A.x = 1
- assert A.__dict__["x"] == 1
- A.__dict__['x'] = 5
- assert A.x == 5
+ assert d["x"] == 1
def test_we_already_got_one_1(self):
# Issue #2079: highly obscure: CPython complains if we say
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -4,8 +4,8 @@
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.function import (
Function, StaticMethod, ClassMethod, FunctionWithFixedCode)
-from pypy.interpreter.typedef import weakref_descr, GetSetProperty,\
- descr_get_dict, dict_descr, Member, TypeDef
+from pypy.interpreter.typedef import (
+ weakref_descr, GetSetProperty, dict_descr, Member, TypeDef)
from pypy.interpreter.astcompiler.misc import mangle
from pypy.module.__builtin__ import abstractinst
@@ -344,7 +344,7 @@
def deldictvalue(self, space, key):
if self.lazyloaders:
self._cleanup_() # force un-lazification
- if not self.is_heaptype():
+ if not (self.is_heaptype() or self.is_cpytype()):
raise oefmt(space.w_TypeError,
"can't delete attributes on type object '%N'", self)
try:
@@ -483,14 +483,14 @@
self.getdictvalue(self.space, attr)
del self.lazyloaders
- def getdict(self, space): # returning a dict-proxy!
- from pypy.objspace.std.dictproxyobject import DictProxyStrategy
- from pypy.objspace.std.dictproxyobject import W_DictProxyObject
+ def getdict(self, space):
+ from pypy.objspace.std.classdict import ClassDictStrategy
+ from pypy.objspace.std.dictmultiobject import W_DictObject
if self.lazyloaders:
self._cleanup_() # force un-lazification
- strategy = space.fromcache(DictProxyStrategy)
+ strategy = space.fromcache(ClassDictStrategy)
storage = strategy.erase(self)
- return W_DictProxyObject(space, strategy, storage)
+ return W_DictObject(space, strategy, storage)
def is_heaptype(self):
return self.flag_heaptype
@@ -929,6 +929,13 @@
return space.newbool(
abstractinst.p_recursive_isinstance_type_w(space, w_inst, w_obj))
+def type_get_dict(space, w_cls):
+ from pypy.objspace.std.dictproxyobject import W_DictProxyObject
+ w_dict = w_cls.getdict(space)
+ if w_dict is None:
+ return space.w_None
+ return W_DictProxyObject(w_dict)
+
W_TypeObject.typedef = TypeDef("type",
__new__ = gateway.interp2app(descr__new__),
__name__ = GetSetProperty(descr_get__name__, descr_set__name__),
@@ -936,7 +943,7 @@
__bases__ = GetSetProperty(descr_get__bases__, descr_set__bases__),
__base__ = GetSetProperty(descr__base),
__mro__ = GetSetProperty(descr_get__mro__),
- __dict__ = GetSetProperty(descr_get_dict),
+ __dict__=GetSetProperty(type_get_dict),
__doc__ = GetSetProperty(descr__doc, descr_set__doc),
__dir__ = gateway.interp2app(descr__dir),
mro = gateway.interp2app(descr_mro),
More information about the pypy-commit
mailing list