We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Modules, Packaging and Tooling step 14 of 41
Check That Imports Follow Your Layers
Write the check from the article. Given each module's layer and the imports between modules, report every import that points outward, from an inner layer to an outer one. The imports arrive as plain data.
def check_layering(
module_layers: Mapping[str, str],
layer_order: Sequence[str],
imports: Mapping[str, Sequence[str]],
) -> list[tuple[str, str]]:
...
module_layersmaps a module name to its layer name.layer_orderlists the layers from innermost to outermost, such as["domain", "application", "adapters", "entrypoints"].importsmaps a module to the modules it imports directly.
layers = {"domain.money": "domain", "app.quote": "application",
"adapters.db": "adapters"}
order = ["domain", "application", "adapters"]
check_layering(layers, order, {
"app.quote": ["domain.money", "adapters.db", "adapters.db"],
"domain.money": ["app.quote"],
})
# [("app.quote", "adapters.db"), ("domain.money", "app.quote")]
check_layering(layers, order, {"domain.money": ["sqlite3"]}) # []
check_layering(layers, [], {"domain.money": ["adapters.db"]}) # []
Rules
- A layer's rank is its index in
layer_order. If a layer name appears twice, use its last index. - Report
(importer, imported)when the imported module's rank is strictly greater than the importer's. Do not report an import inward, within one layer, or of a module by itself. - Skip an import if either module is missing from
module_layers, or if either module's layer is missing fromlayer_order. An emptylayer_ordertherefore gives no findings. - Match module names exactly. Names are case-sensitive, and an entry for
"domain"inmodule_layersdoes not cover"domain.money". - A module with no entry in
importsimports nothing. - Report each pair once, and return the pairs sorted with normal tuple ordering, so by importer and then by imported module.
- Do not change the inputs.
The sqlite3 example returns [] because sqlite3 has no layer. If your
design bans some third-party packages from the domain, that needs a separate
rule.
The starter compares layer names instead of ranks, raises KeyError on an
unknown module, and keeps duplicate pairs. Fix all three. Your solution must
pass mypy --strict. module_layers.get() returns None for a module to
skip, so check for None before you compare.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.