API: Add entrypoint for plotting
State: closed

Libraries, including pandas, register backends via entrypoints.

xref #26747 

cc @datapythonista @jakevdp @philippjfr

Labels:
name: Visualization
description: plotting

Comments:
this seems like a very complex solution 

why is not the simpler

plotting.backend = ‘altair.pandas_plot’ 
plotting.backend = ‘pandas._matplotlib.plot’

not much more straightforward here?

eg this is a standard import as passed to importlib
We want to decouple the backend name (`altair`) from the implementation. Altair doesn't want and shouldn't need a top-level `altair.pandas_plot` just to implement this backend (which may even be implemented in a separate package).
and how does my suggestion not do this is? it is fully decoupled 
I guess I don't understand your suggestion then. You say 

```
plotting.backend = ‘altair.pandas_plot’
```

which seems to require a top-level `altair.pandas_plot`?
not at all
these are examples of what you could pass; it could be called anything
that’s the point - we don’t care what it’s called
and no pandas code would have to change for this to be added
The reason I proposed this is because I believe it's cleaner for the implementation's code path to be separate from how the user specifies it. My goal would be for a user to write
```
plotting.backend = 'altair'
```
and for this to cause the plotting backend to use Altair.

Before this solution, that would require me to pollute the Altair package's top-level namespace with APIs that are irrelevant to users of the package. I think entrypoints is a clean solution to that problem (decoupling of specification from code paths), and one that is in common use among packages in the jupyter ecosystem.
I just want to avoid a situation where users have to remember, "for Matplotlib use ``plotting.backend = 'matplotlib'``", "for Bokeh, use ``plotting.backend = 'bokeh._pandas_api``", for Altair use ``plotting.backend = 'altair_pandas_backend'``"...

Seems like it would lead to more confusion than necessary.
Thanks @jakevdp. Agreed entirely.
ok I see your point @jakevdp and I agree that is nice to de-couple the user supplied key to plotting.backend, but then again it *does* couple the api of the package to pandas directly, meaning we then *need* to make an update in pandas to actually use a new package / api. 

So this is nice, I would then *also* allow a fully qualified module.function call to succeed
> it does couple the api of the package to pandas directly, meaning we then need to make an update in pandas to actually use a new package / api.

I may be misunderstanding, but I don't see how the change to use entrypoints affects that. If you're saying that we'll need to update pandas so that `set_option('plotting.backend', 'altair')` works, then that's not correct. The only change required after this is that altair (or pdvega, whatever package) adds an EntryPoint for `pandas_plotting_backends` in its setup.py.

Basically, pandas adds an EntryPoint "group" in our setup.py. And third party libraries add items to that group in their setup.pys. Pandas and the library don't need to talk to each other directly to register a backend. We talk through `pkg_resources`.

> So this is nice, I would then also allow a fully qualified module.function call to succeed

We do allow that (see `test_register_import`).
> Basically, pandas adds an EntryPoint "group" in our setup.py. And third party libraries add items to that group in their setup.pys. Pandas and the library don't need to talk to each other directly to register a backend. We talk through `pkg_resources`.
> 

ok so if this works then that's great. +1.

Yep, this should work out just fine.
@datapythonista ok on this?
Thanks, fixed.
thanks @TomAugspurger