Add Poetry package manager support for Python#13086
Conversation
Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 13086Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 13086" |
| .Copy("pyproject.toml", "/app/") | ||
| .Copy("poetry.lock", "/app/") |
There was a problem hiding this comment.
This only works if I didn't split my app into multiple packages :(
But, I don't expect you to solve everything :D
|
Tested locally. Multiple issues:
|
This isn't unique to poetry. I assume this applies to everything in the python (and more), extension methods. |
|
@copilot Implement the PR feedback |
…ction Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Added |
|
@copilot We don't want to override POETRY_VIRTUALENVS_PATH or POETRY_VIRTUALENVS_IN_PROJECT by default. Don't set them |
… default Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Removed default environment variable settings in commit f981883. Poetry will now use its own defaults. Users can configure Poetry behavior (e.g., |
| .Run("groupadd --system --gid 999 appuser && useradd --system --gid 999 --uid 999 --create-home appuser") | ||
| .EmptyLine() | ||
| .Comment("Copy the application and virtual environment from builder") | ||
| .CopyFrom(builderStage.StageName!, "/app", "/app", "appuser:appuser") |
There was a problem hiding this comment.
This would not contain the .venv if not using the POETRY_VIRTUALENVS_IN_PROJECT=true.
I think that in the docker file turning this flag on is preferred, but again, but other users might not like that.
|
@copilot When using poetry and building a container image, assume the venv is not local and run poetry install to create the venv in the container. This will remove a reliance on the venv being on disk and being copied into the container. |
Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Set |
|
@copilot This pattern is broken: // Global configuration via BeforeStartEvent We need to add the installtion managers up front in AddPythonAppCore |
Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Fixed in commit e648bc6. All installation managers (PythonInstallationManager, UvInstallationManager, PoetryInstallationManager) are now registered upfront in |
There was a problem hiding this comment.
Pull request overview
This PR adds Poetry as a third Python package manager option in .NET Aspire, joining pip and uv. Poetry is a popular Python dependency management tool that handles its own virtual environment creation. The implementation follows established patterns from pip/uv while accommodating Poetry's distinct behavior, particularly around virtual environment management.
Key Changes:
- Adds
WithPoetry()extension method with parameters for install control, custom arguments, and environment variable configuration - Implements Poetry-specific Dockerfile generation with multi-stage builds and optimized layer caching
- Registers all installation managers upfront to prevent service collection freezing issues during global configuration
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| PoetryInstallationManager.cs | New installation validator for Poetry CLI tool availability |
| PoetryEnvironmentAnnotation.cs | New annotation to store Poetry-specific environment variables |
| PythonAppResourceBuilderExtensions.cs | Added WithPoetry method, Poetry Dockerfile generation, and upfront service registration |
| AddPythonAppTests.cs | Added 8 comprehensive unit tests covering Poetry functionality |
| Aspire.Hosting.Python.cs | Updated public API surface with WithPoetry signature |
| /// <returns>A reference to the <see cref="IResourceBuilder{T}"/> for method chaining.</returns> | ||
| /// <remarks> | ||
| /// <para> | ||
| /// This method creates a child resource that runs <c>poetry install --no-interaction</c> in the working directory of the Python application. |
There was a problem hiding this comment.
The documentation states this method 'creates a child resource' but should clarify that this only happens when install is true. When install is false, no installer resource is created. Consider rephrasing to: 'When <paramref name="install"/> is true (default), this method creates a child resource that runs...' to match the actual behavior documented in the parameter description.
| /// This method creates a child resource that runs <c>poetry install --no-interaction</c> in the working directory of the Python application. | |
| /// When <paramref name="install"/> is true (default), this method creates a child resource that runs <c>poetry install --no-interaction</c> in the working directory of the Python application. |
Description
Adds Poetry as a Python package manager option in .NET Aspire, following existing patterns for pip and uv. This implementation allows developers to use Poetry for managing Python dependencies and virtual environments in Aspire applications.
Important: Aspire does not override Poetry's default configuration for local development. Users must explicitly configure Poetry's virtual environment behavior via the
envparameter if they want to control where Poetry creates virtual environments (e.g., in-project vs cache directory). However, when building container images, Aspire setsPOETRY_VIRTUALENVS_IN_PROJECT=trueto ensure Poetry creates the virtual environment within the container.Fixes #6742
Changes Made
New Files
PoetryInstallationManager.cs- Validates Poetry installationPoetryEnvironmentAnnotation.cs- Stores custom Poetry environment variables usingIReadOnlyDictionary<string, string>Modified Files
PythonAppResourceBuilderExtensions.cs- AddedWithPoetryextension method, Poetry-specific Dockerfile generation, and registered all installation managers upfront inAddPythonAppCoreAddPythonAppTests.cs- Added 8 comprehensive unit tests for Poetry supportAspire.Hosting.Python.cs- Updated public API surfaceKey Implementation Details
API Signature:
Virtual Environment Management:
POETRY_VIRTUALENVS_IN_PROJECTorPOETRY_VIRTUALENVS_PATHby default. Poetry uses its own default configuration (typically creates venvs in a cache directory). Users can customize Poetry's behavior via theenvparameter.POETRY_VIRTUALENVS_IN_PROJECT=truein the Dockerfile to ensure Poetry creates the virtual environment within the container at/app/.venv. This removes reliance on copying the venv from the host.Installation:
poetry install --no-interactioninstallArgsparameterinstall: falseDockerfile Generation:
POETRY_VIRTUALENVS_IN_PROJECT=trueto create venv in containerpoetry.lockfor reproducible buildsService Collection Registration:
AddPythonAppCoreWithPoetry(),WithUv(), andWithPip()to be called safely duringBeforeStartEventfor global configurationUsage Examples
Checklist
<remarks />and<code />elements on your triple slash comments?WithPoetryextension method, different behavior between local dev and container builds, global configuration pattern, and usage examples)Testing Results
Original prompt
This section details on the original issue you should resolve
<issue_title>Add support for poetry</issue_title>
<issue_description>Poetry is interesting because it is more like uv than pip, but also has some different defaults around the vdir</issue_description>
<agent_instructions># Aspire: Poetry Package Manager Support (Refined API Spec)
Scope
Add support for
Poetryas a Python package manager in Aspire, following existing Pip/Uv patterns.Poetry:
1. Public API
1.1 Enum
1.2 Builder Extension
Single explicit selector; no
AddPoetryApphelper.Parameters
poetry installduring its restore/build phase. If false, Aspire skips installing and only resolves the venv; failure occurs if no venv exists.poetry installcommand (after Aspire’s default flags). Examples:["--no-root"],["--sync"].POETRY_VIRTUALENVS_IN_PROJECT.Behavior
WithPoetrysetsPackageManager = PythonPackageManager.Poetry.PoetryOptionsclass; the method’s parameters replace earlier options concepts.2. Virtual Environment Strategy
2.1 Default Venv Location
WithVirtualEnvironment(path)is NOT specified:POETRY_VIRTUALENVS_IN_PROJECT=trueunless the user overrides it via theenvparameter.<projectPath>/.venvafterpoetry install.2.2 Explicit Virtual Environment Path
WithVirtualEnvironment(customPath)is used:POETRY_VIRTUALENVS_PATH=<customPath>.POETRY_VIRTUALENVS_IN_PROJECTunlesscustomPath == <projectPath>/.venv.install=false), Aspire runspoetry env info --pathto resolve the canonical venv directory (Poetry may hash subdirectories).2.3 Resolution Algorithm (Conceptual)
poetry env info --path; use its result if valid.<projectPath>/.venv; use if exists.install=true, re-run resolution after install.poetry env info --path:2.4 No Aspire-driven venv creation
python -m venvfor Poetry projects.3. Restore / Build Phase
3.1 Command Construction
Base command:
Rules:
--no-interaction.installArgsin order.install=false.3.2 Environment Variables
Aspire-provided defaults (unless overridden in
env):POETRY_VIRTUALENVS_IN_PROJECT=truePOETRY_VIRTUALENVS_PATH=<customPath>User-specified
enventries:envmeans defaults only.Example merge order (conceptual):
WithVirtualEnvironment.envoverrides.3.3 Container Build
POETRY_VIRTUALENVS_IN_PROJECTorPOETRY_VIRTUALENVS_PATH).poetry installcommand unlessinstall=false.4. Execution Phase
<venvPath>/bin/python<venvPath>/Scripts/python.exepoetry run.5. Error Handling
poetryis not on P...✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.