Coverage for pipxl/sync.py: 100%

1# SPDX-FileCopyrightText: 2022-present Jeroen van Zundert <mail@jeroenvanzundert.nl>

2#

3# SPDX-License-Identifier: MIT

4

5 from __future__ import annotations

6

7 import textwrap

8 from pathlib import Path

9

10 import typer

11

12 from pipxl.pip_cli import pip_cli

13 from pipxl.resolver import pip_resolve

14

15 pipxl_deps = ["typer", "click", "pytest", "pytest-cov", "coverage"]

16 PACKAGES_TO_IGNORE = ["pip", "pipxl", *pipxl_deps]

17

18

19 def sync(files_in: list[Path] | None = None, package_spec: list[str] | None = None, dry_run: bool = False) -> None:

20 reqs, _ = pip_resolve(files_in, package_spec)

21 target_install = [r.name + "==" + r.version for r in reqs]

22

23 installed = get_installed_packages()

24

25 to_install, to_uninstall = merge(target_install, installed)

26

27 if dry_run:

28 typer.echo("Would uninstall:")

29 typer.echo(textwrap.indent("\n".join(to_uninstall), prefix="\t"))

30 typer.echo("Would install")

31 typer.echo(textwrap.indent("\n".join(to_install), prefix="\t"))

32 else:

33 uninstall_packages(to_uninstall)

34 install_packages(to_install)

35

36

37 def get_installed_packages() -> list[str]:

38 cmd = ["list", "--format=freeze"]

39 output = pip_cli(cmd).stdout

40 assert isinstance(output, str)

41 return output.splitlines()

42

43

44 def install_packages(targets: list[str]) -> None:

45 cmd = ["install"] + targets

46 pip_cli(cmd)

47

48

49 def uninstall_packages(targets: list[str]) -> None:

50 cmd = ["uninstall", "-y"] + targets

51 pip_cli(cmd)

52

53

54 def merge(target_install: list[str], installed: list[str]) -> tuple[list[str], list[str]]:

55 to_uninstall = set()

56 to_install = set()

57

58 for pkg in installed:

59 if pkg in target_install:

60 continue

61

62 if "==" in pkg and pkg.split("==")[0] in PACKAGES_TO_IGNORE:

63 continue

64

65 to_uninstall.add(pkg)

66

67 for pkg in target_install:

68 if pkg not in installed:

69 to_install.add(pkg)

70

71 return (sorted(list(to_install)), sorted(list(to_uninstall)))