Document difference between poetry plugins and entrypoints.
- [x] 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)
@sdispater - I don't want to open a new issue, so I'll comment here. I'm a little confused, because https://github.com/sdispater/poetry/issues/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?
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"
@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?
@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.
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.
not stale
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".
@mfriedenhagen
As far as I understood it is a taken out of the entry points feature from setuptools:
- https://setuptools.readthedocs.io/en/latest/userguide/entry_point.html
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"].
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"
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
FWIW, I've played around with this a tiny bit and found https://github.com/python-poetry/poetry/issues/658#issuecomment-467952140 to be correct. Here's a very simple example project for using poetry plugins in a CLI app: https://github.com/sdruskat/poetry-entrypoints.
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()