(original) (raw)

"""Sample implementation of the docslots idea.""" import sys class _SlotDescriptor(object): """Emulate builtin slot descriptor""" def __init__(self, name, docstring=None): self.__name__ = name self.__doc__ = docstring self._slotname = "_slotproperty_" + name def __get__(self, obj, cls=None): if obj is None: return self try: return getattr(obj, self._slotname) except AttributeError, e: raise AttributeError(self.__name__) def __set__(self, obj, value): setattr(obj, self._slotname, value) def __delete__(self, obj): delattr(obj, self._slotname) def slots(*args): """Replacement for class "__slots__ = [...]", with docstring support Synopsis: >>> class Foo(object): ... slots( ... 'slot1', ... ('slot2', 'description'), ... ('slot3', '''description ... ...continued'''), ... ) ... >>> Foo.slot2.__doc__ 'description' >>> a = Foo() >>> a.slot1 = a.slot2 = 5 >>> a.slot1, a.slot2 (5, 5) >>> del a.slot2 >>> a.slot2 Traceback (most recent call last): ... AttributeError: slot2 Do not attempt to use this and __slots__ at the same time. Note that, in the current implementation, slots with a docstrings have more access overhead. """ namespace = sys._getframe(1).f_locals __slots__ = [] for item in args: if isinstance(item, tuple): name, docstring = item else: name, docstring = item, None if docstring: descriptor = _SlotDescriptor(name, docstring) __slots__.append(descriptor._slotname) namespace[name] = descriptor else: __slots__.append(name) namespace['__slots__'] = __slots__ def _test(): import doctest doctest.testmod() if __name__ == "__main__": _test()