Enforce using keyword arguments where possible.
Project description
strict-kwargs
Enforce using keyword arguments where possible.
strict-kwargs is a standalone CLI implemented in Rust.
For example, if we have a function which takes two regular arguments, there are three ways to call it. With this tool, only the form where keyword arguments are used is accepted.
"""Showcase errors when calling a function without naming the arguments."""
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
add(a=1, b=2) # OK
add(1, 2) # strict-kwargs reports this; strict-kwargs check --fix can rewrite it
add(1, b=2) # strict-kwargs reports this; strict-kwargs check --fix can rewrite it
Why?
- Like a formatter, such as
blackorruff format, this lets you stop discussing whether a particular function call should use keyword arguments. - Positional arguments can be fine at first. As more are added, calls can become unclear without anyone stopping to refactor them to keyword arguments.
- Type checkers give better errors when keyword arguments are used.
For example, with positional arguments, you may see,
Argument 5 to "add" has incompatible type "str"; expected "int". This requires that you count the arguments to see which one is wrong. With named arguments, you getArgument "e" to "add" has incompatible type "str"; expected "int".
Installation
uv tool install strict-kwargs
or:
pip install strict-kwargs
This is tested on Python 3.11+.
Usage
strict-kwargs check . # check a directory
strict-kwargs check --output-format json . # emit check diagnostics as JSON
strict-kwargs check --output-format github . # emit GitHub Actions annotations
strict-kwargs check --fix . # rewrite positional args in place
strict-kwargs check --diff . # preview fixes, write nothing
strict-kwargs check --fix --unsafe-fixes . # include behavior-changing fixes
strict-kwargs check --python .venv . # point type resolution at an environment
strict-kwargs check --cache-dir .strict-kwargs-cache . # enable the diagnostic cache
Exit codes are:
0: clean1: violations found2: operational error
Output
full, the default check output, writes Ruff-style diagnostics and summaries to stdout.jsonandgithubwrite diagnostics to stdout so machine consumers can read them without mixing in operational messages.- Warnings and operational errors are always written to stderr.
check --diffwrites the unified diff to stdout and its summary to stderr.
Fix behavior
check --fix only rewrites calls whose target parameter names are known unambiguously.
Ambiguous calls are counted as declined.
By default, check --fix rewrites:
- single-signature calls
- overloaded calls, when one precise overload arm can be selected and the rewritten argument types are precise enough
Synthesized constructors are treated as unsafe fixes because generated constructor models can differ from runtime behaviour when class construction is customized.
--unsafe-fixes: include dataclass andNamedTupleconstructor calls whose signatures were synthesized from fields.
Python environment
Use --python to point third-party resolution at an interpreter, virtual environment, or sys.prefix.
- Missing paths are errors.
- A missing
--pythonpath is warned about and ignored.
pre-commit
repos:
- repo: https://github.com/adamtheturtle/strict-kwargs-pre-commit
rev: 2026.6.8.post1 # pin to a release tag
hooks:
- id: strict-kwargs
Configuration
Configuration lives in pyproject.toml:
[tool.strict_kwargs]
required_version = ">=2026.5.19-post.3"
ignore_names = ["main.func", "builtins.str"]
src = ["src"]
namespace_packages = ["src/airflow/providers"]
extend_exclude = ["generated", "vendor"]
force_exclude = true
cache_dir = ".strict-kwargs-cache"
fix_synthesized_constructors = true
output_format = "full" # or "json", "github"
Set required_version to make older or incompatible strict-kwargs binaries fail fast when they read this project configuration.
Supported specifiers are exact versions, such as 2026.5.19-post.3, and minimum versions, such as >=2026.5.19-post.3.
Use the version reported by strict-kwargs --version.
Ignored functions
Use ignore_names for functions that should still allow positional arguments.
This is useful especially for builtins which can look strange with keyword arguments.
For example, str(object=1) is not idiomatic.
Suppressing individual findings
Add a Ruff-style # noqa comment to the line a diagnostic is reported on (the first line of the offending call) to suppress it:
func(1, 2, 3) # noqa: KW001
# noqa: KW001suppresses onlyKW001. A directive naming other codes (for example# noqa: E501) leaves the call reported.- A bare
# noqasuppresses every finding on the line, matching Ruff. - Suppressed calls are skipped by
--fixtoo, so a# noqacall is never rewritten.
For a call spanning multiple lines, put the comment on the first line — the line the path:line:col output points at:
func( # noqa: KW001
1,
2,
3,
)
Using # noqa alongside Ruff
If you also run Ruff with RUF100 (unused noqa) enabled, prefer the coded form # noqa: KW001: Ruff leaves a directive whose only codes it does not recognise untouched, but it will remove a bare # noqa it considers unused. To keep KW001 from being stripped when it shares a directive with a Ruff code (for example # noqa: E501, KW001), declare it as an external code:
[tool.ruff.lint]
external = ["KW001"]
Source discovery
Set src to source-code directories that should be:
- searched for first-party imports
- stripped when deriving module names
Relative paths are resolved against the project root.
For example, src = ["src"] maps src/pkg/mod.py to pkg.mod while preserving the repository root as a fallback source root.
Set namespace_packages to directories that should be treated as namespace packages for module resolution even when they have no __init__.py.
Exclusions
Use extend_exclude to skip generated or vendored Python files during directory runs.
- Patterns use
.gitignore-style matching relative to the project root. - By default, exclusions apply to directory traversal only.
- An explicitly passed file, such as
strict-kwargs check generated/api.py, is still checked. - Set
force_exclude = trueto apply exclusions to explicitly passed files too. This is useful when pre-commit passes changed files directly. - The built-in skips for dot-directories,
venv, and__pycache__remain enabled.
Cache
Set cache_dir to enable the persistent diagnostic cache for strict-kwargs checks.
Relative cache_dir values in pyproject.toml are resolved against the project root.
The cache location precedence is:
--cache-dir[tool.strict_kwargs].cache_dirSTRICT_KWARGS_CACHE_DIR
If none are set, the cache is disabled.
Fix defaults
Set fix_synthesized_constructors = true to make strict-kwargs check --fix include dataclass and NamedTuple constructor rewrites without passing --unsafe-fixes each time.
To find the name of a function to ignore, set the following configuration:
[tool.strict_kwargs]
debug = true
Then run strict-kwargs check and look for the debug output.
Comparison with mypy-strict-kwargs
mypy-strict-kwargs is a mypy plugin that enforces the same rule during type checking.
Use strict-kwargs if you:
- type-check with ty
- prefer a standalone linter without plugins
- want automatic rewrites with
strict-kwargs check --fix
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 Distributions
Built Distributions
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 strict_kwargs-2026.6.8.post1-py3-none-win_amd64.whl.
File metadata
- Download URL: strict_kwargs-2026.6.8.post1-py3-none-win_amd64.whl
- Upload date:
- Size: 2.7 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f515f25fe06b6cb54527d22e2b86a6811bb11617a8f12754318b1c775ff06dc2
|
|
| MD5 |
005d4965d5cac94e787562f420b800b5
|
|
| BLAKE2b-256 |
3392b70c922af8a0da6ea134f0b67dbf590142995c331eecc3d5addbfa0d73ec
|
Provenance
The following attestation bundles were made for strict_kwargs-2026.6.8.post1-py3-none-win_amd64.whl:
Publisher:
release.yml on adamtheturtle/strict-kwargs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
strict_kwargs-2026.6.8.post1-py3-none-win_amd64.whl -
Subject digest:
f515f25fe06b6cb54527d22e2b86a6811bb11617a8f12754318b1c775ff06dc2 - Sigstore transparency entry: 1757135855
- Sigstore integration time:
-
Permalink:
adamtheturtle/strict-kwargs@e0b15b6e501b05b59cd717abb618064fbed42f41 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adamtheturtle
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e0b15b6e501b05b59cd717abb618064fbed42f41 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file strict_kwargs-2026.6.8.post1-py3-none-manylinux_2_39_x86_64.whl.
File metadata
- Download URL: strict_kwargs-2026.6.8.post1-py3-none-manylinux_2_39_x86_64.whl
- Upload date:
- Size: 3.0 MB
- Tags: Python 3, manylinux: glibc 2.39+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd0e2c01f516accd748f51a103ba04b162010bdec4c869df8a16392104d9507b
|
|
| MD5 |
7e5c6316b0ca03dfe8489368f2e1b8d6
|
|
| BLAKE2b-256 |
6734b28fac9d41ae163636b60b0df96c759b909f16c5c335c79cafd0d5572388
|
Provenance
The following attestation bundles were made for strict_kwargs-2026.6.8.post1-py3-none-manylinux_2_39_x86_64.whl:
Publisher:
release.yml on adamtheturtle/strict-kwargs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
strict_kwargs-2026.6.8.post1-py3-none-manylinux_2_39_x86_64.whl -
Subject digest:
dd0e2c01f516accd748f51a103ba04b162010bdec4c869df8a16392104d9507b - Sigstore transparency entry: 1757135788
- Sigstore integration time:
-
Permalink:
adamtheturtle/strict-kwargs@e0b15b6e501b05b59cd717abb618064fbed42f41 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adamtheturtle
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e0b15b6e501b05b59cd717abb618064fbed42f41 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file strict_kwargs-2026.6.8.post1-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: strict_kwargs-2026.6.8.post1-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 2.8 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9856da92bef457ce912ebf42c7b54b25d94323729e27a3f3cf22c962b3c01922
|
|
| MD5 |
e27ac223ff64ebaed009cbd475ad0cfe
|
|
| BLAKE2b-256 |
6177be5a8439df38f15ee00a93caf95b498ca2b379a73840e660c60d7eee10f5
|
Provenance
The following attestation bundles were made for strict_kwargs-2026.6.8.post1-py3-none-macosx_11_0_arm64.whl:
Publisher:
release.yml on adamtheturtle/strict-kwargs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
strict_kwargs-2026.6.8.post1-py3-none-macosx_11_0_arm64.whl -
Subject digest:
9856da92bef457ce912ebf42c7b54b25d94323729e27a3f3cf22c962b3c01922 - Sigstore transparency entry: 1757135989
- Sigstore integration time:
-
Permalink:
adamtheturtle/strict-kwargs@e0b15b6e501b05b59cd717abb618064fbed42f41 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adamtheturtle
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e0b15b6e501b05b59cd717abb618064fbed42f41 -
Trigger Event:
workflow_dispatch
-
Statement type: