Skip to main content

Customs

A Rust lint tool that enforces Python import boundaries declared in pyproject.toml.

[tool.customs]
src-roots = ["src", "."]
ignore = ["examples", "tests"]

[tool.customs.module.my-service]
module = "my_project.apps.service"

[tool.customs.module.libraries-utils]
module = "my_project.libraries.utils"
allow = ["$submodules", "my_project.apps.service"]

Install

uv tool install customs-lint
# or: pip install customs-lint
customs check .

The VS Code extension starts customs lsp from the selected Python interpreter (the same customs-lint install you use for CI) and lints the active Python file on edit.

Commands

  • customs check [paths...] — lint files; exit 0 if clean, 1 on violations, 2 on tool errors
  • customs lsp — Language Server Protocol server on stdio

Configuration

Put a [tool.customs] table in pyproject.toml. Customs walks up from each file to the nearest pyproject.toml.

src-roots (default ["."]) — directories relative to that file, used to map a path to a module. The longest matching root wins. With ["src", "."], src/foo/bar.py is foo.bar, not src.foo.bar.

ignore — module prefixes of importing files to skip. tests skips tests and tests.test_foo, but not testsuite.

[tool.customs.module.<rule-name>] — a named rule. <rule-name> is your label; it appears in diagnostics (for example [my-service]).

  • module (required) — the controlled package. Imports of this module and its submodules are restricted.
  • allow — who may import that tree. Each entry is a module prefix (the named module and its submodules). $submodules means the controlled module and its own children. If allow is omitted, it defaults to ["$submodules"]. If you set allow yourself, $submodules is not implied; list it to keep internal imports allowed.

Development

System dependencies

You must have the following dependencies installed:

  • Rust and Cargo — stable toolchain, rustc 1.77 or newer. Install via rustup.
  • uv — Python package and environment manager (installs Python 3.12 from .python-version when needed).
  • Node.js 20+ and npm to build the VS Code extension.

Run tests

From the repo root, with Rust and Cargo on PATH:

cargo test --workspace

This runs the customs-core unit tests and the customs check integration tests against tests/fixtures/. To run one crate or one test:

cargo test -p customs-core
cargo test -p customs
cargo test -p customs-core longest_prefix_wins

Set up a virtual environment and build the wheel

From the repo root (Rust/Cargo must be on PATH):

uv sync --group dev
uv build --out-dir target/wheels

uv sync creates .venv, installs the locked dev group (maturin), and builds/installs customs into that environment. Wheels from uv build are written to target/wheels/.

Install the wheel into another environment

The distribution name is customs-lint; the installed executable is customs.

uv pip install target/wheels/customs_lint-*.whl

Invoke the CLI

Once the wheel is installed and the environment is active:

customs check .
customs check path/to/file.py
customs lsp   # stdio language server

customs check exits 0 if clean, 1 if it found forbidden imports, and 2 on tool or config errors.

Build the VS Code extension

The extension does not bundle customs. Install customs-lint in the workspace interpreter (or set customs.path). From the repo root:

cd editors/vscode
npm ci
npm run package

npm run package runs vsce package and produces editors/vscode/customs-0.1.0.vsix (version from package.json).

For local iteration without a VSIX, run npm run compile in editors/vscode.

Install the VS Code extension

code --install-extension editors/vscode/customs-0.1.0.vsix

Or use the Command Palette: Extensions: Install from VSIX… and select the .vsix file.

After install, open a Python file and select the project interpreter (the Python extension is required). The extension runs customs lsp from that environment, or from customs.path if you set it. If customs is missing, it reports an error and asks you to install customs-lint in that environment (uv pip install customs-lint or pip install customs-lint).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

customs_lint-0.1.2.tar.gz (24.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

customs_lint-0.1.2-py3-none-win_amd64.whl (1.6 MB view details)

Uploaded Python 3Windows x86-64

customs_lint-0.1.2-py3-none-manylinux_2_28_x86_64.whl (1.9 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ x86-64

customs_lint-0.1.2-py3-none-manylinux_2_28_aarch64.whl (1.9 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARM64

customs_lint-0.1.2-py3-none-macosx_11_0_arm64.whl (1.7 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

customs_lint-0.1.2-py3-none-macosx_10_12_x86_64.whl (1.8 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file customs_lint-0.1.2.tar.gz.

File metadata

  • Download URL: customs_lint-0.1.2.tar.gz
  • Upload date:
  • Size: 24.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for customs_lint-0.1.2.tar.gz
Algorithm Hash digest
SHA256 7816141c6a89b36af33533c0904bbd44188488615867d3317dba125ee2473b97
MD5 0e4481e3324c3433871add0220c519ee
BLAKE2b-256 9a8ccdffd5b6289d9c4a487264347843c5a36ebea6bd4ac536f14dcbce8333db

See more details on using hashes here.

File details

Details for the file customs_lint-0.1.2-py3-none-win_amd64.whl.

File metadata

  • Download URL: customs_lint-0.1.2-py3-none-win_amd64.whl
  • Upload date:
  • Size: 1.6 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for customs_lint-0.1.2-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 0c75d50ce6141da743da915711c1706fc8be2a238898b3410035f12fe138b6c3
MD5 eab3e247b1db57c2db9333afd9e7d5e7
BLAKE2b-256 37272eb48b072bfeb530255404aad231864b14116ebea04193d9342825648f42

See more details on using hashes here.

File details

Details for the file customs_lint-0.1.2-py3-none-manylinux_2_28_x86_64.whl.

File metadata

  • Download URL: customs_lint-0.1.2-py3-none-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: Python 3, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for customs_lint-0.1.2-py3-none-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f03e74d6d9784dcbaa31023f7f91d95c4b1c3fa2c3f3a09c4258f8482bb550b6
MD5 1bc07b299b81f69f029f2b01a9087d2e
BLAKE2b-256 1d0eb6eb64ab5348c5df41bf93a12660d043a372fbdff9126e1179e2b0109cd0

See more details on using hashes here.

File details

Details for the file customs_lint-0.1.2-py3-none-manylinux_2_28_aarch64.whl.

File metadata

  • Download URL: customs_lint-0.1.2-py3-none-manylinux_2_28_aarch64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: Python 3, manylinux: glibc 2.28+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for customs_lint-0.1.2-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 4b129699ad59eb5ca981bc9afad2ccdbaf812a5c6c22621f6c95ee1bd55da7b7
MD5 83d27e29977d960e9657d78429a9db0c
BLAKE2b-256 e5e4aa1e28e34f0cf156b8b1b20c830519a59167e7e8c0911f2f498eb2f10618

See more details on using hashes here.

File details

Details for the file customs_lint-0.1.2-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: customs_lint-0.1.2-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 1.7 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for customs_lint-0.1.2-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 968ce9ca3f0e207d12ead303ed2249db5d495a80a871c939559928aa2b9784ba
MD5 bd798e0f5dc8f1d880c94cfdcffa7bb6
BLAKE2b-256 78c0c3dcb0f08d17ae532b90a6aaf4d7600855e08e58558929894608f7aaa8e3

See more details on using hashes here.

File details

Details for the file customs_lint-0.1.2-py3-none-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: customs_lint-0.1.2-py3-none-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 1.8 MB
  • Tags: Python 3, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for customs_lint-0.1.2-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 f15df0cb7412f1e0eefda9ede7d0f4f944a08e487e6ce2686c007bada90d789f
MD5 2252f620c3f3330713c4978f136df7fb
BLAKE2b-256 ec6620bc82304f10debe3cd19b186b20aaad2259f9e3c9b95e8e15daea02c351

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page