0
# Factory and Core Poetry Functionality
1
2
The factory and core Poetry modules provide central orchestration for creating and managing Poetry project instances. The Factory class serves as the main entry point for creating Poetry objects from project configurations.
3
4
## Core Imports
5
6
```python
7
from poetry.core.factory import Factory
8
from poetry.core.poetry import Poetry
9
from poetry.core.packages.project_package import ProjectPackage
10
from poetry.core.pyproject.toml import PyProjectTOML
11
``` { .api }
12
13
## Factory Class
14
15
The Factory class provides static and instance methods for creating Poetry projects and validating configurations.
16
17
### Factory.__init__
18
19
```python
20
class Factory:
21
"""Factory class to create various elements needed by Poetry."""
22
23
def __init__(self) -> None:
24
"""Initialize Factory instance."""
25
``` { .api }
26
27
### create_poetry
28
29
```python
30
def create_poetry(
31
self,
32
cwd: Path | None = None,
33
with_groups: bool = True
34
) -> Poetry:
35
"""
36
Create a Poetry instance from pyproject.toml configuration.
37
38
Args:
39
cwd: Working directory to search for pyproject.toml. If None, uses current directory.
40
with_groups: Whether to load dependency groups. Set False for build operations.
41
42
Returns:
43
Poetry instance representing the project
44
45
Raises:
46
RuntimeError: If Poetry configuration is invalid
47
PyProjectError: If pyproject.toml is missing or malformed
48
ValidationError: If project schema validation fails
49
50
Example:
51
>>> factory = Factory()
52
>>> poetry = factory.create_poetry()
53
>>> print(f"Project: {poetry.package.name}")
54
Project: my-package
55
56
>>> # Create from specific directory
57
>>> poetry = factory.create_poetry(Path("/path/to/project"))
58
59
>>> # Skip dependency groups for faster loading
60
>>> poetry = factory.create_poetry(with_groups=False)
61
"""
62
``` { .api }
63
64
### get_package (Class Method)
65
66
```python
67
@classmethod
68
def get_package(cls, name: str, version: str) -> ProjectPackage:
69
"""
70
Create a ProjectPackage instance with given name and version.
71
72
Args:
73
name: Package name
74
version: Package version string
75
76
Returns:
77
ProjectPackage instance
78
79
Example:
80
>>> package = Factory.get_package("my-package", "1.0.0")
81
>>> print(f"{package.name} v{package.version}")
82
my-package v1.0.0
83
"""
84
``` { .api }
85
86
### configure_package (Class Method)
87
88
```python
89
@classmethod
90
def configure_package(
91
cls,
92
package: ProjectPackage,
93
pyproject: PyProjectTOML,
94
root: Path,
95
with_groups: bool = True
96
) -> None:
97
"""
98
Configure package metadata, dependencies, and Poetry-specific settings.
99
100
Args:
101
package: ProjectPackage instance to configure
102
pyproject: PyProject TOML configuration
103
root: Project root directory path
104
with_groups: Whether to configure dependency groups
105
106
Raises:
107
ValidationError: If configuration is invalid
108
109
Note:
110
This method modifies the package in-place, setting:
111
- Basic metadata (description, authors, etc.)
112
- Dependencies and dependency groups
113
- Build configuration
114
- Entry points and scripts
115
- Package includes/excludes
116
"""
117
``` { .api }
118
119
### create_dependency (Class Method)
120
121
```python
122
@classmethod
123
def create_dependency(
124
cls,
125
name: str,
126
constraint: DependencyConstraint,
127
groups: list[str] | None = None,
128
root_dir: Path | None = None
129
) -> Dependency:
130
"""
131
Create various types of dependencies from constraint specifications.
132
133
Args:
134
name: Dependency name
135
constraint: Version constraint or dependency specification
136
groups: Dependency groups (e.g., ["dev", "test"])
137
root_dir: Root directory for resolving relative paths
138
139
Returns:
140
Appropriate Dependency subclass instance:
141
- Dependency: Regular version-based dependency
142
- VCSDependency: Git/VCS dependency
143
- FileDependency: Local file dependency
144
- DirectoryDependency: Local directory dependency
145
- URLDependency: URL-based dependency
146
147
Example:
148
>>> # Version constraint
149
>>> dep = Factory.create_dependency("requests", "^2.25.0")
150
151
>>> # Git dependency
152
>>> dep = Factory.create_dependency("mypackage", {
153
... "git": "https://github.com/user/repo.git",
154
... "branch": "main"
155
... })
156
157
>>> # Local path dependency
158
>>> dep = Factory.create_dependency("local-pkg", {"path": "./libs/local"})
159
"""
160
``` { .api }
161
162
### validate (Class Method)
163
164
```python
165
@classmethod
166
def validate(
167
cls,
168
toml_data: dict[str, Any],
169
strict: bool = False
170
) -> dict[str, list[str]]:
171
"""
172
Validate Poetry configuration against JSON schemas.
173
174
Args:
175
toml_data: Raw TOML data from pyproject.toml
176
strict: Whether to treat warnings as errors
177
178
Returns:
179
Dictionary containing validation results:
180
{
181
"errors": ["List of error messages"],
182
"warnings": ["List of warning messages"]
183
}
184
185
Example:
186
>>> from poetry.core.pyproject.toml import PyProjectTOML
187
>>> pyproject = PyProjectTOML(Path("pyproject.toml"))
188
>>> result = Factory.validate(pyproject.data)
189
>>> if result["errors"]:
190
... print("Configuration errors:", result["errors"])
191
>>> if result["warnings"]:
192
... print("Configuration warnings:", result["warnings"])
193
"""
194
``` { .api }
195
196
### locate (Class Method)
197
198
```python
199
@classmethod
200
def locate(cls, cwd: Path | None = None) -> Path:
201
"""
202
Locate pyproject.toml file in current or parent directories.
203
204
Args:
205
cwd: Directory to start search from. If None, uses current directory.
206
207
Returns:
208
Path to the pyproject.toml file
209
210
Raises:
211
RuntimeError: If pyproject.toml cannot be found
212
213
Example:
214
>>> pyproject_path = Factory.locate()
215
>>> print(f"Found: {pyproject_path}")
216
Found: /path/to/project/pyproject.toml
217
218
>>> # Search from specific directory
219
>>> pyproject_path = Factory.locate(Path("/some/subdirectory"))
220
"""
221
``` { .api }
222
223
## Poetry Class
224
225
The Poetry class represents a complete Poetry project context with configuration, package information, and build dependencies.
226
227
### Poetry.__init__
228
229
```python
230
class Poetry:
231
def __init__(
232
self,
233
file: Path,
234
local_config: dict[str, Any],
235
package: ProjectPackage,
236
pyproject_type: type[PyProjectTOML] = PyProjectTOML,
237
) -> None:
238
"""
239
Initialize Poetry instance.
240
241
Args:
242
file: Path to pyproject.toml file
243
local_config: Poetry configuration from [tool.poetry] section
244
package: ProjectPackage instance
245
pyproject_type: PyProjectTOML class (for testing/customization)
246
"""
247
``` { .api }
248
249
### Properties
250
251
#### pyproject
252
253
```python
254
@property
255
def pyproject(self) -> PyProjectTOML:
256
"""
257
PyProject TOML configuration object.
258
259
Returns:
260
PyProjectTOML instance with full project configuration
261
262
Example:
263
>>> poetry = Factory().create_poetry()
264
>>> config = poetry.pyproject
265
>>> print(f"Build system: {config.build_system.build_backend}")
266
"""
267
``` { .api }
268
269
#### pyproject_path
270
271
```python
272
@property
273
def pyproject_path(self) -> Path:
274
"""
275
Path to the pyproject.toml file.
276
277
Returns:
278
Absolute path to pyproject.toml
279
280
Example:
281
>>> poetry = Factory().create_poetry()
282
>>> print(f"Config file: {poetry.pyproject_path}")
283
Config file: /path/to/project/pyproject.toml
284
"""
285
``` { .api }
286
287
#### package
288
289
```python
290
@property
291
def package(self) -> ProjectPackage:
292
"""
293
Project package instance containing metadata and dependencies.
294
295
Returns:
296
ProjectPackage with all package information
297
298
Example:
299
>>> poetry = Factory().create_poetry()
300
>>> pkg = poetry.package
301
>>> print(f"{pkg.name} v{pkg.version}")
302
>>> print(f"Dependencies: {len(pkg.requires)}")
303
"""
304
``` { .api }
305
306
#### is_package_mode
307
308
```python
309
@property
310
def is_package_mode(self) -> bool:
311
"""
312
Whether the project is in package mode.
313
314
Returns:
315
True if in package mode (builds installable package),
316
False if in application mode (no package building)
317
318
Example:
319
>>> poetry = Factory().create_poetry()
320
>>> if poetry.is_package_mode:
321
... print("This project builds a package")
322
... else:
323
... print("This is an application project")
324
"""
325
``` { .api }
326
327
#### local_config
328
329
```python
330
@property
331
def local_config(self) -> dict[str, Any]:
332
"""
333
Local Poetry configuration dictionary.
334
335
Returns:
336
Dictionary containing [tool.poetry] section configuration
337
338
Example:
339
>>> poetry = Factory().create_poetry()
340
>>> config = poetry.local_config
341
>>> print(f"Name: {config.get('name')}")
342
>>> print(f"Version: {config.get('version')}")
343
"""
344
``` { .api }
345
346
#### build_system_dependencies
347
348
```python
349
@property
350
def build_system_dependencies(self) -> list[Dependency]:
351
"""
352
Build system dependencies from [build-system] section.
353
354
Returns:
355
List of Dependency objects required for building
356
357
Example:
358
>>> poetry = Factory().create_poetry()
359
>>> build_deps = poetry.build_system_dependencies
360
>>> for dep in build_deps:
361
... print(f"Build requires: {dep.name} {dep.constraint}")
362
"""
363
``` { .api }
364
365
### Methods
366
367
#### get_project_config
368
369
```python
370
def get_project_config(self, config: str, default: Any = None) -> Any:
371
"""
372
Get project-specific configuration value.
373
374
Args:
375
config: Configuration key to retrieve
376
default: Default value if key not found
377
378
Returns:
379
Configuration value or default
380
381
Example:
382
>>> poetry = Factory().create_poetry()
383
>>> cache_dir = poetry.get_project_config("cache-dir", "~/.cache")
384
>>> print(f"Cache directory: {cache_dir}")
385
"""
386
``` { .api }
387
388
## Type Definitions
389
390
```python
391
from typing import Any, Mapping, Union
392
from pathlib import Path
393
from poetry.core.packages.dependency import Dependency
394
395
# Dependency constraint types
396
DependencyConstraint = Union[str, Mapping[str, Any]]
397
DependencyConfig = Mapping[
398
str, Union[list[DependencyConstraint], DependencyConstraint]
399
]
400
401
# Configuration types
402
LocalConfig = dict[str, Any]
403
ValidationResult = dict[str, list[str]]
404
``` { .api }
405
406
## Complete Usage Examples
407
408
### Creating and Inspecting a Poetry Project
409
410
```python
411
from pathlib import Path
412
from poetry.core.factory import Factory
413
414
def analyze_project(project_path: Path) -> None:
415
"""Analyze a Poetry project and print key information."""
416
417
factory = Factory()
418
419
try:
420
# Create Poetry instance
421
poetry = factory.create_poetry(project_path)
422
423
# Project information
424
pkg = poetry.package
425
print(f"Project: {pkg.name}")
426
print(f"Version: {pkg.version}")
427
print(f"Description: {pkg.description}")
428
print(f"Package mode: {poetry.is_package_mode}")
429
430
# Dependencies
431
print(f"\nDependencies ({len(pkg.requires)}):")
432
for dep in pkg.requires:
433
print(f" {dep.name}: {dep.constraint}")
434
435
# Development dependencies
436
if pkg.has_dependency_group("dev"):
437
dev_deps = pkg.dependency_group("dev").dependencies
438
print(f"\nDev Dependencies ({len(dev_deps)}):")
439
for dep in dev_deps:
440
print(f" {dep.name}: {dep.constraint}")
441
442
# Build system
443
build_deps = poetry.build_system_dependencies
444
print(f"\nBuild Dependencies ({len(build_deps)}):")
445
for dep in build_deps:
446
print(f" {dep.name}: {dep.constraint}")
447
448
except Exception as e:
449
print(f"Error analyzing project: {e}")
450
451
# Usage
452
analyze_project(Path("./my-poetry-project"))
453
``` { .api }
454
455
### Configuration Validation
456
457
```python
458
from pathlib import Path
459
from poetry.core.factory import Factory
460
from poetry.core.pyproject.toml import PyProjectTOML
461
462
def validate_project_config(project_path: Path, strict: bool = False) -> bool:
463
"""Validate Poetry project configuration."""
464
465
try:
466
# Load pyproject.toml
467
pyproject_path = Factory.locate(project_path)
468
pyproject = PyProjectTOML(pyproject_path)
469
470
# Validate configuration
471
result = Factory.validate(pyproject.data, strict=strict)
472
473
# Report results
474
if result["errors"]:
475
print("Configuration Errors:")
476
for error in result["errors"]:
477
print(f" ❌ {error}")
478
479
if result["warnings"]:
480
print("Configuration Warnings:")
481
for warning in result["warnings"]:
482
print(f" ⚠️ {warning}")
483
484
# Return validation status
485
is_valid = not result["errors"]
486
if strict:
487
is_valid = is_valid and not result["warnings"]
488
489
print(f"\nConfiguration is {'valid' if is_valid else 'invalid'}")
490
return is_valid
491
492
except Exception as e:
493
print(f"Validation failed: {e}")
494
return False
495
496
# Usage
497
is_valid = validate_project_config(Path("./my-project"), strict=True)
498
``` { .api }
499
500
### Creating Dependencies Programmatically
501
502
```python
503
from poetry.core.factory import Factory
504
from pathlib import Path
505
506
def create_various_dependencies():
507
"""Demonstrate creating different types of dependencies."""
508
509
# Regular version dependencies
510
requests_dep = Factory.create_dependency("requests", "^2.25.0")
511
print(f"Regular: {requests_dep.name} {requests_dep.constraint}")
512
513
# Git dependency
514
git_dep = Factory.create_dependency("mypackage", {
515
"git": "https://github.com/user/repo.git",
516
"branch": "main",
517
"extras": ["dev"]
518
})
519
print(f"Git: {git_dep.name} from {git_dep.source_url}")
520
521
# Local path dependency
522
path_dep = Factory.create_dependency("local-lib", {
523
"path": "../shared-lib",
524
"develop": True
525
})
526
print(f"Path: {path_dep.name} from {path_dep.source_url}")
527
528
# URL dependency
529
url_dep = Factory.create_dependency("archive-pkg", {
530
"url": "https://example.com/package-1.0.0.tar.gz"
531
})
532
print(f"URL: {url_dep.name} from {url_dep.source_url}")
533
534
# Development dependency
535
dev_dep = Factory.create_dependency(
536
"pytest",
537
"^6.0.0",
538
groups=["dev", "test"]
539
)
540
print(f"Dev: {dev_dep.name} in groups {dev_dep.groups}")
541
542
create_various_dependencies()
543
``` { .api }
544
545
### Custom Project Creation
546
547
```python
548
from pathlib import Path
549
from poetry.core.factory import Factory
550
from poetry.core.packages.project_package import ProjectPackage
551
552
def create_custom_project() -> None:
553
"""Create a custom Poetry project programmatically."""
554
555
factory = Factory()
556
557
# Create base package
558
package = factory.get_package("my-custom-app", "0.1.0")
559
560
# Set metadata
561
package.description = "A custom application"
562
package.authors = ["Developer <dev@example.com>"]
563
package.homepage = "https://github.com/user/my-custom-app"
564
565
# Add dependencies
566
requests_dep = factory.create_dependency("requests", "^2.25.0")
567
click_dep = factory.create_dependency("click", ">=7.0")
568
569
package.add_dependency(requests_dep)
570
package.add_dependency(click_dep)
571
572
# Add development dependencies
573
pytest_dep = factory.create_dependency("pytest", "^6.0.0", groups=["dev"])
574
package.add_dependency(pytest_dep)
575
576
print(f"Created project: {package.name}")
577
print(f"Dependencies: {[d.name for d in package.requires]}")
578
print(f"Dev dependencies: {[d.name for d in package.dev_requires]}")
579
580
create_custom_project()
581
``` { .api }