Skip to main content

pytest-archon

build_and_test

pytest-archon is a little tool that helps you structure (large) Python projects. This tool allows you to define architectural boundaries in your code, also known as forbidden dependencies.

Explicitly defined architectural boundaries helps you keep your code in shape. It avoids the creation of circular dependencies. New people on the project are made aware of the structure through a simple set of rules, instead of lore.

Installation

The simple way:

pip install pytest-archon

Usage

pytest-archon can be used to define architectural boundaries from (unit) tests. Because they're tests, they can be closely tied to the actual application.

You can use pytest-archon in tests by simply importing the archrule function. Using this function you can construct import tests:

from pytest_archon import archrule


def test_rule_basic():
    (
        archrule("name", comment="some comment")
        .match("pytest_archon.col*")
        .exclude("pytest_archon.colgate")
        .should_not_import("pytest_archon.import_finder")
        .should_import("pytest_archon.core*")
        .check("pytest_archon")
    )
  • To match the modules and constraints, fnmatch syntax is used (the default). You can also use regular expressions by supplying the use_regex=True argument to archrule(). Example: archrule(..., use_regex=True).match(...).
  • .exclude() is optional
  • .should_import() and .should_not_import() can be combined and can occur multiple times.
  • .may_import() can be used in combination with .should_not_import().
  • .check() needs either a module object or a string

The check() method can have a few optional parameters, that alter the way the checks are performed.

  • Without parameters, the whole file is checked for imports. So imports done in functions and methods are also found. Transitive dependencies are also checked
  • Option only_toplevel_imports=True will only check for toplevel imports. Conditional imports and import in functions and methods are ignored.
  • skip_type_checking=True will check all imports, but skip imports defined in if typing.TYPE_CHECKING blocks.
  • only_direct_imports=True will only check for imports performed by the module directly and will not check transitive imports.
  • If only_toplevel_imports=True is set, skip_type_checking=True has no effect.
  • Options can be combined.
Check toplevel imports Check TYPE_CHECKING imports Check conditional imports, and imports in functions and methods Check transitive imports
no options enabled ✓ ✓ ✓ ✓
skip_type_checking=True ✓ ✗ ✓ ✓
only_toplevel_imports=True ✓ ✗ ✗ ✓
only_direct_imports=True ✓ ✓ ✓ ✗

Example

Domain model has no dependencies

def test_domain():
    # test if the domain model does not import other submodules
    # (the domain model should be standing on its own and be used by other modules)
    (
        archrule("domain", comment="domain does not import any other submodules")
        .match("packageX.domain*") # matches packageX.domain and packageX.domain.*
        .should_not_import("packageX*")
        .may_import("packageX.domain.*")
        .check("packageX")
    )

util module is used at more than one place

You can also supply custom constraints as predicate functions.

If you, for example, have a common or util module, you might want to make sure that it is used at least at two places (otherwise it would not make sense to have a separate module).

from pytest_archon import archrule


def test_utils_are_shared():
    def have_at_least_two_users(util_module, direct_imports, all_imports):
        # iterate through all imports and find modules using the util_module in question
        users = [k for k, v in all_imports.items() if util_module in v]
        # return True if more than two modules use the util_module
        return len(users) > 2

    archrule("util_is_shared").match("pkg.util").should(have_at_least_two_users).check("pkg")

See also

The blog post How to tame your Python codebase is also a good overview.

Similar projects

Release files for pytest-archon 0.0.7

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

Source distribution (sdist)

Source distribution for pytest-archon 0.0.7
File Size Uploaded
pytest_archon-0.0.7.tar.gz 48.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-archon 0.0.7
File Interpreter ABI Platform
pytest_archon-0.0.7-py3-none-any.whl Python 3 none any Details

Total release size: 93.2 kB

Release files / pytest_archon-0.0.7.tar.gz

Download URL pytest_archon-0.0.7.tar.gz
Size 48.4 kB
Tags Source
SHA-256 checksum
How to use checksums
6a1e814c84adbea4afc188369733ec898f2525cc401f3ca965498f8b3ee454d5
BLAKE2b-256 checksum
How to use checksums
42da8132aa99cee223c7c5b330ffb4bd8094343239774f917e71a21f74d52009
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.11

Release files / pytest_archon-0.0.7-py3-none-any.whl

Download URL pytest_archon-0.0.7-py3-none-any.whl
Size 44.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5aaad17cff853d058ca686dd1da425ce884daf33ae9668011323173631dc4e94
BLAKE2b-256 checksum
How to use checksums
9881a46c239c77d4ec4e3450d463517ff63f10c22962c037ca2b4125394cf400
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.11

Release history Release notifications | RSS feed

This release

0.0.7 This release

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

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