Author: Carl Friedrich Bolz <[email protected]>
Branch:
Changeset: r88581:97648f46bf4e
Date: 2016-11-23 16:18 +0100
http://bitbucket.org/pypy/pypy/changeset/97648f46bf4e/
Log: issue 2435 testing: make sure to ignore the overridden __getitem__
method on subclasses pass as **kwargs. This is bug-to-bug
compatibility with CPython.
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -111,7 +111,9 @@
self.keywords = self.keywords + keywords
self.keywords_w = self.keywords_w + values_w
return
+ is_dict = False
if space.isinstance_w(w_starstararg, space.w_dict):
+ is_dict = True
keys_w = space.unpackiterable(w_starstararg)
else:
try:
@@ -125,7 +127,9 @@
keys_w = space.unpackiterable(w_keys)
keywords_w = [None] * len(keys_w)
keywords = [None] * len(keys_w)
- _do_combine_starstarargs_wrapped(space, keys_w, w_starstararg,
keywords, keywords_w, self.keywords)
+ _do_combine_starstarargs_wrapped(
+ space, keys_w, w_starstararg, keywords, keywords_w, self.keywords,
+ is_dict)
self.keyword_names_w = keys_w
if self.keywords is None:
self.keywords = keywords
@@ -355,7 +359,7 @@
key)
def _do_combine_starstarargs_wrapped(space, keys_w, w_starstararg, keywords,
- keywords_w, existingkeywords):
+ keywords_w, existingkeywords, is_dict):
i = 0
for w_key in keys_w:
try:
@@ -374,7 +378,16 @@
"got multiple values for keyword argument '%s'",
key)
keywords[i] = key
- keywords_w[i] = space.getitem(w_starstararg, w_key)
+ if is_dict:
+ # issue 2435: bug-to-bug compatibility with cpython. for a
subclass of
+ # dict, just ignore the __getitem__ and access the underlying dict
+ # directly
+ from pypy.objspace.descroperation import dict_getitem
+ w_descr = dict_getitem(space)
+ w_value = space.get_and_call_function(w_descr, w_starstararg,
w_key)
+ else:
+ w_value = space.getitem(w_starstararg, w_key)
+ keywords_w[i] = w_value
i += 1
@jit.look_inside_iff(
diff --git a/pypy/interpreter/test/test_argument.py
b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -120,6 +120,12 @@
raise OperationError(AttributeError, name)
return method(*args)
+ def lookup_in_type_where(self, cls, name):
+ return 'hopefully not needed', getattr(cls, name)
+
+ def get_and_call_function(self, w_descr, w_obj, *args):
+ return w_descr.__get__(w_obj)(*args)
+
def type(self, obj):
class Type:
def getname(self, space):
@@ -805,3 +811,19 @@
assert str(e) == "myerror"
else:
assert False, "Expected TypeError"
+
+ def test_dict_subclass_with_weird_getitem(self):
+ # issue 2435: bug-to-bug compatibility with cpython. for a subclass of
+ # dict, just ignore the __getitem__ and behave like ext_do_call in
ceval.c
+ # which just uses the underlying dict
+ class d(dict):
+ def __getitem__(self, key):
+ return key
+
+ for key in ["foo", u"foo"]:
+ q = d()
+ q[key] = "bar"
+
+ def test(**kwargs):
+ return kwargs
+ assert test(**q) == {"foo": "bar"}
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -61,16 +61,24 @@
@specialize.memo()
def str_getitem(space):
"Utility that returns the app-level descriptor str.__getitem__."
- w_src, w_iter = space.lookup_in_type_where(space.w_str,
- '__getitem__')
- return w_iter
+ w_src, w_getitem = space.lookup_in_type_where(space.w_str,
+ '__getitem__')
+ return w_getitem
@specialize.memo()
def unicode_getitem(space):
"Utility that returns the app-level descriptor unicode.__getitem__."
- w_src, w_iter = space.lookup_in_type_where(space.w_unicode,
- '__getitem__')
- return w_iter
+ w_src, w_getitem = space.lookup_in_type_where(space.w_unicode,
+ '__getitem__')
+ return w_getitem
+
[email protected]()
+def dict_getitem(space):
+ "Utility that returns the app-level descriptor dict.__getitem__."
+ w_src, w_getitem = space.lookup_in_type_where(space.w_dict,
+ '__getitem__')
+ return w_getitem
+
def raiseattrerror(space, w_obj, name, w_descr=None):
if w_descr is None:
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit