Skip to content

Add backend-agnostic self-update with uv + pipx support - #2487

Draft
glensc with Copilot wants to merge 3 commits into
mainfrom
copilot/add-uv-installation-support
Draft

Add backend-agnostic self-update with uv + pipx support#2487
glensc with Copilot wants to merge 3 commits into
mainfrom
copilot/add-uv-installation-support

Conversation

Copilot AI commented May 28, 2026

Copy link
Copy Markdown

This change makes uv a first-class managed install backend alongside pipx, and removes installer-specific logic from self-update/version gating paths. self-update now detects and updates all managed PlexTraktSync installs across supported backends, including PR flows.

  • Install backend abstraction

    • Introduced a generic managed-install model and backend interface in plextraktsync/util/packaging.py.
    • Added backend implementations for:
      • pipx (pipx list --json detection, upgrade/install PR commands)
      • uv (uv tool list detection, upgrade/install PR commands)
    • Added shared helpers for cross-backend discovery and self-update eligibility.
  • Self-update orchestration

    • Refactored plextraktsync/commands/self_update.py to:
      • discover installs by backend
      • run backend-specific update commands per detected install
      • apply PR updates per backend
    • Kept pipx PR reinstall behavior scoped to the pipx backend only.
  • CLI/Factory/Version generalization

    • Updated self-update command help text to describe both pipx and uv.
    • Changed Factory.enable_self_update to use backend-agnostic managed-install detection.
    • Replaced pipx-specific version-install check with a generic managed-install check while preserving PR/dev formatting behavior.
  • Docs + tests

    • Updated README install/self-update docs to include uv and multi-backend update behavior.
    • Updated CONTRIBUTING PR-install workflow with uv guidance.
    • Added focused unit tests for backend detection, self-update gating, latest/PR update orchestration, pipx PR workaround, and partial backend availability.
# self-update now targets all detected managed installs, not only pipx
for install in list_managed_installs():
    backend = backend_for_name(install.backend)
    execp(backend.latest_update_command(install))

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 refactors PlexTraktSync’s self-update flow to be install-backend agnostic by introducing a managed-install abstraction with backend implementations for pipx and uv, then updating CLI/docs/tests accordingly.

Changes:

  • Added a backend interface + ManagedInstall model with discovery/update commands for pipx and uv.
  • Refactored self-update to discover all managed installs and run backend-specific latest/PR update commands.
  • Updated docs and added unit tests to cover backend detection and orchestration.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
plextraktsync/util/packaging.py Adds backend abstraction, pipx/uv discovery, and backend-specific update command generation.
plextraktsync/commands/self_update.py Orchestrates self-update across discovered managed installs/backends (latest + PR flows).
plextraktsync/factory/Factory.py Enables the self-update command based on backend-agnostic “managed install exists” detection.
plextraktsync/util/Version.py Generalizes “managed install” detection for PR/dev version formatting.
plextraktsync/cli.py Updates self-update help text/examples to mention both backends.
README.md Documents uv install/upgrade and multi-backend update behavior; updates command list description.
CONTRIBUTING.md Documents PR install workflow for both pipx and uv (including uninstall guidance).
tests/test_self_update_packaging.py Adds unit tests for backend detection and update orchestration behaviors.

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

Comment on lines +159 to +166
def latest_update_command(self, install: ManagedInstall) -> str:
return f"pipx upgrade {install.app_name}"

def pr_update_commands(self, pr: int, installs: list[ManagedInstall]) -> list[str]:
target_name = f"plextraktsync@{pr}"
commands = []
if any(install.app_name.lower() == target_name for install in installs):
commands.append(f"pipx uninstall {target_name}")
Comment on lines 46 to +53
def pipx_installed(package: str):
for install in PIPX_BACKEND.list_installs():
if install.app_name.lower() == package.lower():
return {"package": install.package_name, "package_or_url": install.source}

return None



installs = list_managed_installs()
if not installs:
print("No managed PlexTraktSync installation found in pipx or uv")
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