example-code-2e/descriptors/doc_descriptor.py
2015-01-05 03:20:08 -02:00

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')