Allow help () to work with a partial function object

I am trying to run help() in Python 2.7. The REPL displays __doc__ for a function that was wrapped in functools.partial . Currently, help() on the functools.partial function maps to __doc__ class, and not my wrapped __doc__ function. Is there any way to achieve this?

Consider the following challenges:

 def foo(a): """My function""" pass partial_foo = functools.partial(foo, 2) 

Running help(foo) will display foo.__doc__ . However, running help(partial_foo) results in a __doc__ partial object .

My first approach was to use functools.update_wrapper , which correctly replaces the partial __doc__ object with foo.__doc__ . However, this does not fix the β€œproblem” due to how pydoc is .

I researched the pydoc code, and the problem is that partial_foo is not actually a Partial object / typical callable function, see this question for more information about this detail.

By default, pydoc will display the __doc__ of the object type, not the instance if the object that was passed is defined as the inspect.isclass class. For more information about the code itself, see the render_doc function .

So, in my script above, pydoc displays help like functools.partial NOT __doc__ my functools.partial instance.

Is there a way to change my instance call help() or functools.partial , which is passed to help() so that it displays the __doc__ instance, not type?

+6
source share
2 answers

I found a pretty hacky way to do this. I wrote the following function to override the __builtins__.help function:

 def partialhelper(object=None): if isinstance(object, functools.partial): return pydoc.help(object.func) else: # Preserve the ability to go into interactive help if user calls # help() with no arguments. if object is None: return pydoc.help() else: return pydoc.help(object) 

Then just replace it in REPL with:

 __builtins__.help = partialhelper 

This works and does not seem to have any major flaws. However, there is no way for the aforementioned naive implementation to support still showing __doc__ some functools.partial objects. This is all or nothing, but it is possible, perhaps, to attach an attribute to a wrapped (original) function to indicate whether the original __doc__ should be shown. However, in my scenario, I never want to do this.

Please note that the above does not work when using IPython and the built-in function . This is because IPython directly defines a shell namespace with links to "real" __builtin__ , see the code and the old mailing list for information on why this is so.

So, after some investigation, there is another way to crack this in IPython. We must override the site._Helper class that IPython uses to explicitly configure the help system . The following code will only do this when calling BEFORE IPython.embed :

 import site site._Helper.__call__ = lambda self, *args, **kwargs: partialhelper(*args, **kwargs) 

Are there any other disadvantages missing here?

+2
source

how to execute your own?

 def partial_foo(*args): """ some doc string """ return foo(*((2)+args)) 

not the perfect answer, but if you really want it, I suspect this is the only way to do it.

0
source

Source: https://habr.com/ru/post/945503/


All Articles