22import os
33import pathlib
44import shutil
5- import typing
6- from typing import Iterable
75
86import typer
97
108from openllm .common import VENV_DIR , VERBOSE_LEVEL , BentoInfo , VenvSpec , output , run_command
119
1210
1311@functools .lru_cache
14- def _resolve_packages (requirement : typing .Union [pathlib .Path , str ]):
15- from pip_requirements_parser import RequirementsFile
16-
17- requirements_txt = RequirementsFile .from_file (str (requirement ), include_nested = True )
18- return requirements_txt
19-
20-
21- def _filter_preheat_packages (requirements : Iterable ) -> list [str ]:
22- PREHEAT_PIP_PACKAGES = ['torch' , 'vllm' ]
23-
24- deps : list [str ] = []
25- for req in requirements :
26- if req .is_editable or req .is_local_path or req .is_url or req .is_wheel or not req .name or not req .specifier :
27- continue
28- for sp in req .specifier :
29- if sp .operator == '==' and req .name in PREHEAT_PIP_PACKAGES :
30- assert req .line is not None
31- deps .append (req .line )
32- break
33- return deps
34-
35-
36- @functools .lru_cache
37- def _resolve_bento_env_specs (bento : BentoInfo ):
12+ def _resolve_bento_env_spec (bento : BentoInfo ):
3813 ver_file = bento .path / 'env' / 'python' / 'version.txt'
3914 assert ver_file .exists (), f'cannot find version file in { bento .path } '
4015
4116 lock_file = bento .path / 'env' / 'python' / 'requirements.lock.txt'
4217 if not lock_file .exists ():
4318 lock_file = bento .path / 'env' / 'python' / 'requirements.txt'
4419
45- reqs = _resolve_packages (lock_file )
46- packages = reqs .requirements
47- options = reqs .options
48- preheat_packages = _filter_preheat_packages (packages )
4920 ver = ver_file .read_text ().strip ()
50- return (
51- VenvSpec (
52- python_version = ver , python_packages = preheat_packages , name_prefix = f"{ bento .tag .replace (':' , '_' )} -1-"
53- ),
54- VenvSpec (
55- python_version = ver ,
56- python_packages = [v .line for v in packages ],
57- options = [o .line for o in options ],
58- name_prefix = f"{ bento .tag .replace (':' , '_' )} -2-" ,
59- ),
60- )
21+ reqs = lock_file .read_text ().strip ()
6122
23+ return VenvSpec (python_version = ver , requirements_txt = reqs , name_prefix = f"{ bento .tag .replace (':' , '_' )} -1-" )
6224
63- def _get_lib_dir (venv : pathlib .Path ) -> pathlib .Path :
64- if os .name == 'nt' :
65- return venv / 'Lib/site-packages'
66- else :
67- return next (venv .glob ('lib/python*' )) / 'site-packages'
6825
69-
70- def _ensure_venv (env_spec : VenvSpec , parrent_venv : typing .Optional [pathlib .Path ] = None ) -> pathlib .Path :
26+ def _ensure_venv (env_spec : VenvSpec ) -> pathlib .Path :
7127 venv = VENV_DIR / str (hash (env_spec ))
7228 if venv .exists () and not (venv / 'DONE' ).exists ():
7329 shutil .rmtree (venv , ignore_errors = True )
@@ -77,22 +33,18 @@ def _ensure_venv(env_spec: VenvSpec, parrent_venv: typing.Optional[pathlib.Path]
7733 venv_py = venv / 'Scripts' / 'python.exe' if os .name == 'nt' else venv / 'bin' / 'python'
7834 try :
7935 run_command (['python' , '-m' , 'uv' , 'venv' , venv ], silent = VERBOSE_LEVEL .get () < 10 )
80- lib_dir = _get_lib_dir (venv )
81- if parrent_venv is not None :
82- parent_lib_dir = _get_lib_dir (parrent_venv )
83- with open (lib_dir / f'{ parrent_venv .name } .pth' , 'w+' ) as f :
84- f .write (str (parent_lib_dir ))
8536 with open (venv / 'requirements.txt' , 'w' ) as f :
86- with open (venv / 'requirements.txt' , 'w' ) as f :
87- f .write ('\n ' .join (env_spec .options + sorted (env_spec .python_packages )))
37+ f .write (env_spec .normalized_requirements_txt )
8838 run_command (
8939 ['python' , '-m' , 'uv' , 'pip' , 'install' , '-p' , str (venv_py ), '-r' , venv / 'requirements.txt' ],
9040 silent = VERBOSE_LEVEL .get () < 10 ,
9141 )
9242 with open (venv / 'DONE' , 'w' ) as f :
9343 f .write ('DONE' )
94- except Exception :
44+ except Exception as e :
9545 shutil .rmtree (venv , ignore_errors = True )
46+ if VERBOSE_LEVEL .get () >= 10 :
47+ output (e , style = 'red' )
9648 output (f'Failed to install dependencies to { venv } . Cleaned up.' , style = 'red' )
9749 raise typer .Exit (1 )
9850 output (f'Successfully installed dependencies to { venv } .' , style = 'green' )
@@ -101,26 +53,18 @@ def _ensure_venv(env_spec: VenvSpec, parrent_venv: typing.Optional[pathlib.Path]
10153 return venv
10254
10355
104- def _ensure_venvs (env_spec_list : Iterable [VenvSpec ]) -> pathlib .Path :
105- last_venv = None
106- for env_spec in env_spec_list :
107- last_venv = _ensure_venv (env_spec , last_venv )
108- assert last_venv is not None
109- return last_venv
110-
111-
11256def ensure_venv (bento : BentoInfo ) -> pathlib .Path :
113- return _ensure_venvs (_resolve_bento_env_specs (bento ))
57+ env_spec = _resolve_bento_env_spec (bento )
58+ venv = _ensure_venv (env_spec )
59+ assert venv is not None
60+ return venv
11461
11562
116- def _check_venv (env_spec : VenvSpec ) -> bool :
63+ def check_venv (bento : BentoInfo ) -> bool :
64+ env_spec = _resolve_bento_env_spec (bento )
11765 venv = VENV_DIR / str (hash (env_spec ))
11866 if not venv .exists ():
11967 return False
12068 if venv .exists () and not (venv / 'DONE' ).exists ():
12169 return False
12270 return True
123-
124-
125- def check_venv (bento : BentoInfo ) -> bool :
126- return all (_check_venv (env_spec ) for env_spec in _resolve_bento_env_specs (bento ))
0 commit comments