0
# Poetry Plugin Export
1
2
A Poetry plugin that extends Poetry's functionality by providing an export command to convert locked dependencies from poetry.lock files into various standardized formats like requirements.txt and constraints.txt. The plugin serves as a bridge between Poetry's modern dependency management system and traditional pip-based workflows.
3
4
## Package Information
5
6
- **Package Name**: poetry-plugin-export
7
- **Package Type**: Poetry plugin
8
- **Language**: Python
9
- **Installation**: `poetry self add poetry-plugin-export` or via pipx: `pipx inject poetry poetry-plugin-export`
10
11
## Core Imports
12
13
```python
14
from poetry_plugin_export.exporter import Exporter
15
from poetry_plugin_export.command import ExportCommand
16
from poetry_plugin_export.plugins import ExportApplicationPlugin
17
```
18
19
For version information:
20
21
```python
22
from poetry_plugin_export import __version__
23
```
24
25
For walker utilities:
26
27
```python
28
from poetry_plugin_export.walker import get_project_dependency_packages, get_project_dependency_packages2
29
```
30
31
## Basic Usage
32
33
The plugin is primarily used through Poetry's CLI command interface:
34
35
```bash
36
# Export to requirements.txt
37
poetry export -f requirements.txt --output requirements.txt
38
39
# Export to constraints.txt
40
poetry export -f constraints.txt --output constraints.txt
41
42
# Export with extras and specific dependency groups
43
poetry export -f requirements.txt -E web -E dev --with test --output requirements.txt
44
```
45
46
For programmatic usage:
47
48
```python
49
from poetry_plugin_export.exporter import Exporter
50
from cleo.io.buffered_io import BufferedIO
51
from poetry.factory import Factory
52
53
# Load Poetry project
54
poetry = Factory().create_poetry("path/to/project")
55
io = BufferedIO()
56
57
# Create and configure exporter
58
exporter = Exporter(poetry, io)
59
exporter.with_extras(["web", "dev"])
60
exporter.only_groups(["main", "test"])
61
exporter.with_hashes(True)
62
63
# Export to file
64
from pathlib import Path
65
exporter.export("requirements.txt", Path.cwd(), "requirements.txt")
66
```
67
68
## Architecture
69
70
The plugin integrates with Poetry through the plugin system and provides:
71
72
- **ExportApplicationPlugin**: Main plugin class that registers with Poetry's application
73
- **ExportCommand**: CLI command implementation with extensive options
74
- **Exporter**: Core export engine with fluent configuration API
75
- **Walker Module**: Dependency resolution utilities for traversing lock files
76
77
## Capabilities
78
79
### Plugin Integration
80
81
Poetry plugin system integration providing the export command to Poetry installations.
82
83
```python { .api }
84
class ExportApplicationPlugin(ApplicationPlugin):
85
"""Main plugin class for Poetry integration."""
86
87
@property
88
def commands(self) -> list[type[Command]]:
89
"""Returns list containing ExportCommand."""
90
91
def activate(self, application: Application) -> None:
92
"""Activates plugin and registers export command."""
93
```
94
95
### Export Command
96
97
CLI command interface for exporting dependencies with comprehensive option support.
98
99
```python { .api }
100
class ExportCommand(GroupCommand):
101
"""CLI command for exporting dependencies to various formats."""
102
103
name: str = "export"
104
description: str = "Exports the lock file to alternative formats."
105
106
@property
107
def default_groups(self) -> set[str]:
108
"""Returns default dependency groups to include."""
109
110
def handle(self) -> int:
111
"""Main command execution logic."""
112
```
113
114
#### Command Options
115
116
The export command supports extensive configuration through command-line options:
117
118
- `--format (-f)`: Export format (requirements.txt, constraints.txt)
119
- `--output (-o)`: Output file path
120
- `--without-hashes`: Exclude package hashes
121
- `--without-urls`: Exclude repository URLs
122
- `--with-credentials`: Include credentials for private repositories
123
- `--extras (-E)`: Include specific extra dependency sets
124
- `--all-extras`: Include all extra dependencies
125
- `--with`: Include specific dependency groups
126
- `--only`: Include only specified dependency groups
127
- `--all-groups`: Include all dependency groups
128
- `--dev`: Include development dependencies (deprecated)
129
- `--without`: Exclude dependency groups (deprecated)
130
131
### Core Export Engine
132
133
Main export functionality with fluent configuration API supporting multiple output formats.
134
135
```python { .api }
136
class Exporter:
137
"""Core exporter class for converting lock files to different formats."""
138
139
FORMAT_CONSTRAINTS_TXT: str = "constraints.txt"
140
FORMAT_REQUIREMENTS_TXT: str = "requirements.txt"
141
ALLOWED_HASH_ALGORITHMS: tuple = ("sha256", "sha384", "sha512")
142
143
def __init__(self, poetry: Poetry, io: IO) -> None:
144
"""Initialize exporter with Poetry instance and IO handler."""
145
146
@classmethod
147
def is_format_supported(cls, fmt: str) -> bool:
148
"""Check if the specified format is supported for export."""
149
150
def with_extras(self, extras: Collection[NormalizedName]) -> Exporter:
151
"""Configure exporter to include specified extra dependency sets."""
152
153
def only_groups(self, groups: Iterable[str]) -> Exporter:
154
"""Configure exporter to include only specified dependency groups."""
155
156
def with_urls(self, with_urls: bool = True) -> Exporter:
157
"""Configure whether to include repository URLs in output."""
158
159
def with_hashes(self, with_hashes: bool = True) -> Exporter:
160
"""Configure whether to include package hashes in output."""
161
162
def with_credentials(self, with_credentials: bool = True) -> Exporter:
163
"""Configure whether to include repository credentials in output."""
164
165
def export(self, fmt: str, cwd: Path, output: IO | str) -> None:
166
"""Export dependencies to specified format and output destination."""
167
```
168
169
### Dependency Resolution
170
171
Utilities for walking and resolving dependencies from Poetry lock files.
172
173
```python { .api }
174
def get_project_dependency_packages(
175
locker: Locker,
176
project_requires: list[Dependency],
177
root_package_name: NormalizedName,
178
project_python_marker: BaseMarker | None = None,
179
extras: Collection[NormalizedName] = ()
180
) -> Iterator[DependencyPackage]:
181
"""Get dependency packages for a project (legacy method)."""
182
183
def get_project_dependency_packages2(
184
locker: Locker,
185
project_python_marker: BaseMarker | None = None,
186
groups: Collection[str] = (),
187
extras: Collection[NormalizedName] = ()
188
) -> Iterator[DependencyPackage]:
189
"""Get dependency packages for a project (modern method for locked groups/markers)."""
190
191
def get_project_dependencies(
192
project_requires: list[Dependency],
193
locked_packages: list[Package],
194
root_package_name: NormalizedName
195
) -> Iterable[tuple[Package, Dependency]]:
196
"""Get project dependencies as package/dependency tuples."""
197
198
def walk_dependencies(
199
dependencies: list[Dependency],
200
packages_by_name: dict[str, list[Package]],
201
root_package_name: NormalizedName
202
) -> dict[Package, Dependency]:
203
"""Walk dependency tree to resolve all nested dependencies."""
204
```
205
206
### Utility Functions
207
208
Additional utility functions for dependency resolution.
209
210
```python { .api }
211
def get_locked_package(
212
dependency: Dependency,
213
packages_by_name: dict[str, list[Package]],
214
decided: dict[Package, Dependency] | None = None
215
) -> Package | None:
216
"""Find locked package matching dependency constraints."""
217
218
def get_python_version_region_markers(packages: list[Package]) -> list[BaseMarker]:
219
"""Generate markers for Python version regions from packages."""
220
```
221
222
## Types
223
224
```python { .api }
225
from typing import Collection, Iterable, Iterator
226
from pathlib import Path
227
from packaging.utils import NormalizedName
228
from poetry.poetry import Poetry
229
from poetry.packages import Locker
230
from poetry.core.packages.dependency import Dependency
231
from poetry.core.packages.package import Package
232
from poetry.core.version.markers import BaseMarker
233
from poetry.packages import DependencyPackage
234
from cleo.io.io import IO
235
236
# Module-level attributes
237
__version__: str # Package version
238
239
class DependencyWalkerError(Exception):
240
"""Exception raised when dependency walking fails."""
241
```
242
243
## Error Handling
244
245
The plugin handles various error conditions:
246
247
- **Invalid export format**: Raises `ValueError` if unsupported format is specified
248
- **Missing lock file**: Automatically runs `poetry lock` if lock file doesn't exist
249
- **Stale lock file**: Returns error code 1 if pyproject.toml has changed significantly
250
- **Conflicting options**: Returns error code 1 for incompatible option combinations
251
- **Dependency resolution errors**: Raises `DependencyWalkerError` for unresolvable dependencies
252
253
Common error scenarios:
254
255
```python
256
# Check format support before export
257
if not Exporter.is_format_supported("invalid-format"):
258
raise ValueError("Invalid export format: invalid-format")
259
260
# Handle dependency walker errors
261
try:
262
packages = list(get_project_dependency_packages(...))
263
except DependencyWalkerError as e:
264
print(f"Dependency resolution failed: {e}")
265
```