Skip to content

Commit

Permalink
update BrewProvider to use brew info to get version info when cmd is …
Browse files Browse the repository at this point in the history
…not available
  • Loading branch information
pirate committed Oct 1, 2024
1 parent 226de32 commit e989764
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 17 deletions.
6 changes: 3 additions & 3 deletions pydantic_pkgr/binprovider.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from typing import Callable, Iterable, Any, Optional, List, Dict, ClassVar, cast
from pathlib import Path
from subprocess import run, PIPE, CompletedProcess
from subprocess import run, CompletedProcess

from pydantic_core import ValidationError
from pydantic import BaseModel, Field, TypeAdapter, validate_call, ConfigDict, InstanceOf, computed_field, model_validator
Expand Down Expand Up @@ -146,7 +146,7 @@ def exec(
assert self.loaded_version, "Binary must have a loaded_version, make sure to load_or_install() first"
assert Path(cwd).is_dir(), f"cwd must be a valid directory: {cwd}"
cmd = [str(bin_name), *(str(arg) for arg in cmd)]
return subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd=str(cwd), **kwargs)
return subprocess.run(cmd, capture_output=True, text=True, cwd=str(cwd), **kwargs)


class BinProvider(BaseModel):
Expand Down Expand Up @@ -224,7 +224,7 @@ def exec(self, bin_name: BinName | HostBinPath, cmd: Iterable[str | Path | int |
assert bin_abspath, f'BinProvider {self.name} cannot execute bin_name {bin_name} because it could not find its abspath. (Did {self.__class__.__name__}.load_or_install({bin_name}) fail?)'
assert Path(cwd).is_dir(), f'cwd must be a valid directory: {cwd}'
cmd = [str(bin_abspath), *(str(arg) for arg in cmd)]
return run(cmd, stdout=PIPE, stderr=PIPE, text=True, cwd=str(cwd), **kwargs)
return run(cmd, capture_output=True, text=True, cwd=str(cwd), **kwargs)

def get_default_handlers(self):
return self.get_handlers_for_bin('*')
Expand Down
55 changes: 41 additions & 14 deletions pydantic_pkgr/binprovider_brew.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@

import sys
import platform
from pathlib import Path
from typing import Optional
from pathlib import Path
from subprocess import run

from pydantic import model_validator, TypeAdapter

from .base_types import BinProviderName, PATHStr, BinName, InstallArgs
from .base_types import BinProviderName, PATHStr, BinName, InstallArgs, HostBinPath, bin_abspath
from .semver import SemVer
from .binprovider import BinProvider

OS = platform.system().lower()

DEFAULT_MACOS_DIR = Path('/opt/homebrew/bin') if platform.machine() == 'arm64' else Path('/usr/local/bin')
DEFAULT_LINUX_DIR = Path('/home/linuxbrew/.linuxbrew/bin')


class BrewProvider(BinProvider):
name: BinProviderName = "brew"
Expand All @@ -26,10 +33,6 @@ def load_PATH(self):
self.PATH: PATHStr = ""
return self

OS = platform.system().lower()
DEFAULT_MACOS_DIR = Path('/opt/homebrew/bin') if platform.machine() == 'arm64' else Path('/usr/local/bin')
DEFAULT_LINUX_DIR = Path('/home/linuxbrew/.linuxbrew/bin')

PATHs = set()

if OS == 'darwin' and DEFAULT_MACOS_DIR.exists():
Expand Down Expand Up @@ -74,14 +77,38 @@ def on_install(self, bin_name: str, packages: Optional[InstallArgs] = None, **co

return proc.stderr.strip() + "\n" + proc.stdout.strip()

# def on_get_version(self, bin_name: BinName, abspath: Optional[HostBinPath]=None, **context) -> SemVer | None:
# # print(f'[*] {self.__class__.__name__}: Getting version for {bin_name}...')
# version_stdout_str = run(['brew', 'info', '--quiet', bin_name], stdout=PIPE, stderr=PIPE, text=True).stdout
# try:
# return SemVer.parse(version_stdout_str)
# except ValidationError:
# raise
# return None
def on_get_abspath(self, bin_name: BinName | HostBinPath, **context) -> HostBinPath | None:
# print(f'[*] {self.__class__.__name__}: Getting abspath for {bin_name}...')

if not self.PATH:
return None

# not all brew-installed binaries are symlinked into the default bin dir (e.g. curl)
# because it might conflict with a system binary of the same name (e.g. /usr/bin/curl)
# so we need to check for the binary in the namespaced opt dir as well
extra_path = self.PATH.replace('/bin', '/opt/{bin_name}/bin') # e.g. /opt/homebrew/opt/curl/bin/curl

return bin_abspath(bin_name, PATH=f'{self.PATH}:{extra_path}')


def on_get_version(self, bin_name: BinName, abspath: Optional[HostBinPath]=None, **context) -> SemVer | None:
# print(f'[*] {self.__class__.__name__}: Getting version for {bin_name}...')
try:
return super().on_get_version(bin_name, abspath, **context)
except ValueError:
pass

if not self.INSTALLER_BIN_ABSPATH:
return None

version = self.exec(bin_name=self.INSTALLER_BIN_ABSPATH, cmd=['info', '--quiet', bin_name], text=True).stdout.strip()

version_stdout_str = run([str(self.INSTALLER_BIN_ABSPATH), 'info', '--quiet', bin_name], stdout=PIPE, stderr=PIPE, text=True).stdout
try:
return SemVer.parse(version_stdout_str)
except ValidationError:
raise
return None

if __name__ == "__main__":
result = brew = BrewProvider()
Expand Down

0 comments on commit e989764

Please sign in to comment.