Skip to content

Modules

Functions dealing with modules and imports.


as_module_type

as_module_type(package)

Convert a package name or module to a ModuleType.

Parameters:

Name Type Description Default
package str | ModuleType

A module object or a fully qualified module name string.

required

Returns:

Type Description
ModuleType

The corresponding ModuleType instance.

Source code in src/aibs_informatics_core/utils/modules.py
19
20
21
22
23
24
25
26
27
28
def as_module_type(package: str | ModuleType) -> ModuleType:
    """Convert a package name or module to a ``ModuleType``.

    Args:
        package: A module object or a fully qualified module name string.

    Returns:
        The corresponding ``ModuleType`` instance.
    """
    return package if isinstance(package, ModuleType) else importlib.import_module(package)

get_all_subclasses

get_all_subclasses(cls, ignore_abstract=False)

Get all loaded subclasses of a given class

Parameters:

Name Type Description Default
cls type[T]

class object

required
ignore_abstract bool

boolean to filter out abstract classes

False

Returns:

Type Description
list

all subclasses imported into python

Source code in src/aibs_informatics_core/utils/modules.py
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def get_all_subclasses(cls: type[T], ignore_abstract: bool = False) -> list[type[T]]:
    """Get all loaded subclasses of a given class

    Args:
        cls: class object
        ignore_abstract (bool): boolean to filter out abstract classes

    Returns:
        (list): all subclasses imported into python

    """
    subclasses = cls.__subclasses__() + [
        g for sub_cls in cls.__subclasses__() for g in get_all_subclasses(sub_cls)
    ]
    return [
        subclass
        for subclass in subclasses
        if not ignore_abstract or not inspect.isabstract(subclass)
    ]

get_qualified_name

get_qualified_name(obj)

Returns the fully qualified name of the object provided.

Resources: - PEP 3155 for qualified name https://peps.python.org/pep-3155/ - solution from https://stackoverflow.com/questions/2020014/get-fully-qualified-class-name-of-an-object-in-python

Parameters:

Name Type Description Default
obj Any

variable to get qualified name of (class, function, object etc.)

required

Returns:

Type Description
str

fully qualified name of object

Source code in src/aibs_informatics_core/utils/modules.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
def get_qualified_name(obj: Any) -> str:
    """Returns the fully qualified name of the object provided.

    Resources:
    - PEP 3155 for qualified name https://peps.python.org/pep-3155/
    - solution from https://stackoverflow.com/questions/2020014/get-fully-qualified-class-name-of-an-object-in-python

    Args:
        obj (Any): variable to get qualified name of (class, function, object etc.)

    Returns:
        fully qualified name of object
    """
    try:
        # if obj is a class or function, get module directly
        module = obj.__module__
    except AttributeError:
        # then get module from o's class
        module = obj.__class__.__module__
    try:
        # if o is a class or function, get name directly
        name = obj.__qualname__
    except AttributeError:
        # then get o's class name
        name = obj.__class__.__qualname__ if not isinstance(obj, ModuleType) else obj.__name__
    # if o is a method of builtin class, then module will be None
    if module == "builtins" or module is None:
        return name
    return module + "." + name

load_all_modules_from_pkg

load_all_modules_from_pkg(
    package, recursive=True, include_packages=False
)

Import all modules found within the package

Parameters:

Name Type Description Default
package (string_types, module)

imported module or string name of module

required
recursive bool

whether to recursively import modules.

True
include_packages bool

whether to include packages in results

False

Returns: (dict): mapping of package/module to module

Source code in src/aibs_informatics_core/utils/modules.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
def load_all_modules_from_pkg(
    package: str | ModuleType,
    recursive: bool = True,
    include_packages: bool = False,
) -> dict:
    """
    Import all modules found within the package

    Args:
        package (string_types, module): imported module or string name of module
        recursive (bool): whether to recursively import modules.
        include_packages (bool): whether to include packages in results
    Returns:
        (dict): mapping of package/module to module
    """
    mod_type_package: ModuleType = as_module_type(package)
    # If package is actually a module, then return as is.
    if not hasattr(mod_type_package, "__path__"):
        return {mod_type_package.__package__: mod_type_package}
    results = {}
    for loader, name, is_pkg in pkgutil.walk_packages(mod_type_package.__path__):  # type: ignore  # mypy issue #1422
        full_name = mod_type_package.__name__ + "." + name
        if include_packages or not is_pkg:
            results[full_name] = importlib.import_module(full_name)
        if recursive and is_pkg:
            results.update(
                load_all_modules_from_pkg(
                    full_name, recursive=recursive, include_packages=include_packages
                )
            )
    return results

load_type_from_qualified_name

load_type_from_qualified_name(
    qualified_name: str, expected_type: type[T]
) -> T
load_type_from_qualified_name(
    qualified_name: str, expected_type: Literal[None] = None
) -> Any
load_type_from_qualified_name(
    qualified_name, expected_type=None
)

Load a type from its fully qualified name

Parameters:

Name Type Description Default
qualified_name str

fully qualified name of type

required

Returns:

Type Description
type

type object

Source code in src/aibs_informatics_core/utils/modules.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def load_type_from_qualified_name(
    qualified_name: str, expected_type: type[T] | None = None
) -> Any | T:
    """Load a type from its fully qualified name

    Args:
        qualified_name (str): fully qualified name of type

    Returns:
        (type): type object
    """
    if "." not in qualified_name:
        module_name = "builtins"
        type_name = qualified_name
    else:
        module_name, type_name = qualified_name.rsplit(".", 1)
    module = as_module_type(module_name)
    if not hasattr(module, type_name):
        raise ValueError(f"Unable to find type {type_name} in module {module_name}")
    loaded_type = getattr(module, type_name)
    if expected_type is not None and not issubclass(loaded_type, expected_type):
        raise ValueError(
            f"Loaded type {loaded_type} is not a subclass of expected type {expected_type}"
        )
    return loaded_type