{"id":13492721,"url":"https://github.com/jwbargsten/pytest-archon","last_synced_at":"2026-01-16T14:12:12.926Z","repository":{"id":63521965,"uuid":"567621303","full_name":"jwbargsten/pytest-archon","owner":"jwbargsten","description":"Rule your architecture like a real developer","archived":false,"fork":false,"pushed_at":"2025-09-19T20:56:26.000Z","size":250,"stargazers_count":66,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-19T23:16:24.266Z","etag":null,"topics":["architecture","archunit","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jwbargsten.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-18T07:28:16.000Z","updated_at":"2025-09-19T20:52:32.000Z","dependencies_parsed_at":"2024-02-26T20:49:07.072Z","dependency_job_id":null,"html_url":"https://github.com/jwbargsten/pytest-archon","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/jwbargsten/pytest-archon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwbargsten%2Fpytest-archon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwbargsten%2Fpytest-archon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwbargsten%2Fpytest-archon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwbargsten%2Fpytest-archon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jwbargsten","download_url":"https://codeload.github.com/jwbargsten/pytest-archon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwbargsten%2Fpytest-archon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28479193,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["architecture","archunit","python"],"created_at":"2024-07-31T19:01:08.614Z","updated_at":"2026-01-16T14:12:12.903Z","avatar_url":"https://github.com/jwbargsten.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# pytest-archon\n\n[![build_and_test](https://github.com/jwbargsten/pytest-archon/actions/workflows/tests.yml/badge.svg)](https://github.com/jwbargsten/pytest-archon/actions/workflows/tests.yml)\n\n`pytest-archon` is a little tool that helps you structure (large) Python projects. This\ntool allows you to define architectural boundaries in your code, also known as\n_forbidden dependencies_.\n\nExplicitly defined architectural boundaries helps you keep your code in shape. It avoids\nthe creation of circular dependencies. New people on the project are made aware of the\nstructure through a simple set of rules, instead of lore.\n\n## Installation\n\nThe simple way:\n\n```sh\npip install pytest-archon\n```\n\n## Usage\n\n_pytest-archon_ can be used to define architectural boundaries from (unit) tests.\nBecause they're tests, they can be closely tied to the actual application.\n\nYou can use _pytest-archon_ in tests by simply importing the `archrule` function. Using\nthis function you can construct import tests:\n\n```python\nfrom pytest_archon import archrule\n\n\ndef test_rule_basic():\n    (\n        archrule(\"name\", comment=\"some comment\")\n        .match(\"pytest_archon.col*\")\n        .exclude(\"pytest_archon.colgate\")\n        .should_not_import(\"pytest_archon.import_finder\")\n        .should_import(\"pytest_archon.core*\")\n        .check(\"pytest_archon\")\n    )\n```\n\n- To match the modules and constraints,\n  [fnmatch](https://docs.python.org/3/library/fnmatch.html) syntax is used (the\n  default). You can also use\n  [regular expressions](https://docs.python.org/3/library/re.html#regular-expression-syntax)\n  by supplying the `use_regex=True` argument to `archrule()`. Example: `archrule(..., use_regex=True).match(...)`.\n- `.exclude()` is optional\n- `.should_import()` and `.should_not_import()` can be combined and can occur multiple\n  times.\n- `.may_import()` can be used in combination with `.should_not_import()`.\n- `.check()` needs either a module object or a string\n\nThe `check()` method can have a few optional parameters, that alter the way the checks\nare performed.\n\n- Without parameters, the whole file is checked for imports. So imports done in\n  functions and methods are also found. Transitive dependencies are also checked\n- Option `only_toplevel_imports=True` will only check for toplevel imports. Conditional\n  imports and import in functions and methods are ignored.\n- `skip_type_checking=True` will check all imports, but skip imports defined in\n  `if typing.TYPE_CHECKING` blocks.\n- `only_direct_imports=True` will only check for imports performed by the module\n  directly and will not check transitive imports.\n- If `only_toplevel_imports=True` is set, `skip_type_checking=True` has no effect.\n- Options can be combined.\n\n|                              | Check toplevel imports | Check `TYPE_CHECKING` imports | Check conditional imports, and imports in functions and methods | Check transitive imports |\n| ---------------------------- | :--------------------: | :---------------------------: | :-------------------------------------------------------------: | :----------------------: |\n| no options enabled           |           ✓            |               ✓               |                                ✓                                |            ✓             |\n| `skip_type_checking=True`    |           ✓            |               ✗               |                                ✓                                |            ✓             |\n| `only_toplevel_imports=True` |           ✓            |               ✗               |                                ✗                                |            ✓             |\n| `only_direct_imports=True`   |           ✓            |               ✓               |                                ✓                                |            ✗             |\n\n## Example\n\n### Domain model has no dependencies\n\n```python\ndef test_domain():\n    # test if the domain model does not import other submodules\n    # (the domain model should be standing on its own and be used by other modules)\n    (\n        archrule(\"domain\", comment=\"domain does not import any other submodules\")\n        .match(\"packageX.domain*\") # matches packageX.domain and packageX.domain.*\n        .should_not_import(\"packageX*\")\n        .may_import(\"packageX.domain.*\")\n        .check(\"packageX\")\n    )\n```\n\n### `util` module is used at more than one place\n\nYou can also supply custom constraints as predicate functions.\n\nIf you, for example, have a common or util module, you might want to make sure that it\nis used at least at two places (otherwise it would not make sense to have a separate\nmodule).\n\n```python\nfrom pytest_archon import archrule\n\n\ndef test_utils_are_shared():\n    def have_at_least_two_users(util_module, direct_imports, all_imports):\n        # iterate through all imports and find modules using the util_module in question\n        users = [k for k, v in all_imports.items() if util_module in v]\n        # return True if more than two modules use the util_module\n        return len(users) \u003e 2\n\n    archrule(\"util_is_shared\").match(\"pkg.util\").should(have_at_least_two_users).check(\"pkg\")\n```\n\n## See also\n\nThe blog post [How to tame your Python codebase](https://bargsten.org/wissen/how-to-tame-your-python-codebase/) is also a good overview.\n\n## Similar projects\n\n- [Archunit](https://www.archunit.org/) (Java)\n- [Dependency Cruiser](https://github.com/sverweij/dependency-cruiser) (Javascript)\n- [import-linter](https://github.com/seddonym/import-linter) (Python)\n- [pytestarch](https://pypi.org/project/pytestarch/) (Python)\n- [Maintain A Clean Architecture With Dependency Rules - sourcery.ai](https://sourcery.ai/blog/dependency-rules/)\n  (Python)\n- [GitHub - zyskarch/pytestarch: Test framework for software architecture based on imports between modules.](https://github.com/zyskarch/pytestarch) (Python)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwbargsten%2Fpytest-archon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjwbargsten%2Fpytest-archon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwbargsten%2Fpytest-archon/lists"}