Author: Armin Rigo <[email protected]>
Branch:
Changeset: r65997:e98d284a2cae
Date: 2013-08-07 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/e98d284a2cae/
Log: Test and fix, giving a clearer error message (thanks krono).
diff --git a/rpython/annotator/description.py b/rpython/annotator/description.py
--- a/rpython/annotator/description.py
+++ b/rpython/annotator/description.py
@@ -391,6 +391,7 @@
instance_level = False
all_enforced_attrs = None # or a set
settled = False
+ _detect_invalid_attrs = None
def __init__(self, bookkeeper, pyobj=None,
name=None, basedesc=None, classdict=None,
@@ -714,6 +715,10 @@
# by changing the result's annotation (but not, of course, doing an
# actual copy in the rtyper). Tested in
rpython.rtyper.test.test_rlist,
# test_immutable_list_out_of_instance.
+ if self._detect_invalid_attrs and attr in self._detect_invalid_attrs:
+ raise Exception("field %r was migrated to %r from a subclass in "
+ "which it was declared as _immutable_fields_" %
+ (attr, self.pyobj))
search1 = '%s[*]' % (attr,)
search2 = '%s?[*]' % (attr,)
cdesc = self
@@ -724,6 +729,14 @@
s_result.listdef.never_resize()
s_copy = s_result.listdef.offspring()
s_copy.listdef.mark_as_immutable()
+ #
+ cdesc = cdesc.basedesc
+ while cdesc is not None:
+ if cdesc._detect_invalid_attrs is None:
+ cdesc._detect_invalid_attrs = set()
+ cdesc._detect_invalid_attrs.add(attr)
+ cdesc = cdesc.basedesc
+ #
return s_copy
cdesc = cdesc.basedesc
return s_result # common case
diff --git a/rpython/annotator/test/test_annrpython.py
b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -3717,6 +3717,24 @@
a = self.RPythonAnnotator()
a.build_types(f, [int])
+ def test_immutable_field_subclass(self):
+ class Root:
+ pass
+ class A(Root):
+ _immutable_fields_ = '_my_lst[*]'
+ def __init__(self, lst):
+ self._my_lst = lst
+ def foo(x):
+ return len(x._my_lst)
+
+ def f(n):
+ foo(A([2, n]))
+ foo(Root())
+
+ a = self.RPythonAnnotator()
+ e = py.test.raises(Exception, a.build_types, f, [int])
+ assert "field '_my_lst' was migrated" in str(e.value)
+
def test_call_classes_with_noarg_init(self):
class A:
foo = 21
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit