Skip to content

Add uv support: requirements-to-uv, uv-to-requirements, auto-detection in existing commands#5

Merged
devin-ai-integration[bot] merged 14 commits intomainfrom
devin/1770481980-add-uv-support
Feb 7, 2026
Merged

Add uv support: requirements-to-uv, uv-to-requirements, auto-detection in existing commands#5
devin-ai-integration[bot] merged 14 commits intomainfrom
devin/1770481980-add-uv-support

Conversation

@MrLYC
Copy link
Owner

@MrLYC MrLYC commented Feb 7, 2026

Add uv support with auto-detection for package manager commands

Summary

Adds uv as a supported package manager alongside Poetry. New CLI commands (requirements-to-uv, uv-to-requirements) mirror the existing Poetry commands. Existing commands (extract-private-packages, obfuscate-private-packages) now auto-detect whether the project uses uv or Poetry by checking for uv.lock / poetry.lock.

New files:

  • versifier/uv.pyUv class with same interface as Poetry (add_packages, export_requirements, install, run_command, init_if_needed)
  • tests/test_uv.py — unit tests for the Uv class

Modified files:

  • versifier/core.pyPackageManager = Union[Poetry, Uv] type alias; DependencyManager, DependencyExporter, PackageExtractor now accept either
  • versifier/__main__.pyContext gains uv_path, uv property, package_manager auto-detection property; new --uv-path CLI option; new requirements-to-uv and uv-to-requirements commands; extract-private-packages and obfuscate-private-packages switched from ctx.poetryctx.package_manager
  • tests/test_main.py — existing tests updated for new uv_path field; new tests for uv commands and auto-detection

Updates since last revision

Addressed review feedback:

  • Uv.install() now honors include_dev_requirements — passes --no-dev to uv sync when include_dev_requirements=False (the default)
  • Uv.export_requirements() warns on with_credentials=True — logs a warning that uv export does not support embedding credentials, instead of silently ignoring the parameter
  • Test specificitytest_context_package_manager_none now asserts click.UsageError with message match instead of broad Exception

Review & Testing Checklist for Human

  • Breaking change: auto-detection requires lock fileextract-private-packages and obfuscate-private-packages now raise UsageError if neither uv.lock nor poetry.lock exists. Previously they would always use Poetry (even without a lock file). Verify this is acceptable behavior.
  • Field named poetry accepts Uv instancescore.py dataclasses keep the field name poetry: PackageManager for backward compat, so callers write DependencyManager(poetry=uv_instance). Confirm this naming tradeoff is acceptable vs. a rename.
  • Auto-detection prefers uv when both lock files exist — verify this priority is desired.
  • No formal Protocol/ABCUv and Poetry share the same duck-typed interface but there is no shared base class or Protocol enforcing it. A future method addition to one could silently break the other.

Recommended test plan:

  1. In a uv-managed project, run versifier uv-to-requirements -o /tmp/req.txt and verify output
  2. In a Poetry-managed project, run versifier extract-private-packages -P <pkg> and verify it still works
  3. In a directory with neither lock file, run versifier extract-private-packages -P foo and confirm the error message

Notes

  • All 144 tests pass locally (87 warnings are pre-existing deprecation warnings in stub.py)
  • Tests are mocked; no integration tests against real uv CLI

Link to Devin run: https://app.devin.ai/sessions/2b89e39464164fe085c3208ff2b164d7
Requested by: @MrLYC

…n in existing commands

Co-Authored-By: 刘奕聪 <github@m.mrlyc.com>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
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 first-class support for the uv package manager alongside Poetry, including new conversion commands and auto-detection of the active package manager based on lockfiles.

Changes:

  • Introduces Uv package-manager adapter with a Poetry-compatible interface.
  • Extends core dependency management/export/extraction to accept either Poetry or uv.
  • Updates CLI to add requirements-to-uv / uv-to-requirements and to auto-detect the package manager for existing private-package commands; updates and adds tests.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
versifier/uv.py Adds Uv implementation for add/export/sync/run/lock behaviors.
versifier/core.py Generalizes dependency operations to accept Poetry or Uv via a union type.
versifier/__main__.py Adds --uv-path, uv commands, and lockfile-based package-manager auto-detection for relevant commands.
tests/test_uv.py Adds unit tests for Uv behavior (mocking subprocess calls).
tests/test_main.py Updates CLI/context tests for uv support and auto-detection scenarios; adds uv command tests.

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

Comment on lines +29 to +54
def export_requirements(
self,
include_dev_requirements: bool = False,
extra_requirements: Optional[Iterable[str]] = None,
with_credentials: bool = False,
) -> RequirementsFile:
with TemporaryDirectory() as td:
requirement_path = os.path.join(td, "requirements.txt")

commands = [
self.uv_path,
"export",
"--no-hashes",
f"--output-file={requirement_path}",
]

if not include_dev_requirements:
commands.append("--no-dev")

if extra_requirements:
commands.extend(f"--extra={i}" for i in extra_requirements)

check_call(commands)
rf = RequirementsFile.from_file(requirement_path)

return rf
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

with_credentials parameter is accepted but never used. This matters because PackageExtractor calls export_requirements(..., with_credentials=True) for private package extraction; silently ignoring it can lead to exporting requirements without embedded auth data and break installs against private indices. Consider either implementing an equivalent behavior for uv, or explicitly warning/raising when with_credentials=True so callers don’t get a false sense of security.

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed: export_requirements() now logs a warning when with_credentials=True since uv export has no equivalent flag. Added a test to verify the warning is emitted.

Comment on lines +56 to +64
def install(
self, include_dev_requirements: bool = False, extra_requirements: Optional[Iterable[str]] = None
) -> None:
commands = [self.uv_path, "sync"]

if extra_requirements:
commands.extend(f"--extra={i}" for i in extra_requirements)

check_call(commands)
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

include_dev_requirements is currently unused in install(), so callers can’t control whether dev dependencies are installed (and the parameter is misleading). Either honor the flag (e.g., pass the appropriate uv sync option) or remove/rename the parameter and adjust the shared interface accordingly.

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed: install() now passes --no-dev when include_dev_requirements=False (the default). Added test_install_with_dev to verify both paths.

Comment on lines +144 to +145
with pytest.raises(Exception):
ctx.package_manager
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

This test asserts a very broad exception type. Since Context.package_manager raises a specific click.UsageError, the test should assert that exact exception (and ideally the message) to avoid masking unrelated failures.

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed: Now asserts click.UsageError with message match "No uv.lock or poetry.lock found" instead of broad Exception.

Copy link
Contributor

Copilot AI commented Feb 7, 2026

@MrLYC I've opened a new pull request, #8, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Feb 7, 2026

@MrLYC I've opened a new pull request, #9, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Feb 7, 2026

@MrLYC I've opened a new pull request, #10, to work on those changes. Once the pull request is ready, I'll request review from you.

MrLYC and others added 10 commits February 8, 2026 02:07
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ements in install(), use specific click.UsageError in test

Co-Authored-By: 刘奕聪 <github@m.mrlyc.com>
Co-authored-by: MrLYC <6391488+MrLYC@users.noreply.github.com>
…tion

Co-authored-by: MrLYC <6391488+MrLYC@users.noreply.github.com>
Co-authored-by: MrLYC <6391488+MrLYC@users.noreply.github.com>
Co-authored-by: MrLYC <6391488+MrLYC@users.noreply.github.com>
Honor include_dev_requirements flag in Uv.install()
Assert specific click.UsageError in package manager auto-detection test
@devin-ai-integration devin-ai-integration bot merged commit 7f69464 into main Feb 7, 2026
3 checks passed
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.

3 participants