61 lines
1.5 KiB
Python
61 lines
1.5 KiB
Python
|
|
"""
|
|
|
|
>>> f = Foo()
|
|
>>> f.bar = 77
|
|
>>> f.bar
|
|
77
|
|
>>> Foo.bar.__doc__
|
|
'The "bar" attribute'
|
|
>>> import pydoc
|
|
>>> pydoc.getdoc(Foo.bazz)
|
|
'The "bazz" attribute'
|
|
|
|
"""
|
|
|
|
|
|
def doc_descriptor_wrapper_factory(descriptor):
|
|
wrapper_cls_name = 'DocDescriptorWrapper'
|
|
wrapper_cls_attrs = descriptor.__dict__.copy()
|
|
wrapper_cls_attrs['__slots__'] = ['_wrapped']
|
|
|
|
def wrapped_getter(self):
|
|
"the wrapped descriptor instance"
|
|
return self._wrapped
|
|
|
|
def wrapper_repr(self):
|
|
return '<{} {!r}>'.format(wrapper_cls_name, self.__doc__)
|
|
|
|
wrapper_cls_attrs['wrapped'] = property(wrapped_getter)
|
|
wrapper_cls_attrs['__repr__'] = wrapper_repr
|
|
wrapper_cls = type(wrapper_cls_name, (), wrapper_cls_attrs)
|
|
wrapper = wrapper_cls()
|
|
wrapper._wrapped = descriptor
|
|
return wrapper
|
|
|
|
|
|
class DocDescriptor:
|
|
"""A documented descriptor"""
|
|
|
|
def __init__(self, documentation):
|
|
self.__doc__ = documentation
|
|
cls_name = self.__class__.__name__
|
|
self.storage_name = '_{}_{:x}'.format(cls_name, id(self))
|
|
|
|
def __get__(self, instance, owner):
|
|
"""The __get__ method"""
|
|
if instance is None:
|
|
return doc_descriptor_wrapper_factory(self)
|
|
else:
|
|
return getattr(instance, self.storage_name)
|
|
|
|
def __set__(self, instance, value):
|
|
setattr(instance, self.storage_name, value)
|
|
|
|
|
|
class Foo:
|
|
"""The "Foo" class"""
|
|
|
|
bar = DocDescriptor('The "bar" attribute')
|
|
bazz = DocDescriptor('The "bazz" attribute')
|