Skip to content

Releases

0.7.1

Choose a tag to compare

@github-actions github-actions released this 06 Nov 21:22

Changes

  • blanket-ignore (SMP004) leaves the bare noqa, ruff: noqa and flake8: noqa comments to Ruff's PGH004, and bare type: ignore and pyright: ignore to PGH003, when the project's Ruff configuration selects those rules. The ty, pyrefly, simplint and ruff: ignore forms are still reported here (#65) by @gaborbernat.
  • constant-assert (SMP804) leaves a tuple test it cannot fix, such as assert (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 with Any, as in Any | 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 as assert 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 under not or and, in call arguments, and every misspelling are still reported here (#65) by @gaborbernat.
  • module-variable-case (SMP102) leaves a mixedCase module variable it cannot rename to Ruff's N816 when the project's Ruff configuration selects it and does not list the name in pep8-naming ignore-names. Renameable names and every lower_case name are still reported here (#65) by @gaborbernat.
  • single-letter-name (SMP101) leaves l, I and O on 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, match captures 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, a yield from of 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 full text 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 json a quarter of the time. The cache grows by about the size of the full report it keeps (#62) by @gaborbernat.

🐍 PyPI release

📜 Full Changelog

0.7.0

Choose a tag to compare

@github-actions github-actions released this 06 Nov 09:12

Features

  • catch-all-module (SMP104) reports modules and packages named utils, helpers and other grab-bag names, from the naming.catch-all-modules list (#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 with max-cognitive-complexity under [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, and logic.min-duplicate-statements sets 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 with exec, eval, locals or six.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, under if TYPE_CHECKING:, a __main__ guard, a false constant or a version check the project's target never passes, and except 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's E501 and W505 report 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 with max-tuple-elements under [tool.simplint.logic] (#55) by @gaborbernat.
  • loop-in-test (SMP813) reports a for loop 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, range sweeps, while loops, loops that only compare items with one result, and assertions inside self.subTest(...) or pytest's subtests.test(...) are left alone (#55) by @gaborbernat.
  • meaningless-name (SMP103) reports variables, parameters and attributes named with a placeholder word such as foo, from the naming.meaningless-names list (#55) by @gaborbernat.
  • mock-assertion-typo (SMP814) reports mock assertion methods written without their assert_ prefix, such as called_once_with, or misspelled, such as assert_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 unprefixed awaited names 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) reports from module import * when the project defines module and 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 of super() called with its own arguments, such as return 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 a usefixtures or getfixturevalue argument, 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 of gzip, bz2, lzma and zlib from Python 3.14, where the compression package names them. The fix is unsafe: compression re-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 as threading.currentThread, calendar.January and configparser.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) reports re.match() from Python 3.15, where re.prefixmatch() is the same function under a clearer name. The fix renames the call (#55) by @gaborbernat.
  • up-utf8-encoding-default (SMP521) reports encoding="utf-8" on open(), io.open(), Path text 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 with PYTHONUTF8=0 or -X utf8=0 (#55) by @gaborbernat.
  • up-warnings-deprecated (SMP524) reports functions and classes that start with a DeprecationWarning warning from Python 3.13, where @warnings.deprecated marks 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 renamed class-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, and definition-before-use (SMP201) and this rule compute the same order, so one --fix settles a class body. Both count moving a method whose decorators are all pure, ...
Read more

0.6.0

Choose a tag to compare

@github-actions github-actions released this 05 Nov 18:51

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, so klass._make() in a classmethod counts as a use, as do klass().load() and a local that a method assigns from klass() or super().__new__(klass). A lambda in a class body, as property(lambda self: self._load()), reads its first parameter the same way. A staticmethod has no such parameter, so self or cls in one no longer counts as a use (#54) by @gaborbernat.

🐍 PyPI release

📜 Full Changelog

0.5.1

Choose a tag to compare

@github-actions github-actions released this 05 Nov 10:03

Bug fixes

  • dataclass-frozen (SMP701) and dataclass-slots (SMP702) treat whatever a method names its first parameter as the instance, not only self, so attributes set through def m(this) count (#50) by @gaborbernat.
  • mock-without-spec (SMP806) flags PropertyMock too, matching the mock classes the project index knows (#50) by @gaborbernat.
  • up-asyncio-iscoroutinefunction (SMP516) adds its inspect import in the standard-library section, where isort puts it, as up-chdir-restore (SMP513) and missing-final (SMP601) do (#50) by @gaborbernat.

Security

  • simplint clean no longer follows a .ruff_cache that is a symlink, which could delete a simplint directory outside the project (#50) by @gaborbernat.

Performance

  • Repeated runs without --fix reuse 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.

🐍 PyPI release

📜 Full Changelog

0.5.0

Choose a tag to compare

@github-actions github-actions released this 05 Nov 05:26

Features

  • simplint publishes a JSON Schema of the [tool.simplint] table as simplint.schema.json, which editors use to check the table as the user types. simplint config-schema prints 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) flags suggest_on_error=True in argparse.ArgumentParser() calls, which Python 3.15 makes the default, with a safe fix that drops the keyword (#48) by @gaborbernat.
  • up-asyncio-iscoroutinefunction (SMP516) flags asyncio.iscoroutinefunction() calls, which inspect.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 as tomli for tomllib on Python 3.11 and later; the tomli and exceptiongroup imports get a fix (#48) by @gaborbernat.
  • up-chdir-restore (SMP513) flags a working directory restored in a finally clause, which contextlib.chdir does on Python 3.11 and later, with a safe fix that adds the contextlib import (#48) by @gaborbernat.
  • up-codecs-open (SMP517) flags codecs.open() calls, which the builtin open() replaces with newline="" and an encoding, with an unsafe fix since line iteration differs for some separators (#48) by @gaborbernat.
  • up-comprehension-unpacking (SMP508) flags a nested for clause 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 a ContextVar.set() token that a try block resets in its finally clause, which a with block does on Python 3.14 and later, with a safe fix (#48) by @gaborbernat.
  • up-event-loop-in-coroutine (SMP515) flags asyncio.get_event_loop() calls in coroutines, which asyncio.get_running_loop() replaces on Python 3.10 and later, with a safe fix (#48) by @gaborbernat.
  • up-exc-info-exception (SMP510) flags sys.exc_info() reads of the exception being handled, which sys.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 as lazy import, and fixes both (#48) by @gaborbernat.
  • up-object-sentinel (SMP511) flags module and class constants assigned a bare object(), which the Python 3.15 sentinel builtin names, with an unsafe fix since the repr changes (#48) by @gaborbernat.
  • up-re-error-alias (SMP518) flags re.error references, which re.PatternError replaces on Python 3.13 and later, with a safe fix (#48) by @gaborbernat.
  • up-removed-ast-node (SMP520) flags ast.Num, ast.Str, ast.Bytes, ast.NameConstant and ast.Ellipsis references and visit_ methods that Python 3.14 removed, with safe fixes for the common isinstance and constructor forms (#48) by @gaborbernat.
  • up-strptime-date (SMP514) flags datetime.strptime(...).date() and .time() calls, which date.strptime and time.strptime replace 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) flags traceback calls 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) flags if TYPE_CHECKING: blocks of imports that Python 3.15 can spell as lazy imports, with an unsafe fix (#48) by @gaborbernat.
  • up-unittest-assert-helper (SMP811) flags assertTrue and assertFalse on startswith, endswith, hasattr and issubclass checks in TestCase methods, which the Python 3.14 assertStartsWith family replaces (#48) by @gaborbernat.
  • up-unittest-enter-context (SMP812) flags a patch that a TestCase method starts and stops by hand, which self.enterContext replaces 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 a type statement, 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 as asyncio.taskgroups, as shipped only from the version that adds it, using a table generated from CPython's Lib/ 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 as import string.templatelib checked only for existence, and keeps it now with a noqa suppression. The guards around _zstd, compression.zstd and _curses stay unreported (#47) by @gaborbernat.
  • function-docstring (SMP901) reads the functions in a match statement's case bodies, at module and class level, as it already reads those in if and try blocks, 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 named list in def list(self) -> list[str]. Without the import, Python 3.14 and later evaluate that annotation in the class namespace, where list is the method (#47) by @gaborbernat.
  • imprecise-annotation (SMP602) now also reports object and Any in the value of a type statement 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 through ExceptionGroup.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 the lazy keyword 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 made make[Item] call a TypeVar (#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...
Read more

0.4.0

Choose a tag to compare

@gaborbernat gaborbernat released this 04 Nov 22:16

Features

  • blanket-ignore (SMP004) flags every suppression comment that names no error code, such as a bare # noqa, a # ruff: noqa, or a # type: ignore or # ty: ignore without 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 for slots=True on 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 except clause names, so a built-in exception could replace them (#34) by @gaborbernat.
  • long-docstring-paragraph (SMP904) flags a docstring paragraph longer than max-paragraph-words words, as long-paragraph (SMP002) does for comments (#34) by @gaborbernat.
  • module-attribute-import (SMP304) flags module.Name access to a module of the project, which an import of Name replaces. The new imports.module-attributes option 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 new long-docstring-paragraph (SMP904) read their limit from the new max-paragraph-words option, 100 words by default (#34) by @gaborbernat.
  • rst-empty-field (SMP914) reports :param:, :raises:, :returns:, :yields: and :var: fields with no description, which rst-field-syntax reported 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 json now 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) flags time.sleep and asyncio.sleep calls 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) flags unittest.mock imports 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 Final annotation and fills in its type (#34) by @gaborbernat.
  • dataclass-options (SMP701) is renamed to dataclass-frozen and asks only for frozen=True. Its fix no longer adds slots=True, which dataclass-slots (SMP702) now asks for (#34) by @gaborbernat.
  • rst-field-syntax now 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) reports object in any annotation and Any where Ruff's ANN401 does not: in variable annotations and nested positions such as dict[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 new module-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 SMP4 for 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-syntax no longer reports fields with no description; rst-empty-field does (#34) by @gaborbernat.
  • The docstring-style value and the reStructuredText rule names use rst, such as docstring-style = "rst" and rst-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 linter lists each group with its rule codes (#34) by @gaborbernat.
  • single-letter-name (SMP101) now reports for loop targets such as i in for 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-dir in pyproject.toml that 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 a cache-dir can no longer delete directories outside the project. The command line and RUFF_CACHE_DIR still 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.
  • --fix and --diff give 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 --diff on 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. --fix no 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 ...
Read more

0.3.0

Choose a tag to compare

@github-actions github-actions released this 04 Nov 02:59

Features

  • The docstring rules share the new SMP3 group, so select = ["SMP3"] picks all of them: function-docstring is SMP300 (was SMP002), test-module-docstring SMP301 (was SMP004) and undocumented-public-api SMP302 (was SMP116); update select, ignore and noqa comments that name the old codes. Docstrings no longer have a length limit: multiline-module-docstring (SMP003) is gone, and long-paragraph (SMP005) checks comments only (#27) by @gaborbernat.
  • undocumented-public-api (SMP302) and function-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 name or import * needs its docstring where it is defined. A name another module imports counts as public only in a public module, where missing-from-all (SMP113) lists it in __all__, and an application, which nothing installs, has no public API at all. The new project-kind, api-packages and api-modules settings 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 modules api-modules names as written (#27) by @gaborbernat.

Bug fixes

  • --fix, --add-noqa and --add-ignore write 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 a noqa comment for another code sits on, or that holds noqa in a string, instead of leaving the dataclass without kw_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, as text = 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: noqa and 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 once ruff format has 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 an if or try block, 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-commit mirror, 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.

🐍 PyPI release

📜 Full Changelog

0.2.2

Choose a tag to compare

@github-actions github-actions released this 02 Nov 17:47

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.

PyPI release

Full Changelog

0.1.0

Choose a tag to compare

@github-actions github-actions released this 30 Oct 16:33

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.

PyPI release

Full Changelog