Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document difference between poetry plugins and entrypoints. #658

Open
1 task done
brennie opened this issue Nov 21, 2018 · 12 comments
Open
1 task done

Document difference between poetry plugins and entrypoints. #658

brennie opened this issue Nov 21, 2018 · 12 comments
Labels
area/docs Documentation issues/improvements

Comments

@brennie
Copy link

brennie commented Nov 21, 2018

  • I have searched the issues of this repo and believe that this is not a duplicate.

Issue

From a cursory glance, it looks like plugins are converted to entrypoints, but it would be good to clarify this in the documentation because it reads as if they are different:

Poetry supports arbitrary plugins which work similarly to setuptools entry points. (2)

@cjw296
Copy link

cjw296 commented Feb 19, 2019

@sdispater - I don't want to open a new issue, so I'll comment here. I'm a little confused, because #693 would seem to be the right place but that issue has become muddied with discussions around cleo, python version specification, etc.

This issue asks a specific question, but mine is a little broader: It appears that poetry has documentation for its own plugins along with a way of specifying plugins for your own projects. However, it doesn't have any examples/documentation about how to use the latter.

As a concrete example, how would I replace this specification and use of entrypoints if I moved that project to poetry?

@orlnub123
Copy link

I'm not sure why poetry specific plugins are documented since they don't seem to be implemented yet although I might be wrong since I just did a simple grep search.

As @brennie said plugins are simply a way to specify entry points so you wouldn't need to change anything to use them. I'd imagine you'd specify them similarly:

[tool.poetry.scripts]
archivist = "archivist.main:main"

[tool.poetry.plugins."archivist.repo"]
git = "archivist.main:main"

[tool.poetry.plugins."archivist.source"]
crontab = "archivist.sources.crontab:Plugin"
jenkins = "archivist.sources.jenkins:Plugin"
packages = "archivist.sources.packages:Plugin"
paths = "archivist.sources.paths:Plugin"

[tool.poetry.plugins."archivist.notification"]
email = "archivist.notifications.email:Plugin"
stream = "archivist.notifications.stream:Plugin"

@cjw296
Copy link

cjw296 commented Mar 1, 2019

@orlnub123 - great, so this is just a documentation issue.
Related question: Should I specify any dependency to make sure the pkg_resources package is available? I seem to remember that comes from setuptools, so curious about whether that'll "always" be available across virtualenvs, conda environments, etc?

@orlnub123
Copy link

@cjw296 It's probably possible to have an environment where setuptools isn't available at runtime so I'd say it's a good idea to declare it as a dependency.

@cjw296 cjw296 mentioned this issue Mar 3, 2019
2 tasks
@stale
Copy link

stale bot commented Nov 13, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Nov 13, 2019
@cjw296
Copy link

cjw296 commented Nov 15, 2019

not stale

@mfriedenhagen
Copy link

I still do not get it. What is the difference between tool.poetry.script and the stuff you declare beneath tool.poetry.plugins? Scripts I may invoke with "poetry run SCRIPT_NAME".

@sinoroc
Copy link

sinoroc commented Dec 5, 2020

@mfriedenhagen

As far as I understood it is a taken out of the entry points feature from setuptools:

Basically you have named entry points in different categories. The most common category is console_scripts. If you add an entry point in that category, then an executable of the same name is created. The executable will be created so that it runs the function specified as value for the entry point.

In setuptools setup.cfg you might have:

[options.entry_points]
console_scripts =
    mycommand = mypackage.mymodule:my_function

This should result in a mycommand executable that when called, runs the function my_function from mypackage.mymodule. So more or less:

#!/usr/bin/env python

if __name__ == '__main__':
    import mypackage
    mypackage.mymodule.my_function()

In poetry you would write in pyproject.toml either one of the following two:

[tool.poetry.scripts]
mycommand = "mypackage.mymodule:my_function"
[tool.poetry.plugins."console_scripts"]
"mycommand" = "mypackage.mymodule:my_function"

As far as I know they should be the same. Except maybe that first notation also allows to do poetry run mycommand (I am not sure).


As for the more general "plug-ins" side of this, I find it a bit hard to explain...

First I am a bit conflicted on the divide that was created in poetry between scripts and plugins. In both cases these are entry points, true they might be used for console scripts or plug-ins, but maybe for other things as well.

Basically you could write a pluggable application, that will look for any entry point registered in the specific category of your application (you define the name yourself, and it could look like awesomeapplication_plugin_category for example), and then your application can decide to call the associated functions to enhance the features of your pluggable application with plug-ins. So once your pluggable application is published and documented, I could write a plug-in for it:

[tool.poetry.plugins."awesomeapplication_plugin_category"]
"myawesomeplugin_entry_point" = "myawesomeplugin.mymodule:my_function"

So console_scripts is just one category of entry points and [tool.poetry.scripts] is in a way some kind of a shortcut for [tool.poetry.plugins."console_scripts"].

@mfriedenhagen
Copy link

mfriedenhagen commented Dec 5, 2020

Thanks a lot @sinoroc. That now makes sense somehow. So poetry currently does not allow to extend itself with plugins but provides a means to build a package which enhances other software like e.g. pytest, so I the following sample of https://docs.pytest.org/en/stable/writing_plugins.html#setuptools-entry-points could probably be written as

[tool.poetry.plugins."pytest11"]
name_of_plugin = "myproject.pluginmodule"

@sinoroc
Copy link

sinoroc commented Dec 6, 2020

poetry currently does not allow to extend itself with plugins but provides a means to build a package which enhances other software like e.g. pytest

Exactly.

the following sample of https://docs.pytest.org/en/stable/writing_plugins.html#setuptools-entry-points could probably be written as

[tool.poetry.plugins."pytest11"]
name_of_plugin = "myproject.pluginmodule"

Yes, seems right.

Poetry's own plug-in system is scheduled for v1.2. The way this future plug-in system is drafted now, if you were to write a plug-in for poetry in the future, it might look like this in your pyroject.toml:

[tool.poetry.plugins."poetry.plugin"]
demo = "poetry_demo_plugin.plugin:MyPlugin"

-- https://github.com/python-poetry/poetry/blame/605d786a942301374309d67c09d6579bf9165d75/docs/docs/plugins.md#L31-L32

@sdruskat
Copy link

FWIW, I've played around with this a tiny bit and found #658 (comment) to be correct. Here's a very simple example project for using poetry plugins in a CLI app: https://github.com/sdruskat/poetry-entrypoints.

@leoschet
Copy link

I was trying to have a plugin that would be automatically loaded together with my main application.

For context, I am using the Registry design pattern and am using decorators to add new classes to the register. Meaning the module would need to be imported for the classes to be registered. So basically broadcasting/advertising functionality.

For those that get here trying to do something similar, this documentation is what helped me: Advertising behavior.

I basically had to register the python module as a plugin, i.e.:

[tool.poetry.plugins."main_app.plugins"]
"plugin_name" = "path.to.plugin"

And then load available plugins in the __init__.py file at the root of the main_app:

from importlib.metadata import entry_points

for entry_point in entry_points(group="main_app.plugins"):
    # You can add more plugin names here
    if entry_point.name in ["plugin_name"]:
        entry_point.load()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/docs Documentation issues/improvements
Projects
None yet
Development

No branches or pull requests

8 participants