插件

插件 #

Poetry 支持使用和构建插件,如果你希望用自己的插件来改变或扩展 Poetry 的功能。

例如,如果你的环境对 Poetry 的行为提出了特殊的要求,而这些要求不适用于大多数用户,或者你希望以大多数用户不希望的方式使用 Poetry 来完成某些事情。

在这些情况下,你可以考虑创建一个插件来处理你的特定逻辑。

创建插件 #

插件是一个普通的 Python 包,它将代码作为包的一部分进行发布,并且可能还依赖于其他包。

插件包 #

插件包必须依赖于 Poetry,并在 pyproject.toml 文件中声明一个合适的 插件

[tool.poetry]
name = "my-poetry-plugin"
version = "1.0.0"

# ...
[tool.poetry.dependencies]
python = "^3.7"
poetry = "^1.2"

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

通用插件 #

每个插件都必须提供一个实现 poetry.plugins.Plugin 接口的类。

插件的 activate() 方法在插件加载后被调用,并接收一个 Poetry 实例和一个 cleo.io.io.IO 实例。

使用这两个对象,可以读取所有配置,并根据需要操作所有公共内部对象和状态。

示例

from cleo.io.io import IO

from poetry.plugins.plugin import Plugin
from poetry.poetry import Poetry


class MyPlugin(Plugin):

    def activate(self, poetry: Poetry, io: IO):
        io.write_line("Setting readme")
        poetry.package.readme = "README.md"
        ...

应用程序插件 #

如果你想在 poetry 脚本中添加命令或选项,你需要创建一个实现 poetry.plugins.ApplicationPlugin 接口的应用程序插件。

应用程序插件的 activate() 方法在插件加载后被调用,并接收一个 poetry.console.Application 实例。

from cleo.commands.command import Command
from poetry.plugins.application_plugin import ApplicationPlugin


class CustomCommand(Command):

    name = "my-command"

    def handle(self) -> int:
        self.line("My command")

        return 0


def factory():
    return CustomCommand()


class MyApplicationPlugin(ApplicationPlugin):
    def activate(self, application):
        application.command_loader.register_factory("my-command", factory)
注意

可以通过以下方式注册命令

application.add(MyCommand())

但是,强烈建议在命令加载器中注册一个新的工厂,以便在实际调用命令时延迟加载命令。

这将有助于保持 Poetry 的良好性能。

插件还必须在插件包的 pyproject.toml 文件中声明为 poetry.application.plugin 插件

[tool.poetry.plugins."poetry.application.plugin"]
foo-command = "poetry_demo_plugin.plugin:MyApplicationPlugin"
警告
插件**不能**以任何方式删除或修改 Poetry 的核心命令。

事件处理程序 #

插件还可以监听特定事件,并在必要时对其进行操作。

这些事件由 Cleo 触发,可以从 cleo.events.console_events 模块访问。

  • COMMAND:此事件允许在执行任何命令之前附加监听器。
  • SIGNAL:此事件允许在命令执行被中断后执行某些操作。
  • TERMINATE:此事件允许在命令之后附加监听器。
  • ERROR:当抛出未捕获的异常时,会发生此事件。

让我们看看如何实现应用程序事件处理程序。在这个例子中,我们将看到如何在执行命令之前从 .env 文件加载环境变量。

from cleo.events.console_events import COMMAND
from cleo.events.console_command_event import ConsoleCommandEvent
from cleo.events.event_dispatcher import EventDispatcher
from dotenv import load_dotenv
from poetry.console.application import Application
from poetry.console.commands.env_command import EnvCommand
from poetry.plugins.application_plugin import ApplicationPlugin


class MyApplicationPlugin(ApplicationPlugin):
    def activate(self, application: Application):
        application.event_dispatcher.add_listener(
            COMMAND, self.load_dotenv
        )

    def load_dotenv(
        self,
        event: ConsoleCommandEvent,
        event_name: str,
        dispatcher: EventDispatcher
    ) -> None:
        command = event.command
        if not isinstance(command, EnvCommand):
            return

        io = event.io

        if io.is_debug():
            io.write_line(
                "<debug>Loading environment variables.</debug>"
            )

        load_dotenv()

使用插件 #

安装的插件包会在 Poetry 启动时自动加载。

你有几种方法可以为 Poetry 安装插件

使用 pipx inject #

如果你使用 pipx 安装了 Poetry,你可以通过 pipx inject 命令添加插件包。

pipx inject poetry poetry-plugin

如果你想卸载插件,可以运行

pipx uninject poetry poetry-plugin          # For pipx versions >= 1.2.0

pipx runpip poetry uninstall poetry-plugin  # For pipx versions  < 1.2.0

使用 pip #

Poetry 虚拟环境中的 pip 二进制文件也可以用来安装和删除插件。这里的环境变量 $POETRY_HOME 用于表示虚拟环境的路径。如果你不确定 Poetry 安装在哪里,可以参考 安装说明

要添加插件,可以使用 pip install

$POETRY_HOME/bin/pip install --user poetry-plugin

如果你想卸载插件,可以运行

$POETRY_HOME/bin/pip uninstall poetry-plugin

self add 命令 #

警告
尤其是在 Windows 上,self addself remove 可能会有问题,因此应该优先使用其他方法。
poetry self add poetry-plugin

self add 命令将确保插件与当前版本的 Poetry 兼容,并安装插件工作所需的包。

self add 命令支持的包规范格式与 add 命令 支持的格式相同。

如果你不再需要插件并想卸载它,可以使用 self remove 命令。

poetry self remove poetry-plugin

你还可以通过运行以下命令列出所有当前安装的插件

poetry self show plugins

维护插件 #

在编写插件时,你可能会访问 Poetry 的内部,因为没有稳定的公共 API。虽然我们尽力在删除方法之前先将其弃用,但有时必须更改内部方法的签名。

作为插件的作者,你可能正在针对 Poetry 的最新版本测试你的插件。此外,你应该考虑针对 Poetry 的最新发布分支和主分支进行测试,并安排一个定期运行的 CI 作业,即使你没有对插件进行任何更改。这样,你就能立即注意到破坏插件的内部更改,并为下一个 Poetry 版本做好准备。