Skip to main content

Static analysis tool that enforces type annotation presence in Python code

Project description

must-annotate

must-annotate is a Python static analysis tool that enforces the presence of type annotations in Python code.

Unlike mypy or pyright which verify annotation correctness, must-annotate simply checks that every variable, function argument, and return value has an annotation. If it is missing — that is an error.

# ERROR: missing type annotation
a = 3
result = get_user()

# OK: annotation present
a: int = 3
result: User = get_user()

Installation

pip install must-annotate

Requires Python 3.10+.


Usage

# Check a single file
must-annotate check app/models.py

# Check a directory recursively
must-annotate check src/

# Output as JSON (for CI/CD)
must-annotate check src/ --format json

# Check only specific rules
must-annotate check src/ --select TF001,TF002

# Exit with code 1 if errors are found (pre-commit / CI)
must-annotate check src/ --fail-on-error

Example output

src/app/models.py:15:4  TF001  Variable 'result' missing type annotation
src/app/models.py:23:0  TF002  Argument 'user_id' missing type annotation
src/app/views.py:8:0    TF003  Function 'get_data' missing return type annotation

Found 3 errors in 2 files

Error codes

Code Description Example violation
TF001 Variable assignment without a type annotation a = 3
TF002 Function argument without a type annotation def f(x):
TF003 Function missing a return type annotation def f():
TF004 Class attribute assigned without a type annotation self.name = "test"
TF005 Loop/context-manager variable without annotation (opt-in) for i in range(10):

Configuration (pyproject.toml)

[tool.must-annotate]
# Exclude directories or files from analysis
exclude = ["tests/", "migrations/", "conftest.py"]

# Disable specific rules globally
ignore = ["TF005"]

# Disable rules for specific files
per_file_ignores = { "conftest.py" = ["TF001"], "settings.py" = ["TF001"] }

# Strict mode: enables ALL rules, including TF005
strict = false

Inline suppression

Suppress an error on a specific line:

data = json.loads(response.text)  # must-annotate: ignore

Suppress a specific rule code:

data = json.loads(response.text)  # must-annotate: ignore[TF001]

Pre-commit integration

Add to your .pre-commit-config.yaml:

repos:
  - repo: https://github.com/example/must-annotate
    rev: v0.1.0
    hooks:
      - id: must-annotate

What is skipped automatically

  • Dunder variables: __all__, __version__, etc.
  • The unused-value convention: _ = some_func()
  • Tuple unpacking: a, b = func() (hard to annotate inline)
  • Augmented assignment: counter += 1 (type already declared)
  • self and cls as the first argument of methods

Development

# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Type-check the library itself
mypy

License

MIT — see LICENSE.

Project details


Download files

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

Source Distribution

must_annotate-0.1.2.tar.gz (18.1 kB view details)

Uploaded Source

Built Distribution

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

must_annotate-0.1.2-py3-none-any.whl (19.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: must_annotate-0.1.2.tar.gz
  • Upload date:
  • Size: 18.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for must_annotate-0.1.2.tar.gz
Algorithm Hash digest
SHA256 b95c2b4ee3abc966739496e1261d26274bab3b01c6ddb806e0b63bbce323601b
MD5 095058f4b856303855f0ee000f0c25c4
BLAKE2b-256 d030f259349cb986d6ebbb205af793e7a55c686f38d4f9a31a924af9cb2817eb

See more details on using hashes here.

Provenance

The following attestation bundles were made for must_annotate-0.1.2.tar.gz:

Publisher: publish.yml on PitRella/must-annotate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file must_annotate-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: must_annotate-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 19.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for must_annotate-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3692ecb72a650887909104ad18fa43e20b61160c05d9ec0fe4dad260ec3799da
MD5 892ff5b2ded4c345c2c17357cb52dfcb
BLAKE2b-256 d8c9991c07fa63ffadd211cfc256b04823ea152d4a4ca1bf4ba5a618f5dc93d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for must_annotate-0.1.2-py3-none-any.whl:

Publisher: publish.yml on PitRella/must-annotate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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