Architecture¶
Import-graph assertables. See the Architecture guide for examples.
pyssertive.arch.AssertableArch ¶
Fluent architecture assertions over a single module's import graph.
Created via :func:pyssertive.arch.assert_arch. Each method either
returns self (for chaining) or raises AssertionError with a
message that lists every offending dependency.
Three assertion families:
should_depend_on— reachability check; the source must import the target directly or transitively (directly=Trueto require a direct edge).should_not_depend_on— forbidden-import check; the source must not import the target by any path (directly=Trueto ignore transitive paths).should_only_depend_on— allow-list check; every dependency of the source must match an entry in the list. Direct imports by default; passdirectly=Falsefor transitive purity rules. The literal"stdlib"is a magic token expanding to any Python standard library top-level module.
ignoring(patterns) accepts fnmatch glob patterns used to
grandfather known violations. Patterns apply to chain traversals
(the chain BFS skips matching modules so an alternate non-ignored
path is still detected) and to the violation list of
should_only_depend_on (matching dependencies are filtered out).
Source and target modules are validated against the import graph;
typos and unsupported external submodule paths raise ValueError
with a "Did you mean ...?" hint when a close match exists.
Source code in src/pyssertive/arch/assertable.py
ignoring ¶
ignoring(patterns: str | list[str]) -> AssertableArch
Add fnmatch glob patterns excluded from chain checks and dependency lists.
Patterns accumulate across successive calls on the same assertable.
Each assert_arch(...) invocation starts with an empty ignore list,
so scoping is per-assertion-chain — there is no shared state between
tests. Use a fresh assert_arch(...) to start over.
Source code in src/pyssertive/arch/assertable.py
module ¶
module(
name: str,
callback: Callable[
[AssertableArch | AssertableMultiArch], object
]
| None = None,
) -> AssertableArch | AssertableMultiArch
Scope into a submodule, returning an assertable bound to it.
name is resolved relative to the current scope unless it
already starts with the parent path. Glob patterns are
expanded against the graph. With a callback the nested
assertable is passed to it and the outer scope is returned
for continued chaining; without one the nested assertable is
returned directly.
Source code in src/pyssertive/arch/assertable.py
should_depend_on ¶
should_depend_on(
target: str | list[str], directly: bool = False
) -> AssertableArch
Assert the source imports each target directly or transitively.
directly=True requires a direct import edge — useful when
the source must own the import explicitly rather than picking
it up via a re-export.
Source code in src/pyssertive/arch/assertable.py
should_not_depend_on ¶
should_not_depend_on(
target: str | list[str], directly: bool = False
) -> AssertableArch
Assert the source does not import any target, direct or transitive.
directly=True only forbids direct imports; transitive
paths through other modules are tolerated. Useful when the
rule is "you must not write the import yourself" but reaching
the target via an intermediate is acceptable.
Source code in src/pyssertive/arch/assertable.py
should_only_depend_on ¶
should_only_depend_on(
allowed: str | list[str], directly: bool = True
) -> AssertableArch
Assert every dependency of the source matches an entry in allowed.
Direct imports by default — what the module's source code
actually uses. directly=False extends the check to the
transitive closure for stricter purity rules (e.g. domain
code must not transitively reach Django through any helper).
Source code in src/pyssertive/arch/assertable.py
pyssertive.arch.AssertableLayers ¶
Fluent layered-architecture assertion.
Constructed via assert_arch.layers. Each entry is a package or
single-file module treated as a layer, ordered from lowest
(foundational, no dependencies on layers above) to highest. The
should_be_independent check enforces that no layer imports any
layer that follows it in the list, direct or transitive.
ignoring(patterns) accepts fnmatch glob patterns that are
skipped during chain traversal so legacy violations can be
grandfathered. An alternate non-ignored path still triggers the
assertion, matching the semantic used elsewhere in the package.
Source code in src/pyssertive/arch/assertable.py
ignoring ¶
ignoring(patterns: str | list[str]) -> AssertableLayers
Add fnmatch glob patterns excluded from chain traversal.
Patterns accumulate; the list is per-instance, not global.
Source code in src/pyssertive/arch/assertable.py
should_be_independent ¶
should_be_independent() -> AssertableLayers
Assert each layer only depends on layers preceding it in the list.
Source code in src/pyssertive/arch/assertable.py
pyssertive.arch.AssertableModules ¶
Fluent isolation assertion across an unordered set of modules.
Constructed via assert_arch.modules. Each entry is a package
or module that should not depend on any of the others, in either
direction. should_be_isolated flags any cross-import; pair
ignoring(patterns) with it to grandfather permitted bridges
such as published events modules.
Source code in src/pyssertive/arch/assertable.py
ignoring ¶
ignoring(patterns: str | list[str]) -> AssertableModules
Add fnmatch glob patterns excluded from cross-import detection.
Patterns accumulate; the list is per-instance, not global.
Source code in src/pyssertive/arch/assertable.py
should_be_isolated ¶
should_be_isolated() -> AssertableModules
Assert no module in the set imports any other, direct or transitive.
Source code in src/pyssertive/arch/assertable.py
pyssertive.arch.AssertableMultiArch ¶
Wraps several :class:AssertableArch instances obtained by glob-expanding
a source pattern. Each public method dispatches to every member and
aggregates any AssertionErrors into a single message so callers see every
failing source at once.
Source code in src/pyssertive/arch/assertable.py
ignoring ¶
ignoring(patterns: str | list[str]) -> AssertableMultiArch
should_depend_on ¶
should_depend_on(
target: str | list[str], directly: bool = False
) -> AssertableMultiArch
should_not_depend_on ¶
should_not_depend_on(
target: str | list[str], directly: bool = False
) -> AssertableMultiArch
should_only_depend_on ¶
should_only_depend_on(
allowed: str | list[str], directly: bool = True
) -> AssertableMultiArch
module ¶
module(
name: str,
callback: Callable[
[AssertableArch | AssertableMultiArch], object
]
| None = None,
) -> AssertableArch | AssertableMultiArch
Descend each member into name, returning a flattened multi or invoking the callback.