Skip to main content

Static checks distilled from real upstream bugs that off-the-shelf linters miss.

Project description

wildlint

CI PyPI

Static checks distilled from real upstream bugs — the kind off-the-shelf linters miss because they look like ordinary, working code.

Every rule here was born from a concrete bug that was found and fixed in a public project, then generalized to the smallest static check that still catches the class without flooding you with false positives. If a bug could not be turned into a low-noise rule, it is documented as not-shipped rather than added as noise (see Not shipped).

Install

pip install wildlint

Use

wildlint path/to/code        # scan a file or directory (default: .)
wildlint --select WL001,WL002 src/
wildlint --pedantic src/     # also run opt-in, higher-false-positive rules

Exits non-zero when anything is found, so it drops straight into CI or a pre-commit hook.

pre-commit

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/patchwright/wildlint
    rev: v0.1.0
    hooks:
      - id: wildlint

CI (GitHub Actions)

- run: pip install wildlint
- run: wildlint src/

Rules

Code Tier Catches Distilled from
WL001 default x.replace(P, "") guarded by x.startswith(P)/endswith(P) — removes every occurrence, silently corrupting values that contain the marker twice. Meant str.removeprefix/removesuffix. nephila/giturlparse#149
WL002 default s.split(' ') where s.split() was meant — keeps empty tokens and skips whitespace collapsing/trimming, leaking blanks downstream. Advisory: only an exact single-space literal fires. derek73/python-nameparser#164
WL003 pedantic x[-k] with k >= 2IndexError when the sequence is shorter than k. Opt-in because deep negative indexing is often provably safe from context the checker can't see. savoirfairelinux/num2words#661

Each rule is verified against the actual pre-fix source of the project it came from — see the tests, and the rule docstrings in src/wildlint/checkers.py.

Bugs considered but not shipped

Some real bugs do not generalize into a low-false-positive static rule. They are recorded in NON_GENERALIZED in checkers.py so the reasoning is preserved:

  • break-vs-continue (mnamer#371) — whether break should be continue is entirely loop-intent dependent.
  • sign-doubling (humanize#326) — a numeric-formatting concern, not a syntactic pattern.
  • validation-branch-order (validators#463) — specific to one parser's control flow.
  • radix-from-ignored-param (shortuuid#115) — requires matching a docstring contract to the implementation.

Adding a rule

A checker is any object with code, name, tier, and check(tree, path) -> list[Finding]. Append an instance to CHECKERS in checkers.py and add positive/negative tests mirroring the wild bug. That's the whole extension surface — the suite grows one real bug at a time.

License

MIT.

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

wildlint-0.1.0.tar.gz (10.0 kB view details)

Uploaded Source

Built Distribution

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

wildlint-0.1.0-py3-none-any.whl (9.4 kB view details)

Uploaded Python 3

File details

Details for the file wildlint-0.1.0.tar.gz.

File metadata

  • Download URL: wildlint-0.1.0.tar.gz
  • Upload date:
  • Size: 10.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for wildlint-0.1.0.tar.gz
Algorithm Hash digest
SHA256 83729d696d21831b0ec29b911accf391b24e907bdb99c7f517b96b304f0dc510
MD5 9407e7cb387c4c232d5765390c96889b
BLAKE2b-256 5fed808bc8ac93513f0e653f8473590b2c6e8375c71261c3de0659a9d0c8a77f

See more details on using hashes here.

Provenance

The following attestation bundles were made for wildlint-0.1.0.tar.gz:

Publisher: release.yml on patchwright/wildlint

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

File details

Details for the file wildlint-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: wildlint-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for wildlint-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1a13986fc08334d0d3e890a1e50ce22cfc0f625741b617053eb86632956a7d9d
MD5 52a12329063775fe4eb3917880be6d52
BLAKE2b-256 c246ff17b9d18bfecdf2d55fbaa88adbc35f8125153b8041f59d2e11139346e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for wildlint-0.1.0-py3-none-any.whl:

Publisher: release.yml on patchwright/wildlint

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