Skip to content

Resolve requirement names from distribution metadata - #533

Merged
tinovyatkin merged 6 commits into
mainfrom
codex/resolve-requirement-distributions
Jul 17, 2026
Merged

Resolve requirement names from distribution metadata#533
tinovyatkin merged 6 commits into
mainfrom
codex/resolve-requirement-distributions

Conversation

@tinovyatkin

@tinovyatkin tinovyatkin commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • separate requirement-name inference from module classification
  • resolve imports through the selected Python environment using Core Metadata 2.5 Import-Name / Import-Namespace, installed-file records, and legacy top_level.txt
  • add --python, CRIBO_PYTHON, and [requirements] configuration with longest-prefix module-map overrides
  • reject equally strong providers with an actionable error instead of choosing by scan order
  • add end-to-end fixtures for mismatched distribution names and ambiguous namespace providers

Why

Requirements generation previously assumed that a top-level import name was also the installable distribution name. That produces incorrect output for packages such as sklearn / scikit-learn, and filesystem scan order cannot safely resolve namespaces supplied by multiple distributions.

The new resolver uses metadata from the environment that will run the bundle, while retaining explicit configuration for missing or ambiguous metadata.

Closes #141

User impact

--emit-requirements now emits normalized distribution names when installed metadata identifies them. Users can select an interpreter explicitly with --python, CRIBO_PYTHON, or requirements.python; python -m cribo automatically supplies its own interpreter. Ambiguous providers fail with guidance to configure requirements.module-map, while unmapped imports retain a valid normalized fallback.

Validation

  • cargo nextest run --workspace (194 passed)
  • cargo insta test --all-features --check --unreferenced reject (370 passed; no unreferenced snapshots)
  • cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
  • cargo fmt --all -- --check
  • uvx ruff check python/cribo/__main__.py crates/cribo/src/requirement_resolver.py

Summary by CodeRabbit

  • New Features

    • Added automatic generation of Python requirements from imported modules.
    • Added --python and CRIBO_PYTHON options for selecting the Python interpreter.
    • Added configurable import-to-requirement mappings with longest-prefix matching.
    • Improved detection across virtual environments and installed package metadata.
    • Added clear handling for ambiguous or invalid package mappings.
  • Documentation

    • Documented the new command-line option, configuration settings, and environment variable.
  • Bug Fixes

    • Improved package ownership detection and requirements selection across multiple environments.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Requirements generation now uses configured Python environments and distribution metadata to resolve imported modules into PEP 508 requirements. Configuration, CLI and environment overrides, ownership classification, bundled Python metadata lookup, ambiguity handling, and integration tests were added.

Changes

Python requirement resolution

Layer / File(s) Summary
Requirements configuration and entrypoints
Cargo.toml, crates/cribo/Cargo.toml, crates/cribo/src/config.rs, crates/cribo/src/main.rs, python/cribo/__main__.py, README.md, cribo.toml
Adds interpreter and module-map configuration through TOML, CLI, and environment variables, with documentation and configuration validation.
Distribution ownership classification
crates/cribo/src/resolver.rs
Uses Import-Name, Import-Namespace, and RECORD data to classify third-party imports and caches ownership indexes per search root.
Python metadata indexing
crates/cribo/src/requirement_resolver.py
Indexes installed distributions, scores import candidates, handles preferred paths and metadata conflicts, and returns deterministic JSON resolutions.
Requirement resolution and generation
crates/cribo/src/requirement_resolver.rs, crates/cribo/src/orchestrator.rs, crates/cribo/tests/test_cli_stdout.rs
Applies longest-prefix overrides, invokes the Python helper, selects or falls back to package names, propagates errors, and tests virtualenv and PYTHONPATH precedence.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Orchestrator
  participant RequirementResolver
  participant PythonHelper
  participant DistributionMetadata
  CLI->>Orchestrator: generate requirements
  Orchestrator->>RequirementResolver: resolve imported modules
  RequirementResolver->>PythonHelper: send imports and metadata paths
  PythonHelper->>DistributionMetadata: inspect installed distributions
  DistributionMetadata-->>PythonHelper: return scored candidates
  PythonHelper-->>RequirementResolver: return resolutions
  RequirementResolver-->>Orchestrator: return PEP 508 requirements
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.72% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: resolving requirement names from distribution metadata.
Linked Issues check ✅ Passed The PR addresses #141 by resolving requirements from installed distribution metadata instead of assuming import and distribution names match.
Out of Scope Changes check ✅ Passed The added config, CLI, resolver, and tests all support requirements resolution and stay within the issue's scope.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/resolve-requirement-distributions

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.

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown

