diff --git a/src/uvx/_python.py b/src/uvx/_python.py index c5260ff..0dd8af4 100644 --- a/src/uvx/_python.py +++ b/src/uvx/_python.py @@ -40,8 +40,15 @@ def get_python_executable(venv: Path): return str(executable.resolve()) # /usr/bin/python3.xx -def get_package_version(package: str) -> str: +def get_package_version(package: str, venv: Path) -> str: """Get the currently installed version of a specific package.""" # assumes `with virtualenv(venv)` block executing this function # uv pip freeze | grep ^su6== - return (_uv["pip", "freeze"] | grep[f"^{package}=="])().strip().split("==")[-1] + python = venv / "bin" / "python" + + print( + python, + plumbum.local[python]["-m", "uv"]["pip", "freeze"]() + ) + + return (plumbum.local[python]["-m", "uv"]["pip", "freeze"] | grep[f"^{package}=="])().strip().split("==")[-1] diff --git a/src/uvx/core.py b/src/uvx/core.py index 919f485..ed59d5e 100644 --- a/src/uvx/core.py +++ b/src/uvx/core.py @@ -125,10 +125,10 @@ def install_package( with virtualenv(venv), exit_on_pb_error(): try: - animate(uv("pip", "install", package_name), text=f"installing {meta.name}") + animate(uv("pip", "install", meta.install_spec), text=f"installing {meta.name}") # must still be in the venv for these: - meta.installed_version = get_package_version(meta.name) + meta.installed_version = get_package_version(meta.name, venv) meta.python = get_python_version(venv) meta.python_raw = get_python_executable(venv) diff --git a/src/uvx/metadata.py b/src/uvx/metadata.py index f5e7d2b..8b2a2ff 100644 --- a/src/uvx/metadata.py +++ b/src/uvx/metadata.py @@ -1,5 +1,7 @@ """This file contains Logic related to the .metadata file.""" +import json import sys +import tempfile import typing from pathlib import Path from typing import Optional @@ -48,18 +50,36 @@ def check_script_symlinks(self, name: str) -> "Self": quickle_dec = quickle.Decoder(registry=[Metadata]) -@threadful.thread -def resolve_local(spec: str): - # todo: finish +def fake_install(spec: str) -> dict: _python = plumbum.local[sys.executable] _python("-m", "uv", "pip", "install", "pip") # ensure we have pip - result = _python("-m", "pip", "install", "--no-deps", "--dry-run", "--ignore-installed", "--report", - "/tmp/out.json", spec) + with tempfile.NamedTemporaryFile() as f: + _python("-m", "pip", "install", "--no-deps", "--dry-run", "--ignore-installed", "--report", + f.name, spec) + + return json.load(f) + + +@threadful.thread +def resolve_local(spec: str) -> tuple[str | None, str | None]: + try: + full_data = fake_install(spec) + install_data = full_data["install"][0] - print(result) - return result + name = install_data['metadata']["name"] + extras = install_data.get('requested_extras') + file_url = install_data["download_info"]["url"] + + if extras: + _extras = ",".join(extras) + return f"{name}[{_extras}]", file_url + else: + return name, file_url + except Exception as e: + print('eeeee', e) + return None, None def collect_metadata(spec: str) -> Metadata: @@ -67,19 +87,25 @@ def collect_metadata(spec: str) -> Metadata: try: parsed_spec = Requirement(spec) - return Metadata( - install_spec=spec, - name=parsed_spec.name, - scripts={}, # postponed - extras=parsed_spec.extras, - requested_version=str(parsed_spec.specifier), - installed_version="", # postponed - python="", # postponed - ) - except InvalidRequirement: - threadful.animate(resolve_local(spec), text=f"Trying to install local package '{spec}'") - print("reeeeeeeeeeeeeeee") - exit(1) + except InvalidRequirement as e: + local, path = threadful.animate(resolve_local(spec), text=f"Trying to install local package '{spec}'") + + if not local: + raise None + + parsed_spec = Requirement(local) + + spec = f"{parsed_spec.name} @ {path.removeprefix('file://')}" + + return Metadata( + install_spec=spec, + name=parsed_spec.name, + scripts={}, # postponed + extras=parsed_spec.extras, + requested_version=str(parsed_spec.specifier), + installed_version="", # postponed + python="", # postponed + ) def store_metadata(meta: Metadata, venv: Path):