Skip to main content

Module Discovery Utils

Motivation

A simple library to make it easier to dynamically find and discover objects from a predefined set of packages.

There is often a pattern used in python where subclasses of an object are defined, and by virtua of being a subclass, those objects are either directly or indirectly added to a registry.

Examples of this are Flask routes, and Sqlalchemy tables.

This is all well and good, but the problem is, you need to import those modules to register them. A common solution is to create a registry file of sorts, sometimes in the init.py file.

Often, you have a significant number of classes, and are frequently adding new ones, or removing old ones. However, maintaining a single file that imports all of them can be cumbersome, and falls afoul of python style rules and formatting tools, as the imports are technically not used in the registry file.

Thus, using python's importlib, pkgutils, and introspection tools, there are a number of ways to dynamically scan a package, load all submodules, and parse out objects of interest.

I have implemented and reimplemented this sort of code many, many times, and I hope I can prevent others from doing the same in the future.

Usage

To recursively import all modules in a group of packages:

from module_discovery_utils import load_all_modules_in_packages
from blah import package, package2

load_all_modules_in_packages(package)
load_all_modules_in_packages(package2)

OR

from module_discovery_utils import load_all_modules_in_packages
from blah import package, package2

load_all_modules_in_packages([package, package2])

To find all subclasses in a package:

from module_discovery_utils import find_subclasses_in_packages
from blah import package, package2, BaseClass1, BaseClass2

find_subclasses_in_packages([package, package2], [BaseClass1, BaseClass2])

You can also technically do:

from module_discovery_utils import load_all_modules_in_packages
from blah import package, package2, BaseClass

load_all_modules_in_packages([package, package2])
subclasses = BaseClass.__subclasses__()

However, the problem I have with that solution is there are cases (such as testing) where you may not want to retrieve all defined subclasses.

It's pratically impossible to control what gets imported when in a python program, and you don't want to potentially rely on import order, or imports from other parts of the program to determine which subclasses are "visible" at any given time.

To find all instances of a given base class in a given set of packages:

from module_discovery_utils import find_instances_in_packages
from blah import package, package2, BaseClass1, BaseClass2

find_instances_in_packages([package, package2], [BaseClass1, BaseClass2])

Metadata

Release files for module-discovery-utils 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for module-discovery-utils 1.1.1
File Size Uploaded Provenance Actions
module-discovery-utils-1.1.1.tar.gz 4.0 kB Without provenance Details for module-discovery-utils-1.1.1.tar.gz

Release files / module-discovery-utils-1.1.1.tar.gz

Download URL module-discovery-utils-1.1.1.tar.gz
Size 4.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e02a9873a1aa105e893934d4365cd2606996a64c56a45e9c6e6f4faf955f5e7b
BLAKE2b-256 checksum
How to use checksums
c117c0e2a407f736e349962f18ac2ac797b7160ac14e99a9a6272f60f76be988
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.5.0 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.0

Security for module-discovery-utils 1.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.1.1 This release

1 release file No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page