Repository navigation
Releases
Releases · gaborbernat/simplint
0.7.1
Changes
blanket-ignore(SMP004) leaves the barenoqa,ruff: noqaandflake8: noqacomments to Ruff's PGH004, and baretype: ignoreandpyright: ignoreto PGH003, when the project's Ruff configuration selects those rules. Thety,pyrefly,simplintandruff: ignoreforms are still reported here (#65) by @gaborbernat.constant-assert(SMP804) leaves a tuple test it cannot fix, such asassert (1, 2, 3), to Ruff's F631 when the project's Ruff configuration selects it. A two-element tuple without a message keeps its report and fix (#65) by @gaborbernat.imprecise-annotation(SMP602) leaves an annotation that is or starts withAny, as inAny | None, to Ruff's ANN401 only when the project's Ruff configuration selects it; without ANN401 it now reports those annotations too (#65) by @gaborbernat.mock-assertion-typo(SMP814) leaves the prefix-less assertion names Ruff's PGH005 reports, such asassert mock.not_called(), to Ruff when the project's Ruff configuration selects it; with Ruff's preview on, names on a line of their own too. Names undernotorand, in call arguments, and every misspelling are still reported here (#65) by @gaborbernat.module-variable-case(SMP102) leaves amixedCasemodule variable it cannot rename to Ruff's N816 when the project's Ruff configuration selects it and does not list the name inpep8-namingignore-names. Renameable names and everylower_casename are still reported here (#65) by @gaborbernat.single-letter-name(SMP101) leavesl,IandOon variables, parameters and except names to Ruff's E741, on classes to E742 and on functions to E743, when the project's Ruff configuration selects them. Other letters, and these letters on imports,matchcaptures and type parameters, are still reported here (#65) by @gaborbernat.single-use-variable(SMP504) leaves a name returned right after its assignment to Ruff's RET504 only when the project's Ruff configuration selects it, and otherwise now reports it; with Ruff's preview on, ayield fromof the name is left to RUF070 when it is selected and writes the same code (#65) by @gaborbernat.star-import(SMP309) leaves a star import its fix cannot rewrite to Ruff's F403 when the project's Ruff configuration selects it, and reports only the ones it can expand (#65) by @gaborbernat.undocumented-public-api(SMP903) leaves the classes, methods and functions of a public module to Ruff's D101, D102, D103 and D106 when the project's Ruff configuration selects them. Public variables, and definitions a private module makes and a public module re-exports, are still reported here (#65) by @gaborbernat.
Bug fixes
- The run after the one that creates the cache directory reuses the documentation it read instead of sometimes walking the documentation again (#60) by @gaborbernat.
Documentation
- Each rule page with a related Ruff rule, issue or pull request names it under Other tools, with its state and how the rule differs (#63) by @gaborbernat.
- The rules table keeps its rows compact on phones, opens a rule from a click anywhere on its row, marks cross-file rules in a column of their own, and shows every filter option in full (#57) by @gaborbernat.
Performance
- Runs are faster: a run over unchanged files skips building the import index and answers from the cache, reports are written in parallel in every output format, the cache stores fixes and the
fulltext of reports ready to use, and the process exits without freeing what it built. On pandas, scipy, SQLAlchemy and CPython, a second run takes half the time or less, a run without a cache 11 to 25% less, and a second run with--output-format jsona quarter of the time. The cache grows by about the size of thefullreport it keeps (#62) by @gaborbernat.
0.7.0
Features
catch-all-module(SMP104) reports modules and packages namedutils,helpersand other grab-bag names, from thenaming.catch-all-moduleslist (#55) by @gaborbernat.cognitive-complexity(SMP529) reports a function whose cognitive complexity, as SonarSource defines it, is over the limit. The score counts each branch, loop and handler more the deeper it is nested, so the rule reads the nesting that Ruff's cyclomatic complexity check ignores. The limit is 20 by default and is set withmax-cognitive-complexityunder[tool.simplint.logic](#55) by @gaborbernat.collection-built-by-statements(SMP531) reports an empty dict, list or set that the statements right after it only fill with entries, and writes those entries in the literal. The fix is safe when every key and value is a constant, and unsafe when one is a name, since a name that is not defined would leave the collection partly filled (#55) by @gaborbernat.duplicate-code(SMP530) reports six or more statements in a row that another module repeats, comparing their tokens, so comments, layout, imports and docstrings do not count. Test modules and stubs are left out, andlogic.min-duplicate-statementssets how many statements a copy needs. It offers no fix (#55) by @gaborbernat.early-assignment(SMP526) reports a local assigned a constant, such as a number, string or a list of them, above the statements that do not use it, when its first use comes further down the same block. Moving the assignment down to that use keeps the value beside the code that reads it. It stays put in a function that reads names by their text, such as withexec,eval,localsorsix.exec_, and when a string between the assignment and the use spells the name (#55) by @gaborbernat.import-cycle(SMP308) reports a runtime import that closes a cycle of modules importing each other when they load. The report names the cycle and sits on the import that closes it. Imports in a function, underif TYPE_CHECKING:, a__main__guard, a false constant or a version check the project's target never passes, andexcept ImportError:fallbacks stay out of it, as do test modules (#55) by @gaborbernat.long-comment-line(SMP007) rewraps comment and docstring paragraphs with a line past the comment width, the lines Ruff'sE501andW505report but cannot fix (#55) by @gaborbernat.long-tuple-return(SMP528) reports a function that returns a tuple of more elements than the limit, which is two by default, since a tuple of three or more values is a record whose fields a dataclass or a named tuple would name. The limit is set withmax-tuple-elementsunder[tool.simplint.logic](#55) by @gaborbernat.loop-in-test(SMP813) reports aforloop in a test function that runs the code under test once per case from a table the file lists, such as a literal or a module constant, and asserts on each result, since the first failure hides the rest. Parameterize the cases instead. Loops over values the test computes,rangesweeps,whileloops, loops that only compare items with one result, and assertions insideself.subTest(...)or pytest'ssubtests.test(...)are left alone (#55) by @gaborbernat.meaningless-name(SMP103) reports variables, parameters and attributes named with a placeholder word such asfoo, from thenaming.meaningless-nameslist (#55) by @gaborbernat.mock-assertion-typo(SMP814) reports mock assertion methods written without theirassert_prefix, such ascalled_once_with, or misspelled, such asassert_called_ones_with, and renames each to the assertion it stands for. The fix is unsafe: a call that checked nothing becomes a check, which may now fail. The unprefixed names return a child mock and pass silently on Python 3.11 and older, and so do the unprefixedawaitednames on every version (#55) by @gaborbernat.restating-comment(SMP005) reports and removes own-line comments that only repeat the code below them (#55) by @gaborbernat.star-import(SMP309) reportsfrom module import *when the project definesmoduleand the file uses its names, and replaces the*with the names the file reads from it. The fix is safe when the module lists its exports in__all__, and unsafe otherwise (#55) by @gaborbernat.string-statement-comment(SMP006) reports triple-quoted strings used as comments and writes them as#comments (#55) by @gaborbernat.super-forwarding-method(SMP527) reports a method whose only statement returns the same method ofsuper()called with its own arguments, such asreturn super().load(name), when the module defines the parent's method with the same parameters. Deleting the method lets the subclass inherit the parent's method. The fix is not offered for an annotated method, since its annotations are the types the subclass declares (#55) by @gaborbernat.test-only-parameter(SMP410) reports defaulted parameters that only test calls pass, while production calls leave them at their default (#55) by @gaborbernat.unused-definition(SMP409) reports functions, classes, methods and class attributes that nothing in the run uses. Public names of a library and names other code may read are left alone, and so are the names the project's Sphinx documentation gives through roles, autodoc directives or sphinx-argparse options (#55) by @gaborbernat.unused-fixture(SMP815) reports pytest fixtures that no test or fixture requests, by parameter, by a string such as ausefixturesorgetfixturevalueargument, or through the fixture function (#55) by @gaborbernat.unused-return-value(SMP411) reports functions that production code calls without reading the value they return (#55) by @gaborbernat.up-compression-modules(SMP523) reports imports ofgzip,bz2,lzmaandzlibfrom Python 3.14, where thecompressionpackage names them. The fix is unsafe:compressionre-exports the modules, so patches of the old module names do not reach the new ones (#55) by @gaborbernat.up-deprecated-stdlib-alias(SMP525) reports deprecated or removed standard library names that have a replacement, such asthreading.currentThread,calendar.Januaryandconfigparser.SafeConfigParser, from the Python version that deprecates or removes them. Renames are fixed; names that need a review are only reported (#55) by @gaborbernat.up-re-prefixmatch(SMP522) reportsre.match()from Python 3.15, wherere.prefixmatch()is the same function under a clearer name. The fix renames the call (#55) by @gaborbernat.up-utf8-encoding-default(SMP521) reportsencoding="utf-8"onopen(),io.open(),Pathtext methods and similar calls from Python 3.15, where UTF-8 is the default encoding. Its fix is unsafe: UTF-8 mode can be turned off withPYTHONUTF8=0or-X utf8=0(#55) by @gaborbernat.up-warnings-deprecated(SMP524) reports functions and classes that start with aDeprecationWarningwarning from Python 3.13, where@warnings.deprecatedmarks them for type checkers. The fix is unsafe: a class then warns when instantiated, not when defined (#55) by @gaborbernat.
Changes
constructor-after-method(SMP203) is renamedclass-member-order, and it now orders the whole class body rather than only its constructors. A class body reads in sections: nested classes, class attributes, constructors in the order Python runs them, alternative constructors, other dunder methods, properties, then methods. A member that sits above a member of an earlier section is reported, with the section it belongs with, and one fix moves the members into place. A helper still follows its first caller, whatever its section, anddefinition-before-use(SMP201) and this rule compute the same order, so one--fixsettles a class body. Both count moving a method whose decorators are all pure, ...
0.6.0
Features
constructor-after-method(SMP203) reports a constructor (__new__,__init__,__post_init__or__init_subclass__) defined below another method of its class, and moves it above that method.definition-before-use(SMP201) no longer moves a constructor below a method that calls it, so the two fixes agree (#54) by @gaborbernat.
Bug fixes
definition-before-use(SMP201) reads a method's first parameter as the instance or class whatever its name, soklass._make()in a classmethod counts as a use, as doklass().load()and a local that a method assigns fromklass()orsuper().__new__(klass). A lambda in a class body, asproperty(lambda self: self._load()), reads its first parameter the same way. Astaticmethodhas no such parameter, soselforclsin one no longer counts as a use (#54) by @gaborbernat.
0.5.1
Bug fixes
dataclass-frozen(SMP701) anddataclass-slots(SMP702) treat whatever a method names its first parameter as the instance, not onlyself, so attributes set throughdef m(this)count (#50) by @gaborbernat.mock-without-spec(SMP806) flagsPropertyMocktoo, matching the mock classes the project index knows (#50) by @gaborbernat.up-asyncio-iscoroutinefunction(SMP516) adds itsinspectimport in the standard-library section, where isort puts it, asup-chdir-restore(SMP513) andmissing-final(SMP601) do (#50) by @gaborbernat.
Security
simplint cleanno longer follows a.ruff_cachethat is a symlink, which could delete asimplintdirectory outside the project (#50) by @gaborbernat.
Performance
- Repeated runs without
--fixreuse the cached reports of files that did not change, rather than only skipping files that had none, and the project index resolves each imported module once per directory (#50) by @gaborbernat.
0.5.0
Features
- simplint publishes a JSON Schema of the
[tool.simplint]table assimplint.schema.json, which editors use to check the table as the user types.simplint config-schemaprints it (#46) by @gaborbernat. - Types in a public signature count as public API: a class or alias that an exported name's annotations or bases refer to is no longer reported as unused in
__all__, and missing-from-all lists it there (#47) by @gaborbernat. up-argparse-suggest-on-error(SMP519) flagssuggest_on_error=Trueinargparse.ArgumentParser()calls, which Python 3.15 makes the default, with a safe fix that drops the keyword (#48) by @gaborbernat.up-asyncio-iscoroutinefunction(SMP516) flagsasyncio.iscoroutinefunction()calls, whichinspect.iscoroutinefunction()replaces, with an unsafe fix since the two differ for legacy coroutine markers (#48) by @gaborbernat.up-backport-import(SMP305) flags imports of backports the standard library replaced, such astomlifortomllibon Python 3.11 and later; thetomliandexceptiongroupimports get a fix (#48) by @gaborbernat.up-chdir-restore(SMP513) flags a working directory restored in afinallyclause, whichcontextlib.chdirdoes on Python 3.11 and later, with a safe fix that adds thecontextlibimport (#48) by @gaborbernat.up-codecs-open(SMP517) flagscodecs.open()calls, which the builtinopen()replaces withnewline=""and an encoding, with an unsafe fix since line iteration differs for some separators (#48) by @gaborbernat.up-comprehension-unpacking(SMP508) flags a nestedforclause that only unpacks its iterable, which Python 3.15 lets the element do with*or**, with a safe fix for lists, sets and generators (#48) by @gaborbernat.up-context-var-token-reset(SMP512) flags aContextVar.set()token that atryblock resets in itsfinallyclause, which awithblock does on Python 3.14 and later, with a safe fix (#48) by @gaborbernat.up-event-loop-in-coroutine(SMP515) flagsasyncio.get_event_loop()calls in coroutines, whichasyncio.get_running_loop()replaces on Python 3.10 and later, with a safe fix (#48) by @gaborbernat.up-exc-info-exception(SMP510) flagssys.exc_info()reads of the exception being handled, whichsys.exception()returns directly on Python 3.11 and later, with a safe fix (#48) by @gaborbernat.up-lazy-modules-list(SMP307) flags a__lazy_modules__list whose imports Python 3.15 can spell aslazy import, and fixes both (#48) by @gaborbernat.up-object-sentinel(SMP511) flags module and class constants assigned a bareobject(), which the Python 3.15sentinelbuiltin names, with an unsafe fix since the repr changes (#48) by @gaborbernat.up-re-error-alias(SMP518) flagsre.errorreferences, whichre.PatternErrorreplaces on Python 3.13 and later, with a safe fix (#48) by @gaborbernat.up-removed-ast-node(SMP520) flagsast.Num,ast.Str,ast.Bytes,ast.NameConstantandast.Ellipsisreferences andvisit_methods that Python 3.14 removed, with safe fixes for the commonisinstanceand constructor forms (#48) by @gaborbernat.up-strptime-date(SMP514) flagsdatetime.strptime(...).date()and.time()calls, whichdate.strptimeandtime.strptimereplace on Python 3.14 and later, with a safe fix for dates and for times in literal formats without%z(#48) by @gaborbernat.up-traceback-exception-arguments(SMP509) flagstracebackcalls that pass an exception's type and traceback next to the exception, which Python 3.10 reads from the exception, with a safe fix (#48) by @gaborbernat.up-type-checking-lazy-import(SMP306) flagsif TYPE_CHECKING:blocks of imports that Python 3.15 can spell aslazyimports, with an unsafe fix (#48) by @gaborbernat.up-unittest-assert-helper(SMP811) flagsassertTrueandassertFalseonstartswith,endswith,hasattrandissubclasschecks inTestCasemethods, which the Python 3.14assertStartsWithfamily replaces (#48) by @gaborbernat.up-unittest-enter-context(SMP812) flags a patch that aTestCasemethod starts and stops by hand, whichself.enterContextreplaces on Python 3.11 and later (#48) by @gaborbernat.
Bug fixes
constant-assert(SMP804) no longer offers a fix that writes invalid syntax when the tuple holds a walrus or a starred element: a walrus check gets parentheses, and a tuple with a starred element gets no fix (#47) by @gaborbernat.dataclass-kw-only(SMP703) passes the fields of a call in an f-string=debug field by keyword without changing the printed text. The call's source text stays, and its value follows in a plain field (#47) by @gaborbernat.definition-before-use(SMP201) no longer reads the bound or default of a type parameter, or the value of atypestatement, as a read at import time. A helper that the same function calls is reported again (#47) by @gaborbernat.dependency-import-guard(SMP303) counts a submodule of a standard library package, such asasyncio.taskgroups, as shipped only from the version that adds it, using a table generated from CPython'sLib/trees, so the guard around it is reported on the targets that have it. Its unsafe fix removed an import left unused by the unwrap, such asimport string.templatelibchecked only for existence, and keeps it now with anoqasuppression. The guards around_zstd,compression.zstdand_cursesstay unreported (#47) by @gaborbernat.function-docstring(SMP901) reads the functions in amatchstatement'scasebodies, at module and class level, as it already reads those inifandtryblocks, so a docstring on an internal one is reported (#47) by @gaborbernat.future-annotations(SMP301) no longer reports the import when a class annotation reads a name the class body binds, such as a method namedlistindef list(self) -> list[str]. Without the import, Python 3.14 and later evaluate that annotation in the class namespace, wherelistis the method (#47) by @gaborbernat.imprecise-annotation(SMP602) now also reportsobjectandAnyin the value of atypestatement and in the bounds and defaults of type parameters (#47) by @gaborbernat.indistinct-error-class(SMP704) no longer reports an exception class that a handler selects throughExceptionGroup.split(...)or.subgroup(...)(#47) by @gaborbernat.init-module-content(SMP407) accepts__lazy_modules__in a public package's__init__.py, which Python 3.15 reads from the module globals to make the package's imports lazy (#47) by @gaborbernat.module-attribute-import(SMP304) keeps thelazykeyword when its fix rewrites a lazy import, so the module still loads on first use of a name. Its fix is no longer offered when a parameter, local, comprehension target, match capture or type parameter of the same name would take the bare name, which mademake[Item]call aTypeVar(#47) by @gaborbernat.module-variable-case(SMP102) no longer renames a name read in a t-string, where the kept text would change. The name is still reported, without a fix. A name read in an f-string=debug field is renamed with the printed text unchanged (#47) by @gaborbernat.module-variable-case(SM...
0.4.0
Features
blanket-ignore(SMP004) flags every suppression comment that names no error code, such as a bare# noqa, a# ruff: noqa, or a# type: ignoreor# ty: ignorewithout brackets (#34) by @gaborbernat.simplint rule, its JSON output and the documentation mark the rules that read other files of the run, whose results another file can change (#34) by @gaborbernat.dataclass-slots(SMP702) asks forslots=Trueon a dataclass decorator and its fix adds it, unless checked code breaks the slotted class (#34) by @gaborbernat.- Telling exceptions apart by the text of their message is reported as
error-message-matching(SMP507) (#34) by @gaborbernat. - Flags exception classes that no
exceptclause names, so a built-in exception could replace them (#34) by @gaborbernat. long-docstring-paragraph(SMP904) flags a docstring paragraph longer thanmax-paragraph-wordswords, aslong-paragraph(SMP002) does for comments (#34) by @gaborbernat.module-attribute-import(SMP304) flagsmodule.Nameaccess to a module of the project, which an import ofNamereplaces. The newimports.module-attributesoption leaves the modules it lists alone (#34) by @gaborbernat.module-variable-prefix(SMP404) flags a module variable whose leading underscore does not match its visibility: a name that no other module imports and__all__does not list needs one, and a name__all__lists must not have one (#34) by @gaborbernat.long-paragraph(SMP002) and the newlong-docstring-paragraph(SMP904) read their limit from the newmax-paragraph-wordsoption, 100 words by default (#34) by @gaborbernat.rst-empty-field(SMP914) reports:param:,:raises:,:returns:,:yields:and:var:fields with no description, whichrst-field-syntaxreported before. The fixes of the missing-field rules add such fields, so this rule can be turned off on its own (#34) by @gaborbernat.simplint rules --output-format jsonnow lists each rule's examples as parsed blocks with their line numbers, and each rule's short group title. A rule page whose examples do not parse reports the error in place of its examples (#34) by @gaborbernat.- SMP505 flags a private helper with one short call site, which inlining into its caller would keep short (#34) by @gaborbernat.
- SMP504 flags a function local that is assigned once and read once, right below the assignment (#34) by @gaborbernat.
sleep-in-test(SMP808) flagstime.sleepandasyncio.sleepcalls in test modules that wait on a fixed time (#34) by @gaborbernat.split-composite-assert(SMP807) flags consecutive asserts that compare fields of one object one by one, and its unsafe fix joins them into one assert over a tuple (#34) by @gaborbernat.stdlib-mock(SMP809) flagsunittest.mockimports in test modules of projects that depend on pytest-mock (#34) by @gaborbernat.- Flags module-level functions and classes that only test modules use, so they can move into the tests (#34) by @gaborbernat.
- A parameter default that every call in the run passes explicitly is reported as
unused-default(SMP506), with an unsafe fix that removes it (#34) by @gaborbernat.
Changes
- missing-final (SMP601) also reports a bare
Finalannotation and fills in its type (#34) by @gaborbernat. dataclass-options(SMP701) is renamed todataclass-frozenand asks only forfrozen=True. Its fix no longer addsslots=True, whichdataclass-slots(SMP702) now asks for (#34) by @gaborbernat.rst-field-syntaxnow reports aliases of field names, such as:arg:or:return:, and its fix renames them to:param:,:raises:,:returns:or:yields:.:var:,:ivar:and:cvar:stay distinct (#34) by @gaborbernat.imprecise-annotation(SMP602) reportsobjectin any annotation andAnywhere Ruff's ANN401 does not: in variable annotations and nested positions such asdict[str, Any](#34) by @gaborbernat.module-variable-case(SMP102) checks only the case of module variables,UPPER_CASE, and keeps the leading underscore a name has. The underscore is checked by the newmodule-variable-prefix(SMP404) (#34) by @gaborbernat.- Rule codes now follow their group: the first digit names one of ten groups, so a prefix selects a whole group, such as
SMP4for Public API. The groups are Comments (SMP0), Naming (SMP1), Module layout (SMP2), Imports and dependencies (SMP3), Public API (SMP4), Logic (SMP5), Typing (SMP6), Classes (SMP7), Tests (SMP8) and Docstrings (SMP9) (#34) by @gaborbernat. rst-field-syntaxno longer reports fields with no description;rst-empty-fielddoes (#34) by @gaborbernat.- The
docstring-stylevalue and the reStructuredText rule names userst, such asdocstring-style = "rst"andrst-field-syntax(#34) by @gaborbernat. - Rules now group by what they check, one group per topic such as Naming, Public API or Docstrings, instead of four groups by code range.
simplint linterlists each group with its rule codes (#34) by @gaborbernat. single-letter-name(SMP101) now reportsforloop targets such asiinfor i in range(3), since a loop body can run far from the line that says what the name holds. Names inside comprehensions stay exempt (#35) by @gaborbernat.
Bug fixes
- A
cache-dirinpyproject.tomlthat points outside the project is ignored, and the cache goes to Ruff's default directory inside it. Stale cache removal now touches only directories of other simplint builds, so acache-dircan no longer delete directories outside the project. The command line andRUFF_CACHE_DIRstill choose any directory (#34) by @gaborbernat. - Deeply nested expressions, such as a list nested ten thousand levels deep or a
+chain of that length, no longer crash simplint with a stack overflow (#34) by @gaborbernat. --fixand--diffgive the same result on every run; some fixes used to vary between runs because they followed the iteration order of randomly seeded hash maps (#34) by @gaborbernat.- With
--diffon several files, the diffs print in the same file order on every run, instead of in the order the files finished linting (#34) by @gaborbernat. - When an
extended configuration file outside the project is not valid, simplint reports its path without its text, so the first line of an arbitrary file no longer appears in the error (#34) by @gaborbernat. - A fix loop that does not settle stops with a "Failed to converge" error after 100 rounds, as the loop within a round already did, instead of running on (#34) by @gaborbernat.
- A symlink to a file outside the paths being checked is skipped with a warning.
--fixno longer writes through it, and the report no longer shows the text of the file it points at (#34) by @gaborbernat.
Documentation
- The README and documentation pages are split ...
0.3.0
Features
- The docstring rules share the new
SMP3group, soselect = ["SMP3"]picks all of them:function-docstringis SMP300 (was SMP002),test-module-docstringSMP301 (was SMP004) andundocumented-public-apiSMP302 (was SMP116); updateselect,ignoreandnoqacomments that name the old codes. Docstrings no longer have a length limit:multiline-module-docstring(SMP003) is gone, andlong-paragraph(SMP005) checks comments only (#27) by @gaborbernat. undocumented-public-api(SMP302) andfunction-docstring(SMP300) now follow a library's public API as the typing spec and PEP 8 define it: modules under a_-prefixed path are internal, a public module without__all__offers every name without a leading underscore, and a name a public module re-exports through__all__,from m import name as nameorimport *needs its docstring where it is defined. A name another module imports counts as public only in a public module, wheremissing-from-all(SMP113) lists it in__all__, and an application, which nothing installs, has no public API at all. The newproject-kind,api-packagesandapi-modulessettings tune this (#27) by @gaborbernat.init-module-content(SMP109) lets a public package of a library re-export its API from private modules (#27) by @gaborbernat.- The new reStructuredText rules, SMP310 to SMP323, check reStructuredText field lists in docstrings when
docstring-style = "rest": every field is well formed, described with more than its name and separated from the text above by a blank line, documents a parameter or attribute that exists, with:ivar:or:cvar:as fits, once, and carries no type, which belongs in annotations; roles keep their backticks and inline literals close; a public function or class documents each parameter, attribute, return or yield value and exception it raises itself, and no internal name. Their fixes add each missing field with an empty description for you to fill in, and remove or correct fields for what no longer exists (#27) by @gaborbernat. unused-export(SMP117) removes names from__all__that no other module of the run imports, keeping the__all__of a library's top-level package and of the modulesapi-modulesnames as written (#27) by @gaborbernat.
Bug fixes
--fix,--add-noqaand--add-ignorewrite a file by renaming a complete copy over it, so a failed write no longer leaves a cut-short source, and a file edited during the run keeps the edit. A symlink stays a symlink and the file keeps its permissions (#33) by @gaborbernat.- A run no longer deletes the new, still empty cache directory of another simplint version running at the same time, as pre-commit and the command line can, which made that other run fail (#33) by @gaborbernat.
- A development build no longer warns that it cannot read the cache an earlier build of the same version wrote, and the caches of other builds go away once no run has written to them for 30 days (#27) by @gaborbernat.
- A file that linted clean is checked again when a name moves between two of the run's sets, as from a name read off a module to a base class, instead of reusing its stale cached result (#33) by @gaborbernat.
dataclass-kw-only(SMP114) rewrites a positional call that anoqacomment for another code sits on, or that holdsnoqain a string, instead of leaving the dataclass withoutkw_only=True; only a comment that suppresses SMP114 keeps the call as it is (#33) by @gaborbernat.string-concatenation(SMP112) no longer slows to a crawl on a function where many names each extend themselves in turn, astext = text + "!"does; such chains now take time in proportion to their length (#33) by @gaborbernat.suppression-without-reason(SMP060) reads suppression comments the way they take effect, so it now also flags# flake8: noqaand a directive with extra space around its colon, such as# ruff : ignore[...](#33) by @gaborbernat.test-class(SMP200) now fixes a class whose methods have docstrings spanning several lines, as it does onceruff formathas joined them, so one round of fixes settles (#28) by @gaborbernat.undocumented-public-api(SMP302) and the reStructuredText attribute rules now see the docstring under a variable defined in anifortryblock, so they no longer report it as undocumented (#33) by @gaborbernat.
Documentation
- The changelog page renders again when a release lists no changes (#18) by @gaborbernat.
- The pre-commit setup uses the
simplint-pre-commitmirror, which installs the released wheel and so runs on pre-commit.ci without a Rust toolchain (#27) by @gaborbernat. - The PyPI page shows a short introduction with links to the documentation instead of the full documentation pages (#20) by @gaborbernat.
0.2.2
Bug fixes
- Release wheels build again: the profile-guided optimization run no longer stops on the Ruff docstring rules simplint refuses to run beside (#17) by @gaborbernat.
0.1.0
Features
- First release: 32 rules for the parts of the simp house style Ruff has no rule for, with safe and unsafe fixes and a cross-module import index by Bernát Gábor.