Skip to content

Instantly share code, notes, and snippets.

@tombulled
Last active April 30, 2020 21:26
Show Gist options
  • Save tombulled/5115d241164f7ed9e351db1a67e258d8 to your computer and use it in GitHub Desktop.
Save tombulled/5115d241164f7ed9e351db1a67e258d8 to your computer and use it in GitHub Desktop.
Python3: Automatically attempt to import relative modules
'''
Module containing the utility function: include
'''
import pkgutil
import importlib
import sys
from typing import Callable
from _frozen_importlib import ModuleSpec
def include(spec: ModuleSpec, func: Callable = None) -> dict:
'''
Include relative libraries, or an object they contain.
If a relative library exists with an object of the same name inside,
it returns that object, otherwise, it returns the library. Libraries
or objects are only returned if func(module_name) is true.
Args:
spec: The specification of the module to import from
Example: utils.__spec__
func: A function to filter items by
Example: lambda module_name: module_name.endswith('.foo')
Returns:
A dictionary of imported libraries or objects
Example:
Package named utils containing foo.py, with a function inside named foo:
>>> include(utils.__spec__)
{'foo': <function foo at 0x0000027A533CE790>}
>>>
Package named utils containing foo.py with a function inside named bar:
>>> include(utils.__spec__)
<module 'utils.foo' from '/path/to/utils/foo.py'>
>>>
'''
if not func:
func = lambda module_name: True
importlib.util.module_from_spec(spec)
module = sys.modules[spec.name]
sub_modules = pkgutil.iter_modules(spec.submodule_search_locations)
imported = {}
for sub_module in sub_modules:
sub_module_name = sub_module.name
if not func(sub_module_name): continue
sub_module = importlib.import_module \
(
name = f'.{sub_module_name}',
package = spec.name,
)
object = getattr(sub_module, sub_module_name, None) or sub_module
setattr(module, sub_module_name, object)
imported[sub_module_name] = object
return imported
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment