Skip to content

[ANE-2877] Support PEP 621 project.dependencies in Poetry 2.x strategy#1683

Open
zlav wants to merge 7 commits intomasterfrom
fix/poetry-pep621-deps
Open

[ANE-2877] Support PEP 621 project.dependencies in Poetry 2.x strategy#1683
zlav wants to merge 7 commits intomasterfrom
fix/poetry-pep621-deps

Conversation

@zlav
Copy link
Copy Markdown
Member

@zlav zlav commented Apr 3, 2026

Overview

Poetry 2.x introduced PEP 621 support, allowing production dependencies to be declared in [project].dependencies instead of legacy [tool.poetry.dependencies]. The Poetry strategy only read the latter, so projects using PEP 621 had their production deps missed entirely.

The [project] section was already parsed into PyProjectMetadata but never consumed by the Poetry strategy. This PR wires it into both the lock-file and no-lock-file paths while preserving full backward compatibility.

Key changes:

  • allPoetryProductionDeps merges PEP 621 deps with legacy Poetry deps (legacy wins on dedup)
  • pyProjectDeps includes PEP 621 deps as production in the no-lock-file path
  • Shared reqName helper extracted to Strategy.Python.Util (previously duplicated in PDM)

Acceptance criteria

  • Poetry 2.x projects using [project].dependencies have production deps detected
  • Legacy [tool.poetry.dependencies] projects continue to work unchanged
  • Mixed-format projects deduplicate correctly (Poetry-style wins)

Testing plan

  • Unit tests for PEP 621 detection, mixed-format dedup, and allPoetryProductionDeps
  • New test fixtures for pure PEP 621 and mixed-format projects
  • Existing Poetry tests pass
  • CI build and formatter checks pass

Risks

Minimal -- additive change. Legacy behavior is unchanged; PEP 621 deps are merged via Map.union with legacy entries taking precedence.

Metrics

N/A

References

