Metaclass to rewrite class __doc__?

Peter Otten __peter__ at web.de
Thu Feb 23 15:02:13 EST 2017


Skip Montanaro wrote:

> I stumbled upon this use of a metaclass to modify function docstrings:
> 
> http://www.jesshamrick.com/2013/04/17/rewriting-python-docstrings-with-a-metaclass/
> 
> In certain circumstances (mostly when extending some Pybind11 wrappers),
> it might be nice to extend/modify a class's docstring in a similar manner.
> Alas, my first attempt at that was unsuccessful. All I was trying to do
> was the following (skipping any error checking):
> 
> class _RewriteDocMeta(type):
>     def __new__(cls, name, parents, attrs):
>         cls.__doc__ = parents[0].__doc__ + "\n\n" + cls.__doc__

Here cls is _RewriteDocMeta, but I think you want to change the not yet 
existing class, i. e. an instance of _RewriteDocMeta.
As its attributes are in the attrs dict you have to update that dictionary:

$ cat demo.py
class Meta(type):
    def __new__(cls, classname, bases, attrs):
        attrs["__doc__"] = "{}: {}".format(
          classname, attrs.get("__doc__") or "<undocumented>"
        )
        return type.__new__(cls, classname, bases, attrs)

class A(metaclass=Meta):
    "hello"
print(A.__doc__)

class B(A):
    "goodbye"
print(B.__doc__)

class C(metaclass=Meta):
    pass
print(C.__doc__)
$ python3 demo.py 
A: hello
B: goodbye
C: <undocumented>
$


>         return super(_RewriteDocMeta, cls).__new__(cls, name, parents,
> attrs)
> 
> Using that as the __metaclass__ for a class resulted in:
> 
>     ... '__doc__' of 'type' objects is not writable.
> 
> Does this imply a requirement for a metaclass metaclass? In Jess Hamrick's
> blog, she built entirely new function objects out of their constituent
> bits, then set their __doc__ attributes. She didn't attempt to
> replace/modify an existing function (or unbound method) docstring. I fear
> that might be required in this case as well.
> 
> This works:
> 
> class F(object):
>   "F doc"
>   pass
> 
> G = type(F)("G", (F,), {"__doc__": F.__doc__ + "\n" + "G doc"})
> 
> but I'm not sure how to translate that into a working __metaclass__
> example (my brain is slowly exploding
> <https://www.python.org/doc/essays/metaclasses/>[*] as I write this)...
> 
> Thx,
> 
> Skip
> 
> [*] Whatever happened to Don Beaudry?





More information about the Python-list mailing list