Skip to content

Instantly share code, notes, and snippets.

@shawnohare
Last active August 1, 2018 22:56
Show Gist options
  • Save shawnohare/a146d8580020c5ad91cf37c94535d295 to your computer and use it in GitHub Desktop.
Save shawnohare/a146d8580020c5ad91cf37c94535d295 to your computer and use it in GitHub Desktop.
Get all modules from a package.
import inspect
import pkgutil
from importlib import import_module
def get_package_modules(package):
"""Recursively get all modules of a package, including modules of any
subpackages.
"""
modules = []
for _, name, ispkg in pkgutil.iter_modules(package.__path__):
mod = import_module('.' + name, package=package.__name__)
# Include package modules in the list to inspect what might be defined there.
modules.append(mod)
if ispkg:
modules.extend(_get_package_modules(mod))
return modules
def get_defined_subclasses(module, cls):
"""Get any subclasses that are defined in the specified module.
This can include the class itself.
Args:
module (module): Module instance to inspect.
cls (class): Class to find subclasses of.
Returns:
list(class): List of subclasses defined in the module.
"""
def ok(member):
return (
inspect.isclass(member) and
member.__module__ == module.__name__ and
issubclass(member, cls) and
)
return [m for _, m in inspect.getmembers(module, ok)]
def subclasses(cls, module=None):
"""Finds subclasses of given class and returns as a :py:class:`dict`
of subclass name key to its class object value. Subclasses are
looked for within the same package where ``cls`` is defined, or within
a specific module when ``module`` is provided.
Args:
cls (class): Class to find subclasses of.
module (str or module): A module instance to inspect. Only classes defined
in the module are included.
"""
ispkg = lambda mod: hasattr(mod, '__path__')
# Look in either the specified module or the package containing cls.
module = import_module(module) if isinstance(module, basestring) else module
if module is not None:
modules = _get_package_modules(module) if ispkg(module) else [module]
else:
# Look at all modules in the top-most package containing cls.
package_name = cls.__module__.split('.', 1)[0]
modules = _get_package_modules(import_module(package_name))
subclasses = []
for module in modules:
subclasses.extend(get_defined_subclasses(module))
return subclasses
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment