Author: Ronan Lamy <[email protected]>
Branch: no-class-specialize
Changeset: r80579:15047fa335bd
Date: 2015-11-07 18:19 +0000
http://bitbucket.org/pypy/pypy/changeset/15047fa335bd/

Log:    Special handling for _immutable_fields_ in ClassDesc so that it
        works with mixins

diff --git a/rpython/annotator/classdesc.py b/rpython/annotator/classdesc.py
--- a/rpython/annotator/classdesc.py
+++ b/rpython/annotator/classdesc.py
@@ -512,6 +512,15 @@
         elif baselist == [BaseException]:
             baselist = [Exception]
 
+        immutable_fields = cls.__dict__.get('_immutable_fields_', [])
+        # To prevent confusion, we forbid strings. Any other bona fide sequence
+        # of strings is OK.
+        if isinstance(immutable_fields, basestring):
+            raise AnnotatorError(
+                "In class %s, '_immutable_fields_' must be a sequence of "
+                "attribute names, not a string." % cls)
+        self.immutable_fields = set(immutable_fields)
+
         mixins_before = []
         mixins_after = []
         base = object
@@ -627,6 +636,10 @@
                 if name in skip:
                     continue
                 self.add_source_attribute(name, value, mixin=True)
+            if '_immutable_fields_' in base.__dict__:
+                self.immutable_fields.update(
+                    set(base.__dict__['_immutable_fields_']))
+
 
     def add_sources_for_class(self, cls):
         for name, value in cls.__dict__.items():
@@ -794,8 +807,8 @@
         search2 = '%s?[*]' % (attr,)
         cdesc = self
         while cdesc is not None:
-            immutable_fields = cdesc.get_param('_immutable_fields_', 
inherit=False)
-            if immutable_fields is not None:
+            immutable_fields = cdesc.immutable_fields
+            if immutable_fields:
                 if (search1 in immutable_fields or search2 in 
immutable_fields):
                     s_result.listdef.never_resize()
                     s_copy = s_result.listdef.offspring()
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
@@ -3730,7 +3730,7 @@
 
     def test_return_immutable_list(self):
         class A:
-            _immutable_fields_ = 'lst[*]'
+            _immutable_fields_ = ['lst[*]']
         def f(n):
             a = A()
             l1 = [n, 0]
@@ -3744,7 +3744,7 @@
 
     def test_return_immutable_list_quasiimmut_field(self):
         class A:
-            _immutable_fields_ = 'lst?[*]'
+            _immutable_fields_ = ['lst?[*]']
         def f(n):
             a = A()
             l1 = [n, 0]
@@ -3758,7 +3758,7 @@
 
     def test_immutable_list_is_actually_resized(self):
         class A:
-            _immutable_fields_ = 'lst[*]'
+            _immutable_fields_ = ['lst[*]']
         def f(n):
             a = A()
             l1 = [n]
@@ -3771,7 +3771,7 @@
 
     def test_immutable_list_is_assigned_a_resizable_list(self):
         class A:
-            _immutable_fields_ = 'lst[*]'
+            _immutable_fields_ = ['lst[*]']
         def f(n):
             a = A()
             foo = []
@@ -3783,7 +3783,7 @@
 
     def test_can_merge_immutable_list_with_regular_list(self):
         class A:
-            _immutable_fields_ = 'lst[*]'
+            _immutable_fields_ = ['lst[*]']
         def foo(lst):
             pass
 
@@ -3821,7 +3821,7 @@
         class Root:
             pass
         class A(Root):
-            _immutable_fields_ = '_my_lst[*]'
+            _immutable_fields_ = ['_my_lst[*]']
             def __init__(self, lst):
                 self._my_lst = lst
         def foo(x):
diff --git a/rpython/annotator/test/test_description.py 
b/rpython/annotator/test/test_description.py
--- a/rpython/annotator/test/test_description.py
+++ b/rpython/annotator/test/test_description.py
@@ -30,3 +30,14 @@
 
     assert is_mixin(Mixin1)
     assert not is_mixin(A)
+
+def test_immutable_fields_collection():
+    class Base(object):
+        _immutable_fields_ = ['a']
+    class Mixin(object):
+        _mixin_ = True
+        _immutable_fields_ = ['b']
+    class A(Base, Mixin):
+        _immutable_fields_ = ['c']
+    bk = FakeBookkeeper()
+    assert bk.getdesc(A).immutable_fields == {'b', 'c'}
diff --git a/rpython/rtyper/rclass.py b/rpython/rtyper/rclass.py
--- a/rpython/rtyper/rclass.py
+++ b/rpython/rtyper/rclass.py
@@ -2,7 +2,6 @@
 import types
 
 from rpython.flowspace.model import Constant
-from rpython.flowspace.operation import op
 from rpython.annotator import description, model as annmodel
 from rpython.rlib.objectmodel import UnboxedValue
 from rpython.tool.pairtype import pairtype, pair
@@ -543,11 +542,9 @@
                     self.classdef,))
         else:
             hints['immutable'] = True
-        self.immutable_field_set = set()  # unless overwritten below
-        if classdesc.get_param('_immutable_fields_'):
-            own_fields = classdesc.get_param('_immutable_fields_', 
inherit=False)
-            if own_fields is not None:
-                self.immutable_field_set = set(own_fields)
+        self.immutable_field_set = classdesc.immutable_fields
+        if (classdesc.immutable_fields or
+                'immutable_fields' in self.rbase.object_type._hints):
             accessor = FieldListAccessor()
             hints['immutable_fields'] = accessor
         return hints
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to