[pypy-svn] r37312 - in pypy/dist/pypy: annotation annotation/test jit/timeshifter

pedronis at codespeak.net pedronis at codespeak.net
Thu Jan 25 03:56:04 CET 2007


Author: pedronis
Date: Thu Jan 25 03:56:00 2007
New Revision: 37312

Modified:
   pypy/dist/pypy/annotation/classdef.py
   pypy/dist/pypy/annotation/description.py
   pypy/dist/pypy/annotation/test/test_annrpython.py
   pypy/dist/pypy/annotation/unaryop.py
   pypy/dist/pypy/jit/timeshifter/rcontainer.py
   pypy/dist/pypy/jit/timeshifter/rvalue.py
   pypy/dist/pypy/jit/timeshifter/rvirtualizable.py
   pypy/dist/pypy/jit/timeshifter/vdict.py
Log:
introduce _atts_ as a way to enforce attrs without the special side-effects of __slots__,

use _attrs_ instead of slots for the various jit runtime helpers. As much as possible that is using __slots__
should move to use _attrs_.



Modified: pypy/dist/pypy/annotation/classdef.py
==============================================================================
--- pypy/dist/pypy/annotation/classdef.py	(original)
+++ pypy/dist/pypy/annotation/classdef.py	Thu Jan 25 03:56:00 2007
@@ -72,7 +72,7 @@
         self.bookkeeper = bookkeeper
         self.s_value = s_ImpossibleValue
         self.readonly = True
-        self.slot_allowed = True
+        self.attr_allowed = True
         self.read_locations = {}
 
     def add_constant_source(self, classdef, source):
@@ -121,17 +121,17 @@
                                                         (self.name, homedef))
                                 break
 
-        # check for attributes forbidden by slots
-        if homedef.classdesc.allslots is not None:
-            if self.name not in homedef.classdesc.allslots:
-                self.slot_allowed = False
+        # check for attributes forbidden by slots or _attrs_
+        if homedef.classdesc.all_enforced_attrs is not None:
+            if self.name not in homedef.classdesc.all_enforced_attrs:
+                self.attr_allowed = False
                 if not self.readonly:
-                    raise NoSuchSlotError(homedef, self.name)
+                    raise NoSuchAttrError(homedef, self.name)
 
     def modified(self, classdef='?'):
         self.readonly = False
-        if not self.slot_allowed:
-            raise NoSuchSlotError(classdef, self.name)
+        if not self.attr_allowed:
+            raise NoSuchAttrError(classdef, self.name)
 
 
 class ClassDef:
@@ -419,8 +419,8 @@
         try:
             v = getattr(self.obj, name)
         except AttributeError:
-            allslots = classdef.classdesc.allslots
-            if allslots and name in allslots:
+            all_enforced_attrs = classdef.classdesc.all_enforced_attrs
+            if all_enforced_attrs and name in all_enforced_attrs:
                 return s_ImpossibleValue
             raise
         s_value = self.bookkeeper.immutablevalue(v)
@@ -439,8 +439,9 @@
                         result.extend(slots)
         return result
 
-class NoSuchSlotError(Exception):
-    "Raised when an attribute is found on a class where __slots__ forbits it."
+class NoSuchAttrError(Exception):
+    """Raised when an attribute is found on a class where __slots__
+     or _attrs_ forbits it."""
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/annotation/description.py
==============================================================================
--- pypy/dist/pypy/annotation/description.py	(original)
+++ pypy/dist/pypy/annotation/description.py	Thu Jan 25 03:56:00 2007
@@ -350,7 +350,7 @@
 class ClassDesc(Desc):
     knowntype = type
     instance_level = False