📊 Ecosystem Test Results

📋 Test Status

Test Summary:

  • Total: 49
  • ✅ Passed: 48
  • ❌ Failed: 0
  • ⚠️ Errors: 0
  • ⏭️ Skipped: 1

📈 Benchmark Results

📊 View detailed benchmark report

📦 Package Bundling Metrics
Package Bundle Time Bundle Size
httpx 239.42 ms 321 KB
idna 51.56 ms 244.96 KB
pyyaml 188.39 ms 237.6 KB
requests 154.9 ms 216.8 KB
rich 933.03 ms 943.23 KB

Benchmark metrics are tracked via Bencher.dev

📊 View detailed performance trends and comparisons on the Bencher dashboard.

Generated by ecosystem-tests workflow

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the accuracy of requirement generation by moving away from simple import-to-package name assumptions. By leveraging actual Python environment metadata, the tool can now correctly identify distributions for packages with non-obvious names, such as scikit-learn. The changes include a new resolution module, enhanced configuration options for interpreter selection, and better handling of ambiguous namespace providers.

Highlights

  • Requirement Resolution: Decoupled requirement name inference from module classification and implemented a robust resolution strategy using Python distribution metadata.
  • Environment Awareness: Added support for Core Metadata 2.5 (Import-Name/Import-Namespace), installed-file records, and legacy top_level.txt to accurately map imports to distribution names.
  • Configuration: Introduced the --python flag, CRIBO_PYTHON environment variable, and [requirements] configuration block to allow explicit interpreter selection.
  • Error Handling: Improved reliability by rejecting ambiguous requirement providers with actionable error messages instead of relying on scan order.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown

🐰 Bencher Report

Branchcodex/resolve-requirement-distributions
Testbedubuntu-latest
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
nanoseconds (ns)
(Result Δ%)
Upper Boundary
nanoseconds (ns)
(Limit %)
build_dependency_graph📈 view plot
🚷 view threshold
626.80 ns
(-90.14%)Baseline: 6,356.00 ns
15,194.65 ns
(4.13%)
bundle_simple_project📈 view plot
🚷 view threshold
1,429,700.00 ns
(-53.29%)Baseline: 3,060,777.81 ns
15,245,117.38 ns
(9.38%)
resolve_module_path📈 view plot
🚷 view threshold
115.20 ns
(+3.63%)Baseline: 111.16 ns
144.18 ns
(79.90%)
🐰 View full continuous benchmarking report in Bencher

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request introduces a requirement resolution mechanism to map Python imports to installed distribution packages (PEP 508 requirements) using a new RequirementResolver and a Python helper script. The review feedback highlights several critical improvements: resolving potential encoding issues on Windows by using UTF-8 buffers for standard I/O, supporting absolute paths for editable installs, defensively catching general exceptions for malformed metadata, and ensuring case-insensitive matching for Core Metadata headers.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/cribo/src/requirement_resolver.py Outdated
Comment on lines +31 to +39
if path == prefix + ".py" or path == prefix + "/__init__.py":
return 4000 + depth, "installed file"

for suffix in importlib.machinery.EXTENSION_SUFFIXES:
if path == prefix + suffix or path == prefix + "/__init__" + suffix:
return 4000 + depth, "installed extension"

if path.startswith(prefix + "/"):
return 3000 + depth, "installed namespace descendant"

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.

medium

