豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

feat: handle hybrid Poetry v2 dependency updates#14658

Merged
markhallen merged 11 commits intomainfrom
feat/hybrid-poetry-v2-updates
Apr 9, 2026
Merged

feat: handle hybrid Poetry v2 dependency updates#14658
markhallen merged 11 commits intomainfrom
feat/hybrid-poetry-v2-updates

Conversation

@markhallen
Copy link
Copy Markdown
Contributor

What are you trying to accomplish?

Poetry v2 supports declaring dependencies in both project.dependencies (PEP 621) and tool.poetry.dependencies simultaneously:

[project]
dependencies = [
    "requests>=2.13.0",
]

[tool.poetry.dependencies]
requests = { version = "^2.13", source = "private-source" }

Here project.dependencies provides the version for package metadata, and tool.poetry.dependencies enriches it with source/marker info for locking. When Dependabot updates a dependency, it must update the version in project.dependencies AND update the version in tool.poetry.dependencies (if it contains a version key), while leaving enrichment-only entries (no version key) unchanged.

Before this PR, the updater had two gaps:

  1. replace_dep would match the [tool.poetry.dependencies] header via declaration_regex but fail to find the PEP 621 requirement string in the matched declaration, returning unchanged content without falling through to the pep621_declaration_regex.
  2. freeze_dependencies_being_updated and freeze_top_level_dependencies_except only froze deps in tool.poetry.* — PEP 621 project.dependencies were left unfrozen during lockfile regeneration, potentially causing incorrect lock resolution.

Closes github/dependabot-updates#12980

Anything you want to highlight for special attention from reviewers?

replace_dep guard change (poetry_file_updater.rb L127): Added include?(old_req) check before returning from the Poetry declaration_regex match. This changes the fallthrough behavior — previously a no-op .sub() would return unchanged content, now it falls through to try the PEP 621 regex. For pure Poetry v1 projects (no [project] section), the PEP 621 regex won't match either, so the result is identical. Risk is limited to edge cases where declaration_regex matches a header but the requirement string differs from what the parser reported.

Freeze logic split: freeze_pep621_deps! is a class method on PyprojectPreparer (used by both the updater's freeze_dependencies_being_updated and the preparer's freeze_top_level_dependencies_except). The instance method freeze_pep621_top_level_deps! handles the "freeze everything except excluded deps" case by looking up locked versions from the lockfile.

All new code paths guard on pyproject_object["project"] being present — pure Poetry v1 projects without a [project] section are completely unaffected.

How will you know you've accomplished your goal?

All tests pass (71 examples, 0 failures) including 9 new tests:

poetry_file_updater_spec.rb — 6 new tests:

  • Hybrid project with version in both sections: both project.dependencies and tool.poetry.dependencies are updated
  • Hybrid project with enrichment-only: only project.dependencies is updated, enrichment entry preserved
  • Metadata (source) is preserved after update

pyproject_preparer_spec.rb — 3 new tests:

  • PEP 621 deps frozen to locked versions
  • Poetry deps frozen alongside PEP 621
  • Excluded deps are not frozen
bin/test python spec/dependabot/python/file_updater/poetry_file_updater_spec.rb  # 31 examples, 0 failures
bin/test python spec/dependabot/python/file_updater/pyproject_preparer_spec.rb   # 24 examples, 0 failures
bin/test python spec/dependabot/python/file_updater_spec.rb                      # 16 examples, 0 failures
bin/test python rubocop                                                          # 0 new offenses

Checklist

  • I have run the complete test suite to ensure all tests and linters pass.
  • I have thoroughly tested my code changes to ensure they work as expected, including adding additional tests for new functionality.
  • I have written clear and descriptive commit messages.
  • I have provided a detailed description of the changes in the pull request, including the problem it addresses, how it fixes the problem, and any relevant details about the implementation.
  • I have ensured that the code is well-documented and easy to understand.

Add two fixture files for testing hybrid Poetry v2 projects:
- pep621_hybrid_version_in_both.toml: dep in both project.dependencies
  and tool.poetry.dependencies with version specifiers in both
- pep621_hybrid_enrichment_only.toml: dep in project.dependencies with
  enrichment-only entry (no version key) in tool.poetry.dependencies
When a dependency exists in both project.dependencies (PEP 621) and
tool.poetry.dependencies, Dependabot must update both consistently.

