[pypy-svn] r10280 - pypy/dist/pypy/module/builtin

arigo at codespeak.net arigo at codespeak.net
Mon Apr 4 14:19:39 CEST 2005


Author: arigo
Date: Mon Apr  4 14:19:39 2005
New Revision: 10280

Modified:
   pypy/dist/pypy/module/builtin/app_descriptor.py
Log:
Cleaned up the propertydoc hack.  Now a general class docstring which behaves
like, well, a docstring when put in a class, but also allows to capture and
behave like an instance slot.


Modified: pypy/dist/pypy/module/builtin/app_descriptor.py
==============================================================================
--- pypy/dist/pypy/module/builtin/app_descriptor.py	(original)
+++ pypy/dist/pypy/module/builtin/app_descriptor.py	Mon Apr  4 14:19:39 2005
@@ -2,26 +2,95 @@
 Plain Python definition of the builtin descriptors.
 """
 
-# Don't look!  This is needed for the property class, which has a slot
-# called __doc__ but also needs a __doc__ string for itself.
-class propertydoc(object):
+# Descriptor code, shamelessly stolen to Raymond Hettinger:
+#    http://users.rcn.com/python/download/Descriptor.htm
+
+
+# XXX there is an interp-level pypy.interpreter.function.StaticMethod
+# XXX because __new__ needs to be a StaticMethod early.
+class staticmethod(object):
+    __slots__ = ['_f']
+
+    def __init__(self, f):
+        self._f = f
+
+    def __get__(self, obj, objtype=None):
+        return self._f
+
+
+class classmethod(object):
+    __slots__ = ['_f']
+
+    def __init__(self, f):
+        self._f = f
+
+    def __get__(self, obj, klass=None):
+        if klass is None:
+            klass = type(obj)
+        def newfunc(*args, **kwargs):
+            return self._f(klass, *args, **kwargs)
+        return newfunc
+
+
+# It's difficult to have a class that has both a docstring and a slot called
+# '__doc__', but not impossible...
+class docstring(object):
+
+    def __init__(self, classdocstring):
+        self.classdocstring = classdocstring
+        self.slot = None
+
+    def capture(cls, slotname):
+        self = cls.__dict__['__doc__']
+        slot = cls.__dict__[slotname]
+        if not isinstance(self, docstring):
+            raise TypeError, "the class __doc__ must be a docstring instance"
+        self.slot = slot
+        delattr(cls, slotname)
+    capture = staticmethod(capture)
+
     def __get__(self, p, cls=None):
         if p is None:
-            return PROPERTY_DOCSTRING   # getting __doc__ on the class
+            return self.classdocstring  # getting __doc__ on the class
+        elif self.slot is None:
+            raise AttributeError, "'%s' instance has no __doc__" % (
+                p.__class__.__name__,)
         else:
-            return PROPERTY_DOCSLOT.__get__(p)          # on an instance
+            return self.slot.__get__(p) # getting __doc__ on an instance
+
+    def __set__(self, p, value):
+        if hasattr(self.slot, '__set__'):
+            return self.slot.__set__(p, value)
+        else:
+            raise AttributeError, "cannot write __doc__"
+
+    def __delete__(self, p):
+        if hasattr(self.slot, '__delete__'):
+            return self.slot.__delete__(p)
+        else:
+            raise AttributeError, "cannot write __doc__"
+
 
-# Descriptor code, shamelessly stolen to Raymond Hettinger:
-#    http://users.rcn.com/python/download/Descriptor.htm
 class property(object):
-    __slots__ = ['fget', 'fset', 'fdel', 'doc']   # NB. 'doc' hacked away below
-    __doc__ = propertydoc()
+    __doc__ = docstring(
+        '''property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
+
+fget is a function to be used for getting an attribute value, and likewise
+fset is a function for setting, and fdel a function for deleting, an
+attribute.  Typical use is to define a managed attribute x:
+class C(object):
+    def getx(self): return self.__x
+    def setx(self, value): self.__x = value
+    def delx(self): del self.__x
+    x = property(getx, setx, delx, "I am the 'x' property.")''')
+
+    __slots__ = ['fget', 'fset', 'fdel', 'slot__doc__']
 
     def __init__(self, fget=None, fset=None, fdel=None, doc=None):
         self.fget = fget
         self.fset = fset
         self.fdel = fdel
-        PROPERTY_DOCSLOT.__set__(self, doc)
+        self.__doc__ = doc
 
     def __get__(self, obj, objtype=None):
         if obj is None:
@@ -40,45 +109,8 @@
             raise AttributeError, "can't delete attribute"
         self.fdel(obj)
 
-PROPERTY_DOCSTRING = '''property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
-
-fget is a function to be used for getting an attribute value, and likewise
-fset is a function for setting, and fdel a function for deleting, an
-attribute.  Typical use is to define a managed attribute x:
-class C(object):
-    def getx(self): return self.__x
-    def setx(self, value): self.__x = value
-    def delx(self): del self.__x
-    x = property(getx, setx, delx, "I am the 'x' property.")'''
-
-PROPERTY_DOCSLOT = property.doc
-del property.doc
-
-
-# XXX there is an interp-level pypy.interpreter.function.StaticMethod
-# XXX because __new__ needs to be a StaticMethod early.
-class staticmethod(object):
-    __slots__ = ['_f']
-
-    def __init__(self, f):
-        self._f = f
-
-    def __get__(self, obj, objtype=None):
-        return self._f
-
-
-class classmethod(object):
-    __slots__ = ['_f']
-
-    def __init__(self, f):
-        self._f = f
+docstring.capture(property, 'slot__doc__')
 
-    def __get__(self, obj, klass=None):
-        if klass is None:
-            klass = type(obj)
-        def newfunc(*args, **kwargs):
-            return self._f(klass, *args, **kwargs)
-        return newfunc
 
 # super is a modified version from Guido's tutorial
 #     http://www.python.org/2.2.3/descrintro.html



More information about the Pypy-commit mailing list