Author: Armin Rigo <[email protected]>
Branch:
Changeset: r90065:6b030e17ad91
Date: 2017-02-12 09:58 +0100
http://bitbucket.org/pypy/pypy/changeset/6b030e17ad91/
Log: In the common strategies, implement a version of pop() doing only
one dict lookup
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
@@ -365,6 +365,13 @@
corresponding value\nIf key is not found, d is returned if given,
otherwise KeyError is raised
"""
+ strategy = self.get_strategy()
+ if strategy.has_pop:
+ try:
+ return strategy.pop(self, w_key, w_default)
+ except KeyError:
+ raise space.raise_key_error(w_key)
+ # fall-back
w_item = self.getitem(w_key)
if w_item is None:
if w_default is not None:
@@ -616,6 +623,7 @@
has_iterreversed = False
has_move_to_end = False
+ has_pop = False
# ^^^ no default implementation available for these methods
def rev_update1_dict_dict(self, w_dict, w_updatedict):
@@ -890,6 +898,9 @@
if hasattr(dictimpl, 'move_to_end'):
dictimpl.has_move_to_end = True
+ if hasattr(dictimpl, 'pop'):
+ dictimpl.has_pop = True
+
@jit.look_inside_iff(lambda self, w_dict, w_updatedict:
w_dict_unrolling_heuristic(w_dict))
def rev_update1_dict_dict(self, w_dict, w_updatedict):
@@ -1028,6 +1039,21 @@
key, value = self.unerase(w_dict.dstorage).popitem()
return (self.wrap(key), value)
+ def pop(self, w_dict, w_key, w_default):
+ space = self.space
+ if self.is_correct_type(w_key):
+ key = self.unwrap(w_key)
+ d = self.unerase(w_dict.dstorage)
+ if w_default is None:
+ return d.pop(key)
+ else:
+ return d.pop(key, w_default)
+ elif self._never_equal_to(space.type(w_key)):
+ raise KeyError
+ else:
+ self.switch_to_object_strategy(w_dict)
+ return w_dict.get_strategy().pop(w_dict, w_key, w_default)
+
def clear(self, w_dict):
self.unerase(w_dict.dstorage).clear()
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
@@ -663,6 +663,18 @@
else:
assert False, 'Expected KeyError'
+ def test_pop_switching_strategy(self):
+ class Foo:
+ def __hash__(self):
+ return hash("a")
+ def __eq__(self, other):
+ return other == "a"
+ d = {"a": 42}
+ x = d.pop(Foo())
+ assert x == 42 and len(d) == 0
+ d = {"b": 43}
+ raises(KeyError, d.pop, Foo())
+
def test_no_len_on_dict_iter(self):
iterable = {1: 2, 3: 4}
raises(TypeError, len, iter(iterable))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit