{"id":2069,"library":"import-linter","title":"Import Linter","description":"Import Linter is a command-line tool designed to lint your Python architecture by imposing constraints on the imports between your Python modules. It analyzes imports against a set of rules defined in a configuration file, helping to enforce specific architectural styles in complex codebases. The library also provides a browser-based user interface for exploring the architecture of any Python package. It is actively developed, with the current version being 2.11.","status":"active","version":"2.11","language":"python","source_language":"en","source_url":"https://github.com/seddonym/import-linter","tags":["linter","static analysis","architecture","code quality","python"],"install":[{"cmd":"pip install import-linter","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Required Python version for the library.","package":"python","version":">=3.10","optional":false}],"imports":[{"note":"The primary way to use Import Linter is via its command-line interface.","symbol":"CLI","correct":"lint-imports"},{"note":"For programmatic usage, e.g., integrating into unit tests, this function can be imported.","symbol":"lint_imports function","correct":"from importlinter.cli import lint_imports"}],"quickstart":{"code":"# myproject/domain/__init__.py\n# (empty file)\n\n# myproject/domain/models.py\n# (some model code)\n\n# myproject/services/__init__.py\n# (empty file)\n\n# myproject/services/users.py\n# (some service code)\n\n# .importlinter (create this file in your project root)\n[importlinter]\nroot_package = myproject\n\n[importlinter:contract:domain-no-services]\nname = Domain layer must not import from services layer\ntype = forbidden\nsource_modules = myproject.domain\nforbidden_modules = myproject.services\n\n# Run from your project root in the terminal:\n# lint-imports","lang":"python","description":"Install `import-linter`, then create a `.importlinter` file (or `pyproject.toml`/`setup.cfg`) in your project's root. Define your contracts, specifying rules like 'forbidden' or 'layers'. Finally, run `lint-imports` from your terminal to check for architectural violations. The example demonstrates a forbidden contract preventing imports from `myproject.services` into `myproject.domain`."},"warnings":[{"fix":"Place your configuration in a recognized file (e.g., `.importlinter` or `pyproject.toml`) or use `lint-imports --config path/to/your_config.ini`.","message":"Import Linter searches for configuration in `setup.cfg` (INI format), `.importlinter` (INI format), or `pyproject.toml` (TOML format) by default. Ensure your configuration is in one of these files or specify it explicitly using `--config`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Correctly specify either `root_package = my_single_package` or `root_packages = package_one package_two` in your `[importlinter]` section.","message":"Use `root_package` for a single root package or `root_packages` for multiple root packages in your configuration. Mixing them or omitting both will lead to errors.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Be aware that contracts will only check imports into external packages, not their internal dependencies.","message":"When `include_external_packages = True` is set, external packages are included in the import graph, allowing you to check imports *to* them. However, Import Linter does not statically analyze the *internal* imports of these external packages.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Check the integer return value of `lint_imports()` to determine contract adherence.","message":"When using the `lint_imports` function programmatically (e.g., in unit tests), it returns an exit code (0 for success, non-zero for failure) rather than raising an exception for broken contracts. Directly asserting the return value (e.g., `assert 0 == lint_imports()`) is the expected pattern.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure each contract section has a unique, arbitrary identifier appended after `importlinter:contract:`.","message":"In INI-style configuration files (`.importlinter` or `setup.cfg`), each contract section (e.g., `[importlinter:contract:my-contract-id]`) requires a unique identifier (like `my-contract-id`). Duplicate IDs will result in configuration parsing issues.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"search_vec":"'2.11':76 'activ':69 'also':51 'analysi':79 'analyz':28 'architectur':16,44,62,80 'base':56 'browser':55 'browser-bas':54 'code':81 'codebas':48 'command':8 'command-lin':7 'complex':47 'configur':38 'constraint':19 'current':73 'defin':35 'design':11 'develop':70 'enforc':42 'explor':60 'file':39 'help':40 'import':1,3,22,29 'impos':18 'interfac':58 'librari':50 'line':9 'lint':13 'linter':2,4,77 'modul':26 'packag':66 'provid':52 'python':15,25,65,83 'qualiti':82 'rule':34 'set':32 'specif':43 'static':78 'style':45 'tool':10 'user':57 'version':74","created_at":"2026-04-09T18:42:11.807845+00:00","updated_at":"2026-04-16T15:43:13.232681+00:00","problems":[{"fix":"Refactor the offending import in your Python code to comply with the defined contract, or adjust the contract in your '.importlinter' file if the rule is too strict or incorrect for your intended architecture.","cause":"An import within your Python codebase violates one of the architectural contracts defined in your '.importlinter' configuration file.","error":"Contract 'My Contract Name' was broken: my_package.module_a imports my_package.module_b"},{"fix":"Ensure the 'root_package' name in '.importlinter' exactly matches an importable Python package. Verify that the project root (containing the specified package) is in your PYTHONPATH, or that the package is installed (e.g., 'pip install -e .') in the environment where the linter runs.","cause":"The 'root_package' specified in your '.importlinter' configuration file is not correctly installed or not discoverable in the Python environment where 'lint-imports' is being executed.","error":"Package 'my_project' could not be found."},{"fix":"Add an 'ignore_imports' list to the relevant contract in your '.importlinter' configuration file, specifying the exact import path to be ignored (e.g., 'ignore_imports= my_package.source.importer -> my_package.forbidden.imported').","cause":"You have an intentional import that breaks a defined contract, but you want 'import-linter' to disregard this specific instance without altering the general architectural rule.","error":"How to ignore specific imports in import-linter?"},{"fix":"Ensure your 'root_package' is structured as a proper Python package (a directory with an '__init__.py' file). If you need to lint a single file, consider wrapping it in a minimal package structure or defining contracts that target specific modules within that file's context rather than attempting to set the single file as a top-level 'root_package'.","cause":"Import Linter is primarily designed to analyze Python packages (directories containing an '__init__.py' file) and may not correctly process a 'root_package' specified as a single Python file.","error":"No error printed for root_package that is a single file module"}],"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"2.13","cli_name":"import-linter","cli_version":"import-linter 2.11","type":"library","homepage":null,"github":"https://github.com/seddonym/import-linter","docs":"https://import-linter.readthedocs.io/","changelog":null,"pypi":"https://pypi.org/project/import-linter/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["testing","devops"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-28","last_verified":"2026-08-28","next_check":"2026-07-28","install_tag":null}}