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=...). ClassVar assignments are ignored because they are not dataclass fields.

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.

The scheduled Typeshed benchmark workflow repeats this against a pinned upstream revision and fails on parser errors, unexpected results, or a gross performance regression.

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.0.tar.gz (25.6 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.0-py3-none-win_amd64.whl (1.9 MB view details)

Uploaded Python 3Windows x86-64

no_defaults-1.0.0-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.0-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.0.tar.gz.

File metadata

  • Download URL: no_defaults-1.0.0.tar.gz
  • Upload date:
  • Size: 25.6 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.0.tar.gz
Algorithm Hash digest
SHA256 dfaaa9ad0e009c3af3e498d304368fb8d3a6973e029a8d3273aec6b6fc3bd282
MD5 b71914fa07d8b4486b740e7bca6a38cd
BLAKE2b-256 a231a26d2ccff9c4935006385b77e121b20ca1b73677ea0cd76b53255769043a

See more details on using hashes here.

Provenance

The following attestation bundles were made for no_defaults-1.0.0.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.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: no_defaults-1.0.0-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.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 2e300d41386161bd9d9726939c2e6b10632d17acc154dd4ac3542a6eeb862f57
MD5 0ff7a7e0993394a78ea79ec55c39923a
BLAKE2b-256 9ec026ef1e7cf4508b60ec15458fddd8988136493f14cd799b21fb7a0d60c620

See more details on using hashes here.

Provenance

The following attestation bundles were made for no_defaults-1.0.0-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.0-py3-none-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for no_defaults-1.0.0-py3-none-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 0a43a1ef8b9a99d0e6a106bade1840e4ccf25933d32247b310e66f8abf9edb48
MD5 de82ca2f8d7e6e88f9fc3a6952e66c89
BLAKE2b-256 3cdee51079006752bcbd4f46285b7abf945772a298650e16de4f58fb163b74c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for no_defaults-1.0.0-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.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for no_defaults-1.0.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8e29dc5a41f1f55f01e81a4172f695c981f6475e5293b44ae3b00b1b381ef459
MD5 fde072b1384a2e11c8149b71625c2562
BLAKE2b-256 29a94383807e8f257e7112e7f18c20cd4a0fe1151fa0a906d88b1eaae394f39e

See more details on using hashes here.

Provenance

The following attestation bundles were made for no_defaults-1.0.0-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