To support editable installs and other non-standard virtualenv layouts where PackagePath objects can return absolute paths, we should make file_score robust against absolute paths by checking if the path ends with the expected relative path preceded by a path separator.

Suggested change
if path == prefix + ".py" or path == prefix + "/__init__.py":
return 4000 + depth, "installed file"
for suffix in importlib.machinery.EXTENSION_SUFFIXES:
if path == prefix + suffix or path == prefix + "/__init__" + suffix:
return 4000 + depth, "installed extension"
if path.startswith(prefix + "/"):
return 3000 + depth, "installed namespace descendant"
if path == prefix + ".py" or path.endswith("/" + prefix + ".py") or path == prefix + "/__init__.py" or path.endswith("/" + prefix + "/__init__.py"):
return 4000 + depth, "installed file"
for suffix in importlib.machinery.EXTENSION_SUFFIXES:
if path == prefix + suffix or path.endswith("/" + prefix + suffix) or path == prefix + "/__init__" + suffix or path.endswith("/" + prefix + "/__init__" + suffix):
return 4000 + depth, "installed extension"
if path.startswith(prefix + "/") or ("/" + prefix + "/") in path:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in d6f5d2a. Absolute package paths are relativized against normalized import roots before root-anchored matching. Coverage verifies an editable absolute path and rejects nested paths such as pandera/api/polars; full validation: nextest 199/199, Insta 380/380, strict Clippy, fmt, and Ruff.

Comment thread crates/cribo/src/requirement_resolver.py
Comment thread crates/cribo/src/requirement_resolver.py
Comment thread crates/cribo/src/resolver.rs Outdated
@tinovyatkin
tinovyatkin marked this pull request as ready for review July 17, 2026 13:18
Copilot AI review requested due to automatic review settings July 17, 2026 13:18
@tinovyatkin

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 60724723c0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/cribo/src/requirement_resolver.rs Outdated
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown

📊 Source Code Metrics (this PR vs main)

File Cyclomatic Cognitive Functions LLOC MI
crates/cribo/src/resolver.rs 435 (main: 413) 🔴 372 (main: 374) 🟢 90 (main: 84) 🔴 789 (main: 762) 🔴 0 ⚪
crates/cribo/src/orchestrator.rs 240 (main: 236) 🔴 259 (main: 256) 🔴 36 ⚪ 487 (main: 485) 🔴 0 ⚪
crates/cribo/src/config.rs 82 (main: 71) 🔴 48 (main: 42) 🔴 19 (main: 14) 🔴 131 (main: 109) 🔴 0.33 (main: 4.56) 🔴
crates/cribo/src/requirement_resolver.rs 100 🆕 75 🆕 18 🆕 148 🆕 0 🆕
crates/cribo/src/requirement_resolver.py 81 🆕 76 🆕 16 🆕 140 🆕 6.79 🆕
crates/cribo/src/main.rs 18 (main: 17) 🔴 14 (main: 13) 🔴 1 ⚪ 28 (main: 26) 🔴 25.01 (main: 25.94) 🔴
crates/cribo/src/lib.rs 1 ⚪ 0 ⚪ 0 ⚪ 0 ⚪ 45.68 (main: 46.09) 🔴

Generated by mehen v1.3.0 — the code quality watcher.

Copilot AI left a comment

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.

Pull request overview

This PR improves --emit-requirements by resolving requirement (distribution) names from the selected Python environment’s installed distribution metadata, decoupling requirement inference from module classification, and adding configuration/CLI/env plumbing to control which interpreter is inspected.

Changes:

  • Introduce a dedicated requirement resolver (Rust + embedded Python) that maps imports to normalized distribution names using Core Metadata Import-Name / Import-Namespace, installed files, and top_level.txt, with actionable ambiguity errors.
  • Add interpreter selection via --python, CRIBO_PYTHON, and [requirements] config (including longest-prefix module-map overrides).
  • Add end-to-end fixtures + snapshot updates covering distribution-name mismatches and ambiguous namespace providers.

Reviewed changes

