Package: autoload-module
autoload_moduleThis library will give you comfortable Python metaprogramming.The following is a plain example.Directoryproject/
 ├ example.py
 └ validator/
   ├ validator_a.py
   ├ validator_b.py
   └ validator_c.pyexample.pyfromautoloadimportModuleLoaderinput="foo bar baz"loader=ModuleLoader()# Automatically import modules and return class objectsvalidator_classes=loader.load_classes("validator")try:# initialize and execute method[clazz().validate(input)forclazzinvalidator_classes]except:print("input is invalid!!")Installpip install autoload-moduleUsageConstructorModuleLoader(
  base_path: Optional[str] = None,
  strict: bool = False
)The ModuleLoader can be generated with no parameters.
In that case, the instance has the absolute path where
it was initialized.Directory/usr/local/src/project/
  ├ example.py
  └ validator/
    ├ validator_a.py
    ├ validator_b.py
    └ validator_c.pyexample.pyfromautoloadimportModuleLoader# The instance has '/usr/local/src/project/'loader=ModuleLoader()# load modules in the directory; '/usr/local/src/project/validator/'validator_classes=loader.load_classes("validator")If you want to change the base path, you must generate the ModuleLoader with an absolute path parameter.loader=ModuleLoader('/user/local/src/custom')About strict parameter, please seehere.You can also create global setting and initialize singleton object.fromautoloadimportModuleLoaderimportos# global settingModuleLoader.set_setting(base_path=os.getcwd(),strict=True)loader_a=ModuleLoader()loader_b=ModuleLoader()print(loader_a.base_path)# -> /Users/user1/abcprint(loader_b.base_path)# -> /Users/user1/abc# singleton settingModuleLoader.set_setting(singleton=True)loader_c=ModuleLoader()loader_d=ModuleLoader()loader_e=ModuleLoader('/test')assertloader_cisloader_d# OKassertloader_cisloader_e# OK# The base_path is '/Users/user1/abc'assertloader_c.base_pathisloader_e.base_path# OKMethodsload_classesload_classes(
    src: str,
    excludes: Iterable[str] = (),
    recursive: bool = False,
) -> Tuple[Type, ...]:This method read the Python package or module and return the tuple of class objects.Directorypkg/
 ├ example.py
 ├ __init__.py
 ├ config.yaml
 └ main/
     ├ validator_a.py
     ├ validator_b.py
     ├ validator_c.py
     └ sub/
        ├ validator_d.py
        └ validator_e.pyvalidator_a.pyclassValidatorA:defvalidate(self):print("validateA!!")example.pyloader=ModuleLoader()# Automatically read modules without '__init__.py', not py file, and this file.# return the tuple of ValidateA, ValidatorB, and ValidatorC class objectsvalidator_classes=loader.load_classes("main")# initialize and execute method[clazz().validate()forclazzinvalidator_classes]# -> validateA!!# -> validateB!!# -> validateC!!You can also load only specific modules usingexcludesvariable orload_configdecorator as below.# Pattern1: 'excludes'# 'excludes' is a iterable object like tuple, list.# You must specify module names in 'excludes'.validator_classes=loader.load_classes("main",["validator_a"])[clazz().validate()forclazzinvalidator_classes]# -> validateB!!# -> validateC!!# Pattern2: 'load_config'fromautoloadimportload_config@load_config(load=False)classValidatorA:defvalidate(self):print("validateA!!")validator_classes=loader.load_classes("main")[clazz().validate()forclazzinvalidator_classes]# -> validateB!!# -> validateC!!This function will check directory structure recursively if you specifyrecursive=True.# 'recursive=False' is default.# In this case, the loader will also check 'pkg/main/sub/'.validator_classes=loader.load_classes("main",recursive=True)[clazz().validate()forclazzinvalidator_classes]# -> validateA!!# -> validateB!!# -> validateC!!# -> validateD!!# -> validateE!!You can specifysrcas below.loader.load_classes("main/validator_a.py")loader.load_classes("main.validator_a")loader.load_classes("./main/validator_a")loader.load_classes(".main.validator_a")loader.load_classes("main.sub.validator_d")loader.load_classes("./main/sub/validator_d")loader.load_classes("../otherpkg")loader.load_classes("..otherpkg")load_functionsload_functions(
    src: str,
    excludes: Iterable[str] = (),
    recursive: bool = False,
) -> Tuple[Callable, ...]:This method read the Python package or module and return the tuple of functions.
The usage is the same asload_classes.NOTETo search class or function,You must match the name of file, and the one of class or function.For example, if you named the filetest_module.py, you must name the classTestModuleor the functiontest_module.
When you want to customize their name, use@load_configdecorator.validator_a.pyfromautoloadimportload_config@load_config()classCustomValidator:defvalidate(self):print("validateA!!")You can also control the order of loaded class objects using@load_configdecorator.validator_a.pyfromautoloadimportload_config# sort in ascending order@load_config(order=1)classValidatorA:defvalidate(self):print("validateA!!")If you decorate some classes or functions with@load_config, the loader will load them.
However, initializedstrict=True, the loader denies multiple loading as below.pkg/validator_a.pyfromautoloadimportload_config# This will be loaded because of name's rule.classValidatorA:defvalidate(self):print("validateA!!")# Anything goes.@load_config(order=2)classFoo:passmain.pyfromautoloadimportModuleLoaderfromautoload.exceptionimportLoaderStrictModeErrorloader=ModuleLoader()# return ValidatorA and Foo class objects.classes=loader.load_classes("pkg")# ModuleLoader strictly try to load a class or function object# per a Python module on a basis of its name.strict_loader=ModuleLoader(strict=True)try:classes=strict_loader.load_classes("pkg")exceptLoaderStrictModeErrorase:print(e)# -> Loader can only load a 'ValidatorA' class in validator_a module.# -> Please check 'Foo' in validator_a module.load_classload_class(file_name: str)This method read the Python file and return the class object.Directoryproject/
  ├ example.py
  └ validator.pyvalidator.pyclassValidator:defvalidate(self):print("validate!!")example.pyloader=ModuleLoader()clazz=loader.load_class("validator")clazz().validate()# -> validate!!How to specifyfile_nameis the same as that ofload_classes.load_functionload_function(file_name: str)This method read the Python file and return a function object.
The usage is the same asload_class.LicenseReleased under the MIT license.