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