Copilot reviewed 32 out of 33 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Documents --python and [requirements] configuration examples.
python/cribo/main.py Ensures python -m cribo defaults CRIBO_PYTHON to the invoking interpreter.
docs/resolution.md Updates resolution docs to reflect separated requirement inference and new mapping rules.
docs/environment_variables.md Documents CRIBO_PYTHON and its intended behavior.
cribo.toml Adds [requirements] config stub and module-map default.
crates/cribo/tests/snapshots/ruff_lint_results@requirements_distribution_mapping.snap Snapshot for ruff lint results for new fixture.
crates/cribo/tests/snapshots/requirements@try_except_function_export.snap Updates requirements snapshot to reflect normalized fallback naming.
crates/cribo/tests/snapshots/requirements@requirements_distribution_mapping.snap New snapshot verifying mapped distribution names from metadata.
crates/cribo/tests/snapshots/requirements@conditional_imports.snap Updates snapshot to reflect normalized distribution naming.
crates/cribo/tests/snapshots/execution_results@requirements_distribution_mapping.snap New execution snapshot for the distribution-mapping fixture.
crates/cribo/tests/snapshots/bundling_error@xfail_ambiguous_requirement_namespace.snap New snapshot validating actionable error on ambiguous providers.
crates/cribo/tests/snapshots/bundled_code@requirements_distribution_mapping.snap New bundled-code snapshot for the distribution-mapping fixture.
crates/cribo/tests/fixtures/xfail_ambiguous_requirement_namespace/shared/beta.py Fixture module for ambiguity scenario.
crates/cribo/tests/fixtures/xfail_ambiguous_requirement_namespace/shared/alpha.py Fixture module for ambiguity scenario.
crates/cribo/tests/fixtures/xfail_ambiguous_requirement_namespace/main.py Fixture entrypoint that triggers ambiguous namespace mapping.
crates/cribo/tests/fixtures/xfail_ambiguous_requirement_namespace/beta_distribution-1.0.dist-info/METADATA Fixture dist metadata (Beta) including Import-* fields.
crates/cribo/tests/fixtures/xfail_ambiguous_requirement_namespace/alpha_distribution-1.0.dist-info/METADATA Fixture dist metadata (Alpha) including Import-* fields.
crates/cribo/tests/fixtures/requirements_distribution_mapping/shared/beta/init.py Fixture module for mapping scenario.
crates/cribo/tests/fixtures/requirements_distribution_mapping/shared/alpha/init.py Fixture module for mapping scenario.
crates/cribo/tests/fixtures/requirements_distribution_mapping/main.py Fixture entrypoint verifying mapped requirements.
crates/cribo/tests/fixtures/requirements_distribution_mapping/beta_distribution-1.0.dist-info/RECORD Fixture installed-file evidence (RECORD) for Beta distribution.
crates/cribo/tests/fixtures/requirements_distribution_mapping/beta_distribution-1.0.dist-info/METADATA Fixture metadata for Beta distribution (older metadata version).
crates/cribo/tests/fixtures/requirements_distribution_mapping/alpha_distribution-1.0.dist-info/METADATA Fixture metadata for Alpha distribution (with Import-* fields).
crates/cribo/src/resolver.rs Removes requirement from import classification and adds metadata-based ownership check.
crates/cribo/src/requirement_resolver.rs New Rust requirement resolver orchestrating metadata queries and selection logic.
crates/cribo/src/requirement_resolver.py Embedded Python metadata query implementation using importlib.metadata.
crates/cribo/src/orchestrator.rs Routes requirements generation through the new resolver and propagates errors.
crates/cribo/src/main.rs Adds --python CLI flag and wires it into config.
crates/cribo/src/lib.rs Exposes the new requirement_resolver module internally.
crates/cribo/src/config.rs Adds [requirements] configuration + CRIBO_PYTHON env support.
crates/cribo/Cargo.toml Adds serde_json dependency usage for the crate.
Cargo.toml Adds workspace dependency on serde_json.
Cargo.lock Locks serde_json addition.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/cribo/src/resolver.rs Outdated
Comment thread crates/cribo/src/config.rs
@tinovyatkin tinovyatkin changed the title [codex] Resolve requirement names from distribution metadata Resolve requirement names from distribution metadata Jul 17, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d6f5d2acac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/cribo/src/requirement_resolver.rs

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/cribo/src/config.rs`:
- Around line 46-54: Update the Debug behavior for RequirementsConfig and its
use within Config so module_map values are not emitted in Config debug logs,
while preserving useful non-sensitive configuration details. Prefer a custom
redacted Debug implementation that masks the complete PEP 508 mapping contents,
and ensure the existing Config logging path uses this redacted representation.

In `@crates/cribo/src/requirement_resolver.py`:
- Around line 65-134: Build a reusable distribution-ownership index so installed
metadata is scanned once rather than once per import. In
crates/cribo/src/requirement_resolver.py:65-134, refactor
distribution_candidates and main to index metadata headers, importable files,
and top-level names before resolving imports. In
crates/cribo/src/resolver.rs:1276-1323, cache the corresponding ownership data
by search root and reuse it instead of rereading METADATA and RECORD for each
lookup.
- Around line 72-93: Update the requirement resolution logic around the
Import-Name and Import-Namespace metadata loops to detect overlapping declared
names before calling add_candidate. If the same name appears in both fields,
fail fast rather than scoring either candidate; preserve the existing scoring
behavior when the fields are non-overlapping.
- Around line 67-93: Guard access to distribution.metadata in the distribution
iteration so metadata-read exceptions are handled like the existing files and
top_level.txt lookups. Skip the affected distribution and continue resolving
other candidates, while preserving the Import-Name and Import-Namespace
processing for successfully read metadata.

In `@crates/cribo/src/requirement_resolver.rs`:
- Around line 43-283: Document every newly introduced Rust function with
appropriate doc comments: add method and helper documentation throughout
RequirementResolver in crates/cribo/src/requirement_resolver.rs (lines 43-283),
document the environment-path parsing function in crates/cribo/src/config.rs
(lines 233-239), the classification constructor in crates/cribo/src/resolver.rs
(line 303), and metadata-header matching functions in
crates/cribo/src/resolver.rs (lines 1325-1341).

In `@python/cribo/__main__.py`:
- Around line 16-19: Update the environment setup in the module entrypoint to
replace CRIBO_PYTHON when it is unset or empty, using sys.executable in both
cases. Preserve any non-empty CRIBO_PYTHON value before invoking subprocess.run.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 830a831c-b73c-43a8-b6d5-d857a58a19be

📥 Commits

Reviewing files that changed from the base of the PR and between 4103338 and d6f5d2a.

⛔ Files ignored due to path filters (21)
  • Cargo.lock is excluded by !**/*.lock
  • crates/cribo/tests/fixtures/requirements_distribution_mapping/alpha_distribution-1.0.dist-info/METADATA is excluded by !**/tests/fixtures/**
  • crates/cribo/tests/fixtures/requirements_distribution_mapping/beta_distribution-1.0.dist-info/METADATA is excluded by !**/tests/fixtures/**
  • crates/cribo/tests/fixtures/requirements_distribution_mapping/beta_distribution-1.0.dist-info/RECORD is excluded by !**/tests/fixtures/**
  • crates/cribo/tests/fixtures/requirements_distribution_mapping/main.py is excluded by !**/tests/fixtures/**
  • crates/cribo/tests/fixtures/requirements_distribution_mapping/shared/alpha/__init__.py is excluded by !**/tests/fixtures/**
  • crates/cribo/tests/fixtures/requirements_distribution_mapping/shared/beta/__init__.py is excluded by !**/tests/fixtures/**
  • crates/cribo/tests/fixtures/xfail_ambiguous_requirement_namespace/alpha_distribution-1.0.dist-info/METADATA is excluded by !**/tests/fixtures/**
  • crates/cribo/tests/fixtures/xfail_ambiguous_requirement_namespace/beta_distribution-1.0.dist-info/METADATA is excluded by !**/tests/fixtures/**
  • crates/cribo/tests/fixtures/xfail_ambiguous_requirement_namespace/main.py is excluded by !**/tests/fixtures/**
  • crates/cribo/tests/fixtures/xfail_ambiguous_requirement_namespace/shared/alpha.py is excluded by !**/tests/fixtures/**
  • crates/cribo/tests/fixtures/xfail_ambiguous_requirement_namespace/shared/beta.py is excluded by !**/tests/fixtures/**
  • crates/cribo/tests/snapshots/bundled_code@requirements_distribution_mapping.snap is excluded by !**/*.snap
  • crates/cribo/tests/snapshots/bundling_error@xfail_ambiguous_requirement_namespace.snap is excluded by !**/*.snap
  • crates/cribo/tests/snapshots/execution_results@requirements_distribution_mapping.snap is excluded by !**/*.snap
  • crates/cribo/tests/snapshots/requirements@conditional_imports.snap is excluded by !**/*.snap
  • crates/cribo/tests/snapshots/requirements@requirements_distribution_mapping.snap is excluded by !**/*.snap
  • crates/cribo/tests/snapshots/requirements@try_except_function_export.snap is excluded by !**/*.snap
  • crates/cribo/tests/snapshots/ruff_lint_results@requirements_distribution_mapping.snap is excluded by !**/*.snap
  • docs/environment_variables.md is excluded by !**/docs/**
  • docs/resolution.md is excluded by !**/docs/**
📒 Files selected for processing (12)
  • Cargo.toml
  • README.md
  • crates/cribo/Cargo.toml
  • crates/cribo/src/config.rs
  • crates/cribo/src/lib.rs
  • crates/cribo/src/main.rs
  • crates/cribo/src/orchestrator.rs
  • crates/cribo/src/requirement_resolver.py
  • crates/cribo/src/requirement_resolver.rs
  • crates/cribo/src/resolver.rs
  • cribo.toml
  • python/cribo/__main__.py

Comment thread crates/cribo/src/config.rs Outdated
Comment thread crates/cribo/src/requirement_resolver.py Outdated
Comment thread crates/cribo/src/requirement_resolver.py
Comment thread crates/cribo/src/requirement_resolver.py Outdated
Comment thread crates/cribo/src/requirement_resolver.rs
Comment thread python/cribo/__main__.py
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 17, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 119ec49343

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/cribo/src/requirement_resolver.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 79163ee2de

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/cribo/src/requirement_resolver.py
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
crates/cribo/src/requirement_resolver.rs (1)

304-315: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Search every metadata path when auto-detecting Python.

Using only the first path misses a CWD fallback virtualenv when the entry file is external, despite its site-packages being included later. The helper then runs under PATH Python, adding unrelated sys.path providers and interpreter-specific extension suffixes. Iterate all metadata paths and cover the external-entry layout without an explicit --python.

Proposed direction
-        let first_path = self.metadata_paths.first()?;
-        for ancestor in first_path.ancestors() {
-            for environment_name in AUTO_DETECTED_VIRTUALENV_NAMES {
-                let candidate = Self::environment_python(&ancestor.join(environment_name));
-                if candidate.is_file() {
-                    return Some(candidate);
+        for metadata_path in &self.metadata_paths {
+            for ancestor in metadata_path.ancestors() {
+                for environment_name in AUTO_DETECTED_VIRTUALENV_NAMES {
+                    let candidate = Self::environment_python(&ancestor.join(environment_name));
+                    if candidate.is_file() {
+                        return Some(candidate);
+                    }
                 }
             }
         }

Also applies to: 388-408

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/cribo/src/requirement_resolver.rs` around lines 304 - 315, Update
auto_detected_python to iterate through every path in self.metadata_paths rather
than only self.metadata_paths.first(), checking each path’s ancestors for the
conventional virtualenv names. Preserve the existing candidate validation and
return the first matching interpreter, including virtualenvs associated with
external-entry and CWD metadata paths.
crates/cribo/src/resolver.rs (1)