Checklist

  • I added tests for this PR's change (or explained in the PR description why tests don't make sense).
  • If this PR introduced a user-visible change, I added documentation into docs/.
    • N/A -- fixes existing detection gap.
  • If this change is externally visible, I updated Changelog.md. If this PR did not mark a release, I added my changes into an ## Unreleased section at the top.
  • If I made changes to .fossa.yml or fossa-deps.{json.yml}, I updated docs/references/files/*.schema.json AND I have updated example files used by fossa init command.
    • N/A
  • If I made changes to a subcommand's options, I updated docs/references/subcommands/<subcommand>.md.
    • N/A

Poetry 2.x introduced PEP 621 support, allowing production dependencies
to be declared in the project.dependencies section instead of the legacy
tool.poetry.dependencies. The Poetry strategy only read the latter,
causing production deps to be missed for Poetry 2.x projects using the
standard format.

Changes:
- allPoetryProductionDeps now merges PEP 621 deps with legacy Poetry deps
  (legacy takes precedence for dedup)
- pyProjectDeps includes PEP 621 deps as production in the no-lock-file path
- Extract reqName to shared Util module (used by both Poetry and PDM)
- Add test fixtures and tests for PEP 621 and mixed-format projects

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@zlav zlav requested a review from a team as a code owner April 3, 2026 18:28
@zlav zlav requested review from nficca and removed request for nficca April 3, 2026 18:28
@zlav zlav marked this pull request as draft April 3, 2026 18:46
zlav and others added 2 commits April 3, 2026 12:00
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@zlav zlav marked this pull request as ready for review April 8, 2026 18:14
@zlav zlav requested a review from tjugdev April 8, 2026 18:14
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 8, 2026

Walkthrough

The change adds support for detecting PEP 621 [project].dependencies alongside legacy Poetry [tool.poetry.dependencies] configuration in Poetry 2.x projects. The implementation introduces a helper function reqName in the utilities module, refactors dependency matching logic in PDM and Poetry modules to use this function, and extends the Poetry dependency extraction logic to combine dependencies from both sources while prioritizing Poetry-style entries in case of conflicts. Test fixtures and test cases validate the new functionality across various scenarios.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding PEP 621 project.dependencies support to the Poetry 2.x strategy, which is the central objective of this PR.
Description check ✅ Passed The description comprehensively covers all template sections: Overview explains the intent, Acceptance criteria defines success metrics, Testing plan documents validation steps, Risks addresses safety, References links to relevant tickets, and Checklist items are explicitly marked. All critical sections are filled out with substantive content.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Strategy/Python/Util.hs`:
- Around line 178-180: The functions depName and reqName duplicate the same
logic; remove the duplicate by consolidating them: either export the existing
depName as the public API and delete reqName, or make depName a local alias to
reqName (or vice‑versa) so only one implementation remains. Update any
references to use the retained symbol (depName or reqName) and adjust the module
exports accordingly to avoid duplication while preserving external API.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: c025a036-747d-47d6-8f70-9691f319f758

📥 Commits

Reviewing files that changed from the base of the PR and between 3341930 and 1093d0f.

📒 Files selected for processing (8)
  • Changelog.md
  • src/Strategy/Python/PDM/PdmLock.hs
  • src/Strategy/Python/Poetry/Common.hs
  • src/Strategy/Python/Poetry/PyProject.hs
  • src/Strategy/Python/Util.hs
  • test/Python/Poetry/CommonSpec.hs
  • test/Python/Poetry/testdata/pep621-mixed/pyproject.toml
  • test/Python/Poetry/testdata/pep621/pyproject.toml

Comment on lines +178 to +180
reqName :: Req -> Text
reqName (NameReq name _ _ _) = name
reqName (UrlReq name _ _ _) = name
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider consolidating with existing depName function.

The new reqName function (lines 178-180) has identical implementation to the existing depName function (lines 40-42):

-- depName at lines 40-42:
depName :: Req -> Text
depName (NameReq nm _ _ _) = nm
depName (UrlReq nm _ _ _) = nm

-- reqName at lines 178-180:
reqName :: Req -> Text
reqName (NameReq name _ _ _) = name
reqName (UrlReq name _ _ _) = name

Consider either:

  1. Exporting depName instead of introducing reqName, or
  2. Keeping reqName as the public API and making depName a local alias

This would eliminate code duplication within the same module.

♻️ Proposed refactor
 module Strategy.Python.Util (
   buildGraph,
   buildGraphSetupFile,
   Version (..),
   Marker (..),
   MarkerOp (..),
   Operator (..),
   Req (..),
-  reqName,
+  reqName,  -- exported name
   requirementParser,
   reqToDependency,
   toConstraint,
 ) where

...

-depName :: Req -> Text
-depName (NameReq nm _ _ _) = nm
-depName (UrlReq nm _ _ _) = nm
+-- | Extract the package name from a Req.
+reqName :: Req -> Text
+reqName (NameReq nm _ _ _) = nm
+reqName (UrlReq nm _ _ _) = nm
+
+-- | Alias for reqName, used internally.
+depName :: Req -> Text
+depName = reqName

...

--- Remove the duplicate definition at lines 178-180
-reqName :: Req -> Text
-reqName (NameReq name _ _ _) = name
-reqName (UrlReq name _ _ _) = name
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Strategy/Python/Util.hs` around lines 178 - 180, The functions depName
and reqName duplicate the same logic; remove the duplicate by consolidating
them: either export the existing depName as the public API and delete reqName,
or make depName a local alias to reqName (or vice‑versa) so only one
implementation remains. Update any references to use the retained symbol
(depName or reqName) and adjust the module exports accordingly to avoid
duplication while preserving external API.

zlav and others added 2 commits April 8, 2026 11:22
CodeRabbit caught that depName and reqName had identical implementations
in the same module. Removed depName and updated its two internal usages
to use reqName instead. reqName is the more accurate name since it
operates on Req values.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@zlav zlav enabled auto-merge (squash) April 8, 2026 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant