Author: Antonio Cuni <[email protected]>
Branch: identity-dict-strategy
Changeset: r45744:6a28c75d117e
Date: 2011-07-19 18:30 +0200
http://bitbucket.org/pypy/pypy/changeset/6a28c75d117e/
Log: update the global version counter if we change the class of an
object whose old class was tracked as compares_by_identity
diff --git a/pypy/objspace/std/objecttype.py b/pypy/objspace/std/objecttype.py
--- a/pypy/objspace/std/objecttype.py
+++ b/pypy/objspace/std/objecttype.py
@@ -43,6 +43,9 @@
assert isinstance(w_oldcls, W_TypeObject)
if w_oldcls.get_full_instance_layout() ==
w_newcls.get_full_instance_layout():
w_obj.setclass(space, w_newcls)
+ if space.config.objspace.std.trackcomparebyidentity:
+ if not w_oldcls.overrides_hash_eq_or_cmp and not
w_newcls.compares_by_identity():
+ space.bump_compares_by_identity_version()
else:
raise operationerrfmt(space.w_TypeError,
"__class__ assignment: '%s' object layout
differs from '%s'",
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
@@ -43,6 +43,13 @@
"""The standard object space, implementing a general-purpose object
library in Restricted Python."""
+ # a global version counter to track live instances which "compare by
+ # identity" (i.e., whose __eq__, __cmp__ and __hash__ are the default
+ # ones). The idea is to track only classes for which we checked the
+ # compares_by_identity() status at least once: we increment the version if
+ # its status might change, e.g. because we set one of those attributes.
+ # The actual work is done by W_TypeObject.mutated() and
+ # objecttype:descr_setclass
compares_by_identity_version = None
def initialize(self):
@@ -81,14 +88,8 @@
# the type of old-style classes
self.w_classobj = self.builtin.get('__metaclass__')
- # a global version counter to track live instances which "compare by
- # identity" (i.e., whose __eq__, __cmp__ and __hash__ are the default
- # ones). The idea is to track only classes for which we checked the
- # compares_by_identity() status at least once: we increment the
- # version if its status might change, e.g. because we set one of those
- # attributes. The actual work is done by W_TypeObject.mutated()
if self.config.objspace.std.trackcomparebyidentity:
- self.compares_by_identity_version = VersionTag()
+ self.bump_compares_by_identity_version()
# final setup
self.setup_builtin_modules()
@@ -579,3 +580,6 @@
if isinstance(w_sub, W_TypeObject) and isinstance(w_type,
W_TypeObject):
return self.wrap(w_sub.issubtype(w_type))
raise OperationError(self.w_TypeError, self.wrap("need type objects"))
+
+ def bump_compares_by_identity_version(self):
+ self.compares_by_identity_version = VersionTag()
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
@@ -1279,3 +1279,22 @@
# version
Y.__eq__ = lambda x: None
assert self.get_version() == 2
+
+ def test_change___class__(self):
+ class X(object):
+ pass
+
+ class Y(object):
+ pass
+
+ class Z(object):
+ def __eq__(self, other):
+ pass
+
+ x = X()
+ assert self.compares_by_identity(X)
+ assert self.get_version() == 0
+ x.__class__ = Y
+ assert self.get_version() == 0
+ x.__class__ = Z
+ assert self.get_version() == 1
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
@@ -175,7 +175,7 @@
key == '__cmp__' or
key == '__hash__'):
w_self.overrides_hash_eq_or_cmp = True
- w_self.space.compares_by_identity_version = VersionTag()
+ w_self.space.bump_compares_by_identity_version()
if space.config.objspace.std.newshortcut:
w_self.w_bltin_new = None
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit