Releases: pylint-dev/pylint
v4.0.0
-
Pylint now supports Python 3.14.
-
Pylint's inference engine (
astroid
) is now much more precise,
understanding implicit booleanness and ternary expressions. (Thanks @zenlyj!)
Consider this example:
class Result:
errors: dict | None = None
result = Result()
if result.errors:
result.errors[field_key]
# inference engine understands result.errors cannot be None
# pylint no longer raises unsubscriptable-object
The required astroid
version is now 4.0.0. See the astroid changelog for additional fixes, features, and performance improvements applicable to pylint.
- Handling of
invalid-name
at the module level was patchy. Now,
module-level constants that are reassigned are treated as variables and checked
against--variable-rgx
rather than--const-rgx
. Module-level lists,
sets, and objects can pass against either regex.
Here, LIMIT
is reassigned, so pylint only uses --variable-rgx
:
LIMIT = 500 # [invalid-name]
if sometimes:
LIMIT = 1 # [invalid-name]
If this is undesired, refactor using exclusive assignment so that it is
evident that this assignment happens only once:
if sometimes:
LIMIT = 1
else:
LIMIT = 500 # exclusive assignment: uses const regex, no warning
Lists, sets, and objects still pass against either const-rgx
or variable-rgx
even if reassigned, but are no longer completely skipped:
MY_LIST = []
my_list = []
My_List = [] # [invalid-name]
Remember to adjust the regexes and allow lists to your liking.
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
-
The unused
pylintrc
argument toPyLinter.__init__()
is deprecated
and will be removed.Refs #6052
-
Commented out code blocks such as
# bar() # TODO: remove dead code
will no longer emitfixme
.Refs #9255
-
pyreverse
Run
was changed to no longer callsys.exit()
in its__init__
.
You should now callRun(args).run()
which will return the exit code instead.
Having a class that always raised aSystemExit
exception was considered a bug.Normal usage of pyreverse through the CLI will not be affected by this change.
Refs #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
-
The
async.py
checker module has been renamed toasync_checker.py
sinceasync
is a Python keyword
and cannot be imported directly. This allows for better testing and extensibility of the async checker functionality.Refs #10071
-
The message-id of
continue-in-finally
was changed fromE0116
toW0136
. The warning is
now emitted for every Python version since it will raise a syntax warning in Python 3.14.
See PEP 765 - Disallow return/break/continue that exit a finally block.Refs #10480
-
Removed support for
nmp.NaN
alias fornumpy.NaN
being recognized in ':ref:nan-comparison
'. Usenp
ornumpy
instead.Refs #10583
-
Version requirement for
isort
has been bumped to >=5.0.0.
The internal compatibility for olderisort
versions exposed viapylint.utils.IsortDriver
has
been removed.Refs #10637
New Features
-
comparison-of-constants
now uses the unicode from the ast instead of reformatting from
the node's values preventing some bad formatting due toutf-8
limitation. The message now uses
"
instead of'
to better work with what the python ast returns.Refs #8736
-
Enhanced pyreverse to properly distinguish between UML relationship types (association, aggregation, composition) based on object ownership semantics. Type annotations without assignment are now treated as associations, parameter assignments as aggregations, and object instantiation as compositions.
-
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
-
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
-
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
-
colorized reporter now colorizes messages/categories that have been configured as
fail-on
in red inverse.
This makes it easier to quickly find the errors that are causing pylint CI job failures.Closes #9898
-
Enhanced support for @Property decorator in pyreverse to correctly display return types of annotated properties when generating class diagrams.
Closes #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
-
Handle deferred evaluation of annotations in Python 3.14.
Closes #10149
-
Enhanced pyreverse to properly detect aggregations for comprehensions (list, dict, set, generator).
Closes #10236
-
pyreverse
: add support for colorized output when using output formatmmd
(MermaidJS) andhtml
.Closes #10242
-
pypy 3.11 is now officially supported.
Refs #10287
-
Add support for Python 3.14.
Refs #10467
-
Add naming styles for
ParamSpec
andTypeVarTuple
that align with theTypeVar
style.Refs #10541
New Checks
-
Add
match-statements
checker and the following message:
bare-name-capture-pattern
.
This will emit an error message when a name capture pattern is used in a match statement which would make the remaining patterns unreachable.
This code is a SyntaxError at runtime.Closes #7128
-
Add new check
async-context-manager-with-regular-with
to detect async context managers used with regularwith
statements instead ofasync with
.Refs #10408
-
Add
break-in-finally
warning. Usingbreak
inside thefinally
clause
will raise a syntax warning in Python 3.14.
SeePEP 765 - Disallow return/break/continue that exit a finally block <https://peps.python.org/pep-0765/>
_.Refs #10480
-
Add new checks for invalid uses of class patterns in :keyword:
match
.- :ref:
invalid-match-args-definition
is emitted if :py:data:object.__match_args__
isn't a tuple of strings. - :ref:
too-many-positional-sub-patterns
if there are more positional sub-patterns than specified in :py:data:object.__match_args__
. - :ref:
multiple-class-sub-patterns
if there are multiple sub-patterns for the same attribute.
Refs #10559
- :ref:
-
Add additional checks for suboptimal uses of class patterns in :keyword:
match
.- :ref:
match-class-bind-self
is emitted if a name is bound toself
instead of
using anas
pattern. - :ref:
match-class-positional-attributes
is emitted if a class pattern has positional
attributes when keywords could be used.
Refs #10587
- :ref:
-
Add a
consider-math-not-float
message.float("nan")
andfloat("inf")
are slower
than their counterpartmath.inf
andmath.nan
by a factor of 4 (notwithstanding
the initial import of math) and they are also not well typed when using mypy.
This check also catches typos in float calls as a side effect.The :ref:
pylint.extensions.code_style
need to be activated for this check to work.Refs #10621
False Positives Fixed
-
Fix a false positive for
used-before-assignment
when a variable defined under
anif
and via a named expression (walrus operator) is used later when guarded
under the sameif
test.Closes #10061
-
Fix :ref:
no-name-in-module
for members ofconcurrent.futures
with Python 3.14.Closes #10632
False Negatives Fixed
-
Fix false negative for
used-before-assignment
when aTYPE_CHECKING
import is used as a type annotation prior to erroneous usage.Refs #8893
-
Match cases are now counted as edges in the McCabe graph and will increase the complexity accordingly.
Refs #9667
-
Check module-level constants with type annotations for
invalid-name
.
Remember to adjustconst-naming-style
orconst-rgx
to your liking.Closes #9770
-
Fix false negative where function-redefined (E0102) was not reported for functions with a leading underscore.
Closes #9894
-
We now raise a
logging-too-few-args
for format string with no
interpolation arguments at all (i.e. for something likelogging.debug("Awaiting process %s")
orlogging.debug("Awaiting process {pid}")
). Previously we did not rais...
v3.3.9
What's new in Pylint 3.3.9?
Release date: 2025-10-05
False Positives Fixed
-
Fix used-before-assignment for PEP 695 type aliases and parameters.
Closes #9815
-
No longer flag undeprecated functions in
importlib.resources
as deprecated.Closes #10593
-
Fix false positive
inconsistent-return-statements
when usingquit()
orexit()
functions.Closes #10508
-
Fix false positive
undefined-variable
(E0602) for for-loop variable shadowing patterns likefor item in item:
when the variable was previously defined.Closes #10562
Other Bug Fixes
-
Fixed crash in 'unnecessary-list-index-lookup' when starting an enumeration using
minus the length of an iterable inside a dict comprehension when the len call was only
made in this dict comprehension, and not elsewhere. Also changed the approach,
to use inference in all cases but the simple ones, so we don't have to fix crashes
one by one for arbitrarily complex expressions in enumerate.Closes #10510
v3.3.8
What's new in Pylint 3.3.8?
Release date: 2025-08-09
This patch release includes an exceptional fix for a false negative issue. For details, see: #10482 (comment)
False Positives Fixed
-
Fix false positives for
possibly-used-before-assignment
when variables are exhaustively
assigned within amatch
block.Closes #9668
-
Fix false positive for
missing-raises-doc
andmissing-yield-doc
when the method length is less than docstring-min-length.Refs #10104
-
Fix a false positive for
unused-variable
when multiple except handlers bind the same name under a try block.Closes #10426
False Negatives Fixed
-
Fix false-negative for
used-before-assignment
withfrom __future__ import annotations
in function definitions.Refs #10482
Other Bug Fixes
v3.3.7
What's new in Pylint 3.3.7?
Release date: 2025-05-04
False Positives Fixed
-
Comparisons between two calls to
type()
won't raise anunidiomatic-typecheck
warning anymore, consistent with the behavior applied only for==
previously.Closes #10161
Other Bug Fixes
-
Fixed a crash when importing a class decorator that did not exist with the same name as a class attribute after the class definition.
Closes #10105
-
Fix a crash caused by malformed format strings when using
.format
with keyword arguments.Closes #10282
-
Using a slice as a class decorator now raises a
not-callable
message instead of crashing. 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
Other Changes
-
The algorithm used for
no-member
suggestions is now more efficient and cuts the
calculation when the distance score is already above the threshold.Refs #10277
v3.3.6
v3.3.5
What's new in Pylint 3.3.5?
Release date: 2025-03-09
False Positives Fixed
-
Fix false positives for
use-implicit-booleaness-not-comparison
,use-implicit-booleaness-not-comparison-to-string
anduse-implicit-booleaness-not-comparison-to-zero
when chained comparisons are checked.Closes #10065
-
Fix a false positive for
invalid-getnewargs-ex-returned
when the tuple or dict has been assigned to a name.Closes #10208
-
Remove
getopt
andoptparse
from the list of deprecated modules.Closes #10211
Other Bug Fixes
-
Fixed conditional import x.y causing false positive possibly-used-before-assignment.
Closes #10081
-
Fix a crash when something besides a class is found in an except handler.
Closes #10106
-
Fixed raising invalid-name when using camelCase for private methods with two leading underscores.
Closes #10189
Other Changes
-
Upload release assets to PyPI via Trusted Publishing.
Closes #10256
v3.3.5a0
v3.3.4
Other Bug Fixes
-
Fixes "skipped files" count calculation; the previous method was displaying an arbitrary number.
Closes #10073
-
Fixes a crash that occurred when pylint was run in a container on a host with cgroupsv2 and restrictions on CPU usage.
Closes #10103
-
Relaxed the requirements for isort so pylint can benefit from isort 6.
Closes #10203
v3.3.3
What's new in Pylint 3.3.3?
Release date: 2024-12-23
False Positives Fixed
-
Fix false positives for
undefined-variable
for classes using Python 3.12
generic type syntax.Closes #9335
-
Fix a false positive for
use-implicit-booleaness-not-len
. No lint should be emitted for
generators (len
is not defined for generators).Refs #10100
Other Bug Fixes
-
Fix
Unable to import 'collections.abc' (import-error)
on Python 3.13.1.Closes #10112
v3.3.2
False Positives Fixed
-
Fix a false positive for
potential-index-error
when an indexed iterable
contains a starred element that evaluates to more than one item.Closes #10076
Other Bug Fixes
-
Fixes the issue with --source-root option not working when the source files are in a subdirectory of the source root (e.g. when using a /src layout).
Closes #10026