0

I'm working on a piece of code that uses Pyhton's magical __getattr___ method to allow for call of 'functions' that are not really defined.
The problem is that help() returns the wrong docstring, that of the class, instead of that defined using __doc__. I can, however, print the correct docstring.
What must I do to get help() working as I want it to do?

Example:

class MathOperations(object):

    class VariableFunction(object):
        """This is the standard docstring of the class."""

        def __init__(self, name):
            if name == 'add':
                self.__doc__ = 'Return the sum'

    def __getattr__(self, attr):
        return self.VariableFunction(attr)

MathOperations = MathOperations()

help(MathOperations.add)
print(MathOperations.add.__doc__)

Which gives:

Help on VariableFunction in module __main__ object:

class VariableFunction(__builtin__.object)
 |  This is the standard docstring of the class.
 |  
 |  Methods defined here:
 |  
 |  __init__(self, name)
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)

Return the sum

I didn't write the original code, but I want to get it running.

Markus
  • 385
  • 2
  • 10
  • That's what's supposed to happen; `help` gives you the documentation on the *type* of the object: https://github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Lib/pydoc.py#L1660; you end up in [`TextDoc.docclass`](https://github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Lib/pydoc.py#L1213). – jonrsharpe May 07 '17 at 11:37
  • Didn't doubt that this is supposed to happen. My question is: can I change something in the code that ```help``` gives me the desired docstring? – Markus May 08 '17 at 15:37
  • In your code? You would need to get `VariableFunction` to pass one of [these tests](https://github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Lib/pydoc.py#L1654) such that you get the help for the object itself not the class. I'm not sure how you could sensibly go about that. – jonrsharpe May 08 '17 at 16:16

1 Answers1

0

Since help() in this case will always print the docstring of the class, the trick is to change the class' docstring programmatically. I found solutions in these SO topics: How do I programmatically set the docstring?, doc for __getattr__ defined attributes.

So in my case I changed the code as follows:

class MathOperations(object):

    class VariableFunction(object):
        """This is the standard docstring of the class."""

        def __init__(self, name):
            if name == 'add':
                self.__doc__ = 'Return the sum'


    def __getattr__(self, attr):
        wrapper = self.VariableFunction(attr)
        wrapper_type = type(wrapper)
        wrapper_dict = wrapper_type.__dict__.copy()
        wrapper_dict['__doc__'] = wrapper.__doc__
        variable_function = type('VariableFunction', (object,), wrapper_dict)
        return variable_function(attr)

MathOperations = MathOperations()

help(MathOperations.add)
print(MathOperations.add.__doc__)

And this is the output:

Help on VariableFunction in module __main__ object:

class VariableFunction(__builtin__.object)
 |  Return the sum
 |  
 |  Methods defined here:
 |  
 |  __init__(self, name)
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)

Return the sum
Community
  • 1
  • 1
Markus
  • 385
  • 2
  • 10