[pypy-commit] pypy default: issue 2029: try a bit harder to hide the "default_factory" attribute
arigo
noreply at buildbot.pypy.org
Tue Apr 14 13:01:38 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r76789:494280f37b17
Date: 2015-04-14 13:01 +0200
http://bitbucket.org/pypy/pypy/changeset/494280f37b17/
Log: issue 2029: try a bit harder to hide the "default_factory" attribute
diff --git a/pypy/module/_collections/app_defaultdict.py b/pypy/module/_collections/app_defaultdict.py
--- a/pypy/module/_collections/app_defaultdict.py
+++ b/pypy/module/_collections/app_defaultdict.py
@@ -11,6 +11,7 @@
class defaultdict(dict):
+ __slots__ = ['__default_factory']
def __init__(self, *args, **kwds):
if len(args) > 0:
@@ -20,7 +21,7 @@
raise TypeError("first argument must be callable")
else:
default_factory = None
- self.default_factory = default_factory
+ defaultdict.__default_factory.__set__(self, default_factory)
super(defaultdict, self).__init__(*args, **kwds)
def __missing__(self, key):
@@ -33,15 +34,15 @@
return "defaultdict(...)"
try:
recurse.add(id(self))
- return "defaultdict(%s, %s)" % (repr(self.default_factory), super(defaultdict, self).__repr__())
+ return "defaultdict(%s, %s)" % (self.__default_factory,
+ super(defaultdict, self).__repr__())
finally:
recurse.remove(id(self))
def copy(self):
- return type(self)(self.default_factory, self)
+ return type(self)(self.__default_factory, self)
- def __copy__(self):
- return self.copy()
+ __copy__ = copy
def __reduce__(self):
"""
@@ -55,4 +56,5 @@
This API is used by pickle.py and copy.py.
"""
- return (type(self), (self.default_factory,), None, None, self.iteritems())
+ return (type(self), (self.__default_factory,), None, None,
+ defaultdict.iteritems(self))
diff --git a/pypy/module/_collections/interp_defaultdict.py b/pypy/module/_collections/interp_defaultdict.py
--- a/pypy/module/_collections/interp_defaultdict.py
+++ b/pypy/module/_collections/interp_defaultdict.py
@@ -4,7 +4,8 @@
# An interp-level version of this method. This is mostly only
# useful because it can be executed atomically in the presence of
# threads.
- w_default_factory = space.getattr(w_self, space.wrap('default_factory'))
+ w_default_factory = space.getattr(w_self,
+ space.wrap('_defaultdict__default_factory'))
if space.is_w(w_default_factory, space.w_None):
raise OperationError(space.w_KeyError, space.newtuple([w_key]))
w_value = space.call_function(w_default_factory)
diff --git a/pypy/module/_collections/test/test_defaultdict.py b/pypy/module/_collections/test/test_defaultdict.py
--- a/pypy/module/_collections/test/test_defaultdict.py
+++ b/pypy/module/_collections/test/test_defaultdict.py
@@ -54,3 +54,17 @@
assert len(d2) == 1
assert d2[2] == 3
assert d2[3] == 42
+
+ def test_no_dict(self):
+ import _collections
+ assert not hasattr(_collections.defaultdict(), '__dict__')
+
+ def test_no_setattr(self):
+ import _collections
+ class D(_collections.defaultdict):
+ def __setattr__(self, attr, name):
+ raise AssertionError
+ d = D(int)
+ assert d['5'] == 0
+ d['6'] += 3
+ assert d['6'] == 3
More information about the pypy-commit
mailing list