Changelog¶
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]¶
Added¶
--output-formatchooses the output:grouped(the default) prints each file once with its findings below it,fulladds a hint under each finding,conciseis the former one-line output for editors and CI, andjsonis the former--json.- JSON output includes
hint.Findinghas a newhintfield. - A
[tool.namelint]table inpyproject.tomlsetsselect,ignore,excludeandoutput-format. The command line's--selectand--output-formatreplace the configured values, and--ignoreadds to them. An unknown key is an error. namelint explain [CODE] [--level junior|senior|expert]explains the naming conventions, or one check, at three depths.--output-format githubprints GitHub Actions annotations.--exit-zeroreports findings and exits 0.--show-settingsprints the resolved settings with the path of theirpyproject.toml.--force-excludeappliesexcludeto files named on the command line, for pre-commit.- A pre-commit hook,
namelint, in.pre-commit-hooks.yaml. per-file-ignoresin[tool.namelint]skips checks in files matching a path pattern.- Directory walks skip what git ignores. Set
respect-gitignore = falseto walk all files. namelint allow --prunealso removes allowlist entries that match no finding.
Changed¶
- Linting is now
namelint check PATH.... A barenamelint PATH...is an error. With no path,checklints the current directory. namelint initwrites[tool.namelint]with each setting at its default, as well as the empty allowlist. It refuses to run when[tool.namelint]already exists.--jsonis replaced by--output-format json.- The command line is built on Cyclopts, namelint's first runtime dependency. The checks still import nothing beyond
ast. - The default output is grouped by file. Use
--output-format concisefor the previouspath:line:col:lines. Finding.messageno longer contains the advice, which moved toFinding.hint.- A returned expression quoted in a
NAM103orNAM104message is cut at 40 characters.
[0.2.0] - 2026-10-15¶
Added¶
NAM102: a@propertywhose name opens with a word the UD English treebanks tag as a bare verb at least 90% of the time. The table is derived bytools/build_verb_table.pyand shipped as package data.NAM104: a command verb (set_,reset_,clear_,update_, …) that returns a value. Replaces the specified "bool under a non-predicate name", which found nothing genuine in the corpus (0 of 9).NAM105: a value verb (get_,find_,to_,as_,format_, …) whose body never returns a value.NAM108: a method whose name repeats its class name as a run of words.- An allowlist:
[tool.namelint.allow]inpyproject.tomlmaps a code to function names orClass.methodpatterns, with shell wildcards. namelint initadds an empty[tool.namelint.allow]table topyproject.toml;namelint init --accept-existingfills it with every current finding, for adopting namelint on an existing codebase.namelint allowadds the current findings to the allowlist. Both accept--select/--ignoreand paths, and rewrite only the[tool.namelint.allow]table.--jsonoutput includesqualname(Class.method).Findinghas a newownerfield.
Fixed¶
--statscounted nested functions, which no check reads, so every rate was understated by up to a third. The calibration table is re-measured over 71,274 functions (previously 85,368).--selectand--ignoreexit 2 on an unknown code.NAM101reported unittest'ssetUp/tearDownand pytest'ssetup_module-style hooks, a third of its corpus findings. Setup and teardown hooks are now exempt.NAM107suggestediter__entryfor a private_entry; it now suggests_iter_entry.- An allowlist entry containing a backslash or a quote was written back unescaped, which changed the pattern.
Changed¶
NAM103treatscheck_as a predicate prefix. Acheck_annotated-> Nonestays quiet, since it answers by raising.NAM107is opt-in: it runs only with--select NAM107, while it fires 17 times per thousand functions inhttpx.- The library API is renamed so namelint passes its own lint:
check_moduleandcheck_sourceare nowlint_moduleandlint_source. Each check is namedfind_<what it reports>. --no-allowlistreports every finding, allowlist or not.
[0.1.0] - 2026-10-02¶
This first release claims the name on PyPI. Four of the eight specified checks are implemented; NAM107 is on probation.
Added¶
NAM101: a function in a test module that contains an assertion, takes no arguments, and is not namedtest*, so pytest never collects it.NAM103: anis_/has_/can_/should_/was_that returns a non-bool, read from the return annotation or from an evidently non-bool return. Two findings in 85,368 corpus functions, both genuine.NAM106: aget_whose body reaches a disk, a socket, a subprocess or a database.NAM107: a generator whose name reads as if it returned a container.- The
namelintCLI:--select,--ignore,--json,--stats,--version. Exit 0 clean, 1 findings, 2 the tool itself failed. tools/calibrate.py: fetches the nine-project golden corpus and measures every check against it, writing a summary table, every finding as JSONL, and a seeded sample to adjudicate by hand.
Known¶
NAM107fires at 15.9 per thousand functions inhttpxand 13.7 inrich. That rate puts the rule in question; it says nothing about those codebases. The false-positive class is the undecorated protocol generator.- Configuration and suppression are both absent; they wait on corpus evidence about what needs suppressing.