Skip to main content

CI PyPI

no-defaults

A fast, standalone Python linter that forbids defaults in function signatures and dataclasses. It is implemented in Rust and parses Python with Ruff's parser.

from dataclasses import dataclass, field

def connect(timeout=30):  # NOD001
    pass

@dataclass
class Job:
    retries: int = 3  # NOD001
    tags: list[str] = field(default_factory=list)  # NOD001

Installation

uv tool install no-defaults

Usage

no-defaults .
no-defaults --fix .
no-defaults --diff .
no-defaults --private-only src tests
no-defaults --output-format json .
no-defaults --output-format github .
no-defaults --show-settings src/package/api.py

Exit status is 0 when clean, 1 when violations are found, and 2 for an operational error. Directories are walked in parallel, respecting .gitignore and standard hidden-file filters. Diagnostics use Ruff's concise format and include a summary:

src/example.py:4:17: NOD001 parameter `timeout` of function `connect` has a default
Found 1 error.

Pass --fix to remove defaults automatically. Function parameters and ordinary dataclass assignments become required. For field(...), only the positional default, default=, or default_factory= argument is removed; other metadata is preserved:

retries: int = field(default=3, kw_only=True)
# becomes
retries: int = field(kw_only=True)

After a successful fix, the command exits with status 0 and prints a Ruff-style summary such as Found 2 errors (2 fixed, 0 remaining). Writes use an atomic same-directory replacement. --diff prints a unified diff, writes nothing, and exits with status 1 when changes are available.

The default full output includes source excerpts and carets. concise emits one diagnostic per line, json emits a machine-readable array, and github emits workflow commands for GitHub Actions annotations.

The linter detects defaults on positional-only, positional-or-keyword, and keyword-only parameters. For classes decorated with @dataclass or @dataclasses.dataclass, it detects assigned defaults plus field(default=...) and field(default_factory=...) in the class body. ClassVar assignments are ignored because they are not dataclass fields, and annotated assignments inside method bodies are ignored because they are locals.

Suppress an individual violation with either a blanket # noqa or the rule-specific # noqa: NOD001 on the line containing the default:

def compatible(timeout=30):  # noqa: NOD001
    pass

Suppress the rule for an entire file with # ruff: noqa or # ruff: noqa: NOD001.

Configuration

Configuration lives in pyproject.toml:

[tool.no_defaults]
private_only = true

[tool.no_defaults.per_file_enforcement]
"tests/**" = "all"
"src/**" = "private"

Private means a name that starts with one underscore. In private-only mode, the rule applies to private modules and packages, private functions and methods, all members of private classes, and private dataclass fields. For example, all defaults in _module.py and _package/module.py are checked. Dunder names such as __init__.py are not considered private by themselves.

per_file_enforcement accepts Ruff-style glob patterns relative to the directory containing pyproject.toml. Use "all" to reject every default in matching files or "private" to reject defaults only in private scopes. Patterns without a slash match file names at any depth. An initial ! negates a pattern. If multiple patterns match, the most specific pattern wins; equally specific patterns are resolved lexicographically so results never depend on TOML table order.

The --private-only CLI flag overrides the configuration for every checked file.

Like Ruff, no-defaults discovers the closest pyproject.toml containing [tool.no_defaults] separately for each file. This supports monorepos with nested configuration; files without a local table continue searching parent directories.

Performance

An optimized 1.0.0 development build checked a pinned Typeshed checkout containing 5,368 Python and stub files (12.5 MiB) in a median 0.29 seconds across five warm runs on an Apple Silicon Mac, or roughly 18,000 files per second. It produced 50,974 diagnostics; an earlier full-output measurement used approximately 41 MiB maximum RSS.

CodSpeed runs parser-and-rule benchmarks for representative modules on every pull request and every push to main, providing stable comparisons against the default-branch baseline. The scheduled Typeshed benchmark remains as a real-project correctness and gross-regression check.

pre-commit

repos:
  - repo: https://github.com/adamtheturtle/no-defaults
    rev: v1.0.0
    hooks:
      - id: no-defaults

License

MIT

See CONTRIBUTING.md, SECURITY.md, and CHANGELOG.md.

Download files

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

Source Distribution

no_defaults-1.0.1.tar.gz (28.4 kB view details)

Uploaded Source

Built Distributions

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

no_defaults-1.0.1-py3-none-win_amd64.whl (1.9 MB view details)

Uploaded Python 3Windows x86-64

no_defaults-1.0.1-py3-none-manylinux_2_34_x86_64.whl (2.2 MB view details)

Uploaded Python 3manylinux: glibc 2.34+ x86-64

no_defaults-1.0.1-py3-none-macosx_11_0_arm64.whl (2.0 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file no_defaults-1.0.1.tar.gz.

File metadata

  • Download URL: no_defaults-1.0.1.tar.gz
  • Upload date:
  • Size: 28.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for no_defaults-1.0.1.tar.gz
Algorithm Hash digest
SHA256 c309ae30960a08ebc2436e7a45aeea46b5eb1c73c65bf02220e41e5b5d01721c
MD5 954d3658edb4b36f07ffa01dd6eac445
BLAKE2b-256 f2543454e62945b092758b587e0e4b7cf35aa77f88da5fc43f20790bf5d433ad

See more details on using hashes here.

Provenance

The following attestation bundles were made for no_defaults-1.0.1.tar.gz:

Publisher: release.yml on adamtheturtle/no-defaults

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

File details

Details for the file no_defaults-1.0.1-py3-none-win_amd64.whl.

File metadata

  • Download URL: no_defaults-1.0.1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for no_defaults-1.0.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 31c9f3252b54d5e04e061f7aaf3b08571236eec5db1f20be91cc3cbf4be92827
MD5 acc58c2e3125058429d6f36c4d96eff0
BLAKE2b-256 fea066a4ac44d0216e88e924e54756cee8282f4f04f646c02c5931b7f9bed933

See more details on using hashes here.

Provenance

The following attestation bundles were made for no_defaults-1.0.1-py3-none-win_amd64.whl:

Publisher: release.yml on adamtheturtle/no-defaults

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

File details

Details for the file no_defaults-1.0.1-py3-none-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for no_defaults-1.0.1-py3-none-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 da5ed90cedddebddfbda4bd3fa180eba42b39814e118b7f297cd6f7705edb6a7
MD5 f639cdd5b8c94cffb31690125b59c367
BLAKE2b-256 8a2cff7f38b88649560ca6d18a0a5652c30f969438f0a8d993991825ba8c7ee9

See more details on using hashes here.

Provenance

The following attestation bundles were made for no_defaults-1.0.1-py3-none-manylinux_2_34_x86_64.whl:

Publisher: release.yml on adamtheturtle/no-defaults

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

File details

Details for the file no_defaults-1.0.1-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for no_defaults-1.0.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4584dff7a7bdf632ccff600bae628276ba66a9ede156808e55e6c9c411982d4f
MD5 82baea08d61b9d18ca914d1005ef7f50
BLAKE2b-256 6dde1e7659c6ce5babd9fa57c14463e2b50536b9d6d1754f58db0f0307da6986

See more details on using hashes here.

Provenance

The following attestation bundles were made for no_defaults-1.0.1-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on adamtheturtle/no-defaults

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