77 lines
2.2 KiB
Python
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
|