Allow help() to work on partial function object

2024/10/5 9:29:59

I'm trying to make sure running help() at the Python 2.7 REPL displays the __doc__ for a function that was wrapped with functools.partial. Currently running help() on a functools.partial 'function' displays the __doc__ of the functools.partial class, not my wrapped function's __doc__. Is there a way to achieve this?

Consider the following callables:

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

Running help(foo) will result in showing foo.__doc__. However, running help(partial_foo) results in the __doc__ of a Partial object.

My first approach was to use functools.update_wrapper which correctly replaces the partial object's __doc__ with foo.__doc__. However, this doesn't fix the 'problem' because of how pydoc.

I've investigated the pydoc code, and the issue seems to be that partial_foo is actually a Partial object not a typical function/callable, see this question for more information on that detail.

By default, pydoc will display the __doc__ of the object type, not instance if the object it was passed is determined to be a class by inspect.isclass. See the render_doc function for more information about the code itself.

So, in my scenario above pydoc is displaying the help of the type, functools.partial NOT the __doc__ of my functools.partial instance.

Is there anyway to make alter my call to help() or functools.partial instance that's passed to help() so that it will display the __doc__ of the instance, not type?

Answer

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 the REPL with:

__builtins__.help = partialhelper

This works and doesn't seem to have any major downsides, yet. However, there isn't a way with the above naive implementation to support still showing the __doc__ of some functools.partial objects. It's all or nothing, but could probably attach an attribute to the wrapped (original) function to indicate whether or not the original __doc__ should be shown. However, in my scenario I never want to do this.

Note the above does NOT work when using IPython and the embed functionality. This is because IPython directly sets the shell's namespace with references to the 'real' __builtin__, see the code and old mailing list for information on why this is.

So, after some investigation there's another way to hack this into IPython. We must override the site._Helper class, which is used by IPython to explicitly setup the help system. The following code will do just that when called BEFORE IPython.embed:

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

Are there any other downsides I'm missing here?

https://en.xdnf.cn/q/70501.html

Related Q&A

How To Fix Miscased Procfile in Heroku

Heroku will not reload my corrected ProcfileI have ran git status which shows me the Procfile and I realized that I spelled Procfile with a lower case p. I saw the error and updated the file name in my…

Using Pythons xml.etree to find element start and end character offsets

I have XML data that looks like:<xml> The captial of <place pid="1">South Africa</place> is <place>Pretoria</place>. </xml>I would like to be able to extra…

How to get public key using PyOpenSSL?

Im tring to create python script, that would take PKCS#12 package and print some information contained in x509 certificate and using for this purpouses PyOpenSSL module. So far i want to fetch from cer…

what is the best way to extract data from pdf

I have thousands of pdf file that I need to extract data from.This is an example pdf. I want to extract this information from the example pdf.I am open to nodejs, python or any other effective method. …

Get random key:value pairs from dictionary in python

Im trying to pull out a random set of key-value pairs from a dictionary I made from a csv file. The dictionary contains information for genes, with the gene name being the dictionary key, and a list of…

UnicodeDecodeError: ascii codec cant decode byte 0xc5

UnicodeDecodeError: ascii codec cant decode byte 0xc5 in position 537: ordinal not in range(128), referer: ...I always get this error when I try to output my whole website with characters "č"…

wpa-handshake with python - hashing difficulties

I try to write a Python program which calculates the WPA-handshake, but I have problems with the hashes. For comparison I installed cowpatty (to see where I start beeing wrong).My PMK-generation works …

Group by column in pandas dataframe and average arrays

I have a movie dataframe with movie names, their respective genre, and vector representation (numpy arrays).ID Year Title Genre Word Vector 1 2003.0 Dinosaur Planet Documentary [-0.55423898,…

Python dynamic properties and mypy

Im trying to mask some functions as properties (through a wrapper which is not important here) and add them to the object dynamically, however, I need code completion and mypy to work.I figured out how…

Flask-login: remember me not working if login_managers session_protection is set to strong

i am using flask-login to integrate session management in my flask app. But the remember me functionality doesnt work if i set the session_protection to strong, however, it works absolutely fine if its…