-
Notifications
You must be signed in to change notification settings - Fork 385
/
install.py
114 lines (103 loc) · 4.02 KB
/
install.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from pathlib import Path
from typing import List, Optional
from pipx import constants
from pipx.commands.common import package_name_from_spec, run_post_install_actions
from pipx.constants import EXIT_CODE_INSTALL_VENV_EXISTS, EXIT_CODE_OK, ExitCode
from pipx.interpreter import DEFAULT_PYTHON
from pipx.util import pipx_wrap
from pipx.venv import Venv, VenvContainer
def install(
venv_dir: Optional[Path],
package_names: Optional[List[str]],
package_specs: List[str],
local_bin_dir: Path,
local_man_dir: Path,
python: Optional[str],
pip_args: List[str],
venv_args: List[str],
verbose: bool,
*,
force: bool,
reinstall: bool,
include_dependencies: bool,
preinstall_packages: Optional[List[str]],
suffix: str = "",
) -> ExitCode:
"""Returns pipx exit code."""
# package_spec is anything pip-installable, including package_name, vcs spec,
# zip file, or tar.gz file.
python_flag_was_passed = python is not None
python = python or DEFAULT_PYTHON
package_names = package_names or []
if len(package_names) != len(package_specs):
package_names = [
package_name_from_spec(package_spec, python, pip_args=pip_args, verbose=verbose)
for package_spec in package_specs
]
for package_name, package_spec in zip(package_names, package_specs):
if venv_dir is None:
venv_container = VenvContainer(constants.PIPX_LOCAL_VENVS)
venv_dir = venv_container.get_venv_dir(f"{package_name}{suffix}")
try:
exists = venv_dir.exists() and bool(next(venv_dir.iterdir()))
except StopIteration:
exists = False
venv = Venv(venv_dir, python=python, verbose=verbose)
if exists:
if not reinstall and force and python_flag_was_passed:
print(
pipx_wrap(
f"""
--python is ignored when --force is passed.
If you want to reinstall {package_name} with {python},
run `pipx reinstall {package_spec} --python {python}` instead.
"""
)
)
if force:
print(f"Installing to existing venv {venv.name!r}")
pip_args = ["--force-reinstall"] + pip_args
else:
print(
pipx_wrap(
f"""
{venv.name!r} already seems to be installed. Not modifying
existing installation in '{venv_dir}'. Pass '--force'
to force installation.
"""
)
)
return EXIT_CODE_INSTALL_VENV_EXISTS
try:
# Enable installing shared library `pip` with `pipx`
override_shared = package_name == "pip"
venv.create_venv(venv_args, pip_args, override_shared)
for dep in preinstall_packages or []:
dep_name = package_name_from_spec(dep, python, pip_args=pip_args, verbose=verbose)
venv.upgrade_package_no_metadata(dep_name, [])
venv.install_package(
package_name=package_name,
package_or_url=package_spec,
pip_args=pip_args,
include_dependencies=include_dependencies,
include_apps=True,
is_main_package=True,
suffix=suffix,
)
run_post_install_actions(
venv,
package_name,
local_bin_dir,
local_man_dir,
venv_dir,
include_dependencies,
force=force,
)
except (Exception, KeyboardInterrupt):
print()
venv.remove_venv()
raise
# Reset venv_dir to None ready to install the next package in the list
venv_dir = None
# Any failure to install will raise PipxError, otherwise success
return EXIT_CODE_OK