Tools for deducing things about python.
In this module, we mainly use 'python' and 'python3'. Use of 'py' alias can be a bit fickle.
TODO(@sas): Check python version before enabling note adding as this is a python 3.11 feature.
deduce_default_python_executable()
Deduce default python executable location.
This is done by attempt at subprocessing python/python3 depending on platform.
Returns:
| Type | Description |
str | None | Path to python executable or None if not found. |
Source code in client/ayon_comfyui/api/deduce_python.py
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 | def deduce_default_python_executable() -> str | None:
"""Deduce default python executable location.
This is done by attempt at subprocessing
python/python3 depending on platform.
Returns:
Path to python executable or None if not found.
"""
script = "import sys;print(sys.executable)"
python_name = "python"
if sys.platform != "win32":
python_name += "3" # python3
try:
proc = subprocess.Popen(
[python_name, "-c", script],
stdout=subprocess.PIPE,
text=True,
)
except FileNotFoundError:
return None
out, _ = proc.communicate()
return out.strip()
|
deduce_default_python_version()
Deduce default python executable version.
This is done by attempt at subprocessing python/python3 depending on platform.
Returns:
| Type | Description |
str | None | Python version as '3.X.X' or None if not found. |
Source code in client/ayon_comfyui/api/deduce_python.py
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 | def deduce_default_python_version() -> str | None:
"""Deduce default python executable version.
This is done by attempt at subprocessing
python/python3 depending on platform.
Returns:
Python version as '3.X.X' or None if not found.
"""
script = (
"import sys;"
"print(sys.version_info.major,sys.version_info.minor,sys.version_info.micro,sep='.')"
)
python_name = "python"
if sys.platform != "win32":
python_name += "3" # python3
try:
proc = subprocess.Popen(
[python_name, "-c", script],
stdout=subprocess.PIPE,
text=True,
)
except FileNotFoundError:
return None
out, _ = proc.communicate()
return out.strip()
|
pip_install_requirements(python_exec_path, requirements_path)
Uses pip to install/update modules from a requirements file.
This process should go pretty quick if requirements are already met.
Raises ChildProcessError if somehow, packages failed to install.
Source code in client/ayon_comfyui/api/deduce_python.py
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 | def pip_install_requirements(
python_exec_path: Path, requirements_path: Path
) -> None:
"""Uses pip to install/update modules from a requirements file.
This process should go pretty quick if requirements are already met.
Raises ChildProcessError if somehow, packages failed to install.
"""
args = [python_exec_path, "-m", "pip", "install", "-r", requirements_path]
delim = ":"
if sys.platform == "win32":
delim = ";"
envdict: dict[str, str] = os.environ._data # noqa: SLF001
envdict["PATH"] = delim.join(
[
pth
for pth in envdict["PATH"].split(delim)
if "AYON" not in pth or "Ayon" not in pth or "ayon" not in pth
]
)
envdict.pop("PYTHONPATH", None)
proc = subprocess.Popen(
args,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
text=True,
)
out, err = proc.communicate()
out, err = out.strip(), err.strip()
if "Error" in out or "ERROR" in out or "Error" in err or "ERROR" in err:
error = ChildProcessError(
"Failed to install packages from requirements."
)
# error.add_note(
# "Failed to install packages from requirements. "
# "Try manually installing them with "
# f"{python_exec_path} -m pip instal -r {requirements_path}"
# )
raise error
|
python_setup_venv_with_depends(python_exec_path, environment_path, requirements_path)
Spawn a virtual environment using venv.
Because a venv points to a path that could be local, we should carefully consider where to place the environment path. Then, set it up with requirements.txt
Returns:
| Type | Description |
Path | path to executable within python environment, |
Path | environment_path/Scripts/python(.exe) |
Source code in client/ayon_comfyui/api/deduce_python.py
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 | def python_setup_venv_with_depends(
python_exec_path: Path, environment_path: Path, requirements_path: Path
) -> Path:
"""Spawn a virtual environment using venv.
Because a venv points to a path that could be local, we should carefully
consider where to place the environment path.
Then, set it up with requirements.txt
Returns:
path to executable within python environment,
environment_path/Scripts/python(.exe)
Raises:
ChildProcessError when failed to set up a virtual environment.
ChildProcessError from setting up environment and failing.
"""
# Only do this if there's no venv already.
if not venv_check_existence(environment_path):
venv_args = [python_exec_path, "-m", "venv", environment_path]
proc = subprocess.Popen(
venv_args,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
text=True,
)
out, err = proc.communicate()
out, err = out.strip(), err.strip()
if out or err:
error = ChildProcessError(
"Failed to set up a virtual environment."
)
# error.add_note("Failed to set up a virtual environment.")
raise error
venv_python = venv_get_python(environment_path)
# Can fail too.
pip_install_requirements(venv_python, requirements_path)
return venv_python
|
venv_check_existence(environment_path)
Returns whether a valid python environment exists at location.
Utility function to check if an environment has previously been made. It is kind of naive, it only checks if the environment has been set up, not if it actually works.
Source code in client/ayon_comfyui/api/deduce_python.py
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 | def venv_check_existence(environment_path: Path) -> bool:
"""Returns whether a valid python environment exists at location.
Utility function to check if an environment has previously been made.
It is kind of naive, it only checks if the environment has been set up,
not if it actually works.
"""
py_path = venv_get_python(environment_path)
bin_path = py_path.parent
asserts = [
environment_path.exists(),
bin_path.exists(),
py_path.exists(),
]
return all(asserts)
|
venv_get_python(environment_path)
Returns path to python executable in environment.
Warning: Does not check if the environment exists / is valid. For that, use venv_check_existence.
Source code in client/ayon_comfyui/api/deduce_python.py
79
80
81
82
83
84
85
86
87
88
89
90
91
92 | def venv_get_python(environment_path: Path) -> Path:
"""Returns path to python executable in environment.
Warning: Does not check if the environment exists / is valid.
For that, use `venv_check_existence`.
"""
bin_directory = "bin"
python_name = "python"
if sys.platform == "win32":
python_name += ".exe"
bin_directory = "Scripts"
return environment_path / bin_directory / python_name
|