1367-1387: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Index top_level.txt before classifying resolved imports as first-party.

This index ignores the legacy source supported by requirement_resolver.py. A PYTHONPATH distribution with only top_level.txt ownership is classified FirstParty, so generate_requirements never sends it to metadata resolution. Read top_level.txt here as well and add a regression for that metadata shape.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/cribo/src/resolver.rs` around lines 1367 - 1387, Extend the
distribution indexing flow around `index_distribution_metadata` to read each
`.dist-info` directory’s `top_level.txt` and add its entries to the same
ownership index before resolved imports are classified. Preserve the existing
`METADATA` and `RECORD` handling, and add a regression covering a PYTHONPATH
distribution whose ownership is provided only by `top_level.txt`.
crates/cribo/tests/test_cli_stdout.rs (1)

21-104: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Move these requirement cases into the generic snapshot framework.

Create fixture directories with main.py and extend the generic harness where environment customization is needed, rather than adding bespoke CLI setup and assertions here.

As per coding guidelines, “Use the generic snapshot testing framework located at crates/cribo/tests/test_bundling_snapshots.rs as the primary testing approach for bundling features; create fixture directories with main.py files and run using INSTA_GLOB_FILTER environment variable.”

Also applies to: 271-362

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/cribo/tests/test_cli_stdout.rs` around lines 21 - 104, Move the
requirement-generation cases from the bespoke helpers and assertions in this
test module into the generic snapshot framework in test_bundling_snapshots.rs.
Create fixture directories containing main.py for each case, extend the generic
harness to support the required environment customization, and run the cases
through the INSTA_GLOB_FILTER-based snapshot flow. Remove the now-unneeded
helpers write_test_distribution, cribo_command, run_cribo,
run_requirement_cribo, and assert_requirement_output.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/cribo/src/requirement_resolver.rs`:
- Around line 304-315: Update auto_detected_python to iterate through every path
in self.metadata_paths rather than only self.metadata_paths.first(), checking
each path’s ancestors for the conventional virtualenv names. Preserve the
existing candidate validation and return the first matching interpreter,
including virtualenvs associated with external-entry and CWD metadata paths.

In `@crates/cribo/src/resolver.rs`:
- Around line 1367-1387: Extend the distribution indexing flow around
`index_distribution_metadata` to read each `.dist-info` directory’s
`top_level.txt` and add its entries to the same ownership index before resolved
imports are classified. Preserve the existing `METADATA` and `RECORD` handling,
and add a regression covering a PYTHONPATH distribution whose ownership is
provided only by `top_level.txt`.

In `@crates/cribo/tests/test_cli_stdout.rs`:
- Around line 21-104: Move the requirement-generation cases from the bespoke
helpers and assertions in this test module into the generic snapshot framework
in test_bundling_snapshots.rs. Create fixture directories containing main.py for
each case, extend the generic harness to support the required environment
customization, and run the cases through the INSTA_GLOB_FILTER-based snapshot
flow. Remove the now-unneeded helpers write_test_distribution, cribo_command,
run_cribo, run_requirement_cribo, and assert_requirement_output.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f75a7197-a6aa-415c-b61f-6424f15d890e

📥 Commits

Reviewing files that changed from the base of the PR and between d6f5d2a and b155d80.

📒 Files selected for processing (7)
  • crates/cribo/src/config.rs
  • crates/cribo/src/orchestrator.rs
  • crates/cribo/src/requirement_resolver.py
  • crates/cribo/src/requirement_resolver.rs
  • crates/cribo/src/resolver.rs
  • crates/cribo/tests/test_cli_stdout.rs
  • python/cribo/__main__.py

@tinovyatkin
tinovyatkin merged commit dca13da into main Jul 17, 2026
21 checks passed
@tinovyatkin
tinovyatkin deleted the codex/resolve-requirement-distributions branch July 17, 2026 21:41
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.

Module name are not required to match import name

2 participants