3232)
3333from .eval import AstEval
3434from .event import Event
35- from .mqtt import Mqtt
3635from .function import Function
3736from .global_ctx import GlobalContext , GlobalContextMgr
3837from .jupyter_kernel import Kernel
38+ from .mqtt import Mqtt
3939from .requirements import install_requirements
4040from .state import State , StateVal
4141from .trigger import TrigTime
@@ -98,7 +98,7 @@ def start_global_contexts(global_ctx_only=None):
9898 start_list = []
9999 for global_ctx_name , global_ctx in GlobalContextMgr .items ():
100100 idx = global_ctx_name .find ("." )
101- if idx < 0 or global_ctx_name [0 :idx ] not in {"file" , "apps" }:
101+ if idx < 0 or global_ctx_name [0 :idx ] not in {"file" , "apps" , "scripts" }:
102102 continue
103103 if global_ctx_only is not None :
104104 if global_ctx_name != global_ctx_only and not global_ctx_name .startswith (global_ctx_only + "." ):
@@ -252,7 +252,7 @@ async def unload_scripts(global_ctx_only=None, unload_all=False):
252252 for global_ctx_name , global_ctx in GlobalContextMgr .items ():
253253 if not unload_all :
254254 idx = global_ctx_name .find ("." )
255- if idx < 0 or global_ctx_name [0 :idx ] not in {"file" , "apps" , "modules" }:
255+ if idx < 0 or global_ctx_name [0 :idx ] not in {"file" , "apps" , "modules" , "scripts" }:
256256 continue
257257 if global_ctx_only is not None :
258258 if global_ctx_name != global_ctx_only and not global_ctx_name .startswith (global_ctx_only + "." ):
@@ -273,33 +273,41 @@ def glob_files(load_paths, data):
273273 source_files = []
274274 apps_config = data .get ("apps" , None )
275275 for path , match , check_config in load_paths :
276- for this_path in sorted (glob .glob (os .path .join (pyscript_dir , path , match ))):
276+ for this_path in sorted (glob .glob (os .path .join (pyscript_dir , path , match ), recursive = True )):
277277 rel_import_path = None
278- elts = this_path .split ("/" )
279- if match .find ("/" ) < 0 :
280- # last entry without the .py
281- mod_name = elts [- 1 ][0 :- 3 ]
282- else :
283- # 2nd last entry
284- mod_name = elts [- 2 ]
285- rel_import_path = f"{ path } /mod_name"
278+ rel_path = this_path
279+ if rel_path .startswith (pyscript_dir ):
280+ rel_path = rel_path [len (pyscript_dir ) :]
281+ if rel_path .startswith ("/" ):
282+ rel_path = rel_path [1 :]
283+ if rel_path [0 ] == "#" or rel_path .find ("/#" ) >= 0 :
284+ continue
285+ rel_path = rel_path [0 :- 3 ]
286+ if rel_path .endswith ("/__init__" ):
287+ rel_path = rel_path [0 : - len ("/__init__" )]
288+ rel_import_path = rel_path
289+ mod_name = rel_path .replace ("/" , "." )
286290 if path == "" :
287291 global_ctx_name = f"file.{ mod_name } "
288292 fq_mod_name = mod_name
289293 else :
290- global_ctx_name = f"{ path } .{ mod_name } "
291- fq_mod_name = global_ctx_name
294+ fq_mod_name = global_ctx_name = mod_name
295+ i = fq_mod_name .find ("." )
296+ if i >= 0 :
297+ fq_mod_name = fq_mod_name [i + 1 :]
292298 if check_config :
293- if not isinstance (apps_config , dict ) or mod_name not in apps_config :
299+ if not isinstance (apps_config , dict ) or fq_mod_name not in apps_config :
294300 _LOGGER .debug ("load_scripts: skipping %s because config not present" , this_path )
295301 continue
296302 source_files .append ([global_ctx_name , this_path , rel_import_path , fq_mod_name ])
303+
297304 return source_files
298305
299306 load_paths = [
300307 ["apps" , "*.py" , True ],
301308 ["apps" , "*/__init__.py" , True ],
302309 ["" , "*.py" , False ],
310+ ["scripts" , "**/*.py" , False ],
303311 ]
304312
305313 source_files = await hass .async_add_executor_job (glob_files , load_paths , data )
0 commit comments