0
# Plugin System
1
2
Poetry plugin integration classes and functionality that hook into Poetry's command lifecycle. Provides event-driven activation, command registration, and automatic cleanup for seamless integration with Poetry's build and development workflows.
3
4
## Capabilities
5
6
### Main Plugin Class
7
8
Core Poetry plugin that integrates dynamic versioning into Poetry's application lifecycle with automatic event handling and command registration.
9
10
```python { .api }
11
class DynamicVersioningPlugin(ApplicationPlugin):
12
def __init__(self):
13
"""Initialize plugin with empty application reference."""
14
15
def activate(self, application: Application) -> None:
16
"""
17
Activate the plugin within Poetry application.
18
19
Parameters:
20
- application: Poetry Application instance
21
22
Registers commands, validates configuration, and sets up event listeners
23
for COMMAND, SIGNAL, TERMINATE, and ERROR events.
24
"""
25
```
26
27
### Command Classes
28
29
Poetry command implementations for dynamic versioning operations accessible through Poetry's CLI interface.
30
31
```python { .api }
32
class DynamicVersioningCommand(Command):
33
name: str = "dynamic-versioning"
34
description: str = "Apply the dynamic version to all relevant files..."
35
36
def __init__(self, application: Application):
37
"""
38
Initialize main dynamic versioning command.
39
40
Parameters:
41
- application: Poetry Application instance
42
"""
43
44
def handle(self) -> int:
45
"""
46
Execute dynamic versioning application.
47
48
Returns:
49
int: Exit code (0 for success)
50
"""
51
52
class DynamicVersioningEnableCommand(Command):
53
name: str = "dynamic-versioning enable"
54
description: str = "Update pyproject.toml to enable the plugin..."
55
56
def handle(self) -> int:
57
"""
58
Enable dynamic versioning in project configuration.
59
60
Returns:
61
int: Exit code (0 for success)
62
"""
63
64
class DynamicVersioningShowCommand(Command):
65
name: str = "dynamic-versioning show"
66
description: str = "Print the version without changing any files."
67
68
def handle(self) -> int:
69
"""
70
Show current dynamic version without modifications.
71
72
Returns:
73
int: Exit code (0 for success)
74
"""
75
```
76
77
### Plugin Integration Functions
78
79
Internal functions that handle plugin lifecycle, dependency version patching, and conditional activation based on Poetry commands and environment settings.
80
81
```python { .api }
82
def _apply_version_via_plugin(
83
poetry: Poetry,
84
retain: bool = False,
85
force: bool = False,
86
standalone: bool = False,
87
io: bool = True
88
) -> None:
89
"""
90
Apply version through the plugin system to a Poetry instance.
91
92
Parameters:
93
- poetry: Poetry instance to modify
94
- retain: Don't disable plugin in pyproject.toml if True
95
- force: Apply even if plugin disabled in configuration
96
- standalone: Report application results if True
97
- io: Actually modify files if True
98
"""
99
100
def _patch_dependency_versions(io: bool) -> None:
101
"""
102
Patch Poetry's Factory.create_poetry() for dependency version handling.
103
104
Parameters:
105
- io: Whether to perform actual file I/O operations
106
107
Ensures that dependencies using dynamic versioning also get processed.
108
"""
109
```
110
111
### Build Backend Integration
112
113
Functions that handle PEP 517 build backend integration with automatic patching activation and cleanup.
114
115
```python { .api }
116
def activate() -> None:
117
"""
118
Activate patching for build backend usage.
119
120
Checks configuration, applies necessary patches to Poetry core,
121
and registers cleanup handlers. Called automatically by backend module.
122
"""
123
124
def deactivate() -> None:
125
"""
126
Clean up and revert changes when not in CLI mode.
127
128
Restores original state and removes version modifications
129
to maintain repository cleanliness after build operations.
130
"""
131
```
132
133
### Activation Control
134
135
Functions that determine when the plugin should activate based on Poetry commands and environment configuration.
136
137
```python { .api }
138
def _should_apply(command: str) -> bool:
139
"""
140
Determine if dynamic versioning should apply for a Poetry command.
141
142
Parameters:
143
- command: Poetry command name
144
145
Returns:
146
bool: True if versioning should be applied
147
148
Checks POETRY_DYNAMIC_VERSIONING_COMMANDS environment variable
149
and excludes commands like 'run', 'shell', and dynamic-versioning commands.
150
"""
151
152
def _should_apply_with_io(command: str) -> bool:
153
"""
154
Determine if dynamic versioning should modify files for a command.
155
156
Parameters:
157
- command: Poetry command name
158
159
Returns:
160
bool: True if files should be modified
161
162
Checks POETRY_DYNAMIC_VERSIONING_COMMANDS_NO_IO environment variable
163
and excludes 'version' command by default.
164
"""
165
```
166
167
## Event Handling
168
169
The plugin registers event listeners for comprehensive lifecycle management:
170
171
### Command Events
172
173
- **COMMAND**: Applies dynamic versioning before command execution
174
- **SIGNAL**: Reverts changes on signal interruption
175
- **TERMINATE**: Reverts changes on normal termination
176
- **ERROR**: Reverts changes on error conditions
177
178
### Event Flow
179
180
1. **Plugin Activation**: Registers commands and validates configuration
181
2. **Command Start**: Applies dynamic version if conditions are met
182
3. **Command Execution**: Poetry executes the requested command
183
4. **Cleanup**: Reverts changes regardless of success or failure
184
185
## Environment Variables
186
187
The plugin system respects several environment variables for behavior control:
188
189
```python { .api }
190
# Command filtering
191
POETRY_DYNAMIC_VERSIONING_COMMANDS: str
192
# Comma-separated list of commands to activate on
193
# Default: All commands except 'run', 'shell', and dynamic-versioning commands
194
195
POETRY_DYNAMIC_VERSIONING_COMMANDS_NO_IO: str
196
# Comma-separated list of commands that shouldn't modify files
197
# Default: "version"
198
```
199
200
## Usage Examples
201
202
### Plugin Registration
203
204
The plugin is automatically registered through Poetry's plugin system via entry points in pyproject.toml:
205
206
```toml
207
[tool.poetry.plugins."poetry.application.plugin"]
208
poetry-dynamic-versioning = "poetry_dynamic_versioning.plugin:DynamicVersioningPlugin"
209
```
210
211
### Manual Plugin Usage
212
213
```python
214
from poetry.console.application import Application
215
from poetry_dynamic_versioning.plugin import DynamicVersioningPlugin
216
217
# Create Poetry application
218
app = Application()
219
220
# Manually activate plugin
221
plugin = DynamicVersioningPlugin()
222
plugin.activate(app)
223
224
# Plugin is now registered and will handle events
225
```
226
227
### Command Execution
228
229
Once the plugin is installed and activated, commands are available through Poetry CLI:
230
231
```bash
232
# Apply dynamic versioning manually
233
poetry dynamic-versioning
234
235
# Enable dynamic versioning in project
236
poetry dynamic-versioning enable
237
238
# Show current version without changes
239
poetry dynamic-versioning show
240
```
241
242
### Programmatic Command Usage
243
244
```python
245
from poetry.console.application import Application
246
from poetry_dynamic_versioning.plugin import DynamicVersioningCommand
247
248
# Create application and command
249
app = Application()
250
command = DynamicVersioningCommand(app)
251
252
# Execute command programmatically
253
exit_code = command.handle()
254
print(f"Command completed with exit code: {exit_code}")
255
```
256
257
### Custom Event Handling
258
259
```python
260
from cleo.events.console_command_event import ConsoleCommandEvent
261
from poetry_dynamic_versioning.plugin import DynamicVersioningPlugin
262
263
class CustomPlugin(DynamicVersioningPlugin):
264
def _apply_version(self, event: ConsoleCommandEvent, kind: str, dispatcher) -> None:
265
print(f"Applying version for command: {event.command.name}")
266
super()._apply_version(event, kind, dispatcher)
267
268
def _revert_version(self, event: ConsoleCommandEvent, kind: str, dispatcher) -> None:
269
print(f"Reverting version after command: {event.command.name}")
270
super()._revert_version(event, kind, dispatcher)
271
```
272
273
### Command Filtering
274
275
```python
276
import os
277
from poetry_dynamic_versioning.plugin import _should_apply, _should_apply_with_io
278
279
# Set environment to limit activation to specific commands
280
os.environ["POETRY_DYNAMIC_VERSIONING_COMMANDS"] = "build,publish"
281
282
# Check if versioning should apply
283
should_version = _should_apply("build") # True
284
should_io = _should_apply_with_io("build") # True
285
286
should_version = _should_apply("run") # False (excluded command)
287
should_io = _should_apply_with_io("version") # False (no-IO command)
288
```
289
290
### Build Backend Integration
291
292
The plugin also integrates with PEP 517 build backends through the patch system:
293
294
```python
295
# pyproject.toml configuration
296
[build-system]
297
requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"]
298
build-backend = "poetry_dynamic_versioning.backend"
299
```
300
301
The backend automatically activates patching to ensure dynamic versioning works with tools like `pip` and `build` that use the PEP 517 interface.
302
303
### Factory Patching
304
305
```python
306
from poetry_dynamic_versioning.plugin import _patch_dependency_versions
307
from poetry.core.factory import Factory
308
309
# Check if patching is active
310
from poetry_dynamic_versioning import _state
311
if _state.patched_core_poetry_create:
312
print("Poetry Factory has been patched for dynamic versioning")
313
314
# Manually trigger patching (usually automatic)
315
_patch_dependency_versions(io=True)
316
```