What's New in Pylint 4.0

:Release:4.0 :Date: TBA

Summary -- Release highlights

What's new in Pylint 4.0.0-dev0?

Release date: TBA

Breaking Changes

  • invalid-name now distinguishes module-level constants that are assigned only once from those that are reassigned and now applies --variable-rgx to the latter. Values other than literals (lists, sets, objects) can pass against either the constant or variable regexes (e.g. "LOGGER" or "logger" but not "LoGgEr").

    Remember that --good-names or --good-names-rgxs can be provided to explicitly allow good names.

    Closes #3585 (#3585)

  • Commented out code blocks such as #    bar() # TODO: remove dead code will no longer emit fixme.

    Refs #9255 (#9255)

  • pyreverse Run was changed to no longer call sys.exit() in its __init__. You should now call Run(args).run() which will return the exit code instead. Having a class that always raised a SystemExit exception was considered a bug.

    Normal usage of pyreverse through the CLI will not be affected by this change.

    Refs #9689 (#9689)

  • The suggestion-mode option was removed, as pylint now always emits user-friendly hints instead of false-positive error messages. You should remove it from your conf if it's defined.

    Refs #9962 (#9962)

  • The async.py checker module has been renamed to async_checker.py since async is a Python keyword and cannot be imported directly. This allows for better testing and extensibility of the async checker functionality.

    Refs #10071 (#10071)

New Features

  • The fixme check can now search through docstrings as well as comments, by using check-fixme-in-docstring = true in the [tool.pylint.miscellaneous] section.

    Closes #9255 (#9255)

  • The use-implicit-booleaness-not-x checks now distinguish between comparisons used in boolean contexts and those that are not, enabling them to provide more accurate refactoring suggestions.

    Closes #9353 (#9353)

  • The verbose option now outputs the filenames of the files that have been checked. Previously, it only included the number of checked and skipped files.

    Closes #9357 (#9357)

  • Enhanced support for @property decorator in pyreverse to correctly display return types of annotated properties when generating class diagrams.

    Closes #10057 (#10057)

  • Add --max-depth option to pyreverse to control diagram complexity. A depth of 0 shows only top-level packages, 1 shows one level of subpackages, etc. This helps manage visualization of large codebases by limiting the depth of displayed packages and classes.

    Refs #10077 (#10077)

  • Enhanced pyreverse to properly detect aggregations for comprehensions (list, dict, set, generator).

    Closes #10236 (#10236)

  • pyreverse: add support for colorized output when using output format mmd (MermaidJS) and html.

    Closes #10242 (#10242)

  • pypy 3.11 is now officially supported.

    Refs #10287 (#10287)

False Positives Fixed

  • Fix false positives for possibly-used-before-assignment when variables are exhaustively assigned within a match block.

    Closes #9668 (#9668)

  • Fix a false positive for used-before-assignment when a variable defined under an if and via a named expression (walrus operator) is used later when guarded under the same if test.

    Closes #10061 (#10061)

  • Fix false positives for use-implicit-booleaness-not-comparison, use-implicit-booleaness-not-comparison-to-string and use-implicit-booleaness-not-comparison-to-zero when chained comparisons are checked.

    Closes #10065 (#10065)

  • Fix false positive for missing-raises-doc and missing-yield-doc when the method length is less than docstring-min-length.

    Refs #10104 (#10104)

  • Comparisons between two calls to type() won't raise an unidiomatic-typecheck warning anymore, consistent with the behavior applied only for == previously.

    Closes #10161 (#10161)

  • Fix a false positive for invalid-getnewargs-ex-returned when the tuple or dict has been assigned to a name.

    Closes #10208 (#10208)

  • Remove getopt and optparse from the list of deprecated modules.

    Closes #10211 (#10211)

False Negatives Fixed

  • Fix false negative for used-before-assignment when a TYPE_CHECKING import is used as a type annotation prior to erroneous usage.

    Refs #8893 (#8893)

  • Check module-level constants with type annotations for invalid-name. Remember to adjust const-naming-style or const-rgx to your liking.

    Closes #9770 (#9770)

  • We now raise a logging-too-few-args for format string with no interpolation arguments at all (i.e. for something like logging.debug("Awaiting process %s") or logging.debug("Awaiting process {pid}")). Previously we did not raise for such case.

    Closes #9999 (#9999)

  • Fix false negative for used-before-assignment when a function is defined inside a TYPE_CHECKING guard block and used later.

    Closes #10028 (#10028)

Other Bug Fixes

  • Fixes "skipped files" count calculation; the previous method was displaying an arbitrary number.

    Closes #10073 (#10073)

  • Fixed conditional import x.y causing false positive possibly-used-before-assignment.

    Closes #10081 (#10081)

  • Fixes a crash that occurred when pylint was run in a container on a host with cgroupsv2 and restrictions on CPU usage.

    Closes #10103 (#10103)

  • Fixed a crash when importing a class decorator that did not exist with the same name than a class attribute after the class definition.

    Closes #10105 (#10105)

  • Fix a crash when something besides a class is found in an except handler.

    Closes #10106 (#10106)

  • Fixed raising invalid-name when using camelCase for private methods with two leading underscores.

    Closes #10189 (#10189)

  • Relaxed the requirements for isort so pylint can benefit from isort 6.

    Closes #10203 (#10203)

  • Fixed unidiomatic-typecheck only checking left-hand side.

    Closes #10217 (#10217)

  • Fix a crash caused by malformed format strings when using .format with keyword arguments.

    Closes #10282 (#10282)

  • Using a slice as a class decorator now raise a 'not-callable' message instead of crashing pylint. A lot of checks that dealt with decorators (too many to list) are now shortcut if the decorator can't immediately be inferred to a function or class definition.

    Closes #10334 (#10334)

  • Fix a bug in Pyreverse where aggregations and associations were included in diagrams regardless of the selected --filter-mode (such as PUB_ONLY, ALL, etc.).

    Closes #10373 (#10373)

  • Fix double underscores erroneously rendering as bold in pyreverse's Mermaid output.

    Closes #10402 (#10402)

Other Changes

  • Upload release assets to PyPI via Trusted Publishing.

    Closes #10256 (#10256)

  • The algorithm used for no-member suggestions is now more efficient and cut the calculation when the distance score is already above the threshold.

    Refs #10277 (#10277)

  • Remove support for launching pylint with Python 3.9. Code that supports Python 3.9 can still be linted with the --py-version=3.9 setting.

    Refs #10405 (#10405)

Internal Changes

  • Modified test framework to allow for different test output for different Python versions.

    Refs #10382 (#10382)