Skip to content

Core API

The primary API entrypoint is the deescovery.discover function.

IRule

Generic type for a discovery rule.

Normally, you use one of its subclasses: ModuleRule or ObjectRule

ModuleRule dataclass

Do something with all modules matching the rule.

For each module, found by deescovery.discover, the rule decides if it should be processed (calls module_matcher), and if the result is positive, calls module_action.

Example:

Import all controllers.py of the project.

from importlib import import_module
from flask import Flask, Blueprint
from deescovery import discover, ModuleRule
from deescovery.matchers import MatchByPattern, MatchByType

app = Flask(__name__)

controller_loader = ModuleRule(
    name="Flask blueprints loader",
    module_matches=MatchByPattern(["*.controllers"]),
    module_action=import_module,
)

discover("myapp", [controller_loader])

Attributes:

Name Type Description
name str

the rule name. Used for logging purposes.

module_matches Callable[[str], bool]

a callable (function) that takes the module name and returns True if the module should be processed. You can write your own ad-hoc function, or use a deescovery.matchers.MatchByPattern class.

module_action Callable[[str], Any]

a callable (function) that takes the module name. The action will only be executed if the module matches the pre-condition of module_matches. The most common action is importing the module to execute its content. For example, you can use it to register all API controllers that the module contains and defines with decorators.

ObjectRule dataclass

Do something with all objects, matching the rules.

For each module, found by deescovery.discover, the rule decides if the module should be processed (calls module_matches). If the result is positive, the module is imported, and all its members are inspected with object_matches. If the returned value of the object matcher is also True, calls object_action.

Example:

Find all Flask blueprints in the files controllers.py of the project and register them in the Flask application.

from flask import Flask, Blueprint
from deescovery import discover, ObjectRule
from deescovery.matchers import MatchByPattern, MatchByType

app = Flask(__name__)

blueprints_loader = ObjectRule(
    name="Flask blueprints loader",
    module_matches=MatchByPattern(["*.controllers"]),
    object_matches=MatchByType(Blueprint),
    object_action=app.register_blueprint,
)

discover("myapp", [blueprints_loader])

Attributes:

Name Type Description
name str

the rule name. Used for logging purposes.

module_matches Callable[[str], bool]

a callable (function) that takes the module name and returns True if objects of the module should be inspected further with object_matches. You can write your own ad-hoc function or use a deescovery.matchers.MatchByPattern class.

object_matches Callable[[Any], bool]

a callable (function) that takes the object and returns True if the object should be processed with object_action. You can write your own ad-hoc function or use one of the classes defined in the deescovery.matchers module.

object_action Callable[[Any], Any]

a callable (function) that takes the found object. The action will only be executed when the object's module pre-condition passes the module_matches test, and object itself passes the pre-condition of object_matches.

discover(import_path: str, rules: List[deescovery.discovery.IRule])

Discover all objects.

Scan the package, find all modules and objects, matching the given set of rules, and apply actions defined in them.

Parameters:

Name Type Description Default
import_path str

top-level module name to start scanning. Usually, it's a name of your application, e.g., "myapp". If your application doesn't have a single top-level module, you will probably call it for all top-level modules.

required
rules List[deescovery.discovery.IRule]

a list of module and objects rules. Each rule contains the match specification and the action, if the object matches. Normally, it's a list IRule subclasses: ModuleRule or ObjectRule.

required