-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpip.py
More file actions
126 lines (104 loc) · 4.02 KB
/
pip.py
File metadata and controls
126 lines (104 loc) · 4.02 KB
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
115
116
117
118
119
120
121
122
123
124
125
126
import typing as t
from dataclasses import dataclass
from urllib.parse import urlparse
from deploy.Windows.config import DeployConfig
from deploy.Windows.logger import logger
from deploy.Windows.utils import *
@dataclass
class DataDependency:
name: str
version: str
def __post_init__(self):
# uvicorn[standard] -> uvicorn
self.name = re.sub(r'\[.*\]', '', self.name)
# opencv_python -> opencv-python
self.name = self.name.replace('_', '-').strip()
# PyYaml -> pyyaml
self.name = self.name.lower()
self.version = self.version.strip()
@cached_property
def pretty_name(self):
return f'{self.name}=={self.version}'
def __str__(self):
return self.pretty_name
__repr__ = __str__
def __eq__(self, other):
return str(self) == str(other)
def __hash__(self):
return hash(str(self))
class PipManager(DeployConfig):
@cached_property
def pip(self):
return f'"{self.python}" -m pip'
@cached_property
def python_site_packages(self):
return os.path.abspath(os.path.join(self.python, '../Lib/site-packages')) \
.replace(r"\\", "/").replace("\\", "/")
@cached_property
def set_installed_dependency(self) -> t.Set[DataDependency]:
data = []
regex = re.compile(r'(.*)-(.*).dist-info')
try:
for name in os.listdir(self.python_site_packages):
res = regex.search(name)
if res:
dep = DataDependency(name=res.group(1), version=res.group(2))
data.append(dep)
except FileNotFoundError:
logger.info(f'Directory not found: {self.python_site_packages}')
return set(data)
@cached_property
def set_required_dependency(self) -> t.Set[DataDependency]:
data = []
regex = re.compile('(.*)==(.*)[ ]*#')
file = self.filepath('./requirements.txt')
try:
with open(file, 'r', encoding='utf-8') as f:
for line in f.readlines():
res = regex.search(line)
if res:
dep = DataDependency(name=res.group(1), version=res.group(2))
data.append(dep)
except FileNotFoundError:
logger.info(f'File not found: {file}')
return set(data)
@cached_property
def set_dependency_to_install(self) -> t.Set[DataDependency]:
"""
A poor dependency comparison, but much much faster than `pip install` and `pip list`
"""
data = []
for dep in self.set_required_dependency:
if dep not in self.set_installed_dependency:
data.append(dep)
return set(data)
def pip_install(self):
logger.hr('Update Dependencies', 0)
if not self.InstallDependencies:
logger.info('InstallDependencies is disabled, skip')
return
if not len(self.set_dependency_to_install):
logger.info('All dependencies installed')
return
else:
logger.info(f'Dependencies to install: {self.set_dependency_to_install}')
# Install
logger.hr('Check Python', 1)
self.execute(f'"{self.python}" --version')
arg = []
if self.PypiMirror:
mirror = self.PypiMirror
arg += ['-i', mirror]
# Trust http mirror or skip ssl verify
if 'http:' in mirror or not self.SSLVerify:
arg += ['--trusted-host', urlparse(mirror).hostname]
elif not self.SSLVerify:
arg += ['--trusted-host', 'pypi.org']
arg += ['--trusted-host', 'files.pythonhosted.org']
# Don't update pip, just leave it.
# logger.hr('Update pip', 1)
# self.execute(f'"{self.pip}" install --upgrade pip{arg}')
arg += ['--disable-pip-version-check']
logger.hr('Update Dependencies', 1)
arg = ' ' + ' '.join(arg) if arg else ''
self.execute(f'{self.pip} install -r {self.requirements_file}{arg}')