11import inspect
22import json
33import os
4+ import re
45import sys
56from enum import Enum
67from typing import Any , Dict , List , Optional
@@ -100,13 +101,13 @@ def install_package_python(pkg: str, verbose: bool = True):
100101 log (f"Installed { pkg } " , force_verbose = verbose )
101102
102103
103- async def install_packages (notebook_name : str , requirements_path : str = "" , verbose : bool = True ):
104+ async def install_packages (notebook_name_pattern : str , config_file_path : str = "" , verbose : bool = True ):
104105 """
105106 Install the packages listed in the requirements file for the notebook with the given name.
106107
107108 Args:
108- notebook_name (str): The name of the notebook for which to install packages.
109- requirements_path (str): The path to the requirements file.
109+ notebook_name_pattern (str): The name pattern of the notebook for which to install packages.
110+ config_file_path (str): The path to the requirements file.
110111 verbose (bool): Whether to print the names of the installed packages and status of installation.
111112 """
112113 if ENVIRONMENT == EnvironmentEnum .PYODIDE :
@@ -116,44 +117,44 @@ async def install_packages(notebook_name: str, requirements_path: str = "", verb
116117 import yaml
117118
118119 base_path = os .getcwd ()
119- if requirements_path == "" :
120- requirements_file = os .path .normpath (os .path .join ("/drive/" , "./config.yml" ))
121- print (requirements_file )
122- else :
123- requirements_file = os .path .normpath (os .path .join (base_path , requirements_path ))
120+ config_file_full_path = os .path .normpath (os .path .join ("/drive/" , "./config.yml" ))
121+ if config_file_path != "" :
122+ config_file_full_path = os .path .normpath (os .path .join (base_path , config_file_path ))
124123
125- with open (requirements_file , "r" ) as f :
126- requirements = yaml .safe_load (f )
124+ with open (config_file_full_path , "r" ) as f :
125+ requirements_dict = yaml .safe_load (f )
127126
128- # Hash the requirements to avoid re-installing packages
129- requirements_hash = str (hash (json .dumps (requirements )))
130- if os .environ .get ("requirements_hash" ) != requirements_hash :
131- packages_default_common = requirements .get ("default" , {}).get ("packages_common" , []) or []
132- packages_default_environment_specific = (
133- requirements .get ("default" , {}).get (f"packages_{ ENVIRONMENT .value } " , []) or []
134- )
127+ packages_default_common = requirements_dict .get ("default" , {}).get ("packages_common" , [])
128+ packages_default_environment_specific = requirements_dict .get ("default" , {}).get (
129+ f"packages_{ ENVIRONMENT .value } " , []
130+ )
135131
136- notebook_requirements = next (
137- (cfg for cfg in requirements .get ("notebooks" , []) if cfg .get ("name" ) == notebook_name ), None
138- )
139- if notebook_requirements :
140- packages_notebook_common = notebook_requirements .get ("packages_common" , []) or []
141- packages_notebook_environment_specific = (
142- notebook_requirements .get (f"packages_{ ENVIRONMENT .value } " , []) or []
143- )
144- else :
145- packages_notebook_common = []
146- packages_notebook_environment_specific = []
147-
148- # Note: environment specific packages have to be installed first,
149- # because in Pyodide common packages might depend on them
150- packages = [
151- * packages_default_environment_specific ,
152- * packages_notebook_environment_specific ,
153- * packages_default_common ,
154- * packages_notebook_common ,
155- ]
132+ matching_notebook_requirements_list = [
133+ cfg for cfg in requirements_dict .get ("notebooks" , []) if re .search (cfg .get ("name" ), notebook_name_pattern )
134+ ]
135+ packages_notebook_common = []
136+ packages_notebook_environment_specific = []
137+
138+ for notebook_requirements in matching_notebook_requirements_list :
139+ packages_common = notebook_requirements .get ("packages_common" , [])
140+ packages_environment_specific = notebook_requirements .get (f"packages_{ ENVIRONMENT .value } " , [])
141+ if packages_common :
142+ packages_notebook_common .extend (packages_common )
143+ if packages_environment_specific :
144+ packages_notebook_environment_specific .extend (packages_environment_specific )
145+
146+ # Note: environment specific packages have to be installed first,
147+ # because in Pyodide common packages might depend on them
148+ packages = [
149+ * packages_default_environment_specific ,
150+ * packages_notebook_environment_specific ,
151+ * packages_default_common ,
152+ * packages_notebook_common ,
153+ ]
156154
155+ # Hash the requirements to avoid re-installing packages
156+ requirements_hash = str (hash (json .dumps (packages )))
157+ if os .environ .get ("requirements_hash" ) != requirements_hash :
157158 for pkg in packages :
158159 if ENVIRONMENT == EnvironmentEnum .PYODIDE :
159160 await install_package_pyodide (pkg , verbose )
@@ -163,6 +164,9 @@ async def install_packages(notebook_name: str, requirements_path: str = "", verb
163164 if verbose :
164165 log ("Packages installed successfully." , force_verbose = verbose )
165166 os .environ ["requirements_hash" ] = requirements_hash
167+ else :
168+ if verbose :
169+ log ("Packages are already installed." , force_verbose = verbose )
166170
167171
168172def set_data_pyodide (key : str , value : Any ):
0 commit comments