Changes:
- Add include? guard in replace_dep so the Poetry declaration_regex
  falls through to the PEP 621 regex when the matched line doesn't
  contain the old requirement string
- Add freeze_pep621_deps! class method to PyprojectPreparer to pin
  PEP 621 deps during lockfile regeneration
- Add freeze_pep621_top_level_deps! to freeze non-target PEP 621 deps
  to their locked versions in freeze_top_level_dependencies_except
- Call freeze_pep621_deps! from freeze_dependencies_being_updated

Closes github/dependabot-updates#12980
Add tests for hybrid projects in poetry_file_updater_spec.rb:
- Version in both sections: both project.dependencies and
  tool.poetry.dependencies are updated consistently
- Enrichment-only: only project.dependencies is updated,
  tool.poetry.dependencies enrichment entry is preserved

Add tests for PEP 621 freeze in pyproject_preparer_spec.rb:
- Freezes PEP 621 deps to locked versions
- Freezes tool.poetry.dependencies alongside PEP 621
- Respects excluded dependencies
@markhallen markhallen requested a review from a team as a code owner April 8, 2026 15:20
Copilot AI review requested due to automatic review settings April 8, 2026 15:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds Poetry v2 “hybrid” support to the Python Poetry updater so Dependabot can correctly update and freeze dependencies declared in both PEP 621 ([project]) and Poetry’s legacy tables ([tool.poetry]).

Changes:

  • Adjusts replace_dep to fall through to PEP 621 matching when a [tool.poetry.*] match doesn’t actually contain the old requirement string.
  • Extends freezing logic to cover PEP 621 project.dependencies / project.optional-dependencies during lockfile regeneration.
  • Adds fixtures and specs covering hybrid update behavior and PEP 621 freezing.
Show a summary per file
File Description
python/lib/dependabot/python/file_updater/poetry_file_updater.rb Fixes replace_dep fallthrough and freezes PEP 621 deps during update.
python/lib/dependabot/python/file_updater/pyproject_preparer.rb Implements PEP 621 freezing/pinning helpers and integrates them into top-level freezing.
python/spec/dependabot/python/file_updater/poetry_file_updater_spec.rb Adds hybrid project update coverage (both sections updated; enrichment preserved).
python/spec/dependabot/python/file_updater/pyproject_preparer_spec.rb Adds coverage for freezing PEP 621 project.dependencies alongside Poetry deps.
python/spec/fixtures/pyproject_files/pep621_hybrid_version_in_both.toml Fixture for hybrid dependency with versions in both sections.
python/spec/fixtures/pyproject_files/pep621_hybrid_enrichment_only.toml Fixture for hybrid dependency with enrichment-only Poetry entry.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 3

Comment thread python/lib/dependabot/python/file_updater/pyproject_preparer.rb Outdated
Comment thread python/lib/dependabot/python/file_updater/pyproject_preparer.rb Outdated
- Handle bare deps without version specifiers by appending ==version
- Preserve whitespace before environment markers using non-greedy regex
- Make pin_pep621_dep_in_arrays! a private class method
- Use consistent name-matching regex in freeze_pep621_dep_array!
- Remove unused named capture group and redundant && dep.version
- Add tests for environment markers and optional-dependencies
- Add explicit block parameter to freeze_pep621_deps! sig and def
- Wrap match[1] in T.must for nilability checks in freeze_pep621_dep_array!
- Extract shared pep508_name_pattern and pin_pep508_entry helpers
- Handle underscores and dots in PEP 508 name matching (not just hyphens)
- Guard enrichment-only Poetry entries from version injection
- Restore original method chain formatting
- Use explicit block variable check with yield to satisfy both
  Performance/BlockGivenWithExplicitBlock and RedundantBlockCall
- Compact delegation methods to reduce PoetryFileUpdater class length
  below Metrics/ClassLength limit (350)
…sion test

- Extract collect_pep621_dep_arrays to validate that dep_arrays entries
  guarding against unexpected TOML values at runtime.
- Add test coverage for excluded dependencies within
  project.optional-dependencies.
@markhallen markhallen merged commit e70a010 into main Apr 9, 2026
91 checks passed
@markhallen markhallen deleted the feat/hybrid-poetry-v2-updates branch April 9, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants