44
55from __future__ import annotations
66
7+ from importlib import import_module
78from pathlib import Path
8- from typing import Callable , Union
9+ from typing import Callable
910
1011from digitalhub .stores .data .api import get_store
1112from digitalhub .utils .generic_utils import (
1920from digitalhub .utils .uri_utils import (
2021 get_filename_from_uri ,
2122 has_git_scheme ,
22- has_local_scheme ,
2323 has_remote_scheme ,
2424 has_s3_scheme ,
2525 has_zip_scheme ,
26+ has_local_scheme
2627)
2728
2829DEFAULT_PY_FILE = "main.py"
@@ -276,52 +277,43 @@ def save_function_source(path: Path, source_spec: dict) -> Path:
276277 raise RuntimeError (f"Unable to collect source from: { source } " )
277278
278279
279- def _get_func_path_remote ( source_path : Path , source_spec : dict ) -> tuple [Path , str ]:
280+ def _get_function_to_import ( handler : str , source_code : str | None ) -> tuple [str , str ]:
280281 """
281- Get function path and name from handler for remote execution .
282+ Get function name from handler string .
282283
283284 Parameters
284285 ----------
285- source_path : Path
286- Root path where the function source is located .
287- source_spec : dict
288- Function source spec .
286+ handler : str
287+ Function handler in format 'module: function' or 'path.to.module:function' .
288+ source_code : str | None
289+ Source code (used to infer function name if handler is just a function name) .
289290
290291 Returns
291292 -------
292- tuple[Path, str]
293- Function path and function name.
293+ tuple
294+ Function module and function name.
294295 """
295- handler_path , function_name = _parse_handler (source_spec .get ("handler" ))
296-
297- # If no handler path, try to get from source
298- if handler_path == Path ("" ):
299- # If source is None (e.g. whan code is inline), use default main.py
300- if (source := source_spec .get ("source" )) is None :
301- return source_path / Path (DEFAULT_PY_FILE ), function_name
302-
303- # If source has local scheme, use it directly
304- if has_local_scheme (source ):
305- return source_path / Path (source ), function_name
306-
307- # Otherwise, use default main.py
308- return source_path / Path (DEFAULT_PY_FILE ), function_name
296+ # If handler is not specified, assume function module is in main
297+ try :
298+ function_module , function_name = handler .split (":" )
299+ except ValueError :
300+ function_name = handler
301+ if source_code is not None and has_local_scheme (source_code ):
302+ function_module = get_filename_from_uri (source_code ).removesuffix (".py" )
303+ else :
304+ function_module = DEFAULT_PY_FILE .removesuffix (".py" )
309305
310- # If handler path is given, use it
311- return (source_path / handler_path ).with_suffix (".py" ), function_name
306+ return function_module , function_name
312307
313308
314309def import_function_and_init_from_source (
315- path : Path ,
316310 source_spec : dict ,
317- ) -> tuple [Callable , Union [ Callable , None ] ]:
311+ ) -> tuple [Callable , Callable | None ]:
318312 """
319313 Import main function and optional init function from source.
320314
321315 Parameters
322316 ----------
323- path : Path
324- Root path where the function source is downloaded.
325317 source_spec : dict
326318 Function source spec.
327319
@@ -330,14 +322,19 @@ def import_function_and_init_from_source(
330322 tuple
331323 Main function and optional init function.
332324 """
333- # Get function path and import main function
334- function_path , handler_name = _get_func_path_remote (path , source_spec )
335- main_function = _import_function_from_path (function_path , handler_name )
325+ handler = source_spec .get ("handler" )
326+ source_code = source_spec .get ("source" )
327+
328+ function_module , function_name = _get_function_to_import (handler , source_code )
329+
330+ # Import module and get main function
331+ module = import_module (function_module )
332+ main_function = getattr (module , function_name )
336333
337334 # Import init function if specified
338335 init_function : Callable | None = None
339336 init_handler : str | None = source_spec .get ("init_function" )
340337 if init_handler is not None :
341- init_function = _import_function_from_path ( function_path , init_handler )
338+ init_function = getattr ( module , init_handler )
342339
343340 return main_function , init_function
0 commit comments