-    allslots = None   # or a set
+    all_enforced_attrs = None   # or a set
 
     def __init__(self, bookkeeper, pyobj=None,
                  name=None, basedesc=None, classdict=None,
@@ -400,17 +400,21 @@
             if base is not object:
                 self.basedesc = bookkeeper.getdesc(base)
 
-            if '__slots__' in cls.__dict__:
-                slots = cls.__dict__['__slots__']
-                if isinstance(slots, str):
-                    slots = (slots,)
-                slots = dict.fromkeys(slots)
+            if '__slots__' in cls.__dict__ or '_attrs_' in cls.__dict__:
+                attrs = {}
+                for decl in ('__slots__', '_attrs_'):
+                    decl = cls.__dict__.get(decl, [])
+                    if isinstance(decl, str):
+                        decl = (decl,)
+                    decl = dict.fromkeys(decl)
+                    attrs.update(decl)
                 if self.basedesc is not None:
-                    if self.basedesc.allslots is None:
-                        raise Exception("%r has slots, but not its base class"
+                    if self.basedesc.all_enforced_attrs is None:
+                        raise Exception("%r has slots or _attrs_, "
+                                        "but not its base class"
                                         % (pyobj,))
-                    slots.update(self.basedesc.allslots)
-                self.allslots = slots
+                    attrs.update(self.basedesc.all_enforced_attrs)
+                self.all_enforced_attrs = attrs
 
     def add_source_attribute(self, name, value, mixin=False):
         if isinstance(value, types.FunctionType):

Modified: pypy/dist/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/dist/pypy/annotation/test/test_annrpython.py	Thu Jan 25 03:56:00 2007
@@ -2420,8 +2420,8 @@
             if works:
                 a.build_types(fun, [int])
             else:
-                from pypy.annotation.classdef import NoSuchSlotError
-                py.test.raises(NoSuchSlotError, a.build_types, fun, [int])
+                from pypy.annotation.classdef import NoSuchAttrError
+                py.test.raises(NoSuchAttrError, a.build_types, fun, [int])
 
     def test_slots_enforce_attrs(self):
         class Superbase(object):
@@ -2445,6 +2445,56 @@
         s = a.build_types(fun, [str])
         assert s == annmodel.s_ImpossibleValue   # but not blocked blocks
 
+    def test_enforced_attrs_check(self):
+        class Base(object):
+            _attrs_ = 'x'
+        class A(Base):
+            _attrs_ = 'y'
+            def m(self):
+                return 65
+        class C(Base):
+            _attrs_ = 'z'
+            def m(self):
+                return 67
+        for attrname, works in [('x', True),
+                                ('y', False),
+                                ('z', False),
+                                ('t', False)]:
+            def fun(n):
+                if n: o = A()
+                else: o = C()
+                setattr(o, attrname, 12)
+                return o.m()
+            a = self.RPythonAnnotator()
+            if works:
+                a.build_types(fun, [int])
+            else:
+                from pypy.annotation.classdef import NoSuchAttrError
+                py.test.raises(NoSuchAttrError, a.build_types, fun, [int])
+
+    def test_attrs_enforce_attrs(self):
+        class Superbase(object):
+            _attrs_ = 'x'
+        class Base(Superbase):
+            pass
+        class A(Base):
+            pass
+        class B(Base):
+            pass
+        def fun(s):
+            if s is None:   # known not to be None in this test
+                o = B()
+                o.x = 12
+            elif len(s) > 5:
+                o = A()
+            else:
+                o = Base()
+            return o.x
+        a = self.RPythonAnnotator()
+        s = a.build_types(fun, [str])
+        assert s == annmodel.s_ImpossibleValue   # but not blocked blocks
+
+
     def test_pbc_enforce_attrs(self):
         class F(object):
             _attrs_ = ['foo',]

Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py	(original)
+++ pypy/dist/pypy/annotation/unaryop.py	Thu Jan 25 03:56:00 2007
@@ -529,9 +529,9 @@
                 # blocking is harmless if the attribute is explicitly listed
                 # in the class or a parent class.
                 for basedef in ins.classdef.getmro():
-                    if basedef.classdesc.allslots is not None:
-                        if attr in basedef.classdesc.allslots:
-                            raise HarmlesslyBlocked("getattr on a slot")
+                    if basedef.classdesc.all_enforced_attrs is not None:
+                        if attr in basedef.classdesc.all_enforced_attrs:
+                            raise HarmlesslyBlocked("get enforced attr")
             return s_result
         return SomeObject()
     getattr.can_only_throw = []

Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py	Thu Jan 25 03:56:00 2007
@@ -12,7 +12,7 @@
 debug_pdb = lloperation.llop.debug_pdb
 
 class AbstractContainer(object):
-    __slots__ = []
+    _attrs_ = []
 
     def op_getfield(self, jitstate, fielddesc):
         raise NotImplementedError
@@ -25,11 +25,11 @@
 
 
 class VirtualContainer(AbstractContainer):
-    __slots__ = []
+    _attrs_ = []
 
 
 class FrozenContainer(AbstractContainer):
-    __slots__ = []
+    _attrs_ = []
 
     def exactmatch(self, vstruct, outgoingvarboxes, memo):
         raise NotImplementedError
@@ -44,7 +44,7 @@
 
     VirtualStructCls = None # patched later with VirtualStruct
 
-    __slots__ =  """TYPE PTRTYPE
+    _attrs_ =  """TYPE PTRTYPE
                     firstsubstructdesc arrayfielddesc
                     innermostdesc
                     ptrkind
@@ -59,9 +59,8 @@
                     gv_vrti_get_global_shape_ptr
                     vrti_read_forced_token
                     gv_vrti_read_forced_ptr
-                    __dict__
-                 """.split()  # XXX remove rpython abuse of __slots__
-                              # use our own _attrs_ instead
+                 """.split()
+                            
 
     firstsubstructdesc = None
     materialize = None
@@ -188,7 +187,7 @@
 
     VirtualStructCls = None # patched later with VirtualizableStruct
 
-    __slots__ =  """redirected_fielddescs
+    _attrs_  =  """redirected_fielddescs
                     base_desc rti_desc access_desc
                     gv_access
                     gv_access_is_null_ptr access_is_null_token
@@ -498,7 +497,7 @@
 
 
 class VirtualStruct(VirtualContainer):
-    __slots__ = "typedesc content_boxes ownbox".split()
+    _attrs_ = "typedesc content_boxes ownbox".split()
 
     def __init__(self, typedesc):
         self.typedesc = typedesc

Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rvalue.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rvalue.py	Thu Jan 25 03:56:00 2007
@@ -32,7 +32,7 @@
     pass
 
 class RedBox(object):
-    __slots__ = ['kind', 'genvar']
+    _attrs_ = ['kind', 'genvar']
 
     def __init__(self, kind, genvar=None):
         self.kind = kind

Modified: pypy/dist/pypy/jit/timeshifter/rvirtualizable.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rvirtualizable.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rvirtualizable.py	Thu Jan 25 03:56:00 2007
@@ -3,7 +3,8 @@
 from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
 
 class VirtualRTI(object):
-    __slots__ = 'rgenop varindexes vrtis bitmask'.split()
+    _attrs_ = 'rgenop varindexes vrtis bitmask'.split()
+    
     def __init__(self, rgenop, bitmask):
         self.rgenop = rgenop
         self.varindexes = []
@@ -39,7 +40,7 @@
     get_forced._annspecialcase_ = "specialize:arg(2)"
 
 class VirtualizableRTI(VirtualRTI):
-    __slots__ = "frameinfo vable_getset_rtis".split()
+    _attrs_ = "frameinfo vable_getset_rtis".split()
             
     def get_global_shape(self):
         return 0
@@ -64,7 +65,7 @@
         return state
 
 class WithForcedStateVirtualizableRTI(VirtualizableRTI):
-    __slots__ = "state".split()
+    _attrs_ = "state"
 
     def __init__(self, vablerti, state):
         self.rgenop = vablerti.rgenop

Modified: pypy/dist/pypy/jit/timeshifter/vdict.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/vdict.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/vdict.py	Thu Jan 25 03:56:00 2007
@@ -142,7 +142,7 @@
 
 
 class AbstractFrozenVirtualDict(FrozenContainer):
-    __slots__ = ('typedesc',)
+    _attrs_ = ('typedesc',)
 
     def __init__(self, typedesc):
         self.typedesc = typedesc
@@ -183,7 +183,7 @@
 
 
 class AbstractVirtualDict(VirtualContainer):
-    __slots__ = ('typedesc', 'ownbox')     # and no item_boxes
+    _attrs_ = ('typedesc', 'ownbox')     # and no item_boxes
 
     FrozenVirtualDict = AbstractFrozenVirtualDict    # overridden in subclasses
 



More information about the Pypy-commit mailing list