Static analysis tool that enforces type annotation presence in Python code
Project description
typestrict
typestrict is a Python static analysis tool that enforces the presence of type annotations in Python code.
Unlike mypy or pyright which verify annotation correctness, typestrict 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 typestrict
Requires Python 3.10+.
Usage
# Check a single file
typestrict check app/models.py
# Check a directory recursively
typestrict check src/
# Output as JSON (for CI/CD)
typestrict check src/ --format json
# Check only specific rules
typestrict check src/ --select TF001,TF002
# Exit with code 1 if errors are found (pre-commit / CI)
typestrict 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.typestrict]
# 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) # typestrict: ignore
Suppress a specific rule code:
data = json.loads(response.text) # typestrict: ignore[TF001]
Pre-commit integration
Add to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/example/typestrict
rev: v0.1.0
hooks:
- id: typestrict
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) selfandclsas 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file must_annotate-0.1.1.tar.gz.
File metadata
- Download URL: must_annotate-0.1.1.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01e98688ec01e2c2a30aa8509b4834114dd0a6e852ff77a52e07e4cf089ecb51
|
|
| MD5 |
fbe748d991b243b927489c69285a80ec
|
|
| BLAKE2b-256 |
d3479ab17bce98b74851b2c2be28a183d02e6b2353dba6cd6c2718b8c4e7402c
|
Provenance
The following attestation bundles were made for must_annotate-0.1.1.tar.gz:
Publisher:
publish.yml on PitRella/typestrict
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
must_annotate-0.1.1.tar.gz -
Subject digest:
01e98688ec01e2c2a30aa8509b4834114dd0a6e852ff77a52e07e4cf089ecb51 - Sigstore transparency entry: 1154735842
- Sigstore integration time:
-
Permalink:
PitRella/typestrict@f87771b1b6d913546d2f763b6e02d7fd27695de2 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/PitRella
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f87771b1b6d913546d2f763b6e02d7fd27695de2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file must_annotate-0.1.1-py3-none-any.whl.
File metadata
- Download URL: must_annotate-0.1.1-py3-none-any.whl
- Upload date:
- Size: 18.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9c5b554cb32541e73ffc970d89333fa0e38a1c6ee78bac905975b58cd8ed31a1
|
|
| MD5 |
9e80f60e3d1163a588d67a44c29ecaa0
|
|
| BLAKE2b-256 |
51df03195d29901ee93ae75bb5425748af4aac09fa8797f66bd0755f17635eb9
|
Provenance
The following attestation bundles were made for must_annotate-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on PitRella/typestrict
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
must_annotate-0.1.1-py3-none-any.whl -
Subject digest:
9c5b554cb32541e73ffc970d89333fa0e38a1c6ee78bac905975b58cd8ed31a1 - Sigstore transparency entry: 1154735844
- Sigstore integration time:
-
Permalink:
PitRella/typestrict@f87771b1b6d913546d2f763b6e02d7fd27695de2 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/PitRella
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f87771b1b6d913546d2f763b6e02d7fd27695de2 -
Trigger Event:
push
-
Statement type: