ipython / ipykernel

IPython Kernel for Jupyter
https://ipykernel.readthedocs.io/en/stable/
BSD 3-Clause "New" or "Revised" License
649 stars 367 forks source link

Customizable hook for pinfo (?) akin to _ipython_display_ #1005

Open b3m2a1 opened 2 years ago

b3m2a1 commented 2 years ago

[Related to https://github.com/jupyterlab/jupyterlab/issues/13217]

This is mostly applicable to working in a notebook or lab environment, but I would like to be able to customize what happens when I call ? on the classes and objects in the libraries I write. This kind of hook already exists for displaying objects through _ipython_display_ and now I would just like it to also work for calling like ?MyNiceClass

In principle, this should be easy as ? just calls into the pinfo magic which could check for the existence of some hook like _ipython_pinfo_ or something similar, although two variants might be required, one for instances and one for classes

b3m2a1 commented 2 years ago

I was able to monkey patch this in like

def patch_pinfo():
    from IPython.core.oinspect import Inspector
    from IPython.core.display import display

    if not hasattr(Inspector, '_og_pinfo'):
        Inspector._og_pinfo = Inspector.pinfo

    def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0, enable_html_pager=True):
        if hasattr(obj, '_ipython_pinfo_'):
            display(obj._ipython_pinfo_())
        else:
            return Inspector._og_pinfo(self, obj, oname=oname, formatter=formatter, info=info, detail_level=detail_level, enable_html_pager=enable_html_pager)

    Inspector.pinfo = pinfo

and then by using a mixedmethod decorator that acts like a classmethod or a bound method I can add this to an object

    @mixedmethod
    def _ipython_pinfo_(cls):
        return jdoc(cls)

which allows me to do this

image

which is exactly the behavior I want. I'd obviously prefer a solution that doesn't involve monkey patching though.