Javelina/modules/extensions_loader.py
2024-02-04 00:55:51 +01:00

77 lines
2.2 KiB
Python

from importlib.util import module_from_spec, spec_from_file_location
import logging
from os import getcwd, walk
from pathlib import Path
from types import ModuleType
from typing import List, Union
logger = logging.getLogger(__name__)
# Import functions
# Took from https://stackoverflow.com/a/57892961
def get_py_files(src: Union[str, Path]) -> List[str]:
cwd = getcwd() # Current Working directory
py_files = []
for root, dirs, files in walk(src):
py_files.extend(
Path(f"{cwd}/{root}/{file}") for file in files if file.endswith(".py")
)
return py_files
def dynamic_import(module_name: str, py_path: str) -> Union[ModuleType, None]:
try:
module_spec = spec_from_file_location(module_name, py_path)
if module_spec is None:
raise RuntimeError(
f"Module spec from module name {module_name} and path {py_path} is None"
)
module = module_from_spec(module_spec)
if module_spec.loader is None:
logger.warning(
"Could not load extension %s due to spec loader being None.",
module_name,
)
return
module_spec.loader.exec_module(module)
return module
except SyntaxError:
logger.warning(
"Could not load extension %s due to invalid syntax. Check logs/errors.log for details.",
module_name,
)
return
except Exception as exc:
logger.warning("Could not load extension %s due to %s", module_name, exc)
return
def dynamic_import_from_src(src: Union[str, Path], star_import=False) -> None:
my_py_files = get_py_files(src)
for py_file in my_py_files:
module_name = Path(py_file).stem
logger.debug("Importing %s extension...", module_name)
imported_module = dynamic_import(module_name, py_file)
if imported_module != None:
if star_import:
for obj in dir(imported_module):
globals()[obj] = imported_module.__dict__[obj]
else:
globals()[module_name] = imported_module
logger.info("Successfully loaded %s extension", module_name)
return