Python dependency management and packaging made easy.
—
Extensibility interfaces for creating Poetry plugins. Enables custom commands, functionality extensions, and integration with external tools through a flexible plugin architecture.
Abstract base class for all Poetry plugins providing the foundation for extensibility.
class Plugin:
"""
Base plugin interface for Poetry extensions.
Abstract base class that all Poetry plugins must implement
to integrate with Poetry's functionality.
"""
def activate(self, poetry: Poetry, io) -> None:
"""
Activate plugin with Poetry instance.
Args:
poetry: Poetry instance
io: IO interface for output
Raises:
NotImplementedError: Must be implemented by plugins
"""Plugin interface for extending Poetry's CLI with custom commands.
class ApplicationPlugin:
"""
Plugin interface for CLI command extensions.
Allows plugins to register custom commands with Poetry's
command-line interface.
"""
@property
def commands(self) -> list:
"""
List of command classes to register.
Returns:
List of command class instances
"""
def activate(self, application) -> None:
"""
Activate plugin with CLI application.
Args:
application: CLI application instance
"""Manages plugin discovery, loading, and activation within Poetry.
class PluginManager:
"""
Plugin discovery and management system.
Handles loading, activating, and managing Poetry plugins
with support for entry point discovery and error handling.
"""
def __init__(self, group: str = "poetry.plugin"):
"""
Initialize plugin manager.
Args:
group: Entry point group for plugin discovery
"""
def load_plugins(self, env: Env = None) -> None:
"""
Load plugins from entry points.
Args:
env: Environment for plugin loading
"""
def activate_plugins(self, poetry: Poetry, io = None) -> None:
"""
Activate loaded plugins.
Args:
poetry: Poetry instance
io: IO interface
"""
def get_plugin(self, name: str):
"""
Get plugin by name.
Args:
name: Plugin name
Returns:
Plugin instance or None
"""
def has_plugins(self) -> bool:
"""
Check if any plugins are loaded.
Returns:
True if plugins are available
"""from poetry.plugins.plugin import Plugin
class MyPlugin(Plugin):
"""Example Poetry plugin."""
def activate(self, poetry, io):
"""Activate plugin functionality."""
io.write_line("My plugin activated!")
# Access Poetry functionality
project_name = poetry.package.name
io.write_line(f"Working with project: {project_name}")
# Plugin-specific initialization
self.setup_custom_functionality(poetry)
def setup_custom_functionality(self, poetry):
"""Setup plugin-specific functionality."""
passfrom poetry.plugins.application_plugin import ApplicationPlugin
from poetry.console.commands.command import Command
class MyCommand(Command):
"""Custom Poetry command."""
name = "my-command"
description = "My custom command"
def handle(self):
"""Handle command execution."""
self.line("Executing my custom command!")
# Access Poetry instance
poetry = self.poetry
self.line(f"Project: {poetry.package.name}")
# Custom command logic
return 0
class MyCommandPlugin(ApplicationPlugin):
"""Plugin that adds custom commands."""
@property
def commands(self):
"""Return list of commands to register."""
return [MyCommand()]
def activate(self, application):
"""Activate plugin with application."""
pass # Commands are automatically registeredConfigure plugins in pyproject.toml:
[tool.poetry.plugins."poetry.plugin"]
my-plugin = "my_package.plugins:MyPlugin"
[tool.poetry.plugins."poetry.application.plugin"]
my-commands = "my_package.plugins:MyCommandPlugin"from poetry.plugins.plugin import Plugin
class ConfigExtensionPlugin(Plugin):
"""Plugin that extends configuration options."""
def activate(self, poetry, io):
"""Add custom configuration handling."""
config = poetry.config
# Add custom configuration defaults
custom_config = {
"my-plugin.enabled": True,
"my-plugin.custom-setting": "value"
}
config.merge(custom_config)
# Register configuration validators
self.register_validators(config)
def register_validators(self, config):
"""Register custom configuration validators."""
passfrom poetry.plugins.plugin import Plugin
from poetry.repositories.repository import Repository
class CustomRepository(Repository):
"""Custom repository implementation."""
def __init__(self, name, url, config):
"""Initialize custom repository."""
super().__init__(name)
self.url = url
self.config = config
def find_packages(self, dependency):
"""Find packages in custom repository."""
# Custom package discovery logic
return []
class RepositoryPlugin(Plugin):
"""Plugin that adds custom repository support."""
def activate(self, poetry, io):
"""Register custom repository."""
# Add custom repository to pool
custom_repo = CustomRepository(
name="custom",
url="https://custom-repo.example.com",
config=poetry.config
)
poetry.pool.add_repository(custom_repo, priority="supplemental")from poetry.plugins.plugin import Plugin
class BuildIntegrationPlugin(Plugin):
"""Plugin that integrates with build systems."""
def activate(self, poetry, io):
"""Setup build system integration."""
# Hook into build process
self.setup_build_hooks(poetry)
# Add custom build steps
self.register_build_steps(poetry)
def setup_build_hooks(self, poetry):
"""Setup hooks for build process."""
# Pre-build hooks
# Post-build hooks
pass
def register_build_steps(self, poetry):
"""Register custom build steps."""
passfrom poetry.plugins.plugin_manager import PluginManager
from poetry.factory import Factory
def test_plugin_activation():
"""Test plugin activation."""
# Create Poetry instance
poetry = Factory().create_poetry()
# Create plugin manager
plugin_manager = PluginManager()
# Load and activate plugins
plugin_manager.load_plugins()
plugin_manager.activate_plugins(poetry)
# Test plugin functionality
assert plugin_manager.has_plugins()import pytest
from poetry.console.application import Application
def test_command_plugin():
"""Test command plugin integration."""
# Create application with plugins
app = Application()
# Test custom command availability
assert app.has("my-command")
# Test command execution
tester = ApplicationTester(app)
tester.execute("my-command")
assert tester.status_code == 0Plugin system exceptions and error conditions:
class PluginError(PoetryError):
"""Base plugin error."""
class PluginLoadError(PluginError):
"""Plugin loading failures."""
class PluginActivationError(PluginError):
"""Plugin activation errors."""
class InvalidPluginError(PluginError):
"""Invalid plugin configuration or implementation."""Common plugin errors:
Install with Tessl CLI
npx tessl i tessl/pypi-poetry