PYLINT(1) Pylint PYLINT(1)

pylint - Pylint Documentation Pypi Package versionDocumentation Statuspre-commit.ci statusCII Best PracticesDiscord

Pylint is a static code analyser for Python 2 or 3. The latest version supports Python 3.7.2 and above.

Pylint analyses your code without actually running it. It checks for errors, enforces a coding standard, looks for code smells, and can make suggestions about how the code could be refactored. Pylint can infer actual values from your code using its internal code representation (astroid). If your code is import logging as argparse, Pylint will know that argparse.error(...) is in fact a logging call and not an argparse call.

Pylint is highly configurable and permits to write plugins in order to add your own checks (for example, for internal libraries or an internal rule). Pylint has an ecosystem of existing plugins for popular frameworks such as pylint-django or pylint-sonarjson.

Pylint isn't smarter than you: it may warn you about things that you have conscientiously done or check for some things that you don't care about. During adoption, especially in a legacy project where pylint was never enforced, it's best to start with the --errors-only flag, then disable convention and refactor message with --disable=C,R and progressively re-evaluate and re-enable messages as your priorities evolve.

Pylint ships with three additional tools:

  • pyreverse (standalone tool that generates package and class diagrams.)
  • symilar (duplicate code finder that is also integrated in pylint)
  • epylint (Emacs and Flymake compatible Pylint)

Projects that you might want to use alongside pylint include flake8 (faster and simpler checks with very few false positives), mypy, pyright or pyre (typing checks), bandit (security oriented checks), black and isort (auto-formatting), autoflake (automated removal of unused imports or variables), pyupgrade (automated upgrade to newer python syntax) and pydocstringformatter (automated pep257).

For command line use, pylint is installed with:

pip install pylint

It can also be integrated in most editors or IDEs. More information can be found in the documentation.

We welcome all forms of contributions such as updates for documentation, new code, checking issues for duplicates or telling us that we can close them, confirming that issues still exist, creating issues because you found a bug or want a feature, etc. Everything is much appreciated!

Please follow the code of conduct and check the Contributor Guides if you want to make a code contribution.

You can place this badge in your README to let others know your project uses pylint.

.UNINDENT

Learn how to add a badge to your documentation in the the badge documentation.

pylint is, with a few exceptions listed below, GPLv2.

The icon files are licensed under the CC BY-SA 4.0 license:

  • doc/logo.png
  • doc/logo.svg

Please check the contact information.

[image: Tidelift] [image] Professional support for pylint is available as part of the Tidelift Subscription. Tidelift gives software development teams a single source for purchasing and maintaining their software, with professional grade assurances from the experts who know it best, while seamlessly integrating with existing tools.

Robert Kirkpatrick

Beginner to coding standards? Pylint can be your guide to reveal what's really going on behind the scenes and help you to become a more aware programmer.

Sharing code is a rewarding endeavor. Putting your code out there can be either an act of philanthropy, coming of age, or a basic extension of belief in open source. Whatever the motivation, your good intentions may not have the desired outcome if people find your code hard to use or understand. The Python community has formalized some recommended programming styles to help everyone write code in a common, agreed-upon style that makes the most sense for shared code. This style is captured in PEP 8, the "Style Guide for Python Code". Pylint can be a quick and easy way of seeing if your code has captured the essence of PEP 8 and is therefore friendly to other potential users.

Perhaps you're not ready to share your code but you'd like to learn a bit more about writing better code and don't know where to start. Pylint can tell you where you may have run astray and point you in the direction to figure out what you have done and how to do better.

This tutorial is all about approaching coding standards with little or no knowledge of in-depth programming or the code standards themselves. It's the equivalent of skipping the manual and jumping right in.

My command line prompt for these examples is:

robertk01 Desktop$

Running Pylint with no arguments will invoke the help dialogue and give you an idea of the arguments available to you. Do that now, i.e.:

robertk01 Desktop$ pylint
...
a bunch of stuff
...

A couple of the options that we'll focus on here are:

Commands:

--help-msg=<msg-id>
--generate-toml-config Messages control:
--disable=<msg-ids> Reports:
--reports=<y or n>
--output-format=<format>

If you need more detail, you can also ask for an even longer help message, like so:

robertk01 Desktop$ pylint --long-help
...
Even more stuff
...

Pay attention to the last bit of this longer help output. This gives you a hint of what Pylint is going to pick on:

Output:

Using the default text output, the message format is :
MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE
There are 5 kind of message types :
* (C) convention, for programming standard violation
* (R) refactor, for bad code smell
* (W) warning, for python specific problems
* (E) error, for probable bugs in the code
* (F) fatal, if an error occurred which prevented pylint from doing
further processing.

When Pylint is first run on a fresh piece of code, a common complaint is that it is too noisy. The current default configuration is set to enforce all possible warnings. We'll use some of the options I noted above to make it suit your preferences a bit better (and thus make it emit messages only when needed).

We'll use a basic Python script as fodder for our tutorial. The starting code we will use is called simplecaesar.py and is here in its entirety:

#!/usr/bin/env python3
import string;
shift = 3
choice = input("would you like to encode or decode?")
word = input("Please enter text")
letters = string.ascii_letters + string.punctuation + string.digits
encoded = ''
if choice == "encode":

for letter in word:
if letter == ' ':
encoded = encoded + ' '
else:
x = letters.index(letter) + shift
encoded = encoded + letters[x] if choice == "decode":
for letter in word:
if letter == ' ':
encoded = encoded + ' '
else:
x = letters.index(letter) - shift
encoded = encoded + letters[x] print(encoded)

Let's get started.

If we run this:

robertk01 Desktop$ pylint simplecaesar.py
************* Module simplecaesar
simplecaesar.py:3:0: W0301: Unnecessary semicolon (unnecessary-semicolon)
simplecaesar.py:1:0: C0114: Missing module docstring (missing-module-docstring)
simplecaesar.py:5:0: C0103: Constant name "shift" doesn't conform to UPPER_CASE naming style (invalid-name)
simplecaesar.py:9:0: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
simplecaesar.py:13:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
-----------------------------------
Your code has been rated at 7.37/10

Previous experience taught me that the default output for the messages needed a bit more info. We can see the second line is:

"simplecaesar.py:1:0: C0114: Missing module docstring (missing-module-docstring)"

This basically means that line 1 violates a convention C0114. It's telling me I really should have a docstring. I agree, but what if I didn't fully understand what rule I violated. Knowing only that I violated a convention isn't much help if I'm a newbie. Another piece of information there is the message symbol between parens, missing-module-docstring here.

If I want to read up a bit more about that, I can go back to the command line and try this:

robertk01 Desktop$ pylint --help-msg=missing-module-docstring
:missing-module-docstring (C0114): *Missing module docstring*

Used when a module has no docstring.Empty modules do not require a docstring.
This message belongs to the basic checker.

Yeah, ok. That one was a bit of a no-brainer, but I have run into error messages that left me with no clue about what went wrong, simply because I was unfamiliar with the underlying mechanism of code theory. One error that puzzled my newbie mind was:

:too-many-instance-attributes (R0902): *Too many instance attributes (%s/%s)*

I get it now thanks to Pylint pointing it out to me. If you don't get that one, pour a fresh cup of coffee and look into it - let your programmer mind grow!

Now that we got some configuration stuff out of the way, let's see what we can do with the remaining warnings.

If we add a docstring to describe what the code is meant to do that will help. There are 5 invalid-name messages that we will get to later. Lastly, I put an unnecessary semicolon at the end of the import line so I'll fix that too. To sum up, I'll add a docstring to line 2, and remove the ; from line 3.

Here is the updated code:

#!/usr/bin/env python3
"""This script prompts a user to enter a message to encode or decode
using a classic Caesar shift substitution (3 letter shift)"""
import string
shift = 3
choice = input("would you like to encode or decode?")
word = input("Please enter text")
letters = string.ascii_letters + string.punctuation + string.digits
encoded = ''
if choice == "encode":

for letter in word:
if letter == ' ':
encoded = encoded + ' '
else:
x = letters.index(letter) + shift
encoded = encoded + letters[x] if choice == "decode":
for letter in word:
if letter == ' ':
encoded = encoded + ' '
else:
x = letters.index(letter) - shift
encoded = encoded + letters[x] print(encoded)

Here is what happens when we run it:

robertk01 Desktop$ pylint simplecaesar.py
************* Module simplecaesar
simplecaesar.py:7:0: C0103: Constant name "shift" doesn't conform to UPPER_CASE naming style (invalid-name)
simplecaesar.py:11:0: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
simplecaesar.py:15:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
------------------------------------------------------------------
Your code has been rated at 8.42/10 (previous run: 7.37/10, +1.05)

Nice! Pylint told us how much our code rating has improved since our last run, and we're down to just the invalid-name messages.

There are fairly well defined conventions around naming things like instance variables, functions, classes, etc. The conventions focus on the use of UPPERCASE and lowercase as well as the characters that separate multiple words in the name. This lends itself well to checking via a regular expression, thus the should match (([A-Z_][A-Z1-9_]*)|(__.*__))$.

In this case Pylint is telling me that those variables appear to be constants and should be all UPPERCASE. This is an in-house convention that has lived with Pylint since its inception. You too can create your own in-house naming conventions but for the purpose of this tutorial, we want to stick to the PEP 8 standard. In this case, the variables I declared should follow the convention of all lowercase. The appropriate rule would be something like: "should match [a-z_][a-z0-9_]{2,30}$". Notice the lowercase letters in the regular expression (a-z versus A-Z).

If we run that rule using a --const-rgx='[a-z\_][a-z0-9\_]{2,30}$' option, it will now be quite quiet:

robertk01 Desktop$ pylint --const-rgx='[a-z_][a-z0-9_]{2,30}$' simplecaesar.py
-------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 8.42/10, +1.58)

Regular expressions can be quite a beast so take my word on this particular example but go ahead and read up on them if you want.

TIP:

It would really be a pain to specify that regex on the command line all the time, particularly if we're using many other options. That's what a configuration file is for. We can configure our Pylint to store our options for us so we don't have to declare them on the command line. Using a configuration file is a nice way of formalizing your rules and quickly sharing them with others. Invoking pylint --generate-toml-config will create a sample .toml section with all the options set and explained in comments. This can then be added to your pyproject.toml file or any other .toml file pointed to with the --rcfile option.

That's it for the basic intro. More tutorials will follow.

Pylint can be installed:

  • As a command line tool
  • Integrated in your editor/ide
  • As a pre-commit hook
  • For multiple python interpreters in your continuous integration

Pylint is installable using a package manager. Your package manager will find a version that works with your interpreter. We recommend pip:

pip install pylint

Or if you want to also check spelling with enchant (you might need to install the enchant C library):

pip install pylint[spelling]

The newest pylint supports all Python interpreters that are not past end of life.

We recommend to use the latest interpreter because we rely on the ast builtin module that gets better with each new Python interpreter. For example a Python 3.6 interpreter can't analyse 3.8 syntax (amongst others, because of the new walrus operator) while a 3.8 interpreter can also deal with Python 3.6. See using pylint with multiple interpreters for more details.

NOTE:

You can also use conda or your system package manager on debian based OS. These package managers lag a little behind as they are maintained by a separate entity on a slower release cycle.
conda install pylint
sudo apt-get install pylint

Pylint can be integrated in various editors and IDE's. Below you can find tutorials for some of the most common ones.

  • Eclipse
  • Emacs
  • Eric IDE in the Project > Check menu,
  • gedit (another option for gedit)
  • Flymake
  • Jupyter Notebook
  • Komodo
  • Pycharm
  • PyDev
  • pyscripter in the Tool -> Tools menu.
  • Spyder in the View -> Panes -> Static code analysis
  • TextMate
  • Vim
  • Visual Studio Code in the Preferences -> Settings menu
  • Visual Studio Code Pylint Extension
  • Visual Studio in the Python > Run PyLint command on a project's context menu.
  • WingIDE

WARNING:

If you're reading this doc and are actually using flymake please open a support question at https://github.com/PyCQA/pylint/issues/new/choose and tell us, we don't have any maintainers for emacs and are thinking about dropping the support.

To enable Flymake for Python, insert the following into your .emacs:

;; Configure Flymake for Python
(when (load "flymake" t)

(defun flymake-pylint-init ()
(let* ((temp-file (flymake-init-create-temp-buffer-copy
'flymake-create-temp-inplace))
(local-file (file-relative-name
temp-file
(file-name-directory buffer-file-name))))
(list "epylint" (list local-file))))
(add-to-list 'flymake-allowed-file-name-masks
'("\\.py\\'" flymake-pylint-init))) ;; Set as a minor mode for Python (add-hook 'python-mode-hook '(lambda () (flymake-mode)))

Above stuff is in pylint/elisp/pylint-flymake.el, which should be automatically installed on Debian systems, in which cases you don't have to put it in your .emacs file.

Other things you may find useful to set:

;; Configure to wait a bit longer after edits before starting
(setq-default flymake-no-changes-timeout '3)
;; Keymaps to navigate to the errors
(add-hook 'python-mode-hook '(lambda () (define-key python-mode-map "\C-cn" 'flymake-goto-next-error)))
(add-hook 'python-mode-hook '(lambda () (define-key python-mode-map "\C-cp" 'flymake-goto-prev-error)))

Finally, by default Flymake only displays the extra information about the error when you hover the mouse over the highlighted line. The following will use the minibuffer to display messages when you the cursor is on the line.

;; To avoid having to mouse hover for the error message, these functions make Flymake error messages
;; appear in the minibuffer
(defun show-fly-err-at-point ()

"If the cursor is sitting on a Flymake error, display the message in the minibuffer"
(require 'cl)
(interactive)
(let ((line-no (line-number-at-pos)))
(dolist (elem flymake-err-info)
(if (eq (car elem) line-no)
(let ((err (car (second elem))))
(message "%s" (flymake-ler-text err))))))) (add-hook 'post-command-hook 'show-fly-err-at-point)

Alternative, if you only wish to pollute the minibuffer after an explicit flymake-goto-* then use the following instead of a post-command-hook

(defadvice flymake-goto-next-error (after display-message activate compile)

"Display the error in the mini-buffer rather than having to mouse over it"
(show-fly-err-at-point)) (defadvice flymake-goto-prev-error (after display-message activate compile)
"Display the error in the mini-buffer rather than having to mouse over it"
(show-fly-err-at-point))

Install Pylint in the usual way:

pip install pylint

Install the Python bundle for TextMate:

1.
select TextMate > Preferences
2.
select the Bundles tab
3.
find and tick the Python bundle in the list

You should now see it in Bundles > Python.

In Preferences, select the Variables tab. If a TM_PYCHECKER variable is not already listed, add it, with the value pylint.

The default keyboard shortcut to run the syntax checker is Control-Shift-V - open a .py file in Textmate, and try it.

You should see the output in a new window:

PyCheckMate 1.2 – Pylint 1.4.4

No config file found, using default configuration

Then all is well, and most likely Pylint will have expressed some opinions about your Python code (or will exit with 0 if your code already conforms to its expectations).

If you receive a message:

Please install PyChecker, PyFlakes, Pylint, PEP 8 or flake8 for more extensive code checking.

That means that Pylint wasn't found, which is likely an issue with command paths - TextMate needs be looking for Pylint on the right paths.

Check where Pylint has been installed, using which:

$ which pylint
/usr/local/bin/pylint

The output will tell you where Pylint can be found; in this case, in /usr/local/bin.

1.
select TextMate > Preferences
2.
select the Variables tab
3.
find and check that a PATH variable exists, and that it contains the appropriate path (if the path to Pylint were /usr/local/bin/pylint as above, then the variable would need to contain /usr/local/bin). An actual example in this case might be $PATH:/opt/local/bin:/usr/local/bin:/usr/texbin, which includes other paths.

... and try running Pylint again.

pylint can be used as a pre-commit hook.

Since pylint needs to import modules and dependencies to work correctly, the hook only works with a local installation of pylint (in your environment). If you installed pylint locally it can be added to .pre-commit-config.yaml as follows:

- repo: local

hooks:
- id: pylint
name: pylint
entry: pylint
language: system
types: [python]
args:
[
"-rn", # Only display messages
"-sn", # Don't display the score
]

You can use args to pass command line arguments as described in the Tutorial. A hook with more arguments could look something like this:

- repo: local

hooks:
- id: pylint
name: pylint
entry: pylint
language: system
types: [python]
args:
[
"-rn", # Only display messages
"-sn", # Don't display the score
"--rcfile=pylintrc", # Link to your config file
"--load-plugins=pylint.extensions.docparams", # Load an extension
]

It's possible to analyse code written for older or multiple interpreters by using the py-version option and setting it to the oldest supported interpreter of your code. For example you can check that there are no f-strings in Python 3.5 code using Python 3.8 with an up-to-date pylint even if Python 3.5 is past end of life (EOL) and the version of pylint you use is not compatible with it.

We do not guarantee that py-version will work for all EOL Python interpreters indefinitely, (for anything before Python 3.5, it probably won't). If a newer version does not work for you, the best available pylint might be an old version that works with your old interpreter but without the bug fixes and features of later versions.

You can place this badge in your README to let others know your project uses pylint.

.UNINDENT

Use the badge in your project's README.md (or any other Markdown file):

[![linting: pylint](https://img.shields.io/badge/linting-pylint-yellowgreen)](https://github.com/PyCQA/pylint)

Use the badge in your project's README.rst (or any other rst file):

.. image:: https://img.shields.io/badge/linting-pylint-yellowgreen

:target: https://github.com/PyCQA/pylint

If you use GitHub Actions, and one of your CI workflows begins with "name: pylint", you can use GitHub's workflow status badges to show an up-to-date indication of whether pushes to your default branch pass pylint. For more detailed information, check the documentation.

You should probably set the version of pylint in your development environment in order to choose when you actually upgrade pylint's warnings. pylint is following semver versioning. But we can't guarantee that the output between version will stays the same. What this means is that:

In patch release (1.2.3), we only fix false positives and crashes.

You can expect less messages if you set the minor and upgrade to a new patch version. But still, if you enable useless-suppression it still means you can get a new useless-suppression when a false positive that you disabled is now fixed. Also, if a library you're using was upgraded and is understood better or worse than the previous one, you could get new messages too.

In minor releases (1.2.0), we add checks, remove checks, drop python interpreters past end of life, upgrade astroid minor/major versions and fix false negatives.

You can expect a lot more change in output, the main one being new checks.

In major releases (1.0.0) we change everything else (pylint options, json output, dev API...) while still trying to minimize disruption.

You could have to change the command you're launching or the plugin and editor integration you're using.

Pylint is meant to be called from the command line. The usage is

pylint [options] modules_or_packages

By default the pylint command only accepts a list of python modules and packages. On versions below 2.15, specifying a directory that is not an explicit package (with __init__.py) results in an error:

pylint mydir
************* Module mydir
mydir/__init__.py:1:0: F0010: error while code parsing: Unable to load file mydir/__init__.py:
[Errno 2] No such file or directory: 'mydir/__init__.py' (parse-error)

Thus, on versions before 2.15, or when dealing with certain edge cases that have not yet been solved, using the --recursive=y option allows for linting a namespace package:

pylint --recursive=y mydir mymodule mypackage

This option makes pylint attempt to discover all modules (files ending with .py extension) and all explicit packages (all directories containing a __init__.py file).

Pylint will not import this package or module, but it does use Python internals to locate them and as such is subject to the same rules and configuration. You should pay attention to your PYTHONPATH, since it is a common error to analyze an installed version of a module instead of the development version.

It is also possible to analyze Python files, with a few restrictions. As a convenience, you can give it a file name if it's possible to guess a module name from the file's path using the python path. Some examples:

pylint mymodule.py should always work since the current working directory is automatically added on top of the python path

pylint directory/mymodule.py will work if: directory is a python package (i.e. has an __init__.py file), an implicit namespace package or if directory is in the python path.

First of all, we have two basic (but useful) options.

show program's version number and exit
show help about the command line options

Pylint is architected around several checkers. You can disable a specific checker or some of its messages or message categories by specifying --disable=<symbol>. If you want to enable only some checkers or some message symbols, first use --disable=all then --enable=<symbol> with <symbol> being a comma-separated list of checker names and message symbols. See the list of available features for a description of provided checkers with their functionalities. The --disable and --enable options can be used with comma-separated lists mixing checkers, message ids and categories like -d C,W,no-error,design

It is possible to disable all messages with --disable=all. This is useful to enable only a few checkers or a few messages by first disabling everything, and then re-enabling only what you need.

Each checker has some specific options, which can take either a yes/no value, an integer, a python regular expression, or a comma-separated list of values (which are generally used to override a regular expression in special cases). For a full list of options, use --help

Specifying all the options suitable for your setup and coding standards can be tedious, so it is possible to use a configuration file to specify the default values. You can specify a configuration file on the command line using the --rcfile option. Otherwise, Pylint searches for a configuration file in the following order and uses the first one it finds:

1.
pylintrc in the current working directory
2.
.pylintrc in the current working directory
3.
pyproject.toml in the current working directory, providing it has at least one tool.pylint. section. The pyproject.toml must prepend section names with tool.pylint., for example [tool.pylint.'MESSAGES CONTROL']. They can also be passed in on the command line.
4.
setup.cfg in the current working directory, providing it has at least one pylint. section
5.
If the current working directory is in a Python package, Pylint searches up the hierarchy of Python packages until it finds a pylintrc file. This allows you to specify coding standards on a module-by-module basis. Of course, a directory is judged to be a Python package if it contains an __init__.py file.
6.
The file named by environment variable PYLINTRC
7.
if you have a home directory which isn't /root:
1.
.pylintrc in your home directory
2.
.config/pylintrc in your home directory
8.
/etc/pylintrc

The --generate-toml-config option will generate a commented configuration file on standard output according to the current configuration and exit. This includes:

  • Any configuration file found as explained above
  • Options appearing before --generate-toml-config on the Pylint command line

Of course you can also start with the default values and hand-tune the configuration.

Other useful global options include:

Files or directories to be skipped. They should be base names, not paths.
Select output format (text, json, custom).
--msg-template=<template>
Modify text output message template.
Generate pylint's messages.
Display a list of what messages are enabled and disabled with the given configuration.
Generate pylint's full documentation, in reST format.

It is possible to speed up the execution of Pylint. If the running computer has more CPUs than one, then the work for checking all files could be spread across all cores via Pylints's sub-processes. This functionality is exposed via the -j command-line parameter. If the provided number is 0, then the total number of CPUs will be autodetected and used.

Example:

pylint -j 4 mymodule1.py mymodule2.py mymodule3.py mymodule4.py

This will spawn 4 parallel Pylint sub-process, where each provided module will be checked in parallel. Discovered problems by checkers are not displayed immediately. They are shown just after checking a module is complete.

There are some limitations in running checks in parallel in the current implementation. It is not possible to use custom plugins (i.e. --load-plugins option), nor it is not possible to use initialization hooks (i.e. the --init-hook option).

Pylint returns bit-encoded exit codes.

exit code meaning
0 no error
1 fatal message issued
2 error message issued
4 warning message issued
8 refactor message issued
16 convention message issued
32 usage error

For example, an exit code of 20 means there was at least one warning message (4) and at least one convention message (16) and nothing else.

Output by default is written to stdout. The simplest way to output to a file is with the --output=<filename> option.

The default format for the output is raw text. You can change this by passing pylint the --output-format=<value> option. Possible values are: text, json, parseable, colorized and msvs (for Visual Studio).

Multiple output formats can be used at the same time by passing a comma-separated list of formats to --output-format. This output can be redirected to a file by giving a filename after a colon.

For example, to save a json report to somefile.json and print a colorized report to stdout at the same time:

--output-format=json:somefile.json,colorized

You can customize the exact way information are displayed using the --msg-template=<format string> option. The format string uses the Python new format syntax and the following fields are available :

relative path to the file
absolute path to the file
line number
column number
line number of the end of the node
column number of the end of the node
module name
object within the module (if any)
text of the message
the message code (eg. I0011)
symbolic name of the message (eg. locally-disabled)
one letter indication of the message category
fullname of the message category

For example, the former (pre 1.0) default format can be obtained with:

pylint --msg-template='{msg_id}:{line:3d},{column}: {obj}: {msg}'

A few other examples:

the default format:
{path}:{line}:{column}: {msg_id}: {msg} ({symbol})
Visual Studio compatible format (former 'msvs' output format):
{path}({line}): [{msg_id}{obj}] {msg}
Parseable (Emacs and all, former 'parseable' output format) format:
{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}

The --msg-template option can only be combined with text-based reporters (--output-format either unspecified or one of: parseable, colorized or msvs). If both --output-format and --msg-template are specified, the --msg-template option will take precedence over the default line format defined by the reporter class.

If end_line or end_column are None, they will be represented as an empty string by the default TextReporter.

For each python module, Pylint will first display a few '*' characters followed by the name of the module. Then, a number of messages with the following format:

MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE

You can get another output format, useful since it's recognized by most editors or other development tools using the --output-format=parseable option.

The message type can be:

  • [I]nformational messages that Pylint emits (do not contribute to your analysis score)
  • [R]efactor for a "good practice" metric violation
  • [C]onvention for coding standard violation
  • [W]arning for stylistic problems, or minor programming issues
  • [E]rror for important programming issues (i.e. most probably bug)
  • [F]atal for errors which prevented further processing

Sometimes the line of code which caused the error is displayed with a caret pointing to the error. This may be generalized in future versions of Pylint.

Example (extracted from a run of Pylint on itself...):

************* Module pylint.checkers.format
W: 50: Too long line (86/80)
W:108: Operator not followed by a space

print >>sys.stderr, 'Unable to match %r', line
^ W:141: Too long line (81/80) W: 74:searchall: Unreachable code W:171:FormatChecker.process_tokens: Redefining built-in (type) W:150:FormatChecker.process_tokens: Too many local variables (20/15) W:150:FormatChecker.process_tokens: Too many branches (13/12)

Following the analysis message, Pylint can display a set of reports, each one focusing on a particular aspect of the project, such as number of messages by categories, modules dependencies. These features can be enabled through the --reports=y option, or its shorthand version -rn.

For instance, the metrics report displays summaries gathered from the current run.

  • the number of processed modules
  • for each module, the percentage of errors and warnings
  • the total number of errors and warnings
  • percentage of classes, functions and modules with docstrings, and a comparison from the previous run
  • percentage of classes, functions and modules with correct name (according to the coding standard), and a comparison from the previous run
  • a list of external dependencies found in the code, and where they appear

Finally, Pylint displays a global evaluation score for the code, rated out of a maximum score of 10.0. This output can be suppressed through the --score=n option, or its shorthand version -sn.

The evaluation formula can be overridden with the --evaluation=<python_expression> option.

Pylint can emit the following messages:

All messages in the fatal category:

Message emitted:

%s: %s

Description:

Used when an unexpected error occurred while building the Astroid representation. This is usually accompanied by a traceback. Please report such errors !

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

Message emitted:

error while parsing the configuration: %s

Description:

Used when an exception occurred while parsing a pylint configuration file.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

Message emitted:

%s

Description:

Used when an error occurred preventing the analysis of a module (unable to find it for instance).

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

method-check-failed / F0202

Message emitted:

Unable to check methods signature (%s / %s)

Description:

Used when Pylint has been unable to check methods signature compatibility for an unexpected reason. Please report this kind if you don't make sense of it.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

Message emitted:

error while code parsing: %s

Description:

Used when an exception occurred while building the Astroid representation which could be handled by astroid.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

All renamed messages in the fatal category:

"old-import-error has been renamed. The new message can be found at:

import-error / E0401

Message emitted:

Unable to import %s

Description:

Used when pylint has been unable to import a module.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the imports checker.

All messages in the error category:

abstract-class-instantiated / E0110

Message emitted:

Abstract class %r with abstract methods instantiated

Description:

Used when an abstract class with `abc.ABCMeta` as metaclass has abstract methods and is instantiated.

Problematic code:

import abc
class Animal(abc.ABC):

@abc.abstractmethod
def make_sound(self):
pass sheep = Animal() # [abstract-class-instantiated]

Correct code:

import abc
class Animal(abc.ABC):

@abc.abstractmethod
def make_sound(self):
pass class Sheep(Animal):
def make_sound(self):
print("bhaaaaa") sheep = Sheep()

Created by the basic checker.

access-member-before-definition / E0203

Message emitted:

Access to member %r before its definition line %s

Description:

Used when an instance member is accessed before it's actually assigned.

Problematic code:

class Foo:

def __init__(self, param):
if self.param: # [access-member-before-definition]
pass
self.param = param

Correct code:

class Foo:

def __init__(self, param):
self.param = param
if self.param:
pass

Created by the classes checker.

assigning-non-slot / E0237

Message emitted:

Assigning to attribute %r not defined in class slots

Description:

Used when assigning to an attribute not defined in the class slots.

Problematic code:

class Student:

__slots__ = ('name',)
def __init__(self, name, surname):
self.name = name
self.surname = surname # [assigning-non-slot]
self.setup()
def setup(self):
pass

Correct code:

class Student:

__slots__ = ('name', 'surname')
def __init__(self, name, surname):
self.name = name
self.surname = surname
self.setup()
def setup(self):
pass

Created by the classes checker.

assignment-from-no-return / E1111

Message emitted:

Assigning result of a function call, where the function has no return

Description:

Used when an assignment is done on a function call but the inferred function doesn't return anything.

Problematic code:

def add(x, y):

print(x + y) value = add(10, 10) # [assignment-from-no-return]

Correct code:

def add(x, y):

return x + y value = add(10, 10)

Created by the typecheck checker.

assignment-from-none / E1128

Message emitted:

Assigning result of a function call, where the function returns None

Description:

Used when an assignment is done on a function call but the inferred function returns nothing but None.

Problematic code:

def function():

return None f = function() # [assignment-from-none]

Correct code:

def function():

return None f = function() if function() else 1

Created by the typecheck checker.

await-outside-async / E1142

Message emitted:

'await' should be used within an async function

Description:

Emitted when await is used outside an async function.

Problematic code:

import asyncio
def main():

await asyncio.sleep(1) # [await-outside-async]

Correct code:

import asyncio
async def main():

await asyncio.sleep(1)

Related links:

PEP 492

Created by the typecheck checker.

bad-configuration-section / E0014

Message emitted:

Out-of-place setting encountered in top level configuration-section '%s' : '%s'

Description:

Used when we detect a setting in the top level of a toml configuration that shouldn't be there.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

bad-except-order / E0701

Message emitted:

Bad except clauses order (%s)

Description:

Used when except clauses are not in the correct order (from the more specific to the more generic). If you don't fix the order, some exceptions may not be caught by the most specific handler.

Problematic code:

try:

print(int(input())) except Exception:
raise except TypeError: # [bad-except-order]
# This block cannot be reached since TypeError exception
# is caught by previous exception handler.
raise

Correct code:

try:

print(int(input())) except TypeError:
raise except Exception:
raise

Created by the exceptions checker.

bad-exception-cause / E0705

Message emitted:

Exception cause set to something which is not an exception, nor None

Description:

Used when using the syntax "raise ... from ...", where the exception cause is not an exception, nor None.

Problematic code:

def divide(x, y):

result = 0
try:
result = x / y
except ZeroDivisionError:
raise ValueError(f"Division by zero when dividing {x} by {y} !") from result # [bad-exception-cause]
return result

Correct code:

def divide(x, y):

result = 0
try:
result = x / y
except ZeroDivisionError as exc:
raise ValueError(f"Division by zero when dividing {x} by {y} !") from exc
return result

Related links:

  • The raise statement
  • Explicit Exception Chaining per PEP 3134

Created by the exceptions checker.

bad-format-character / E1300

Message emitted:

Unsupported format character %r (%#02x) at index %d

Description:

Used when an unsupported format character is used in a format string.

Problematic code:

print("%s %z" % ("hello", "world"))  # [bad-format-character]

Correct code:

print("%s %s" % ("hello", "world"))

Additional details:

This check is currently only active for "old-style" string formatting as seen in the examples. See Issue #6085 for more information.

Related links:

  • Format String Syntax
  • PyFormat

Created by the string checker.

bad-plugin-value / E0013

Message emitted:

Plugin '%s' is impossible to load, is it installed ? ('%s')

Description:

Used when a bad value is used in 'load-plugins'.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

bad-reversed-sequence / E0111

Message emitted:

The first reversed() argument is not a sequence

Description:

Used when the first argument to reversed() builtin isn't a sequence (does not implement __reversed__, nor __getitem__ and __len__

Problematic code:

reversed({1, 2, 3, 4})  # [bad-reversed-sequence]

Correct code:

reversed([1, 2, 3, 4])

Created by the basic checker.

bad-str-strip-call / E1310

Message emitted:

Suspicious argument in %s.%s call

Description:

The argument to a str.{l,r,}strip call contains a duplicate character,

Problematic code:

"Hello World".strip("Hello")  # [bad-str-strip-call]
# >>> ' World'
"abcbc def bacabc".strip("abcbc ")  # [bad-str-strip-call]
# >>> 'def'

Correct code:

"Hello World".strip("Helo")
# >>> ' World'
"abcbc def bacabc".strip("abc ")
# >>> 'def'

Additional details:

A common misconception is that str.strip('Hello') removes the substring 'Hello' from the beginning and end of the string. This is not the case. From the documentation:

> The chars argument is not a prefix or suffix; rather, all combinations of its values are stripped

Duplicated characters in the str.strip call, besides not having any effect on the actual result, may indicate this misunderstanding.

Related links:

Documentation: str.strip([chars])

Created by the string checker.

bad-string-format-type / E1307

Message emitted:

Argument %r does not match format type %r

Description:

Used when a type required by format string is not suitable for actual argument type

Problematic code:

print("%d" % "1")  # [bad-string-format-type]

Correct code:

print("%d" % 1)

Additional details:

This check is currently only active for "old-style" string formatting as seen in the examples. See Issue #6085 for more information.

Related links:

  • Format String Syntax
  • PyFormat

Created by the string checker.

bad-super-call / E1003

Message emitted:

Bad first argument %r given to super()

Description:

Used when another argument than the current class is given as first argument of the super builtin.

Problematic code:

class Animal:

pass class Tree:
pass class Cat(Animal):
def __init__(self):
super(Tree, self).__init__() # [bad-super-call]
super(Animal, self).__init__()

Correct code:

class Animal:

pass class Tree:
pass class Cat(Animal):
def __init__(self):
super(Animal, self).__init__()

Additional details:

In Python 2.7, super() has to be called with its own class and self as arguments (super(Cat, self)), which can lead to a mix up of parent and child class in the code.

In Python 3 the recommended way is to call super() without arguments (see also super-with-arguments).

One exception is calling super() on a non-direct parent class. This can be used to get a method other than the default method returned by the mro().

Related links:

Documentation for super()

Created by the newstyle checker.

bidirectional-unicode / E2502

Message emitted:

Contains control characters that can permit obfuscated code executed differently than displayed

Description:

bidirectional unicode are typically not displayed characters required to display right-to-left (RTL) script (i.e. Chinese, Japanese, Arabic, Hebrew, ...) correctly. So can you trust this code? Are you sure it displayed correctly in all editors? If you did not write it or your language is not RTL, remove the special characters, as they could be used to trick you into executing code, that does something else than what it looks like. More Information: https://en.wikipedia.org/wiki/Bidirectional_text https://trojansource.codes/

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the unicode_checker checker.

broken-collections-callable / E6005

Message emitted:

'collections.abc.Callable' inside Optional and Union is broken in 3.9.0 / 3.9.1 (use 'typing.Callable' instead)

Description:

``collections.abc.Callable`` inside Optional and Union is broken in Python 3.9.0 and 3.9.1. Use ``typing.Callable`` for these cases instead. https://bugs.python.org/issue42965

Problematic code:

from collections.abc import Callable
from typing import Optional
def func() -> Optional[Callable[[int], None]]:  # [broken-collections-callable]

...

Correct code:

from typing import Callable, Optional
def func() -> Optional[Callable[[int], None]]:

...

Related links:

bpo-42965

NOTE:

This message is emitted by the optional 'typing' checker which requires the pylint.extensions.typing plugin to be loaded.

Created by the typing checker.

broken-noreturn / E6004

Message emitted:

'NoReturn' inside compound types is broken in 3.7.0 / 3.7.1

Description:

``typing.NoReturn`` inside compound types is broken in Python 3.7.0 and 3.7.1. If not dependent on runtime introspection, use string annotation instead. E.g. ``Callable[..., 'NoReturn']``. https://bugs.python.org/issue34921

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'typing' checker which requires the pylint.extensions.typing plugin to be loaded.

Created by the typing checker.

catching-non-exception / E0712

Message emitted:

Catching an exception which doesn't inherit from Exception: %s

Description:

Used when a class which doesn't inherit from Exception is used as an exception in an except clause.

Problematic code:

class FooError:

pass try:
1 / 0 except FooError: # [catching-non-exception]
pass

Correct code:

class FooError(Exception):

pass try:
1 / 0 except FooError:
pass

Created by the exceptions checker.

class-variable-slots-conflict / E0242

Message emitted:

Value %r in slots conflicts with class variable

Description:

Used when a value in __slots__ conflicts with a class variable, property or method.

Problematic code:

class Person:

__slots__ = ("age", "name", "say_hi",) # [class-variable-slots-conflict, class-variable-slots-conflict, class-variable-slots-conflict]
name = None
def __init__(self, age, name):
self.age = age
self.name = name
@property
def age(self):
return self.age
def say_hi(self):
print(f"Hi, I'm {self.name}.")

Correct code:

class Person:

__slots__ = ("_age", "name",)
def __init__(self, age, name):
self._age = age
self.name = name
@property
def age(self):
return self._age
def say_hi(self):
print(f"Hi, I'm {self.name}.")

Created by the classes checker.

continue-in-finally / E0116

Message emitted:

'continue' not supported inside 'finally' clause

Description:

Emitted when the `continue` keyword is found inside a finally clause, which is a SyntaxError.

Problematic code:

while True:

try:
pass
finally:
continue # [continue-in-finally]

Correct code:

while True:

try:
pass
except ValueError:
pass
else:
continue

Additional details:

Note this message can't be emitted when using Python version 3.8 or greater.

Created by the basic checker.

dict-iter-missing-items / E1141

Message emitted:

Unpacking a dictionary in iteration without calling .items()

Description:

Emitted when trying to iterate through a dict without calling .items()

Problematic code:

data = {'Paris': 2_165_423, 'New York City': 8_804_190, 'Tokyo': 13_988_129}
for city, population in data:  # [dict-iter-missing-items]

print(f"{city} has population {population}.")

Correct code:

data = {'Paris': 2_165_423, 'New York City': 8_804_190, 'Tokyo': 13_988_129}
for city, population in data.items():

print(f"{city} has population {population}.")

Created by the typecheck checker.

duplicate-argument-name / E0108

Message emitted:

Duplicate argument name %s in function definition

Description:

Duplicate argument names in function definitions are syntax errors.

Problematic code:

def get_fruits(apple, banana, apple):  # [duplicate-argument-name]

pass

Correct code:

def get_fruits(apple, banana, orange):

pass

Created by the basic checker.

duplicate-bases / E0241

Message emitted:

Duplicate bases for class %r

Description:

Duplicate use of base classes in derived classes raise TypeErrors.

Problematic code:

class Animal:

pass class Cat(Animal, Animal): # [duplicate-bases]
pass

Correct code:

class Animal:

pass class Bird(Animal):
pass class Cat(Animal):
pass

Created by the classes checker.

format-needs-mapping / E1303

Message emitted:

Expected mapping for format string, not %s

Description:

Used when a format string that uses named conversion specifiers is used with an argument that is not a mapping.

Problematic code:

print("%(x)d %(y)d" % [1, 2])  # [format-needs-mapping]

Correct code:

print("%(x)d %(y)d" % {"x": 1, "y": 2})

Created by the string checker.

function-redefined / E0102

Message emitted:

%s already defined line %s

Description:

Used when a function / class / method is redefined.

Problematic code:

def get_email():

pass def get_email(): # [function-redefined]
pass

Correct code:

def get_email():

pass

Created by the basic checker.

inconsistent-mro / E0240

Message emitted:

Inconsistent method resolution order for class %r

Description:

Used when a class has an inconsistent method resolution order.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

inherit-non-class / E0239

Message emitted:

Inheriting %r, which is not a class.

Description:

Used when a class inherits from something which is not a class.

Problematic code:

class Fruit(bool):  # [inherit-non-class]

pass

Correct code:

class Fruit:

def __bool__(self):
pass

Created by the classes checker.

init-is-generator / E0100

Message emitted:

__init__ method is a generator

Description:

Used when the special class method __init__ is turned into a generator by a yield in its body.

Problematic code:

class Fruit:

def __init__(self, worms): # [init-is-generator]
yield from worms apple = Fruit(["Fahad", "Anisha", "Tabatha"])

Correct code:

class Fruit:

def __init__(self, worms):
self.__worms = worms
def worms(self):
yield from self.__worms apple = Fruit(["Fahad", "Anisha", "Tabatha"]) for worm in apple.worms():
pass

Created by the basic checker.

invalid-all-format / E0605

Message emitted:

Invalid format for __all__, must be tuple or list

Description:

Used when __all__ has an invalid format.

Problematic code:

__all__ = ("CONST")  # [invalid-all-format]
CONST = 42

Correct code:

__all__ = ("CONST",)
CONST = 42

Created by the variables checker.

invalid-all-object / E0604

Message emitted:

Invalid object %r in __all__, must contain only strings

Description:

Used when an invalid (non-string) object occurs in __all__.

Problematic code:

__all__ = (

None, # [invalid-all-object]
Fruit,
Worm, ) class Fruit:
pass class Worm:
pass

Correct code:

__all__ = ['Fruit', 'Worm']
class Fruit:

pass class Worm:
pass

Additional details:

"The public names defined by a module are determined by checking the module's namespace for a variable named __all__; if defined, it must be a sequence of strings which are names defined or imported by that module."

Related links:

PEP 8 – Style Guide for Python Code

Created by the variables checker.

invalid-bool-returned / E0304

Message emitted:

__bool__ does not return bool

Description:

Used when a __bool__ method returns something which is not a bool

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

invalid-bytes-returned / E0308

Message emitted:

__bytes__ does not return bytes

Description:

Used when a __bytes__ method returns something which is not bytes

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

invalid-character-backspace / E2510

Message emitted:

Invalid unescaped character backspace, use "b" instead.

Description:

Moves the cursor back, so the character after it will overwrite the character before.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the unicode_checker checker.

invalid-character-carriage-return / E2511

Message emitted:

Invalid unescaped character carriage-return, use "r" instead.

Description:

Moves the cursor to the start of line, subsequent characters overwrite the start of the line.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the unicode_checker checker.

invalid-character-esc / E2513

Message emitted:

Invalid unescaped character esc, use "x1B" instead.

Description:

Commonly initiates escape codes which allow arbitrary control of the terminal.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the unicode_checker checker.

invalid-character-nul / E2514

Message emitted:

Invalid unescaped character nul, use "0" instead.

Description:

Mostly end of input for python.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the unicode_checker checker.

invalid-character-sub / E2512

Message emitted:

Invalid unescaped character sub, use "x1A" instead.

Description:

Ctrl+Z "End of text" on Windows. Some programs (such as type) ignore the rest of the file after it.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the unicode_checker checker.

invalid-character-zero-width-space / E2515

Message emitted:

Invalid unescaped character zero-width-space, use "u200B" instead.

Description:

Invisible space character could hide real code execution.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the unicode_checker checker.

invalid-class-object / E0243

Message emitted:

Invalid __class__ object

Description:

Used when an invalid object is assigned to a __class__ property. Only a class is permitted.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

invalid-enum-extension / E0244

Message emitted:

Extending inherited Enum class "%s"

Description:

Used when a class tries to extend an inherited Enum class. Doing so will raise a TypeError at runtime.

Problematic code:

from enum import Enum
class Color(Enum):

ORANGE = 1
CHERRY = 2 class Fruit(Color): # [invalid-enum-extension]
APPLE = 3

Correct code:

from enum import Enum
class Color(Enum):

ORANGE = 1
CHERRY = 2 class Fruit(Enum):
ORANGE = 1
CHERRY = 2
APPLE = 3

Created by the classes checker.

invalid-envvar-value / E1507

Message emitted:

%s does not support %s type argument

Description:

Env manipulation functions support only string type arguments. See https://docs.python.org/3/library/os.html#os.getenv.

Problematic code:

import os
os.getenv(1)  # [invalid-envvar-value]

Correct code:

import os
os.getenv('1')

Created by the stdlib checker.

invalid-format-returned / E0311

Message emitted:

__format__ does not return str

Description:

Used when a __format__ method returns something which is not a string

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

invalid-getnewargs-ex-returned / E0313

Message emitted:

__getnewargs_ex__ does not return a tuple containing (tuple, dict)

Description:

Used when a __getnewargs_ex__ method returns something which is not of the form tuple(tuple, dict)

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

invalid-getnewargs-returned / E0312

Message emitted:

__getnewargs__ does not return a tuple

Description:

Used when a __getnewargs__ method returns something which is not a tuple

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

invalid-hash-returned / E0309

Message emitted:

__hash__ does not return int

Description:

Used when a __hash__ method returns something which is not an integer

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

invalid-index-returned / E0305

Message emitted:

__index__ does not return int

Description:

Used when an __index__ method returns something which is not an integer

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

invalid-length-hint-returned / E0310

Message emitted:

__length_hint__ does not return non-negative integer

Description:

Used when a __length_hint__ method returns something which is not a non-negative integer

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

invalid-length-returned / E0303

Message emitted:

__len__ does not return non-negative integer

Description:

Used when a __len__ method returns something which is not a non-negative integer

Problematic code:

class FruitBasket:

def __init__(self, fruits):
self.fruits = ["Apple", "Banana", "Orange"]
def __len__(self): # [invalid-length-returned]
return - len(self.fruits)

Correct code:

class FruitBasket:

def __init__(self, fruits):
self.fruits = ["Apple", "Banana", "Orange"]
def __len__(self):
return len(self.fruits)

Created by the classes checker.

invalid-metaclass / E1139

Message emitted:

Invalid metaclass %r used

Description:

Emitted whenever we can detect that a class is using, as a metaclass, something which might be invalid for using as a metaclass.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

invalid-repr-returned / E0306

Message emitted:

__repr__ does not return str

Description:

Used when a __repr__ method returns something which is not a string

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

invalid-sequence-index / E1126

Message emitted:

Sequence index is not an int, slice, or instance with __index__

Description:

Used when a sequence type is indexed with an invalid type. Valid types are ints, slices, and objects with an __index__ method.

Problematic code:

fruits = ['apple', 'banana', 'orange']
print(fruits['apple'])  # [invalid-sequence-index]

Correct code:

fruits = ['apple', 'banana', 'orange']
print(fruits[0])

Additional details:

Be careful with [True] or [False] as sequence index, since True and False will respectively be evaluated as 1 and 0 and will bring the second element of the list and the first without erroring.

Created by the typecheck checker.

invalid-slice-index / E1127

Message emitted:

Slice index is not an int, None, or instance with __index__

Description:

Used when a slice index is not an integer, None, or an object with an __index__ method.

Problematic code:

LETTERS = ["a", "b", "c", "d"]
FIRST_THREE = LETTERS[:"3"]  # [invalid-slice-index]

Correct code:

LETTERS = ["a", "b", "c", "d"]
FIRST_THREE = LETTERS[:3]

Created by the typecheck checker.

invalid-slots / E0238

Message emitted:

Invalid __slots__ object

Description:

Used when an invalid __slots__ is found in class. Only a string, an iterable or a sequence is permitted.

Problematic code:

class Person:  # [invalid-slots]

__slots__ = 42

Correct code:

class Person:

__slots__ = ("name", "age",)

Created by the classes checker.

invalid-slots-object / E0236

Message emitted:

Invalid object %r in __slots__, must contain only non empty strings

Description:

Used when an invalid (non-string) object occurs in __slots__.

Problematic code:

class Person:

__slots__ = ('name', 3) # [invalid-slots-object]

Correct code:

class Person:

__slots__ = ('name', 'surname')

Related links:

Documentation for __slots__

Created by the classes checker.

invalid-star-assignment-target / E0113

Message emitted:

Starred assignment target must be in a list or tuple

Description:

Emitted when a star expression is used as a starred assignment target.

Problematic code:

*fruit = ['apple', 'banana', 'orange']  # [invalid-star-assignment-target]

Correct code:

fruit = ['apple', 'banana', 'orange']

Created by the basic checker.

invalid-str-returned / E0307

Message emitted:

__str__ does not return str

Description:

Used when a __str__ method returns something which is not a string

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

invalid-unary-operand-type / E1130

Message emitted:

%s

Description:

Emitted when a unary operand is used on an object which does not support this type of operation.

Problematic code:

cherries = 10
eaten_cherries = int
cherries = - eaten_cherries  # [invalid-unary-operand-type]

Correct code:

cherries = 10
eaten_cherries = 2
cherries -= eaten_cherries

Created by the typecheck checker.

invalid-unicode-codec / E2501

Message emitted:

UTF-16 and UTF-32 aren't backward compatible. Use UTF-8 instead

Description:

For compatibility use UTF-8 instead of UTF-16/UTF-32. See also https://bugs.python.org/issue1503789 for a history of this issue. And https://softwareengineering.stackexchange.com/questions/102205/should-utf-16-be-considered-harmful for some possible problems when using UTF-16 for instance.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the unicode_checker checker.

logging-format-truncated / E1201

Message emitted:

Logging format string ends in middle of conversion specifier

Description:

Used when a logging statement format string terminates before the end of a conversion specifier.

Problematic code:

import logging
logging.warning("Here is a variable: %", my_var)  # [logging-format-truncated]

Correct code:

import logging
logging.warning("Here is a variable: %s", my_var)

Created by the logging checker.

logging-too-few-args / E1206

Message emitted:

Not enough arguments for logging format string

Description:

Used when a logging format string is given too few arguments.

Problematic code:

import logging
try:

function() except Exception as e:
logging.error('%s error occurred: %s', e) # [logging-too-few-args]
raise

Correct code:

import logging
try:

function() except Exception as e:
logging.error('%s error occurred: %s', type(e), e)
raise

Created by the logging checker.

logging-too-many-args / E1205

Message emitted:

Too many arguments for logging format string

Description:

Used when a logging format string is given too many arguments.

Problematic code:

import logging
try:

function() except Exception as e:
logging.error('Error occurred: %s', type(e), e) # [logging-too-many-args]
raise

Correct code:

import logging
try:

function() except Exception as e:
logging.error('%s error occurred: %s', type(e), e)
raise

Created by the logging checker.

logging-unsupported-format / E1200

Message emitted:

Unsupported logging format character %r (%#02x) at index %d

Description:

Used when an unsupported format character is used in a logging statement format string.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the logging checker.

method-hidden / E0202

Message emitted:

An attribute defined in %s line %s hides this method

Description:

Used when a class defines a method which is hidden by an instance attribute from an ancestor class or set by some client code.

Problematic code:

class Fruit:

def __init__(self, vitamins):
self.vitamins = vitamins
def vitamins(self): # [method-hidden]
pass

Correct code:

class Fruit:

def __init__(self, vitamins):
self.vitamins = vitamins
def antioxidants(self):
pass

Created by the classes checker.

misplaced-bare-raise / E0704

Message emitted:

The raise statement is not inside an except clause

Description:

Used when a bare raise is not used inside an except clause. This generates an error, since there are no active exceptions to be reraised. An exception to this rule is represented by a bare raise inside a finally clause, which might work, as long as an exception is raised inside the try block, but it is nevertheless a code smell that must not be relied upon.

Problematic code:

def validate_positive(x):

if x <= 0:
raise # [misplaced-bare-raise]

Correct code:

def validate_positive(x):

if x <= 0:
raise ValueError(f"{x} is not positive")

Created by the exceptions checker.

misplaced-format-function / E0119

Message emitted:

format function is not called on str

Description:

Emitted when format function is not called on str object. e.g doing print("value: {}").format(123) instead of print("value: {}".format(123)). This might not be what the user intended to do.

Problematic code:

print('Value: {}').format('Car')  # [misplaced-format-function]

Correct code:

print('Value: {}'.format('Car'))

Created by the basic checker.

missing-format-string-key / E1304

Message emitted:

Missing key %r in format string dictionary

Description:

Used when a format string that uses named conversion specifiers is used with a dictionary that doesn't contain all the keys required by the format string.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the string checker.

missing-kwoa / E1125

Message emitted:

Missing mandatory keyword argument %r in %s call

Description:

Used when a function call does not pass a mandatory keyword-only argument.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

mixed-format-string / E1302

Message emitted:

Mixing named and unnamed conversion specifiers in format string

Description:

Used when a format string contains both named (e.g. '%(foo)d') and unnamed (e.g. '%d') conversion specifiers. This is also used when a named conversion specifier contains * for the minimum field width and/or precision.

Problematic code:

print("x=%(x)d, y=%d" % (0, 1))  # [mixed-format-string]

Correct code:

print("x=%d, y=%d" % (0, 1))
print("x=%(x)d, y=%(y)d" % {"x": 0, "y": 1})

Created by the string checker.

modified-iterating-dict / E4702

Message emitted:

Iterated dict '%s' is being modified inside for loop body, iterate through a copy of it instead.

Description:

Emitted when items are added or removed to a dict being iterated through. Doing so raises a RuntimeError.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the modified_iteration checker.

modified-iterating-set / E4703

Message emitted:

Iterated set '%s' is being modified inside for loop body, iterate through a copy of it instead.

Description:

Emitted when items are added or removed to a set being iterated through. Doing so raises a RuntimeError.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the modified_iteration checker.

no-member / E1101

Message emitted:

%s %r has no %r member%s

Description:

Used when a variable is accessed for a nonexistent member.

Problematic code:

from pathlib import Path
directories = Path(".").mothers  # [no-member]
class Cat:

def meow(self):
print("Meow") Cat().roar() # [no-member]

Correct code:

from pathlib import Path
directories = Path(".").parents
class Cat:

def meow(self):
print("Meow") Cat().meow()

Additional details:

If you are getting the dreaded no-member error, there is a possibility that either:

  • pylint found a bug in your code
  • You're launching pylint without the dependencies installed in its environment.
  • pylint would need to lint a C extension module and is refraining to do so.

Linting C extension modules is not supported out of the box, especially since pylint has no way to get an AST object out of the extension module.

But pylint actually has a mechanism which you might use in case you want to analyze C extensions. Pylint has a flag, called extension-pkg-allow-list (formerly extension-pkg-whitelist), through which you can tell it to import that module and to build an AST from that imported module:

$ pylint --extension-pkg-allow-list=your_c_extension

Be aware though that using this flag means that extensions are loaded into the active Python interpreter and may run arbitrary code, which you may not want. This is the reason why we disable by default loading C extensions. In case you do not want the hassle of passing C extensions module with this flag all the time, you can enable unsafe-load-any-extension in your configuration file, which will build AST objects from all the C extensions that pylint encounters:

$ pylint --unsafe-load-any-extension=y

Alternatively, since pylint emits a separate error for attributes that cannot be found in C extensions, c-extension-no-member, you can disable this error for your project.

Created by the typecheck checker.

no-method-argument / E0211

Message emitted:

Method %r has no argument

Description:

Used when a method which should have the bound instance as first argument has no argument defined.

Problematic code:

class Person:

def print_greeting(): # [no-method-argument]
print("hello")

Correct code:

class Person:

def print_greeting(self):
print("hello")

Created by the classes checker.

no-name-in-module / E0611

Message emitted:

No name %r in module %r

Description:

Used when a name cannot be found in a module.

Problematic code:

from os import pizza  # [no-name-in-module]

Correct code:

from os import path

Created by the variables checker.

no-self-argument / E0213

Message emitted:

Method %r should have "self" as first argument

Description:

Used when a method has an attribute different the "self" as first argument. This is considered as an error since this is a so common convention that you shouldn't break it!

Problematic code:

class Fruit:

def __init__(this, name): # [no-self-argument]
this.name = name

Correct code:

class Fruit:

def __init__(self, name):
self.name = name

Created by the classes checker.

no-value-for-parameter / E1120

Message emitted:

No value for argument %s in %s call

Description:

Used when a function call passes too few arguments.

Problematic code:

def add(x, y):

return x + y add(1) # [no-value-for-parameter]

Correct code:

def add(x, y):

return x + y add(1, 2)

Created by the typecheck checker.

non-iterator-returned / E0301

Message emitted:

__iter__ returns non-iterator

Description:

Used when an __iter__ method returns something which is not an iterable (i.e. has no `__next__` method)

Problematic code:

import random
class GenericAstrology:

def __init__(self, signs, predictions):
self.signs = signs
self.predictions = predictions
def __iter__(self): # [non-iterator-returned]
self.index = 0
self.number_of_prediction = len(self.predictions)
return self SIGNS = ["Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra"] PREDICTIONS = ["good things", "bad thing", "existential dread"] for sign, prediction in GenericAstrology(SIGNS, PREDICTIONS):
print(f"{sign} : {prediction} today")

Correct code:

import random
class GenericAstrology:

def __init__(self, signs, predictions):
self.signs = signs
self.predictions = predictions
def __iter__(self):
self.index = 0
self.number_of_prediction = len(self.predictions)
return self
def __next__(self):
if self.index == len(self.signs):
raise StopIteration
self.index += 1
prediction_index = random.randint(0, self.number_of_prediction - 1)
return self.signs[self.index - 1], self.predictions[prediction_index] SIGNS = ["Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra"] PREDICTIONS = ["good things", "bad thing", "existential dread"] for sign, prediction in GenericAstrology(SIGNS, PREDICTIONS):
print(f"{sign} : {prediction} today")

Created by the classes checker.

nonexistent-operator / E0107

Message emitted:

Use of the non-existent %s operator

Description:

Used when you attempt to use the C-style pre-increment or pre-decrement operator -- and ++, which doesn't exist in Python.

Problematic code:

i = 0
while i <= 10:

print(i)
++i # [nonexistent-operator]

Correct code:

i = 0
while i <= 10:

print(i)
i += 1

Created by the basic checker.

nonlocal-and-global / E0115

Message emitted:

Name %r is nonlocal and global

Description:

Emitted when a name is both nonlocal and global.

Problematic code:

NUMBER = 42
def update_number(number):  # [nonlocal-and-global]

global NUMBER
nonlocal NUMBER
NUMBER = number
print(f"New global number is: {NUMBER}") update_number(24)

Correct code:

NUMBER = 42
def update_number(number):

global NUMBER
NUMBER = number
print(f"New global number is: {NUMBER}") update_number(24)

Created by the basic checker.

nonlocal-without-binding / E0117

Message emitted:

nonlocal name %s found without binding

Description:

Emitted when a nonlocal variable does not have an attached name somewhere in the parent scopes

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the basic checker.

not-a-mapping / E1134

Message emitted:

Non-mapping value %s is used in a mapping context

Description:

Used when a non-mapping value is used in place where mapping is expected

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

not-an-iterable / E1133

Message emitted:

Non-iterable value %s is used in an iterating context

Description:

Used when a non-iterable value is used in place where iterable is expected

Problematic code:

for i in 10:  # [not-an-iterable]

pass

Correct code:

for i in "10":

pass

Created by the typecheck checker.

not-async-context-manager / E1701

Message emitted:

Async context manager '%s' doesn't implement __aenter__ and __aexit__.

Description:

Used when an async context manager is used with an object that does not implement the async context management protocol.

Problematic code:

class ContextManager:

def __enter__(self):
pass
def __exit__(self, *exc):
pass async def foo():
async with ContextManager(): # [not-async-context-manager]
pass

Correct code:

class AsyncContextManager:

def __aenter__(self):
pass
def __aexit__(self, *exc):
pass async def foo():
async with AsyncContextManager():
pass

Additional details:

Async context manager doesn't implement __aenter__ and __aexit__. It can't be emitted when using Python < 3.5.

Created by the async checker.

not-callable / E1102

Message emitted:

%s is not callable

Description:

Used when an object being called has been inferred to a non callable object.

Problematic code:

NUMBER = 42
print(NUMBER())  # [not-callable]

Correct code:

NUMBER = 42
print(NUMBER)

Created by the typecheck checker.

not-context-manager / E1129

Message emitted:

Context manager '%s' doesn't implement __enter__ and __exit__.

Description:

Used when an instance in a with statement doesn't implement the context manager protocol(__enter__/__exit__).

Problematic code:

class MyContextManager:

def __enter__(self):
pass with MyContextManager() as c: # [not-context-manager]
pass

Correct code:

class MyContextManager:

def __enter__(self):
pass
def __exit__(self, *exc):
pass with MyContextManager() as c:
pass

Created by the typecheck checker.

not-in-loop / E0103

Message emitted:

%r not properly in loop

Description:

Used when break or continue keywords are used outside a loop.

Problematic code:

def print_even_numbers():

for i in range(100):
if i % 2 == 0:
print(i)
else:
continue # [not-in-loop]

Correct code:

def print_even_numbers():

for i in range(100):
if i % 2:
continue
print(i)

Created by the basic checker.

notimplemented-raised / E0711

Message emitted:

NotImplemented raised - should raise NotImplementedError

Description:

Used when NotImplemented is raised instead of NotImplementedError

Problematic code:

class Worm:

def bore(self):
raise NotImplemented # [notimplemented-raised]

Correct code:

class Worm:

def bore(self):
raise NotImplementedError

Created by the exceptions checker.

potential-index-error / E0643

Message emitted:

Invalid index for iterable length

Description:

Emitted when an index used on an iterable goes beyond the length of that iterable.

Problematic code:

print([1, 2, 3][3])  # [potential-index-error]

Correct code:

print([1, 2, 3][2])

Created by the variables checker.

raising-bad-type / E0702

Message emitted:

Raising %s while only classes or instances are allowed

Description:

Used when something which is neither a class nor an instance is raised (i.e. a `TypeError` will be raised).

Problematic code:

class FasterThanTheSpeedOfLightError(ZeroDivisionError):

def __init__(self):
super().__init__("You can't go faster than the speed of light !") def calculate_speed(distance: float, time: float) -> float:
try:
return distance / time
except ZeroDivisionError as e:
raise None # [raising-bad-type]

Correct code:

class FasterThanTheSpeedOfLightError(ZeroDivisionError):

def __init__(self):
super().__init__("You can't go faster than the speed of light !") def calculate_speed(distance: float, time: float) -> float:
try:
return distance / time
except ZeroDivisionError as e:
raise FasterThanTheSpeedOfLightError() from e

Created by the exceptions checker.

raising-non-exception / E0710

Message emitted:

Raising a new style class which doesn't inherit from BaseException

Description:

Used when a new style class which doesn't inherit from BaseException is raised.

Problematic code:

raise str  # [raising-non-exception]

Correct code:

raise Exception("Goodbye world !")

Created by the exceptions checker.

redundant-keyword-arg / E1124

Message emitted:

Argument %r passed by position and keyword in %s call

Description:

Used when a function call would result in assigning multiple values to a function parameter, one value from a positional argument and one from a keyword argument.

Problematic code:

def square(x):

return x * x square(5, x=4) # [redundant-keyword-arg]

Correct code:

def square(x):

return x * x square(x=4) # or square(5)

Created by the typecheck checker.

relative-beyond-top-level / E0402

Message emitted:

Attempted relative import beyond top-level package

Description:

Used when a relative import tries to access too many levels in the current package.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the imports checker.

repeated-keyword / E1132

Message emitted:

Got multiple values for keyword argument %r in function call

Description:

Emitted when a function call got multiple values for a keyword.

Problematic code:

def func(a, b, c):

return a, b, c func(1, 2, c=3, **{"c": 4}) # [repeated-keyword] func(1, 2, **{"c": 3}, **{"c": 4}) # [repeated-keyword]

Correct code:

def func(a, b, c):

return a, b, c func(1, 2, c=3)

Created by the typecheck checker.

return-arg-in-generator / E0106

Message emitted:

Return with argument inside generator

Description:

Used when a "return" statement with an argument is found outside in a generator function or method (e.g. with some "yield" statements).

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the basic checker.

return-in-init / E0101

Message emitted:

Explicit return in __init__

Description:

Used when the special class method __init__ has an explicit return value.

Problematic code:

class Sum:

def __init__(self, a, b): # [return-in-init]
return a + b

Correct code:

class Sum:

def __init__(self, a, b) -> None:
self.result = a + b

Related links:

__init__ method documentation

Created by the basic checker.

return-outside-function / E0104

Message emitted:

Return outside function

Description:

Used when a "return" statement is found outside a function or method.

Problematic code:

return 42  # [return-outside-function]

Correct code:

def get_the_answer():

return 42

Created by the basic checker.

star-needs-assignment-target / E0114

Message emitted:

Can use starred expression only in assignment target

Description:

Emitted when a star expression is not used in an assignment target.

Problematic code:

stars = *["Sirius", "Arcturus", "Vega"]  # [star-needs-assignment-target]

Correct code:

sirius, *arcturus_and_vega = ["Sirius", "Arcturus", "Vega"]

Created by the basic checker.

Message emitted:

%s

Description:

Used when a syntax error is raised for a module.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

too-few-format-args / E1306

Message emitted:

Not enough arguments for format string

Description:

Used when a format string that uses unnamed conversion specifiers is given too few arguments

Problematic code:

print("Today is {0}, so tomorrow will be {1}".format("Monday"))  # [too-few-format-args]

Correct code:

print("Today is {0}, so tomorrow will be {1}".format("Monday", "Tuesday"))

Related links:

String Formmating

Created by the string checker.

too-many-format-args / E1305

Message emitted:

Too many arguments for format string

Description:

Used when a format string that uses unnamed conversion specifiers is given too many arguments.

Problematic code:

print("Today is {0}, so tomorrow will be {1}".format("Monday", "Tuesday", "Wednesday"))  # [too-many-format-args]

Correct code:

print("Today is {0}, so tomorrow will be {1}".format("Monday", "Tuesday"))

Related links:

String Formmating

Created by the string checker.

too-many-function-args / E1121

Message emitted:

Too many positional arguments for %s call

Description:

Used when a function call passes too many positional arguments.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

too-many-star-expressions / E0112

Message emitted:

More than one starred expression in assignment

Description:

Emitted when there are more than one starred expressions (`*x`) in an assignment. This is a SyntaxError.

Problematic code:

*stars, *constellations = ["Sirius", "Arcturus", "Vega"]  # [too-many-star-expressions]

Correct code:

*sirius_and_arcturus, vega = ["Sirius", "Arcturus", "Vega"]

Created by the basic checker.

truncated-format-string / E1301

Message emitted:

Format string ends in middle of conversion specifier

Description:

Used when a format string terminates before the end of a conversion specifier.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the string checker.

undefined-all-variable / E0603

Message emitted:

Undefined variable name %r in __all__

Description:

Used when an undefined variable name is referenced in __all__.

Problematic code:

__all__ = ["get_fruit_colour"]  # [undefined-all-variable]
def get_fruit_color():

pass

Correct code:

__all__ = ["get_fruit_color"]
def get_fruit_color():

pass

Related links:

Importing * From a Package

Created by the variables checker.

undefined-variable / E0602

Message emitted:

Undefined variable %r

Description:

Used when an undefined variable is accessed.

Problematic code:

print(number + 2)  # [undefined-variable]

Correct code:

number = 3
print(number + 2)

Created by the variables checker.

unexpected-keyword-arg / E1123

Message emitted:

Unexpected keyword argument %r in %s call

Description:

Used when a function call passes a keyword argument that doesn't correspond to one of the function's parameter names.

Problematic code:

def print_coordinates(x=0, y=0):

print(f"{x=}, {y=}") print_coordinates(x=1, y=2, z=3) # [unexpected-keyword-arg]

Correct code:

def print_coordinates(x=0, y=0):

print(f"{x=}, {y=}") print_coordinates(x=1, y=2)

Created by the typecheck checker.

unexpected-special-method-signature / E0302

Message emitted:

The special method %r expects %s param(s), %d %s given

Description:

Emitted when a special method was defined with an invalid number of parameters. If it has too few or too many, it might not work at all.

Problematic code:

class ContextManager:

def __enter__(self, context): # [unexpected-special-method-signature]
pass
def __exit__(self, type): # [unexpected-special-method-signature]
pass

Correct code:

class ContextManager:

def __enter__(self):
pass
def __exit__(self, type, value, traceback):
pass

Created by the classes checker.

unhashable-member / E1143

Message emitted:

'%s' is unhashable and can't be used as a %s in a %s

Description:

Emitted when a dict key or set member is not hashable (i.e. doesn't define __hash__ method).

Problematic code:

# Print the number of apples:
print({"apple": 42}[["apple"]])  # [unhashable-member]

Correct code:

# Print the number of apples:
print({"apple": 42}["apple"])

Created by the typecheck checker.

unpacking-non-sequence / E0633

Message emitted:

Attempting to unpack a non-sequence%s

Description:

Used when something which is not a sequence is used in an unpack assignment

Problematic code:

a, b, c = 1  # [unpacking-non-sequence]

Correct code:

a, b, c = 1, 2, 3

Created by the variables checker.

unrecognized-inline-option / E0011

Message emitted:

Unrecognized file option %r

Description:

Used when an unknown inline option is encountered.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

unrecognized-option / E0015

Message emitted:

Unrecognized option found: %s

Description:

Used when we detect an option that we do not recognize.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

unsubscriptable-object / E1136

Message emitted:

Value '%s' is unsubscriptable

Description:

Emitted when a subscripted value doesn't support subscription (i.e. doesn't define __getitem__ method or __class_getitem__ for a class).

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

unsupported-assignment-operation / E1137

Message emitted:

%r does not support item assignment

Description:

Emitted when an object does not support item assignment (i.e. doesn't define __setitem__ method).

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

unsupported-binary-operation / E1131

Message emitted:

%s

Description:

Emitted when a binary arithmetic operation between two operands is not supported.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

unsupported-delete-operation / E1138

Message emitted:

%r does not support item deletion

Description:

Emitted when an object does not support item deletion (i.e. doesn't define __delitem__ method).

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

unsupported-membership-test / E1135

Message emitted:

Value '%s' doesn't support membership test

Description:

Emitted when an instance in membership test expression doesn't implement membership protocol (__contains__/__iter__/__getitem__).

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

used-before-assignment / E0601

Message emitted:

Using variable %r before assignment

Description:

Emitted when a local variable is accessed before its assignment took place. Assignments in try blocks are assumed not to have occurred when evaluating associated except/finally blocks. Assignments in except blocks are assumed not to have occurred when evaluating statements outside the block, except when the associated try block contains a return statement.

Problematic code:

print(hello)  # [used-before-assignment]
hello = "Hello World !"

Correct code:

hello = "Hello World !"
print(hello)

Created by the variables checker.

used-prior-global-declaration / E0118

Message emitted:

Name %r is used prior to global declaration

Description:

Emitted when a name is used prior a global declaration, which results in an error since Python 3.6.

Problematic code:

TOMATO = "black cherry"
def update_tomato():

print(TOMATO) # [used-prior-global-declaration]
global TOMATO
TOMATO = "cherry tomato"

Correct code:

TOMATO = "black cherry"
def update_tomato():

global TOMATO
TOMATO = "moneymaker"

Created by the basic checker.

yield-inside-async-function / E1700

Message emitted:

Yield inside async function

Description:

Used when an `yield` or `yield from` statement is found inside an async function.

Problematic code:

async def foo():

yield from [1, 2, 3] # [yield-inside-async-function]

Correct code:

async def foo():

def _inner_foo():
yield from [1, 2, 3] async def foo():
yield 42

Additional details:

The message can't be emitted when using Python < 3.5.

Related links:

PEP 525

Created by the async checker.

yield-outside-function / E0105

Message emitted:

Yield outside function

Description:

Used when a "yield" statement is found outside a function or method.

Problematic code:

for i in range(10):

yield i # [yield-outside-function]

Correct code:

def one_to_ten():

for i in range(10):
yield i

Created by the basic checker.

All renamed messages in the error category:

"bad-context-manager has been renamed. The new message can be found at:

"bad-exception-context has been renamed. The new message can be found at:

"bad-option-value has been renamed. The new message can be found at:

useless-option-value / R0022

Message emitted:

Useless option value for '%s', %s

Description:

Used when a value for an option that is now deleted from pylint is encountered.

Problematic code:

"""'bad-continuation' was removed from pylint in https://github.com/PyCQA/pylint/pull/3571"""
# pylint: disable=bad-continuation  # [useless-option-value]

Correct code:

"""'bad-continuation' was removed from pylint in https://github.com/PyCQA/pylint/pull/3571"""

Additional details:

You can disable this check if you don't want to cleanup your configuration of old messages.

Created by the main checker.

Message emitted:

Unknown option value for '%s', expected a valid pylint message and got '%s'

Description:

Used when an unknown value is encountered for an option.

Problematic code:

# pylint: disable=missnig-docstring  # [unknown-option-value]

Correct code:

# pylint: disable=missing-docstring

Created by the main checker.

"maybe-no-member has been renamed. The new message can be found at:

"old-non-iterator-returned-2 has been renamed. The new message can be found at:

"old-unbalanced-tuple-unpacking has been renamed. The new message can be found at:

unbalanced-tuple-unpacking / W0632

Message emitted:

Possible unbalanced tuple unpacking with sequence%s: left side has %d label(s), right side has %d value(s)

Description:

Used when there is an unbalanced tuple unpacking in assignment

Problematic code:

fruits = ("orange", "apple", "strawberry", "peer")
orange, apple, strawberry = fruits  # [unbalanced-tuple-unpacking]

Correct code:

fruits = ("orange", "apple", "strawberry", "peer")
orange, apple, *remaining_fruits = fruits

Related links:

PEP 3132 - Extended Iterable Unpacking

Created by the variables checker.

"unhashable-dict-key has been renamed. The new message can be found at:

All messages in the warning category:

abstract-method / W0223

Message emitted:

Method %r is abstract in class %r but is not overridden

Description:

Used when an abstract method (i.e. raise NotImplementedError) is not overridden in concrete class.

Problematic code:

class Pet:

def make_sound(self):
raise NotImplementedError class Cat(Pet): # [abstract-method]
pass import abc class WildAnimal:
@abc.abstractmethod
def make_sound(self):
pass class Panther(WildAnimal): # [abstract-method]
pass

Correct code:

class Pet:

def make_sound(self):
raise NotImplementedError class Cat(Pet):
def make_sound(self):
print("Meeeow") import abc class WildAnimal:
@abc.abstractmethod
def make_sound(self):
pass class Panther(WildAnimal):
def make_sound(self):
print("MEEEOW")

Created by the classes checker.

anomalous-backslash-in-string / W1401

Message emitted:

Anomalous backslash in string: '%s'. String constant might be missing an r prefix.

Description:

Used when a backslash is in a literal string but not as an escape.

Problematic code:

string = "\z"  # [anomalous-backslash-in-string]

Correct code:

string = r"\z"
string = "\n"

Created by the string checker.

anomalous-unicode-escape-in-string / W1402

Message emitted:

Anomalous Unicode escape in byte string: '%s'. String constant might be missing an r or u prefix.

Description:

Used when an escape like u is encountered in a byte string where it has no effect.

Problematic code:

print(b"\u{0}".format("0394"))  # [anomalous-unicode-escape-in-string]

Correct code:

print(b"\\u{0}".format("0394"))

Created by the string checker.

arguments-differ / W0221

Message emitted:

%s %s %r method

Description:

Used when a method has a different number of arguments than in the implemented interface or in an overridden method. Extra arguments with default values are ignored.

Problematic code:

class Drink:

def mix(self, fluid_one, fluid_two):
return fluid_one + fluid_two class Cocktail(Drink):
def mix(self, fluid_one, fluid_two, alcoholic_fluid_one): # [arguments-differ]
return fluid_one + fluid_two + alcoholic_fluid_one class Car:
tank = 0
def fill_tank(self, gas):
self.tank += gas class Airplane(Car):
kerosene_tank = 0
def fill_tank(self, gas, kerosene): # [arguments-differ]
self.tank += gas
self.kerosene_tank += kerosene

Correct code:

class Drink:

def mix(self, fluid_one, fluid_two):
return fluid_one + fluid_two class Cocktail(Drink):
def mix(self, fluid_one, fluid_two, alcoholic_fluid_one="Beer"):
return fluid_one + fluid_two + alcoholic_fluid_one class Car:
tank = 0
def fill_tank(self, gas):
self.tank += gas class Airplane:
tank = 0
kerosene_tank = 0
def fill_tank(self, gas, kerosene):
self.tank += gas
self.kerosene_tank += kerosene

Additional details:

argument-differ denotes an issue with the Liskov Substitution Principle. This means that the code in question violates an important design principle which does not have one single solution. We recommend to search online for the best solution in your case.

To give some examples of potential solutions: - Add the argument to the parent class - Remove the inheritance completely - Add default arguments to the child class

Related links:

Liskov Substitution Principle

Created by the classes checker.

arguments-out-of-order / W1114

Message emitted:

Positional arguments appear to be out of order

Description:

Emitted when the caller's argument names fully match the parameter names in the function signature but do not have the same order.

Problematic code:

def function_3_args(first_argument, second_argument, third_argument):

"""Three arguments function"""
return first_argument, second_argument, third_argument def args_out_of_order():
first_argument = 1
second_argument = 2
third_argument = 3
function_3_args( # [arguments-out-of-order]
first_argument, third_argument, second_argument
)

Correct code:

def function_3_args(first_argument, second_argument, third_argument):

"""Three arguments function"""
return first_argument, second_argument, third_argument def args_out_of_order():
first_argument = 1
second_argument = 2
third_argument = 3
function_3_args(first_argument, second_argument, third_argument)

Created by the typecheck checker.

arguments-renamed / W0237

Message emitted:

%s %s %r method

Description:

Used when a method parameter has a different name than in the implemented interface or in an overridden method.

Problematic code:

class Fruit:

def brew(self, ingredient_name: str):
print(f"Brewing a {type(self)} with {ingredient_name}") class Apple(Fruit):
... class Orange(Fruit):
def brew(self, flavor: str): # [arguments-renamed]
print(f"Brewing an orange with {flavor}") for fruit, ingredient_name in [[Orange(), "thyme"], [Apple(), "cinnamon"]]:
fruit.brew(ingredient_name=ingredient_name)

Correct code:

class Fruit:

def brew(self, ingredient_name: str):
print(f"Brewing a {type(self)} with {ingredient_name}") class Apple(Fruit):
... class Orange(Fruit):
def brew(self, ingredient_name: str):
print(f"Brewing an orange with {ingredient_name}") for fruit, ingredient_name in [[Orange(), "thyme"], [Apple(), "cinnamon"]]:
fruit.brew(ingredient_name=ingredient_name)

Created by the classes checker.

assert-on-string-literal / W0129

Message emitted:

Assert statement has a string literal as its first argument. The assert will %s fail.

Description:

Used when an assert statement has a string literal as its first argument, which will cause the assert to always pass.

Problematic code:

def test_division():

a = 9 / 3
assert "No ZeroDivisionError were raised" # [assert-on-string-literal]

Correct code:

def test_division():

a = 9 / 3
assert a == 3

Additional details:

Directly asserting a string literal will always pass. The solution is to test something that could fail, or not assert at all.

For unittest assertions there is the similar redundant-unittest-assert / W1503 message.

Related links:

  • Tests without assertion
  • Testing that there is no error raised
  • Parametrizing conditional raising

Created by the basic checker.

assert-on-tuple / W0199

Message emitted:

Assert called on a 2-item-tuple. Did you mean 'assert x,y'?

Description:

A call of assert on a tuple will always evaluate to true if the tuple is not empty, and will always evaluate to false if it is.

Problematic code:

assert (1, None)  # [assert-on-tuple]

Correct code:

x, y = (1, None)
assert x
assert y

Additional details:

test something that could fail, or not assert at all.

For unittest assertions there is the similar redundant-unittest-assert / W1503 message.

Created by the basic checker.

attribute-defined-outside-init / W0201

Message emitted:

Attribute %r defined outside __init__

Description:

Used when an instance attribute is defined outside the __init__ method.

Problematic code:

class Student:

def register(self):
self.is_registered = True # [attribute-defined-outside-init]

Correct code:

class Student:

def __init__(self):
self.is_registered = False
def register(self):
self.is_registered = True

Created by the classes checker.

bad-builtin / W0141

Message emitted:

Used builtin function %s

Description:

Used when a disallowed builtin function is used (see the bad-function option). Usual disallowed functions are the ones like map, or filter , where Python offers now some cleaner alternative like list comprehension.

Problematic code:

numbers = list(map(lambda x: 2 * x, [1, 2, 3]))  # [bad-builtin]
print(numbers)

Correct code:

numbers = [2 * x for x in [1, 2, 3]]
print(numbers)

NOTE:

This message is emitted by the optional 'deprecated_builtins' checker which requires the pylint.extensions.bad_builtin plugin to be loaded.

Created by the deprecated_builtins checker.

bad-format-string / W1302

Message emitted:

Invalid format string

Description:

Used when a PEP 3101 format string is invalid.

Problematic code:

print('{a[0] + a[1]}'.format(a=[0, 1])) # [bad-format-string]

Correct code:

print('{a[0]} + {a[1]}'.format(a=[0, 1]))

Related links:

  • Format String Syntax
  • PyFormat

Created by the string checker.

bad-format-string-key / W1300

Message emitted:

Format string dictionary key should be a string, not %s

Description:

Used when a format string that uses named conversion specifiers is used with a dictionary whose keys are not all strings.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the string checker.

bad-indentation / W0311

Message emitted:

Bad indentation. Found %s %s, expected %s

Description:

Used when an unexpected number of indentation's tabulations or spaces has been found.

Problematic code:

if input():

print('yes') # [bad-indentation]

Correct code:

if input():

print('yes')

Additional details:

The option --indent-string can be used to set the indentation unit for this check.

Created by the format checker.

bad-open-mode / W1501

Message emitted:

"%s" is not a valid mode for open.

Description:

Python supports: r, w, a[, x] modes with b, +, and U (only with r) options. See https://docs.python.org/3/library/functions.html#open

Problematic code:

def foo(file_path):

with open(file_path, "rwx") as file: # [bad-open-mode]
contents = file.read()

Correct code:

def foo(file_path):

with open(file_path, "r") as file:
contents = file.read()

Created by the stdlib checker.

bad-staticmethod-argument / W0211

Message emitted:

Static method with %r as first argument

Description:

Used when a static method has "self" or a value specified in valid-classmethod-first-arg option or valid-metaclass-classmethod-first-arg option as first argument.

Problematic code:

class Wolf:

@staticmethod
def eat(self): # [bad-staticmethod-argument]
pass

Correct code:

class Wolf:

@staticmethod
def eat(sheep):
pass

Created by the classes checker.

bad-thread-instantiation / W1506

Message emitted:

threading.Thread needs the target function

Description:

The warning is emitted when a threading.Thread class is instantiated without the target function being passed. By default, the first parameter is the group param, not the target param.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the stdlib checker.

bare-except / W0702

Message emitted:

No exception type(s) specified

Description:

Used when an except clause doesn't specify exceptions type to catch.

Problematic code:

try:

1 / 0 except: # [bare-except]
pass

Correct code:

try:

1 / 0 except ZeroDivisionError:
pass

Created by the exceptions checker.

binary-op-exception / W0711

Message emitted:

Exception to catch is the result of a binary "%s" operation

Description:

Used when the exception to catch is of the form "except A or B:". If intending to catch multiple, rewrite as "except (A, B):"

Problematic code:

try:

1 / 0 except ZeroDivisionError or ValueError: # [binary-op-exception]
pass

Correct code:

try:

1 / 0 except (ZeroDivisionError, ValueError):
pass

Created by the exceptions checker.

boolean-datetime / W1502

Message emitted:

Using datetime.time in a boolean context.

Description:

Using datetime.time in a boolean context can hide subtle bugs when the time they represent matches midnight UTC. This behaviour was fixed in Python 3.5. See https://bugs.python.org/issue13936 for reference.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the stdlib checker.

broad-except / W0703

Message emitted:

Catching too general exception %s

Description:

Used when an except catches a too general exception, possibly burying unrelated errors.

Problematic code:

try:

1 / 0 except Exception: # [broad-except]
pass

Correct code:

try:

1 / 0 except ZeroDivisionError:
pass

Created by the exceptions checker.

cell-var-from-loop / W0640

Message emitted:

Cell variable %s defined in loop

Description:

A variable used in a closure is defined in a loop. This will result in all closures using the same value for the closed-over variable.

Problematic code:

def foo(numbers):

for i in numbers:
def bar():
print(i) # [cell-var-from-loop]
bar()

Correct code:

def bar(x):

print(x) def foo(numbers):
for i in numbers:
bar(i)

Related links:

Stackoverflow discussion

Created by the variables checker.

comparison-with-callable / W0143

Message emitted:

Comparing against a callable, did you omit the parenthesis?

Description:

This message is emitted when pylint detects that a comparison with a callable was made, which might suggest that some parenthesis were omitted, resulting in potential unwanted behaviour.

Problematic code:

def function_returning_a_fruit() -> str:

return "orange" def is_an_orange(fruit: str = "apple"):
# apple == <function function_returning_a_fruit at 0x7f343ff0a1f0>
return fruit == function_returning_a_fruit # [comparison-with-callable]

Correct code:

def function_returning_a_fruit() -> str:

return "orange" def is_an_orange(fruit: str = "apple"):
# apple == orange
return fruit == function_returning_a_fruit()

Created by the basic checker.

confusing-with-statement / W0124

Message emitted:

Following "as" with another context manager looks like a tuple.

Description:

Emitted when a `with` statement component returns multiple values and uses name binding with `as` only for a part of those values, as in with ctx() as a, b. This can be misleading, since it's not clear if the context manager returns a tuple or if the node without a name binding is another context manager.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the basic checker.

consider-ternary-expression / W0160

Message emitted:

Consider rewriting as a ternary expression

Description:

Multiple assign statements spread across if/else blocks can be rewritten with a single assignment and ternary expression

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'consider_ternary_expression' checker which requires the pylint.extensions.consider_ternary_expression plugin to be loaded.

Created by the consider_ternary_expression checker.

dangerous-default-value / W0102

Message emitted:

Dangerous default value %s as argument

Description:

Used when a mutable value as list or dictionary is detected in a default value for an argument.

Problematic code:

def whats_on_the_telly(penguin=[]):  # [dangerous-default-value]

penguin.append("property of the zoo")
return penguin

Correct code:

def whats_on_the_telly(penguin=None):

if penguin is None:
penguin = []
penguin.append("property of the zoo")
return penguin

Additional details:

With a mutable default value, with each call the default value is modified, i.e.:

whats_on_the_telly() # ["property of the zoo"]
whats_on_the_telly() # ["property of the zoo", "property of the zoo"]
whats_on_the_telly() # ["property of the zoo", "property of the zoo", "property of the zoo"]

Created by the basic checker.

deprecated-argument / W4903

Message emitted:

Using deprecated argument %s of method %s()

Description:

The argument is marked as deprecated and will be removed in the future.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the stdlib checker.

deprecated-class / W4904

Message emitted:

Using deprecated class %s of module %s

Description:

The class is marked as deprecated and will be removed in the future.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the stdlib checker.

deprecated-decorator / W4905

Message emitted:

Using deprecated decorator %s()

Description:

The decorator is marked as deprecated and will be removed in the future.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the stdlib checker.

deprecated-method / W4902

Message emitted:

Using deprecated method %s()

Description:

The method is marked as deprecated and will be removed in the future.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the stdlib checker.

deprecated-module / W4901

Message emitted:

Deprecated module %r

Description:

A module marked as deprecated is imported.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the imports checker.

deprecated-typing-alias / W6001

Message emitted:

'%s' is deprecated, use '%s' instead

Description:

Emitted when a deprecated typing alias is used.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'typing' checker which requires the pylint.extensions.typing plugin to be loaded.

Created by the typing checker.

differing-param-doc / W9017

Message emitted:

"%s" differing in parameter documentation

Description:

Please check parameter names in declarations.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

differing-type-doc / W9018

Message emitted:

"%s" differing in parameter type documentation

Description:

Please check parameter names in type declarations.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

duplicate-except / W0705

Message emitted:

Catching previously caught exception type %s

Description:

Used when an except catches a type that was already caught by a previous handler.

Problematic code:

try:

1 / 0 except ZeroDivisionError:
pass except ZeroDivisionError: # [duplicate-except]
pass

Correct code:

try:

1 / 0 except ZeroDivisionError:
pass

Created by the exceptions checker.

duplicate-key / W0109

Message emitted:

Duplicate key %r in dictionary

Description:

Used when a dictionary expression binds the same key multiple times.

Problematic code:

test_score = {"Mathematics": 85, "Biology": 90, "Mathematics": 75}  # [duplicate-key]

Correct code:

test_score = {"Mathematics": 85, "Biology": 90, "History": 75}

Related links:

  • Python Dictionaries
  • Mapping Types — dict

Created by the basic checker.

duplicate-string-formatting-argument / W1308

Message emitted:

Duplicate string formatting argument %r, consider passing as named argument

Description:

Used when we detect that a string formatting is repeating an argument instead of using named string arguments

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the string checker.

duplicate-value / W0130

Message emitted:

Duplicate value %r in set

Description:

This message is emitted when a set contains the same value two or more times.

Problematic code:

incorrect_set = {'value1', 23, 5, 'value1'} # [duplicate-value]

Correct code:

correct_set = {'value1', 23, 5}

Created by the basic checker.

eq-without-hash / W1641

Message emitted:

Implementing __eq__ without also implementing __hash__

Description:

Used when a class implements __eq__ but not __hash__. Objects get None as their default __hash__ implementation if they also implement __eq__.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'eq-without-hash' checker which requires the pylint.extensions.eq_without_hash plugin to be loaded.

Created by the eq-without-hash checker.

eval-used / W0123

Message emitted:

Use of eval

Description:

Used when you use the "eval" function, to discourage its usage. Consider using `ast.literal_eval` for safely evaluating strings containing Python expressions from untrusted sources.

Problematic code:

eval("[1, 2, 3]")  # [eval-used]

Correct code:

from ast import literal_eval
literal_eval("[1, 2, 3]")

Created by the basic checker.

exec-used / W0122

Message emitted:

Use of exec

Description:

Raised when the 'exec' statement is used. It's dangerous to use this function for a user input, and it's also slower than actual code in general. This doesn't mean you should never use it, but you should consider alternatives first and restrict the functions available.

Problematic code:

username = "Ada"
code_to_execute = f"""input('Enter code to be executed please, {username}: ')"""
program = exec(code_to_execute)  # [exec-used]
exec(program)  # [exec-used]

Correct code:

def get_user_code(name):

return input(f'Enter code to be executed please, {name}: ') username = "Ada" allowed_globals = {'__builtins__' : None} allowed_locals = {'print': print} exec(get_user_code(username), allowed_globals, allowed_locals) # pylint: disable=exec-used

Additional details:

The available methods and variables used in exec() may introduce a security hole. You can restrict the use of these variables and methods by passing optional globals and locals parameters (dictionaries) to the exec() method.

Related links:

Be careful with exec and eval in Python

Created by the basic checker.

expression-not-assigned / W0106

Message emitted:

Expression "%s" is assigned to nothing

Description:

Used when an expression that is not a function call is assigned to nothing. Probably something else was intended.

Problematic code:

str(42) == "42"  # [expression-not-assigned]

Correct code:

are_equal: bool = str(42) == "42"

Created by the basic checker.

f-string-without-interpolation / W1309

Message emitted:

Using an f-string that does not have any interpolated variables

Description:

Used when we detect an f-string that does not use any interpolation variables, in which case it can be either a normal string or a bug in the code.

Problematic code:

x = 1
y = 2
print(f"x + y = x + y")  # [f-string-without-interpolation]

Correct code:

x = 1
y = 2
print(f"{x} + {y} = {x + y}")

Created by the string checker.

Message emitted:

%s

Description:

Used when a warning note as FIXME or XXX is detected.

Problematic code:

# FIXME: Create an issue on the bug tracker for this refactor we might do someday  # [fixme]
...
# TODO: We should also fix this at some point  # [fixme]

Correct code:

# I no longer want to fix this
...
# I have fixed the issue

Additional details:

You can get use regular expressions and the notes-rgx option to create some constraints for this message. See the following issue for some examples.

Created by the miscellaneous checker.

forgotten-debug-statement / W1515

Message emitted:

Leaving functions creating breakpoints in production code is not recommended

Description:

Calls to breakpoint(), sys.breakpointhook() and pdb.set_trace() should be removed from code that is not actively being debugged.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the stdlib checker.

format-combined-specification / W1305

Message emitted:

Format string contains both automatic field numbering and manual field specification

Description:

Used when a PEP 3101 format string contains both automatic field numbering (e.g. '{}') and manual field specification (e.g. '{0}').

Problematic code:

print('{} {1}'.format('hello', 'world'))  # [format-combined-specification]

Correct code:

print('{0} {1}'.format('hello', 'world'))
# or
print('{} {}'.format('hello', 'world'))

Created by the string checker.

format-string-without-interpolation / W1310

Message emitted:

Using formatting for a string that does not have any interpolated variables

Description:

Used when we detect a string that does not have any interpolation variables, in which case it can be either a normal string without formatting or a bug in the code.

Problematic code:

print("number".format(1))  # [format-string-without-interpolation]

Correct code:

print("number: {}".format(1))

Created by the string checker.

global-at-module-level / W0604

Message emitted:

Using the global statement at the module level

Description:

Used when you use the "global" statement at the module level since it has no effect

Problematic code:

price = 25
global price  # [global-at-module-level]

Correct code:

price = 25

Related links:

  • Official Python FAQ - global and local
  • PEP 3104 - Access to Names in Outer Scopes
  • Python global statement

Created by the variables checker.

global-statement / W0603

Message emitted:

Using the global statement

Description:

Used when you use the "global" statement to update a global variable. Pylint just try to discourage this usage. That doesn't mean you cannot use it !

Problematic code:

var = 1
def foo():

global var # [global-statement]
var = 10
print(var) foo() print(var)

Correct code:

var = 1
def foo():

print(var)
return 10 var = foo() print(var)

Created by the variables checker.

global-variable-not-assigned / W0602

Message emitted:

Using global for %r but no assignment is done

Description:

Used when a variable is defined through the "global" statement but no assignment to this variable is done.

Problematic code:

TOMATO = "black cherry"
def update_tomato():

global TOMATO # [global-variable-not-assigned]
print(TOMATO)

Correct code:

TOMATO = "black cherry"
def update_tomato():

global TOMATO
TOMATO = "moneymaker"

Created by the variables checker.

global-variable-undefined / W0601

Message emitted:

Global variable %r undefined at the module level

Description:

Used when a variable is defined through the "global" statement but the variable is not defined in the module scope.

Problematic code:

def update_tomato():

global TOMATO # [global-variable-undefined]
TOMATO = "moneymaker"

Correct code:

TOMATO = "black cherry"
def update_tomato():

global TOMATO
TOMATO = "moneymaker"

Created by the variables checker.

implicit-str-concat / W1404

Message emitted:

Implicit string concatenation found in %s

Description:

String literals are implicitly concatenated in a literal iterable definition : maybe a comma is missing ?

Problematic code:

x = ["a" "b"]  # [implicit-str-concat]
with open("hello.txt" "r") as f:  # [implicit-str-concat]

print(f.read())

Correct code:

x = ["a", "b"]
with open("hello.txt", "r") as f:

print(f.read())

Created by the string checker.

import-self / W0406

Message emitted:

Module import itself

Description:

Used when a module is importing itself.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the imports checker.

inconsistent-quotes / W1405

Message emitted:

Quote delimiter %s is inconsistent with the rest of the file

Description:

Quote delimiters are not used consistently throughout a module (with allowances made for avoiding unnecessary escaping).

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the string checker.

invalid-envvar-default / W1508

Message emitted:

%s default type is %s. Expected str or None.

Description:

Env manipulation functions return None or str values. Supplying anything different as a default may cause bugs. See https://docs.python.org/3/library/os.html#os.getenv.

Problematic code:

import os
env = os.getenv('SECRET_KEY', 1)  # [invalid-envvar-default]

Correct code:

import os
env = os.getenv('SECRET_KEY', '1')

Created by the stdlib checker.

invalid-format-index / W1307

Message emitted:

Using invalid lookup key %r in format specifier %r

Description:

Used when a PEP 3101 format string uses a lookup specifier ({a[1]}), but the argument passed for formatting doesn't contain or doesn't have that key as an attribute.

Problematic code:

not_enough_fruits = ["apple"]
print('The second fruit is a {fruits[1]}'.format(fruits=not_enough_fruits))  # [invalid-format-index]

Correct code:

enough_fruits = ["apple", "banana"]
print('The second fruit is a {fruits[1]}'.format(fruits=enough_fruits))

Created by the string checker.

invalid-overridden-method / W0236

Message emitted:

Method %r was expected to be %r, found it instead as %r

Description:

Used when we detect that a method was overridden in a way that does not match its base class which could result in potential bugs at runtime.

Problematic code:

class Fruit:

async def bore(self, insect):
insect.eat(self) class Apple(Fruit):
def bore(self, insect): # [invalid-overridden-method]
insect.eat(self)

Correct code:

class Fruit:

async def bore(self, insect):
insect.eat(self) class Apple(Fruit):
async def bore(self, insect):
insect.eat(self)

Created by the classes checker.

isinstance-second-argument-not-valid-type / W1116

Message emitted:

Second argument of isinstance is not a type

Description:

Emitted when the second argument of an isinstance call is not a type.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

keyword-arg-before-vararg / W1113

Message emitted:

Keyword argument before variable positional arguments list in the definition of %s function

Description:

When defining a keyword argument before variable positional arguments, one can end up in having multiple values passed for the aforementioned parameter in case the method is called with keyword arguments.

Problematic code:

def func(x=None, *args):  # [keyword-arg-before-vararg]

return [x, *args]

Correct code:

def func(*args, x=None):

return [*args, x]

Created by the typecheck checker.

logging-format-interpolation / W1202

Message emitted:

Use %s formatting in logging functions

Description:

Used when a logging statement has a call form of "logging.<logging method>(format_string.format(format_args...))". Use another type of string formatting instead. You can use % formatting but leave interpolation to the logging function by passing the parameters as arguments. If logging-fstring-interpolation is disabled then you can use fstring formatting. If logging-not-lazy is disabled then you can use % formatting as normal.

Problematic code:

import logging
import sys
logging.error('Python version: {}'.format(sys.version))  # [logging-format-interpolation]

Correct code:

import logging
import sys
logging.error('Python version: %s', sys.version)

Additional details:

Another reasonable option is to use f-string. If you want to do that, you need to enable logging-format-interpolation and disable logging-fstring-interpolation.

Related links:

  • logging variable data
  • rational

Created by the logging checker.

logging-fstring-interpolation / W1203

Message emitted:

Use %s formatting in logging functions

Description:

Used when a logging statement has a call form of "logging.<logging method>(f"...")".Use another type of string formatting instead. You can use % formatting but leave interpolation to the logging function by passing the parameters as arguments. If logging-format-interpolation is disabled then you can use str.format. If logging-not-lazy is disabled then you can use % formatting as normal.

Problematic code:

import logging
import sys
logging.error(f'Python version: {sys.version}')  # [logging-fstring-interpolation]

Correct code:

import logging
import sys
logging.error('Python version: %s', sys.version)

Additional details:

This message permits to allow f-string in logging and still be warned of logging-format-interpolation.

Related links:

  • logging variable data
  • rational

Created by the logging checker.

logging-not-lazy / W1201

Message emitted:

Use %s formatting in logging functions

Description:

Used when a logging statement has a call form of "logging.<logging method>(format_string % (format_args...))". Use another type of string formatting instead. You can use % formatting but leave interpolation to the logging function by passing the parameters as arguments. If logging-fstring-interpolation is disabled then you can use fstring formatting. If logging-format-interpolation is disabled then you can use str.format.

Problematic code:

import logging
try:

function() except Exception as e:
logging.error('Error occurred: %s' % e) # [logging-not-lazy]
raise

Correct code:

import logging
try:

function() except Exception as e:
logging.error('Error occurred: %s', e)
raise

Additional details:

Another reasonable option is to use f-strings. If you want to do that, you need to enable logging-not-lazy and disable logging-fstring-interpolation.

Related links:

  • Logging variable data
  • Rationale

Created by the logging checker.

lost-exception / W0150

Message emitted:

%s statement in finally block may swallow exception

Description:

Used when a break or a return statement is found inside the finally clause of a try...finally block: the exceptions raised in the try clause will be silently swallowed instead of being re-raised.

Problematic code:

class FasterThanTheSpeedOfLightError(ZeroDivisionError):

def __init__(self):
super().__init__("You can't go faster than the speed of light !") def calculate_speed(distance: float, time: float) -> float:
try:
return distance / time
except ZeroDivisionError as e:
raise FasterThanTheSpeedOfLightError() from e
finally:
return 299792458 # [lost-exception]

Correct code:

class FasterThanTheSpeedOfLightError(ZeroDivisionError):

def __init__(self):
super().__init__("You can't go faster than the speed of light !") def calculate_speed(distance: float, time: float) -> float:
try:
return distance / time
except ZeroDivisionError as e:
raise FasterThanTheSpeedOfLightError() from e

Created by the basic checker.

method-cache-max-size-none / W1518

Message emitted:

'lru_cache(maxsize=None)' or 'cache' will keep all method args alive indefinitely, including 'self'

Description:

By decorating a method with lru_cache or cache the 'self' argument will be linked to the function and therefore never garbage collected. Unless your instance will never need to be garbage collected (singleton) it is recommended to refactor code to avoid this pattern or add a maxsize to the cache. The default value for maxsize is 128.

Problematic code:

import functools
class Fibonnaci:

@functools.lru_cache(maxsize=None) # [method-cache-max-size-none]
def fibonacci(self, n):
if n in {0, 1}:
return n
return self.fibonacci(n - 1) + self.fibonacci(n - 2)

Correct code:

import functools
@functools.cache
def cached_fibonacci(n):

if n in {0, 1}:
return n
return cached_fibonacci(n - 1) + cached_fibonacci(n - 2) class Fibonnaci:
def fibonacci(self, n):
return cached_fibonacci(n)

Created by the stdlib checker.

misplaced-future / W0410

Message emitted:

__future__ import is not the first non docstring statement

Description:

Python 2.5 and greater require __future__ import to be the first non docstring statement in the module.

Problematic code:

import sys
from __future__ import print_function  # [misplaced-future]

Correct code:

from __future__ import print_function
import sys

Additional details:

A bare raise statement will re-raise the last active exception in the current scope. If the raise statement is not in an except or finally block, a RuntimeError will be raised instead.

Created by the imports checker.

missing-any-param-doc / W9021

Message emitted:

Missing any documentation in "%s"

Description:

Please add parameter and/or type documentation.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

missing-format-argument-key / W1303

Message emitted:

Missing keyword argument %r for format string

Description:

Used when a PEP 3101 format string that uses named fields doesn't receive one or more required keywords.

Problematic code:

print("My name is {first} {last}".format(first="John"))  # [missing-format-argument-key]

Correct code:

print("My name is {first} {last}".format(first="John", last="Wick"))

Related links:

  • PEP 3101
  • Custom String Formmating

Created by the string checker.

missing-format-attribute / W1306

Message emitted:

Missing format attribute %r in format specifier %r

Description:

Used when a PEP 3101 format string uses an attribute specifier ({0.length}), but the argument passed for formatting doesn't have that attribute.

Problematic code:

print("{0.real}".format("1"))  # [missing-format-attribute]

Correct code:

print("{0.real}".format(1))

Created by the string checker.

missing-param-doc / W9015

Message emitted:

"%s" missing in parameter documentation

Description:

Please add parameter declarations for all parameters.

Problematic code:

def integer_sum(a: int, b):  # [missing-param-doc]

"""Returns sum of two integers
:param a: first integer
"""
return a + b

Correct code:

def integer_sum(a: int, b: int):

"""Returns sum of two integers
:param a: first integer
:param b: second integer
"""
return a + b

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

missing-parentheses-for-call-in-test / W0126

Message emitted:

Using a conditional statement with potentially wrong function or method call due to missing parentheses

Description:

Emitted when a conditional statement (If or ternary if) seems to wrongly call a function due to missing parentheses

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the basic checker.

missing-raises-doc / W9006

Message emitted:

"%s" not documented as being raised

Description:

Please document exceptions for all raised exception types.

Problematic code:

def integer_sum(a: int, b: int):  # [missing-raises-doc]

"""Returns sum of two integers
:param a: first integer
:param b: second integer
"""
if not (isinstance(a, int) and isinstance(b, int)):
raise ValueError('Function supports only integer parameters.')
return a + b

Correct code:

def integer_sum(a: int, b: int):

"""Returns sum of two integers
:param a: first integer
:param b: second integer
:raises ValueError: One of the parameters is not an integer.
"""
if not (isinstance(a, int) and isinstance(b, int)):
raise ValueError('Function supports only integer parameters.')
return a + b

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

missing-return-doc / W9011

Message emitted:

Missing return documentation

Description:

Please add documentation about what this method returns.

Problematic code:

def integer_sum(a: int, b: int):  # [missing-return-doc]

"""Returns sum of two integers
:param a: first integer
:param b: second integer
"""
return a + b

Correct code:

def integer_sum(a: int, b: int) -> int:

"""Returns sum of two integers
:param a: first integer
:param b: second integer
:return: sum of parameters a and b
"""
return a + b

Additional details:

This message is raised only when parameter accept-no-return-doc is set to no.

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

missing-return-type-doc / W9012

Message emitted:

Missing return type documentation

Description:

Please document the type returned by this method.

Problematic code:

def integer_sum(a: int, b: int):  # [missing-return-type-doc]

"""Returns sum of two integers
:param a: first integer
:param b: second integer
:return: sum of parameters a and b
"""
return a + b

Correct code:

def integer_sum(a: int, b: int) -> int:

"""Returns sum of two integers
:param a: first integer
:param b: second integer
:return: sum of parameters a and b
"""
return a + b

Additional details:

This message is raised only when parameter accept-no-return-doc is set to no.

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

missing-timeout / W3101

Message emitted:

Missing timeout argument for method '%s' can cause your program to hang indefinitely

Description:

Used when a method needs a 'timeout' parameter in order to avoid waiting for a long time. If no timeout is specified explicitly the default value is used. For example for 'requests' the program will never time out (i.e. hang indefinitely).

Problematic code:

import requests
requests.post("http://localhost")  # [missing-timeout]

Correct code:

import requests
requests.post("http://localhost", timeout=10)

Additional details:

You can add new methods that should have a defined `timeout argument as qualified names in the timeout-methods option, for example:

  • requests.api.get
  • requests.api.head
  • requests.api.options
  • requests.api.patch
  • requests.api.post
  • requests.api.put
  • requests.api.request

Created by the method_args checker.

missing-type-doc / W9016

Message emitted:

"%s" missing in parameter type documentation

Description:

Please add parameter type declarations for all parameters.

Problematic code:

def integer_sum(a: int, b):  # [missing-type-doc]

"""Returns sum of two integers
:param a: first integer
:param b: second integer
"""
return a + b

Correct code:

def integer_sum(a: int, b: int):

"""Returns sum of two integers
:param a: first integer
:param b: second integer
"""
return a + b

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

missing-yield-doc / W9013

Message emitted:

Missing yield documentation

Description:

Please add documentation about what this generator yields.

Problematic code:

def even_number_under(n: int):  # [missing-yield-doc]

"""Prints even numbers smaller than n.
Args:
n: Upper limit of even numbers.
"""
for i in range(n):
if i % 2 == 1:
continue
yield i

Correct code:

from typing import Iterator
def even_number_under(n: int) -> Iterator[int]:

"""Prints even numbers smaller than n.
Args:
n: Upper limit of even numbers.
Yields:
even numbers
"""
for i in range(n):
if i % 2 == 1:
continue
yield i

Additional details:

This message is raised only when parameter accept-no-yields-doc is set to no.

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

missing-yield-type-doc / W9014

Message emitted:

Missing yield type documentation

Description:

Please document the type yielded by this method.

Problematic code:

def even_number_under(n: int):  # [missing-yield-type-doc]

"""Prints even numbers smaller than n.
Args:
n: Upper limit of even numbers.
Yields:
even numbers
"""
for i in range(n):
if i % 2 == 1:
continue
yield i

Correct code:

from typing import Iterator
def even_number_under(n: int) -> Iterator[int]:

"""Prints even numbers smaller than n.
Args:
n: Upper limit of even numbers.
Yields:
even numbers
"""
for i in range(n):
if i % 2 == 1:
continue
yield i

Additional details:

This message is raised only when parameter accept-no-yields-doc is set to no.

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

modified-iterating-list / W4701

Message emitted:

Iterated list '%s' is being modified inside for loop body, consider iterating through a copy of it instead.

Description:

Emitted when items are added or removed to a list being iterated through. Doing so can result in unexpected behaviour, that is why it is preferred to use a copy of the list.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the modified_iteration checker.

multiple-constructor-doc / W9005

Message emitted:

"%s" has constructor parameters documented in class and __init__

Description:

Please remove parameter declarations in the class or constructor.

Problematic code:

class Point:  # [multiple-constructor-doc]

"""Represents a point in the xy-coordinate plane.
:param x: coordinate
:param y: coordinate
"""
def __init__(self, x, y):
"""Represents a point in the xy-coordinate plane.
:param x: coordinate
:param y: coordinate
"""
self.x = x
self.y = y

Correct code:

class Point:

def __init__(self, x, y):
"""Represents a point in the xy-coordinate plane.
:param x: x coordinate
:param y: y coordinate
"""
self.x = x
self.y = y

Additional details:

Both docstrings are acceptable but not both at the same time.

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

nan-comparison / W0177

Message emitted:

Comparison %s should be %s

Description:

Used when an expression is compared to NaN values like numpy.NaN and float('nan').

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the basic checker.

non-ascii-file-name / W2402

Message emitted:

%s name "%s" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers, not file names.

Description:

Some editors don't support non-ASCII file names properly. Even though Python supports UTF-8 files since Python 3.5 this isn't recommended for interoperability. Further reading: - https://peps.python.org/pep-0489/#export-hook-name - https://peps.python.org/pep-0672/#confusing-features - https://bugs.python.org/issue20485

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the nonascii-checker checker.

non-parent-init-called / W0233

Message emitted:

__init__ method from a non direct base class %r is called

Description:

Used when an __init__ method is called on a class which is not in the direct ancestors for the analysed class.

Problematic code:

class Animal:

def __init__(self):
self.is_multicellular = True class Vertebrate(Animal):
def __init__(self):
super().__init__()
self.has_vertebrae = True class Cat(Vertebrate):
def __init__(self):
Animal.__init__(self) # [non-parent-init-called]
self.is_adorable = True

Correct code:

class Animal:

def __init__(self):
self.is_multicellular = True class Vertebrate(Animal):
def __init__(self):
super().__init__()
self.has_vertebrae = True class Cat(Vertebrate):
def __init__(self):
super().__init__()
self.is_adorable = True

Created by the classes checker.

non-str-assignment-to-dunder-name / W1115

Message emitted:

Non-string value assigned to __name__

Description:

Emitted when a non-string value is assigned to __name__

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

overlapping-except / W0714

Message emitted:

Overlapping exceptions (%s)

Description:

Used when exceptions in handler overlap or are identical

Problematic code:

def divide_x_by_y(x: float, y: float):

try:
print(x / y)
except (ArithmeticError, FloatingPointError) as e: # [overlapping-except]
print(f"There was an issue: {e}")

Correct code:

def divide_x_by_y(x: float, y: float):

try:
print(x / y)
except FloatingPointError as e:
print(f"There was a FloatingPointError: {e}")
except ArithmeticError as e:
# FloatingPointError were already caught at this point
print(f"There was an OverflowError or a ZeroDivisionError: {e}") # Or: def divide_x_by_y(x: float, y: float):
try:
print(x / y)
except ArithmeticError as e:
print(f"There was an OverflowError, a ZeroDivisionError or a FloatingPointError: {e}")

Related links:

Exception hierarchy

NOTE:

This message is emitted by the optional 'overlap-except' checker which requires the pylint.extensions.overlapping_exceptions plugin to be loaded.

Created by the overlap-except checker.

overridden-final-method / W0239

Message emitted:

Method %r overrides a method decorated with typing.final which is defined in class %r

Description:

Used when a method decorated with typing.final has been overridden.

Problematic code:

from typing import final
class Animal:

@final
def can_breathe(self):
return True class Cat(Animal):
def can_breathe(self): # [overridden-final-method]
pass

Correct code:

from typing import final
class Animal:

@final
def can_breathe(self):
return True class Cat(Animal):
def can_purr(self):
return True

Additional details:

The message can't be emitted when using Python < 3.8.

Related links:

PEP 591

Created by the classes checker.

pointless-statement / W0104

Message emitted:

Statement seems to have no effect

Description:

Used when a statement doesn't have (or at least seems to) any effect.

Problematic code:

[1, 2, 3]  # [pointless-statement]

Correct code:

NUMBERS = [1, 2, 3]
print(NUMBERS)

Created by the basic checker.

pointless-string-statement / W0105

Message emitted:

String statement has no effect

Description:

Used when a string is used as a statement (which of course has no effect). This is a particular case of W0104 with its own message so you can easily disable it if you're using those strings as documentation, instead of comments.

Problematic code:

"""This is a docstring which describes the module"""
"""This is not a docstring"""  # [pointless-string-statement]

Correct code:

"""This is a docstring which describes the module"""
# This is comment which describes a particular part of the module.

Created by the basic checker.

possibly-unused-variable / W0641

Message emitted:

Possibly unused variable %r

Description:

Used when a variable is defined but might not be used. The possibility comes from the fact that locals() might be used, which could consume or not the said variable

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the variables checker.

preferred-module / W0407

Message emitted:

Prefer importing %r instead of %r

Description:

Used when a module imported has a preferred replacement module.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the imports checker.

protected-access / W0212

Message emitted:

Access to a protected member %s of a client class

Description:

Used when a protected member (i.e. class member with a name beginning with an underscore) is access outside the class or a descendant of the class where it's defined.

Problematic code:

class Worm:

def __swallow(self):
pass jim = Worm() jim.__swallow() # [protected-access]

Correct code:

class Worm:

def __swallow(self):
pass
def eat(self):
return self.__swallow() jim = Worm() jim.eat()

Created by the classes checker.

raise-missing-from / W0707

Message emitted:

Consider explicitly re-raising using %s'%s from %s'

Description:

Python's exception chaining shows the traceback of the current exception, but also of the original exception. When you raise a new exception after another exception was caught it's likely that the second exception is a friendly re-wrapping of the first exception. In such cases `raise from` provides a better link between the two tracebacks in the final error.

Problematic code:

try:

1 / 0 except ZeroDivisionError as e:
raise ValueError("Rectangle Area cannot be zero") # [raise-missing-from]

Correct code:

try:

1 / 0 except ZeroDivisionError as e:
raise ValueError("Rectangle Area cannot be zero") from e

Related links:

PEP 3134

Created by the exceptions checker.

raising-format-tuple / W0715

Message emitted:

Exception arguments suggest string formatting might be intended

Description:

Used when passing multiple arguments to an exception constructor, the first of them a string literal containing what appears to be placeholders intended for formatting

Problematic code:

raise RuntimeError("This looks wrong %s %s", ("a", "b"))  # [raising-format-tuple]

Correct code:

raise RuntimeError("This looks wrong %s %s" % ("a", "b"))

Created by the exceptions checker.

redeclared-assigned-name / W0128

Message emitted:

Redeclared variable %r in assignment

Description:

Emitted when we detect that a variable was redeclared in the same assignment.

Problematic code:

FIRST, FIRST = (1, 2)  # [redeclared-assigned-name]

Correct code:

FIRST, SECOND = (1, 2)

Created by the basic checker.

redefined-builtin / W0622

Message emitted:

Redefining built-in %r

Description:

Used when a variable or function override a built-in.

Problematic code:

def map():  # [redefined-builtin]

pass

Correct code:

def map_iterable():

pass

Created by the variables checker.

redefined-loop-name / W2901

Message emitted:

Redefining %r from loop (line %s)

Description:

Used when a loop variable is overwritten in the loop body.

Problematic code:

for name in names:

name = name.lower() # [redefined-loop-name]

Correct code:

for name in names:

lowercased_name = name.lower()

NOTE:

This message is emitted by the optional 'redefined-loop-name' checker which requires the pylint.extensions.redefined_loop_name plugin to be loaded.

Created by the redefined-loop-name checker.

redefined-outer-name / W0621

Message emitted:

Redefining name %r from outer scope (line %s)

Description:

Used when a variable's name hides a name defined in an outer scope or except handler.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the variables checker.

redefined-slots-in-subclass / W0244

Message emitted:

Redefined slots %r in subclass

Description:

Used when a slot is re-defined in a subclass.

Problematic code:

class Base:

__slots__ = ("a", "b") class Subclass(Base):
__slots__ = ("a", "d") # [redefined-slots-in-subclass]

Correct code:

class Base:

__slots__ = ("a", "b") class Subclass(Base):
__slots__ = ("d",)

Created by the classes checker.

redundant-returns-doc / W9008

Message emitted:

Redundant returns documentation

Description:

Please remove the return/rtype documentation from this method.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

redundant-u-string-prefix / W1406

Message emitted:

The u prefix for strings is no longer necessary in Python >=3.0

Description:

Used when we detect a string with a u prefix. These prefixes were necessary in Python 2 to indicate a string was Unicode, but since Python 3.0 strings are Unicode by default.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the string checker.

redundant-unittest-assert / W1503

Message emitted:

Redundant use of %s with constant value %r

Description:

The first argument of assertTrue and assertFalse is a condition. If a constant is passed as parameter, that condition will be always true. In this case a warning should be emitted.

Problematic code:

import unittest
class DummyTestCase(unittest.TestCase):

def test_dummy(self):
self.assertTrue("foo") # [redundant-unittest-assert]

Correct code:

import unittest
class DummyTestCase(unittest.TestCase):

def test_dummy(self):
actual = "test_result"
self.assertEqual(actual, "expected")

Additional details:

Directly asserting a string literal will always pass. The solution is to test something that could fail, or not assert at all.

For assertions using assert there are similar messages: assert-on-string-literal / W0129 and assert-on-tuple / W0199.

Related links:

  • Tests without assertion
  • Testing that there is no error raised
  • Parametrizing conditional raising

Created by the stdlib checker.

redundant-yields-doc / W9010

Message emitted:

Redundant yields documentation

Description:

Please remove the yields documentation from this method.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

Message emitted:

Reimport %r (imported line %s)

Description:

Used when a module is reimported multiple times.

Problematic code:

import re
import re  # [reimported]

Correct code:

import re

Created by the imports checker.

self-assigning-variable / W0127

Message emitted:

Assigning the same variable %r to itself

Description:

Emitted when we detect that a variable is assigned to itself

Problematic code:

year = 2000
year = year  # [self-assigning-variable]

Correct code:

year = 2000

Related links:

Python assignment statement

Created by the basic checker.

self-cls-assignment / W0642

Message emitted:

Invalid assignment to %s in method

Description:

Invalid assignment to self or cls in instance or class method respectively.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the variables checker.

shallow-copy-environ / W1507

Message emitted:

Using copy.copy(os.environ). Use os.environ.copy() instead.

Description:

os.environ is not a dict object but proxy object, so shallow copy has still effects on original object. See https://bugs.python.org/issue15373 for reference.

Problematic code:

import copy
import os
copied_env = copy.copy(os.environ)  # [shallow-copy-environ]

Correct code:

import os
copied_env = os.environ.copy()

Created by the stdlib checker.

signature-differs / W0222

Message emitted:

Signature differs from %s %r method

Description:

Used when a method signature is different than in the implemented interface or in an overridden method.

Problematic code:

class Animal:

def run(self, distance=0):
print(f"Ran {distance} km!") class Dog(Animal):
def run(self, distance): # [signature-differs]
super(Animal, self).run(distance)
print("Fetched that stick, wuff !")

Correct code:

class Animal:

def run(self, distance=0):
print(f"Ran {distance} km!") class Dog(Animal):
def run(self, distance=0):
super(Animal, self).run(distance)
print("Fetched that stick, wuff !")

Created by the classes checker.

subclassed-final-class / W0240

Message emitted:

Class %r is a subclass of a class decorated with typing.final: %r

Description:

Used when a class decorated with typing.final has been subclassed.

Problematic code:

from typing import final
@final
class PlatypusData:

"""General Platypus data."""
average_length = 46
average_body_temperature = 32 class FluorescentPlaytipus(PlatypusData): # [subclassed-final-class]
"""Playtipus with fluorescent fur."""

Correct code:

from typing import final
@final
class PlatypusData:

"""General Platypus data."""
average_length = 46
average_body_temperature = 32 def print_average_length_platypus():
output = f"The average length of a platypus is: {PlatypusData.average_length}cm"
print(output)

Additional details:

This message is emitted when a class which is decorated with final is subclassed; the decorator indicates that the class is not intended to be extended.

Note this message can't be emitted when using Python < 3.8.

Related links:

PEP 591

Created by the classes checker.

subprocess-popen-preexec-fn / W1509

Message emitted:

Using preexec_fn keyword which may be unsafe in the presence of threads

Description:

The preexec_fn parameter is not safe to use in the presence of threads in your application. The child process could deadlock before exec is called. If you must use it, keep it trivial! Minimize the number of libraries you call into. See https://docs.python.org/3/library/subprocess.html#popen-constructor

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the stdlib checker.

subprocess-run-check / W1510

Message emitted:

Using subprocess.run without explicitly set check is not recommended.

Description:

The check parameter should always be used with explicitly set `check` keyword to make clear what the error-handling behavior is. See https://docs.python.org/3/library/subprocess.html#subprocess.run

Problematic code:

import subprocess
proc = subprocess.run(["ls"])  # [subprocess-run-check]

Correct code:

import subprocess
proc = subprocess.run(["ls"], check=True)

Created by the stdlib checker.

super-init-not-called / W0231

Message emitted:

__init__ method from base class %r is not called

Description:

Used when an ancestor class method has an __init__ method which is not called by a derived class.

Problematic code:

class Fruit:

def __init__(self, name="fruit"):
self.name = name
print("Creating a {self.name}") class Apple(Fruit):
def __init__(self): # [super-init-not-called]
print("Creating an apple")

Correct code:

class Fruit:

def __init__(self, name="fruit"):
self.name = name
print("Creating a {self.name}") class Apple(Fruit):
def __init__(self):
super().__init__("apple")

Created by the classes checker.

super-without-brackets / W0245

Message emitted:

Super call without brackets

Description:

Used when a call to super does not have brackets and thus is not an actual call and does not work as expected.

Problematic code:

class Soup:

@staticmethod
def temp():
print("Soup is hot!") class TomatoSoup(Soup):
@staticmethod
def temp():
super.temp() # [super-without-brackets]
print("But tomato soup is even hotter!")

Correct code:

class Soup:

@staticmethod
def temp():
print("Soup is hot!") class TomatoSoup(Soup):
@staticmethod
def temp():
super().temp()
print("But tomato soup is even hotter!")

Created by the classes checker.

too-many-try-statements / W0717

Message emitted:

%s

Description:

Try clause contains too many statements.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'broad_try_clause' checker which requires the pylint.extensions.broad_try_clause plugin to be loaded.

Created by the broad_try_clause checker.

try-except-raise / W0706

Message emitted:

The except handler raises immediately

Description:

Used when an except handler uses raise as its first or only operator. This is useless because it raises back the exception immediately. Remove the raise operator or the entire try-except-raise block!

Problematic code:

try:

1 / 0 except ZeroDivisionError as e: # [try-except-raise]
raise

Correct code:

# The try except might be removed entirely:
1 / 0
# Or another more detailed exception can be raised:
try:

1 / 0 except ZeroDivisionError as e:
raise ValueError("The area of the rectangle cannot be zero") from e

Additional details:

There is a legitimate use case for re-raising immediately. E.g. with the following inheritance tree:

+-- ArithmeticError

+-- FloatingPointError
+-- OverflowError
+-- ZeroDivisionError

The following code shows valid case for re-raising exception immediately:

def execute_calculation(a, b):

try:
return some_calculation(a, b)
except ZeroDivisionError:
raise
except ArithmeticError:
return float('nan')

The pylint is able to detect this case and does not produce error.

Created by the exceptions checker.

undefined-loop-variable / W0631

Message emitted:

Using possibly undefined loop variable %r

Description:

Used when a loop variable (i.e. defined by a for loop or a list comprehension or a generator expression) is used outside the loop.

Problematic code:

def find_even_number(numbers):

for x in numbers:
if x % 2 == 0:
break
return x # [undefined-loop-variable]

Correct code:

def find_even_number(numbers):

for x in numbers:
if x % 2:
return x
return None

Created by the variables checker.

unnecessary-ellipsis / W2301

Message emitted:

Unnecessary ellipsis constant

Description:

Used when the ellipsis constant is encountered and can be avoided. A line of code consisting of an ellipsis is unnecessary if there is a docstring on the preceding line or if there is a statement in the same scope.

Problematic code:

def my_function():

"""My docstring"""
... # [unnecessary-ellipsis]

Correct code:

def my_function():

"""My docstring"""

Created by the unnecessary_ellipsis checker.

unnecessary-lambda / W0108

Message emitted:

Lambda may not be necessary

Description:

Used when the body of a lambda expression is a function call on the same argument list as the lambda itself; such lambda expressions are in all but a few cases replaceable with the function being called in the body of the lambda.

Problematic code:

function = lambda x: print(x)  # [unnecessary-lambda]
function("Hello world !")
df.apply(lambda x: str(x))  # [unnecessary-lambda]

Correct code:

print("Hello world !")
df.apply(str)

Created by the basic checker.

unnecessary-pass / W0107

Message emitted:

Unnecessary pass statement

Description:

Used when a "pass" statement that can be avoided is encountered.

Problematic code:

class Foo:

"""Foo docstring."""
pass # [unnecessary-pass]

Correct code:

class Foo:

"""Foo docstring."""

Created by the basic checker.

unnecessary-semicolon / W0301

Message emitted:

Unnecessary semicolon

Description:

Used when a statement is ended by a semi-colon (";"), which isn't necessary (that's python, not C ;).

Problematic code:

print("Hello World!");  # [unnecessary-semicolon]

Correct code:

print("Hello World!")

Created by the format checker.

Message emitted:

Unreachable code

Description:

Used when there is some code behind a "return" or "raise" statement, which will never be accessed.

Problematic code:

def say_hello():

return True
print("Hello World!, Outside function.") # [unreachable]

Correct code:

def say_hello():

print("Hello World!, Inside function.")
return True

Created by the basic checker.

unspecified-encoding / W1514

Message emitted:

Using open without explicitly specifying an encoding

Description:

It is better to specify an encoding when opening documents. Using the system default implicitly can create problems on other operating systems. See https://peps.python.org/pep-0597/

Problematic code:

def foo(file_path):

with open(file_path) as file: # [unspecified-encoding]
contents = file.read()

Correct code:

def foo(file_path):

with open(file_path, encoding="utf-8") as file:
contents = file.read()

Created by the stdlib checker.

unused-argument / W0613

Message emitted:

Unused argument %r

Description:

Used when a function or method argument is not used.

Problematic code:

def print_point(x, y):  # [unused-argument]

print(f"Point is located at {x},{x}")

Correct code:

def print_point(x, y):

print(f"Point is located at {x},{y}")

Created by the variables checker.

unused-format-string-argument / W1304

Message emitted:

Unused format argument %r

Description:

Used when a PEP 3101 format string that uses named fields is used with an argument that is not required by the format string.

Problematic code:

print("{x} {y}".format(x=1, y=2, z=3))  # [unused-format-string-argument]

Correct code:

print("{x} {y} {z}".format(x=1, y=2, z=3))
# or
print("{x} {y}".format(x=1, y=2))

Created by the string checker.

unused-format-string-key / W1301

Message emitted:

Unused key %r in format string dictionary

Description:

Used when a format string that uses named conversion specifiers is used with a dictionary that contains keys not required by the format string.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the string checker.

unused-import / W0611

Message emitted:

Unused %s

Description:

Used when an imported module or variable is not used.

Problematic code:

from logging import getLogger
from pathlib import Path  # [unused-import]
LOGGER = getLogger(__name__)

Correct code:

from logging import getLogger
LOGGER = getLogger(__name__)

Created by the variables checker.

unused-private-member / W0238

Message emitted:

Unused private member %s.%s

Description:

Emitted when a private member of a class is defined but not used.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

unused-variable / W0612

Message emitted:

Unused variable %r

Description:

Used when a variable is defined but not used.

Problematic code:

def print_fruits():

fruit1 = "orange"
fruit2 = "apple" # [unused-variable]
print(fruit1)

Correct code:

def print_fruits():

fruit1 = "orange"
fruit2 = "apple"
print(fruit1, fruit2)

Created by the variables checker.

unused-wildcard-import / W0614

Message emitted:

Unused import(s) %s from wildcard import of %s

Description:

Used when an imported module or variable is not used from a `'from X import *'` style import.

Problematic code:

from abc import *  # [unused-wildcard-import]
class Animal(ABC): ...

Correct code:

from abc import ABC
class Animal(ABC): ...

Created by the variables checker.

useless-else-on-loop / W0120

Message emitted:

Else clause on loop without a break statement, remove the else and de-indent all the code inside it

Description:

Loops should only have an else clause if they can exit early with a break statement, otherwise the statements under else should be on the same scope as the loop itself.

Problematic code:

def find_even_number(numbers):

for x in numbers:
if x % 2 == 0:
return x
else: # [useless-else-on-loop]
print("Did not find an even number")

Correct code:

def find_even_number(numbers):

for x in numbers:
if x % 2 == 0:
return x
print("Did not find an even number")

Created by the basic checker.

useless-param-doc / W9019

Message emitted:

"%s" useless ignored parameter documentation

Description:

Please remove the ignored parameter documentation.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

useless-parent-delegation / W0246

Message emitted:

Useless parent or super() delegation in method %r

Description:

Used whenever we can detect that an overridden method is useless, relying on parent or super() delegation to do the same thing as another method from the MRO.

Problematic code:

class Animal:

def eat(self, food):
print(f"Eating {food}") class Human(Animal):
def eat(self, food): # [useless-parent-delegation]
super(Human, self).eat(food)

Correct code:

class Animal:

def eat(self, food):
print(f"Eating {food}") class Human(Animal):
"""There is no need to override 'eat' it has the same signature as the implementation in Animal."""

Related links:

Stackoverflow explanation for 'useless-super-delegation'

Created by the classes checker.

useless-type-doc / W9020

Message emitted:

"%s" useless ignored parameter type documentation

Description:

Please remove the ignored parameter type documentation.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'parameter_documentation' checker which requires the pylint.extensions.docparams plugin to be loaded.

Created by the parameter_documentation checker.

useless-with-lock / W2101

Message emitted:

'%s()' directly created in 'with' has no effect

Description:

Used when a new lock instance is created by using with statement which has no effect. Instead, an existing instance should be used to acquire lock.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the threading checker.

using-constant-test / W0125

Message emitted:

Using a conditional statement with a constant value

Description:

Emitted when a conditional statement (If or ternary if) uses a constant value for its test. This might not be what the user intended to do.

Problematic code:

if 0:  # [using-constant-test]

print('This code is never executed.') if 1: # [using-constant-test]
print('This code is always executed.')

Correct code:

print('This code is always executed.')

Created by the basic checker.

using-f-string-in-unsupported-version / W2601

Message emitted:

F-strings are not supported by all versions included in the py-version setting

Description:

Used when the py-version set by the user is lower than 3.6 and pylint encounters a f-string.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the unsupported_version checker.

using-final-decorator-in-unsupported-version / W2602

Message emitted:

typing.final is not supported by all versions included in the py-version setting

Description:

Used when the py-version set by the user is lower than 3.8 and pylint encounters a ``typing.final`` decorator.

Problematic code:

from typing import final
@final  # [using-final-decorator-in-unsupported-version]
class Playtypus(Animal):

@final # [using-final-decorator-in-unsupported-version]
def lay_egg(self):
...

Correct code:

class Playtypus(Animal):

def lay_egg(self):
...

Additional details:

The message is emitted when the final decorator is used with a Python version less than 3.8. The final decorator was introduced in Python version 3.8.

Related links:

PEP 591

Created by the unsupported_version checker.

while-used / W0149

Message emitted:

Used while loop

Description:

Unbounded `while` loops can often be rewritten as bounded `for` loops.

Problematic code:

import requests
def fetch_data():

i = 1
while i < 6: # [while-used]
print(f'Attempt {i}...')
try:
return requests.get('https://example.com/data')
except requests.exceptions.RequestException:
pass
i += 1

Correct code:

import requests
def fetch_data():

for i in range(1, 6):
print(f'Attempt {i}...')
try:
return requests.get('https://example.com/data')
except requests.exceptions.RequestException:
pass

Related links:

Stackoverflow discussion

NOTE:

This message is emitted by the optional 'while_used' checker which requires the pylint.extensions.while_used plugin to be loaded.

Created by the while_used checker.

wildcard-import / W0401

Message emitted:

Wildcard import %s

Description:

Used when `from module import *` is detected.

Problematic code:

from abc import *  # [wildcard-import]

Correct code:

# Either import module or
# only import required objects from module.
import abc
from abc import ABC, abstractmethod

Created by the imports checker.

wrong-exception-operation / W0716

Message emitted:

Invalid exception operation. %s

Description:

Used when an operation is done against an exception, but the operation is not valid for the exception in question. Usually emitted when having binary operations between exceptions in except handlers.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the exceptions checker.

All renamed messages in the warning category:

"cache-max-size-none has been renamed. The new message can be found at:

"implicit-str-concat-in-sequence has been renamed. The new message can be found at:

"lru-cache-decorating-method has been renamed. The new message can be found at:

"old-assignment-from-none has been renamed. The new message can be found at:

"old-deprecated-argument has been renamed. The new message can be found at:

"old-deprecated-class has been renamed. The new message can be found at:

"old-deprecated-decorator has been renamed. The new message can be found at:

"old-deprecated-method has been renamed. The new message can be found at:

"old-deprecated-module has been renamed. The new message can be found at:

"old-empty-docstring has been renamed. The new message can be found at:

empty-docstring / C0112

Message emitted:

Empty %s docstring

Description:

Used when a module, function, class or method has an empty docstring (it would be too easy ;).

Problematic code:

def foo():  # [empty-docstring]

""""""

Correct code:

def foo():

"""A dummy description."""

Created by the basic checker.

"old-missing-param-doc has been renamed. The new message can be found at:

"old-missing-returns-doc has been renamed. The new message can be found at:

"old-missing-type-doc has been renamed. The new message can be found at:

"old-missing-yields-doc has been renamed. The new message can be found at:

"old-non-iterator-returned-1 has been renamed. The new message can be found at:

"old-unidiomatic-typecheck has been renamed. The new message can be found at:

unidiomatic-typecheck / C0123

Message emitted:

Use isinstance() rather than type() for a typecheck.

Description:

The idiomatic way to perform an explicit typecheck in Python is to use isinstance(x, Y) rather than type(x) == Y, type(x) is Y. Though there are unusual situations where these give different results.

Problematic code:

test_score = {"Biology": 95, "History": 80}
if type(test_score) is dict:  # [unidiomatic-typecheck]

pass

Correct code:

test_score = {"Biology": 95, "History": 80}
if isinstance(test_score, dict):

pass

Related links:

  • Builtin function type()
  • Builtin function isinstance()

Created by the basic checker.

"old-unpacking-non-sequence has been renamed. The new message can be found at:

"useless-super-delegation has been renamed. The new message can be found at:

All messages in the convention category:

bad-classmethod-argument / C0202

Message emitted:

Class method %s should have %s as first argument

Description:

Used when a class method has a first argument named differently than the value specified in valid-classmethod-first-arg option (default to "cls"), recommended to easily differentiate them from regular instance methods.

Problematic code:

class Klass:

@classmethod
def get_instance(self): # [bad-classmethod-argument]
return self()

Correct code:

class Klass:

@classmethod
def get_instance(cls):
return cls()

Created by the classes checker.

bad-docstring-quotes / C0198

Message emitted:

Bad docstring quotes in %s, expected """, given %s

Description:

Used when a docstring does not have triple double quotes.

Problematic code:

def foo():  # [bad-docstring-quotes]

'Docstring.'
return

Correct code:

def foo():

"""Docstring."""
return

Additional details:

"For consistency, always use """triple double quotes""" around docstrings."

Related links:

PEP 257 – Docstring Conventions

NOTE:

This message is emitted by the optional 'docstyle' checker which requires the pylint.extensions.docstyle plugin to be loaded.

Created by the docstyle checker.

bad-file-encoding / C2503

Message emitted:

PEP8 recommends UTF-8 as encoding for Python files

Description:

PEP8 recommends UTF-8 default encoding for Python files. See https://peps.python.org/pep-0008/#source-file-encoding

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the unicode_checker checker.

bad-mcs-classmethod-argument / C0204

Message emitted:

Metaclass class method %s should have %s as first argument

Description:

Used when a metaclass class method has a first argument named differently than the value specified in valid-metaclass-classmethod-first-arg option (default to "mcs"), recommended to easily differentiate them from regular instance methods.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

bad-mcs-method-argument / C0203

Message emitted:

Metaclass method %s should have %s as first argument

Description:

Used when a metaclass method has a first argument named differently than the value specified in valid-classmethod-first-arg option (default to "cls"), recommended to easily differentiate them from regular instance methods.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

compare-to-empty-string / C1901

Message emitted:

Avoid comparisons to empty string

Description:

Used when Pylint detects comparison to an empty string constant.

Problematic code:

x = ""
y = "hello"
if x == "":  # [compare-to-empty-string]

print("x is an empty string") if y != "": # [compare-to-empty-string]
print("y is not an empty string")

Correct code:

x = ""
y = "hello"
if not x:

print("x is an empty string") if y:
print("y is not an empty string")

NOTE:

This message is emitted by the optional 'compare-to-empty-string' checker which requires the pylint.extensions.emptystring plugin to be loaded.

Created by the compare-to-empty-string checker.

compare-to-zero / C2001

Message emitted:

Avoid comparisons to zero

Description:

Used when Pylint detects comparison to a 0 constant.

Problematic code:

x = 0
y = 1
if x == 0:   # [compare-to-zero]

print("x is equal to zero") if y != 0: # [compare-to-zero]
print("y is not equal to zero")

Correct code:

x = 0
y = 1
if not x:

print("x is equal to zero") if y:
print("y is not equal to zero")

NOTE:

This message is emitted by the optional 'compare-to-zero' checker which requires the pylint.extensions.comparetozero plugin to be loaded.

Created by the compare-to-zero checker.

consider-iterating-dictionary / C0201

Message emitted:

Consider iterating the dictionary directly instead of calling .keys()

Description:

Emitted when the keys of a dictionary are iterated through the ``.keys()`` method or when ``.keys()`` is used for a membership check. It is enough to iterate through the dictionary itself, ``for key in dictionary``. For membership checks, ``if key in dictionary`` is faster.

Problematic code:

FRUITS = {"apple": 1, "pear": 5, "peach": 10}
for fruit in FRUITS.keys():  # [consider-iterating-dictionary]

print(fruit)

Correct code:

FRUITS = {"apple": 1, "pear": 5, "peach": 10}
for fruit in FRUITS:

print(fruit)

Created by the refactoring checker.

consider-using-any-or-all / C0501

Message emitted:

for loop could be %s

Description:

A for loop that checks for a condition and return a bool can be replaced with any or all.

Problematic code:

def any_even(items):

"""Return True if the list contains any even numbers"""
for item in items: # [consider-using-any-or-all]
if item % 2 == 0:
return True
return False def all_even(items):
"""Return True if the list contains all even numbers"""
for item in items: # [consider-using-any-or-all]
if not item % 2 == 0:
return False
return True

Correct code:

def any_even(items):

"""Return True if the list contains any even numbers"""
return any(item % 2 == 0 for item in items) def all_even(items):
"""Return True if the list contains all even numbers"""
return all(item % 2 == 0 for item in items)

NOTE:

This message is emitted by the optional 'consider-using-any-or-all' checker which requires the pylint.extensions.for_any_all plugin to be loaded.

Created by the consider-using-any-or-all checker.

consider-using-dict-items / C0206

Message emitted:

Consider iterating with .items()

Description:

Emitted when iterating over the keys of a dictionary and accessing the value by index lookup. Both the key and value can be accessed by iterating using the .items() method of the dictionary instead.

Problematic code:

ORCHESTRA = {

"violin": "strings",
"oboe": "woodwind",
"tuba": "brass",
"gong": "percussion", } for instrument in ORCHESTRA: # [consider-using-dict-items]
print(f"{instrument}: {ORCHESTRA[instrument]}")

Correct code:

ORCHESTRA = {

"violin": "strings",
"oboe": "woodwind",
"tuba": "brass",
"gong": "percussion", } for instrument, section in ORCHESTRA.items():
print(f"{instrument}: {section}")

Created by the refactoring checker.

consider-using-enumerate / C0200

Message emitted:

Consider using enumerate instead of iterating with range and len

Description:

Emitted when code that iterates with range and len is encountered. Such code can be simplified by using the enumerate builtin.

Problematic code:

seasons = ['Spring', 'Summer', 'Fall', 'Winter']
for i in range(len(seasons)):  # [consider-using-enumerate]

print(i, seasons[i])

Correct code:

seasons = ['Spring', 'Summer', 'Fall', 'Winter']
for i, season in enumerate(seasons):

print(i, season)

Created by the refactoring checker.

consider-using-f-string / C0209

Message emitted:

Formatting a regular string which could be a f-string

Description:

Used when we detect a string that is being formatted with format() or % which could potentially be a f-string. The use of f-strings is preferred. Requires Python 3.6 and ``py-version >= 3.6``.

Problematic code:

from string import Template
menu = ('eggs', 'spam', 42.4)
old_order = "%s and %s: %.2f ¤" % menu # [consider-using-f-string]
beginner_order = menu[0] + " and " + menu[1] + ": " + str(menu[2]) + " ¤"
joined_order = " and ".join(menu[:2])
format_order = "{} and {}: {:0.2f} ¤".format(menu[0], menu[1], menu[2]) # [consider-using-f-string]
named_format_order = "{eggs} and {spam}: {price:0.2f} ¤".format(eggs=menu[0], spam=menu[1], price=menu[2]) # [consider-using-f-string]
template_order = Template('$eggs and $spam: $price ¤').substitute(eggs=menu[0], spam=menu[1], price=menu[2])

Correct code:

menu = ('eggs', 'spam', 42.4)
f_string_order = f"{menu[0]} and {menu[1]}: {menu[2]:0.2f} ¤"

Additional details:

Formatted string literals (f-strings) give a concise, consistent syntax that can replace most use cases for the % formatting operator, str.format() and string.Template.

F-strings also perform better than alternatives; see this tweet for a simple example.

Created by the refactoring checker.

disallowed-name / C0104

Message emitted:

Disallowed name "%s"

Description:

Used when the name matches bad-names or bad-names-rgxs- (unauthorized names).

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the basic checker.

docstring-first-line-empty / C0199

Message emitted:

First line empty in %s docstring

Description:

Used when a blank line is found at the beginning of a docstring.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'docstyle' checker which requires the pylint.extensions.docstyle plugin to be loaded.

Created by the docstyle checker.

import-outside-toplevel / C0415

Message emitted:

Import outside toplevel (%s)

Description:

Used when an import statement is used anywhere other than the module toplevel. Move this import to the top of the file.

Problematic code:

def print_python_version():

import sys # [import-outside-toplevel]
print(sys.version_info)

Correct code:

import sys
def print_python_version():

print(sys.version_info)

Created by the imports checker.

import-private-name / C2701

Message emitted:

Imported private %s (%s)

Description:

Used when a private module or object prefixed with _ is imported. PEP8 guidance on Naming Conventions states that public attributes with leading underscores should be considered private.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'import-private-name' checker which requires the pylint.extensions.private_import plugin to be loaded.

Created by the import-private-name checker.

invalid-characters-in-docstring / C0403

Message emitted:

Invalid characters %r in a docstring

Description:

Used when a word in docstring cannot be checked by enchant.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the spelling checker.

invalid-name / C0103

Message emitted:

%s name "%s" doesn't conform to %s

Description:

Used when the name doesn't conform to naming rules associated to its type (constant, variable, class...).

Problematic code:

class cat:  # [invalid-name]

def Meow(self, NUMBER_OF_MEOW): # [invalid-name, invalid-name]
print("Meow" * NUMBER_OF_MEOW)
return NUMBER_OF_MEOW Cat = cat().Meow(42) # [invalid-name]

Correct code:

class Cat:

def meow(self, number_of_meow):
print("Meow" * number_of_meow)
return number_of_meow CAT = Cat().meow(42)

Additional details:

Pylint recognizes a number of different name types internally. With a few exceptions, the type of the name is governed by the location the assignment to a name is found in, and not the type of object assigned.

Name Type Description
module Module and package names, same as the file names.
const Module-level constants, any variable defined at module level that is not bound to a class object.
class Names in class statements, as well as names bound to class objects at module level.
function Functions, toplevel or nested in functions or methods.
method Methods, functions defined in class bodies. Includes static and class methods.
attr Attributes created on class instances inside methods.
argument Arguments to any function type, including lambdas.
variable Local variables in function scopes.
class-attribute Attributes defined in class bodies.
class-const Enum constants and class variables annotated with ClassVar
inlinevar Loop variables in list comprehensions and generator expressions.
typevar Type variable declared with TypeVar.

By default, Pylint will enforce PEP8-suggested names.

Pylint provides set of predefined naming styles. Those predefined naming styles may be used to adjust Pylint configuration to coding style used in linted project.

Following predefined naming styles are available:

  • snake_case
  • camelCase
  • PascalCase
  • UPPER_CASE
  • any - fake style which does not enforce any limitations

Following options are exposed:

--module-naming-style=<style>

Pylint provides predefined naming patterns for some names. These patterns are often based on a Naming Style but there is no option to choose one of the styles mentioned above. The pattern can be overwritten with the options discussed below.

The following type of names are checked with a predefined pattern:

Name type Good names Bad names
typevar T, _CallableT, _T_co, AnyStr, DeviceTypeT, IPAddressT DICT_T, CALLABLE_T, ENUM_T, DeviceType, _StrType, TAnyStr

If predefined naming styles are too limited, checker behavior may be further customized. For each name type, a separate regular expression matching valid names of this type can be defined. If any of custom regular expressions are defined, it overrides *-naming-style option value.

Regular expressions for the names are anchored at the beginning, any anchor for the end must be supplied explicitly. Any name not matching the regular expression will lead to an instance of invalid-name.

--module-rgx=<regex>

Large code bases that have been worked on for multiple years often exhibit an evolution in style as well. In some cases, modules can be in the same package, but still have different naming style based on the stratum they belong to. However, intra-module consistency should still be required, to make changes inside a single file easier. For this case, Pylint supports regular expression with several named capturing group.

Rather than emitting name warnings immediately, Pylint will determine the prevalent naming style inside each module and enforce it on all names.

Consider the following (simplified) example:

pylint --function-rgx='(?:(?P<snake>[a-z_]+)|(?P<camel>[a-z]+([A-Z][a-z]*)*))$' sample.py

The regular expression defines two naming styles, snake for snake-case names, and camel for camel-case names.

In sample.py, the function name on line 1 and 7 will mark the module and enforce the match of named group snake for the remaining names in the module:

def valid_snake_case(arg):

... def InvalidCamelCase(arg):
... def more_valid_snake_case(arg):
...

Because of this, the name on line 4 will trigger an invalid-name warning, even though the name matches the given regex.

Matches named exempt or ignore can be used for non-tainting names, to prevent built-in or interface-dictated names to trigger certain naming styles.

Default value: empty

Format: comma-separated groups of colon-separated names.

This option can be used to combine name styles. For example, function:method enforces that functions and methods use the same style, and a style triggered by either name type carries over to the other. This requires that the regular expression for the combined name types use the same group names.

Default: off

Include a hint (regular expression used) for the correct name format with every invalid-name warning.

Created by the basic checker.

line-too-long / C0301

Message emitted:

Line too long (%s/%s)

Description:

Used when a line is longer than a given number of characters.

Problematic code:

FRUIT = ["apricot", "blackcurrant", "cantaloupe", "dragon fruit", "elderberry", "fig", "grapefruit"]  # [line-too-long]

Correct code:

FRUIT = [

"apricot",
"blackcurrant",
"cantaloupe",
"dragon fruit",
"elderberry",
"fig",
"grapefruit", ]

Additional details:

If you attempt to disable this message via # pylint: disable=line-too-long in a module with no code, you may receive a message for useless-suppression. This is a false positive of useless-suppression we can't easily fix.

See https://github.com/PyCQA/pylint/issues/3368 for more information.

Created by the format checker.

misplaced-comparison-constant / C2201

Message emitted:

Comparison should be %s

Description:

Used when the constant is placed on the left side of a comparison. It is usually clearer in intent to place it in the right hand side of the comparison.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'comparison-placement' checker which requires the pylint.extensions.comparison_placement plugin to be loaded.

Created by the comparison-placement checker.

missing-class-docstring / C0115

Message emitted:

Missing class docstring

Description:

Used when a class has no docstring. Even an empty class must have a docstring.

Problematic code:

class Person:  # [missing-class-docstring]

def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name

Correct code:

class Person:

"""Class representing a person"""
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name

Created by the basic checker.

missing-final-newline / C0304

Message emitted:

Final newline missing

Description:

Used when the last line in a file is missing a newline.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the format checker.

missing-function-docstring / C0116

Message emitted:

Missing function or method docstring

Description:

Used when a function or method has no docstring. Some special methods like __init__ do not require a docstring.

Problematic code:

import sys
def print_python_version():  # [missing-function-docstring]

print(sys.version)

Correct code:

import sys
def print_python_version():

"""Function printing python version."""
print(sys.version)

Created by the basic checker.

missing-module-docstring / C0114

Message emitted:

Missing module docstring

Description:

Used when a module has no docstring. Empty modules do not require a docstring.

Problematic code:

import sys  # [missing-module-docstring]
def print_python_version():

print(sys.version)

Correct code:

"""Module providingFunction printing python version."""
import sys
def print_python_version():

print(sys.version)

Created by the basic checker.

mixed-line-endings / C0327

Message emitted:

Mixed line endings LF and CRLF

Description:

Used when there are mixed (LF and CRLF) newline signs in a file.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the format checker.

multiple-imports / C0410

Message emitted:

Multiple imports on one line (%s)

Description:

Used when import statement importing multiple modules is detected.

Problematic code:

import os, sys  # [multiple-imports]

Correct code:

import os
import sys

Created by the imports checker.

multiple-statements / C0321

Message emitted:

More than one statement on a single line

Description:

Used when more than on statement are found on the same line.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the format checker.

non-ascii-module-import / C2403

Message emitted:

%s name "%s" contains a non-ASCII character, use an ASCII-only alias for import.

Description:

Used when the name contains at least one non-ASCII unicode character. See https://peps.python.org/pep-0672/#confusing-features for a background why this could be bad. If your programming guideline defines that you are programming in English, then there should be no need for non ASCII characters in Python Names. If not you can simply disable this check.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the nonascii-checker checker.

non-ascii-name / C2401

Message emitted:

%s name "%s" contains a non-ASCII character, consider renaming it.

Description:

Used when the name contains at least one non-ASCII unicode character. See https://peps.python.org/pep-0672/#confusing-features for a background why this could be bad. If your programming guideline defines that you are programming in English, then there should be no need for non ASCII characters in Python Names. If not you can simply disable this check.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the nonascii-checker checker.

single-string-used-for-slots / C0205

Message emitted:

Class __slots__ should be a non-string iterable

Description:

Used when a class __slots__ is a simple string, rather than an iterable.

Problematic code:

class Fruit:  # [single-string-used-for-slots]

__slots__ = "name"
def __init__(self, name):
self.name = name

Correct code:

class Fruit:

__slots__ = ("name",)
def __init__(self, name):
self.name = name

Created by the classes checker.

singleton-comparison / C0121

Message emitted:

Comparison %s should be %s

Description:

Used when an expression is compared to singleton values like True, False or None.

Problematic code:

game_won = True
if game_won == True:  # [singleton-comparison]

print("Game won !")

Correct code:

game_won = True
if game_won:

print("Game won !")

Related links:

PEP 285 – Adding a bool type

Created by the basic checker.

superfluous-parens / C0325

Message emitted:

Unnecessary parens after %r keyword

Description:

Used when a single item in parentheses follows an if, for, or other keyword.

Problematic code:

x = input()
y = input()
if (x == y):  # [superfluous-parens]

pass i = 0 exclude = [] if (i - 0) in exclude: # [superfluous-parens]
pass

Correct code:

x = input()
y = input()
if x == y:

pass i = 0 exclude = [] if i - 0 in exclude:
pass

Created by the format checker.

too-many-lines / C0302

Message emitted:

Too many lines in module (%s/%s)

Description:

Used when a module has too many lines, reducing its readability.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the format checker.

trailing-newlines / C0305

Message emitted:

Trailing newlines

Description:

Used when there are trailing blank lines in a file.

Problematic code:

print("apple")
# The file ends with 2 lines that are empty # +1: [trailing-newlines]

Correct code:

print("apple")

Created by the format checker.

trailing-whitespace / C0303

Message emitted:

Trailing whitespace

Description:

Used when there is whitespace between the end of a line and the newline.

Problematic code:

print("Hello")  # [trailing-whitespace]   
#                                       ^^^ trailing whitespaces

Correct code:

print("Hello")

Created by the format checker.

typevar-double-variance / C0131

Message emitted:

TypeVar cannot be both covariant and contravariant

Description:

Emitted when both the "covariant" and "contravariant" keyword arguments are set to "True" in a TypeVar.

Problematic code:

from typing import TypeVar
T = TypeVar("T", covariant=True, contravariant=True)  # [typevar-double-variance]

Correct code:

from typing import TypeVar
T_co = TypeVar("T_co", covariant=True)
T_contra = TypeVar("T_contra", contravariant=True)

Created by the basic checker.

typevar-name-incorrect-variance / C0105

Message emitted:

Type variable name does not reflect variance%s

Description:

Emitted when a TypeVar name doesn't reflect its type variance. According to PEP8, it is recommended to add suffixes '_co' and '_contra' to the variables used to declare covariant or contravariant behaviour respectively. Invariant (default) variables do not require a suffix. The message is also emitted when invariant variables do have a suffix.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the basic checker.

typevar-name-mismatch / C0132

Message emitted:

TypeVar name "%s" does not match assigned variable name "%s"

Description:

Emitted when a TypeVar is assigned to a variable that does not match its name argument.

Problematic code:

from typing import TypeVar
X = TypeVar("T")  # [typevar-name-mismatch]

Correct code:

from typing import TypeVar
T = TypeVar("T")

Created by the basic checker.

unexpected-line-ending-format / C0328

Message emitted:

Unexpected line ending format. There is '%s' while it should be '%s'.

Description:

Used when there is different newline than expected.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the format checker.

ungrouped-imports / C0412

Message emitted:

Imports from package %s are not grouped

Description:

Used when imports are not grouped by packages.

Problematic code:

import logging
import os
import sys
import logging.config  # [ungrouped-imports]
from logging.handlers import WatchedFileHandler

Correct code:

import logging
import logging.config
import os
import sys
from logging.handlers import FileHandler

Created by the imports checker.

unnecessary-direct-lambda-call / C3002

Message emitted:

Lambda expression called directly. Execute the expression inline instead.

Description:

Used when a lambda expression is directly called rather than executing its contents inline.

Problematic code:

y = (lambda x: x**2 + 2*x + 1)(a)  # [unnecessary-direct-lambda-call]

Correct code:

y = a**2 + 2*a + 1

Created by the lambda-expressions checker.

unnecessary-dunder-call / C2801

Message emitted:

Unnecessarily calls dunder method %s. %s.

Description:

Used when a dunder method is manually called instead of using the corresponding function/method/operator.

Problematic code:

three = 3.0.__str__()  # [unnecessary-dunder-call]
twelve = "1".__add__("2")  # [unnecessary-dunder-call]
def is_bigger_than_two(x):

return x.__gt__(2) # [unnecessary-dunder-call]

Correct code:

three = str(3.0)
twelve = "1" + "2"
def is_bigger_than_two(x):

return x > 2

Created by the unnecessary-dunder-call checker.

unnecessary-lambda-assignment / C3001

Message emitted:

Lambda expression assigned to a variable. Define a function using the "def" keyword instead.

Description:

Used when a lambda expression is assigned to variable rather than defining a standard function with the "def" keyword.

Problematic code:

foo = lambda x: x**2 + 2*x + 1  # [unnecessary-lambda-assignment]

Correct code:

def foo(x):

return x**2 + 2*x + 1

Created by the lambda-expressions checker.

unneeded-not / C0113

Message emitted:

Consider changing "%s" to "%s"

Description:

Used when a boolean expression contains an unneeded negation.

Problematic code:

if not not input():  # [unneeded-not]

pass

Correct code:

if input():

pass

Created by the refactoring checker.

use-implicit-booleaness-not-comparison / C1803

Message emitted:

'%s' can be simplified to '%s' as an empty sequence is falsey

Description:

Used when Pylint detects that collection literal comparison is being used to check for emptiness; Use implicit booleaness instead of a collection classes; empty collections are considered as false

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the refactoring checker.

use-implicit-booleaness-not-len / C1802

Message emitted:

Do not use len(SEQUENCE) without comparison to determine if a sequence is empty

Description:

Used when Pylint detects that len(sequence) is being used without explicit comparison inside a condition to determine if a sequence is empty. Instead of coercing the length to a boolean, either rely on the fact that empty sequences are false or compare the length against a scalar.

Problematic code:

fruits = ["orange", "apple"]
if len(fruits):  # [use-implicit-booleaness-not-len]

print(fruits)

Correct code:

fruits = ["orange", "apple"]
if fruits:

print(fruits)

Created by the refactoring checker.

use-maxsplit-arg / C0207

Message emitted:

Use %s instead

Description:

Emitted when accessing only the first or last element of str.split(). The first and last element can be accessed by using str.split(sep, maxsplit=1)[0] or str.rsplit(sep, maxsplit=1)[-1] instead.

Problematic code:

url = "www.example.com"
suffix = url.split(".")[-1]  # [use-maxsplit-arg]

Correct code:

url = "www.example.com"
suffix = url.rsplit(".", maxsplit=1)[-1]

Additional details:

Be aware that the performance improvement from not splitting the string so many times will only be realized in cases presenting more instances of the splitting character than the minimal example here.

Created by the refactoring checker.

use-sequence-for-iteration / C0208

Message emitted:

Use a sequence type when iterating over values

Description:

When iterating over values, sequence types (e.g., ``lists``, ``tuples``, ``ranges``) are more efficient than ``sets``.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the refactoring checker.

useless-import-alias / C0414

Message emitted:

Import alias does not rename original package

Description:

Used when an import alias is same as original package, e.g., using import numpy as numpy instead of import numpy as np.

Problematic code:

import pandas as pandas  # [useless-import-alias]

Correct code:

import pandas as pd

Additional details:

If you prefer to use "from-as" to explicitly reexport in API (from fruit import orange as orange) instead of using __all__ this message will be a false positive.

If that's the case use pylint: disable=useless-import-alias before your imports in your API files. False positive 'useless-import-alias' error for mypy-compatible explicit re-exports #6006

Related links:

  • PEP 8, Import Guideline
  • Pylint block-disable
  • mypy --no-implicit-reexport

Created by the imports checker.

wrong-import-order / C0411

Message emitted:

%s should be placed before %s

Description:

Used when PEP8 import order is not respected (standard imports first, then third-party libraries, then local imports).

Problematic code:

import os
from . import utils
import pylint  # [wrong-import-order]
import sys  # [wrong-import-order]

Correct code:

import os
import sys
import pylint
from . import utils

Created by the imports checker.

wrong-import-position / C0413

Message emitted:

Import "%s" should be placed at the top of the module

Description:

Used when code and imports are mixed.

Problematic code:

import os
home = os.environ['HOME']
import sys  # [wrong-import-position]
print(f'Home directory is {home}', file=sys.stderr)

Correct code:

import os
import sys
home = os.environ['HOME']
print(f'Home directory is {home}', file=sys.stderr)

Created by the imports checker.

wrong-spelling-in-comment / C0401

Message emitted:

Wrong spelling of a word '%s' in a comment: %s %s Did you mean: '%s'?

Description:

Used when a word in comment is not spelled correctly.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the spelling checker.

wrong-spelling-in-docstring / C0402

Message emitted:

Wrong spelling of a word '%s' in a docstring: %s %s Did you mean: '%s'?

Description:

Used when a word in docstring is not spelled correctly.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the spelling checker.

All renamed messages in the convention category:

"blacklisted-name has been renamed. The new message can be found at:

"len-as-condition has been renamed. The new message can be found at:

"missing-docstring has been renamed. The new message can be found at:

"old-misplaced-comparison-constant has been renamed. The new message can be found at:

"old-non-ascii-name has been renamed. The new message can be found at:

All messages in the refactor category:

chained-comparison / R1716

Message emitted:

Simplify chained comparison between the operands

Description:

This message is emitted when pylint encounters boolean operation like "a < b and b < c", suggesting instead to refactor it to "a < b < c"

Problematic code:

a = int(input())
b = int(input())
c = int(input())
if a < b and b < c:  # [chained-comparison]

pass

Correct code:

a = int(input())
b = int(input())
c = int(input())
if a < b < c:

pass

Created by the refactoring checker.

comparison-of-constants / R0133

Message emitted:

Comparison between constants: '%s %s %s' has a constant value

Description:

When two literals are compared with each other the result is a constant. Using the constant directly is both easier to read and more performant. Initializing 'True' and 'False' this way is not required since Python 2.3.

Problematic code:

def is_the_answer() -> bool:

return 42 == 42 # [comparison-of-constants]

Correct code:

def is_the_answer(meaning_of_life: int) -> bool:

return meaning_of_life == 42

Created by the basic checker.

comparison-with-itself / R0124

Message emitted:

Redundant comparison - %s

Description:

Used when something is compared against itself.

Problematic code:

def is_an_orange(fruit):

an_orange = "orange"
return fruit == fruit # [comparison-with-itself]

Correct code:

def is_an_orange(fruit):

an_orange = "orange"
return an_orange == fruit

Created by the basic checker.

condition-evals-to-constant / R1727

Message emitted:

Boolean condition '%s' will always evaluate to '%s'

Description:

Emitted when a boolean condition can be simplified to a constant value.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the refactoring checker.

confusing-consecutive-elif / R5601

Message emitted:

Consecutive elif with differing indentation level, consider creating a function to separate the inner elif

Description:

Used when an elif statement follows right after an indented block which itself ends with if or elif. It may not be ovious if the elif statement was willingly or mistakenly unindented. Extracting the indented if statement into a separate function might avoid confusion and prevent errors.

Problematic code:

def myfunc(shall_continue: bool, shall_exit: bool):

if shall_continue:
if input("Are you sure?") == "y":
print("Moving on.")
elif shall_exit: # [confusing-consecutive-elif]
print("Exiting.")

Correct code:

# Option 1: add explicit 'else'
def myfunc(shall_continue: bool, shall_exit: bool):

if shall_continue:
if input("Are you sure?") == "y":
print("Moving on.")
else:
pass
elif shall_exit:
print("Exiting.") # Option 2: extract function def user_confirmation():
if input("Are you sure?") == "y":
print("Moving on.") def myfunc2(shall_continue: bool, shall_exit: bool):
if shall_continue:
user_confirmation()
elif shall_exit:
print("Exiting.")

Additional details:

Creating a function for the nested conditional, or adding an explicit else in the indented if statement, even if it only contains a pass statement, can help clarify the code.

NOTE:

This message is emitted by the optional 'confusing_elif' checker which requires the pylint.extensions.confusing_elif plugin to be loaded.

Created by the confusing_elif checker.

consider-alternative-union-syntax / R6003

Message emitted:

Consider using alternative Union syntax instead of '%s'%s

Description:

Emitted when 'typing.Union' or 'typing.Optional' is used instead of the alternative Union syntax 'int | None'.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'typing' checker which requires the pylint.extensions.typing plugin to be loaded.

Created by the typing checker.

consider-merging-isinstance / R1701

Message emitted:

Consider merging these isinstance calls to isinstance(%s, (%s))

Description:

Used when multiple consecutive isinstance calls can be merged into one.

Problematic code:

from typing import Any
def is_number(value: Any) -> bool:

return isinstance(value, int) or isinstance(value, float) # [consider-merging-isinstance]

Correct code:

from typing import Any
def is_number(value: Any) -> bool:

return isinstance(value, (int, float))

Created by the refactoring checker.

consider-swap-variables / R1712

Message emitted:

Consider using tuple unpacking for swapping variables

Description:

You do not have to use a temporary variable in order to swap variables. Using "tuple unpacking" to directly swap variables makes the intention more clear.

Problematic code:

a = 1
b = 2
temp = a  # [consider-swap-variables]
a = b
b = temp

Correct code:

a = 1
b = 2
a, b = b, a

Created by the refactoring checker.

consider-using-alias / R6002

Message emitted:

'%s' will be deprecated with PY39, consider using '%s' instead%s

Description:

Only emitted if 'runtime-typing=no' and a deprecated typing alias is used in a type annotation context in Python 3.7 or 3.8.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'typing' checker which requires the pylint.extensions.typing plugin to be loaded.

Created by the typing checker.

consider-using-assignment-expr / R6103

Message emitted:

Use '%s' instead

Description:

Emitted when an if assignment is directly followed by an if statement and both can be combined by using an assignment expression ``:=``. Requires Python 3.8 and ``py-version >= 3.8``.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'code_style' checker which requires the pylint.extensions.code_style plugin to be loaded.

Created by the code_style checker.

consider-using-dict-comprehension / R1717

Message emitted:

Consider using a dictionary comprehension

Description:

Emitted when we detect the creation of a dictionary using the dict() callable and a transient list. Although there is nothing syntactically wrong with this code, it is hard to read and can be simplified to a dict comprehension. Also it is faster since you don't need to create another transient list

Problematic code:

NUMBERS = [1, 2, 3]
DOUBLED_NUMBERS = dict([(number, number * 2) for number in NUMBERS])  # [consider-using-dict-comprehension]

Correct code:

NUMBERS = [1, 2, 3]
DOUBLED_NUMBERS = {number: number * 2 for number in NUMBERS}

Created by the refactoring checker.

consider-using-from-import / R0402

Message emitted:

Use 'from %s import %s' instead

Description:

Emitted when a submodule of a package is imported and aliased with the same name, e.g., instead of ``import concurrent.futures as futures`` use ``from concurrent import futures``.

Problematic code:

import os.path as path  # [consider-using-from-import]

Correct code:

from os import path

Created by the imports checker.

consider-using-generator / R1728

Message emitted:

Consider using a generator instead '%s(%s)'

Description:

If your container can be large using a generator will bring better performance.

Problematic code:

list([0 for y in list(range(10))])  # [consider-using-generator]
tuple([0 for y in list(range(10))])  # [consider-using-generator]
sum([y**2 for y in list(range(10))])  # [consider-using-generator]
max([y**2 for y in list(range(10))])  # [consider-using-generator]
min([y**2 for y in list(range(10))])  # [consider-using-generator]

Correct code:

list(0 for y in list(range(10)))
tuple(0 for y in list(range(10)))
sum(y**2 for y in list(range(10)))
max(y**2 for y in list(range(10)))
min(y**2 for y in list(range(10)))

Additional details:

Removing [] inside calls that can use containers or generators should be considered for performance reasons since a generator will have an upfront cost to pay. The performance will be better if you are working with long lists or sets.

For max, min and sum using a generator is also recommended by pep289.

Related links:

  • PEP 289
  • Benchmark and discussion for any/all/list/tuple
  • Benchmark and discussion for sum/max/min

Created by the refactoring checker.

consider-using-get / R1715

Message emitted:

Consider using dict.get for getting values from a dict if a key is present or a default if not

Description:

Using the builtin dict.get for getting a value from a dictionary if a key is present or a default if not, is simpler and considered more idiomatic, although sometimes a bit slower

Problematic code:

knights = {"Gallahad": "the pure", "Robin": "the brave"}
if "Gallahad" in knights:  # [consider-using-get]

DESCRIPTION = knights["Gallahad"] else:
DESCRIPTION = ""

Correct code:

knights = {"Gallahad": "the pure", "Robin": "the brave"}
description = knights.get("Gallahad", "")

Created by the refactoring checker.

consider-using-in / R1714

Message emitted:

Consider merging these comparisons with 'in' by using '%s %sin (%s)'. Use a set instead if elements are hashable.

Description:

To check if a variable is equal to one of many values, combine the values into a set or tuple and check if the variable is contained "in" it instead of checking for equality against each of the values. This is faster and less verbose.

Problematic code:

def fruit_is_round(fruit):

return fruit == "apple" or fruit == "orange" or fruit == "melon" # [consider-using-in]

Correct code:

def fruit_is_round(fruit):

return fruit in {"apple", "orange", "melon"}

Created by the refactoring checker.

consider-using-join / R1713

Message emitted:

Consider using str.join(sequence) for concatenating strings from an iterable

Description:

Using str.join(sequence) is faster, uses less memory and increases readability compared to for-loop iteration.

Problematic code:

def fruits_to_string(fruits):

formatted_fruit = ""
for fruit in fruits:
formatted_fruit += fruit # [consider-using-join]
return formatted_fruit print(fruits_to_string(["apple", "pear", "peach"]))

Correct code:

print("".join(["apple", "pear", "peach"]))

Created by the refactoring checker.

consider-using-max-builtin / R1731

Message emitted:

Consider using '%s' instead of unnecessary if block

Description:

Using the max builtin instead of a conditional improves readability and conciseness.

Problematic code:

def get_max(value1, value2):

if value1 < value2: # [consider-using-max-builtin]
value1 = value2
return value1 print(get_max(1, 2))

Correct code:

print(max(1, 2))

Created by the refactoring checker.

consider-using-min-builtin / R1730

Message emitted:

Consider using '%s' instead of unnecessary if block

Description:

Using the min builtin instead of a conditional improves readability and conciseness.

Problematic code:

def get_min(value1, value2):

if value1 > value2: # [consider-using-min-builtin]
value1 = value2
return value1 print(get_min(1, 2))

Correct code:

print(min(1, 2))

Created by the refactoring checker.

consider-using-namedtuple-or-dataclass / R6101

Message emitted:

Consider using namedtuple or dataclass for dictionary values

Description:

Emitted when dictionary values can be replaced by namedtuples or dataclass instances.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'code_style' checker which requires the pylint.extensions.code_style plugin to be loaded.

Created by the code_style checker.

consider-using-set-comprehension / R1718

Message emitted:

Consider using a set comprehension

Description:

Although there is nothing syntactically wrong with this code, it is hard to read and can be simplified to a set comprehension. Also it is faster since you don't need to create another transient list

Problematic code:

NUMBERS = [1, 2, 2, 3, 4, 4]
UNIQUE_EVEN_NUMBERS = set([number for number in NUMBERS if number % 2 == 0])  # [consider-using-set-comprehension]

Correct code:

NUMBERS = [1, 2, 2, 3, 4, 4]
UNIQUE_EVEN_NUMBERS = {number for number in NUMBERS if number % 2 == 0}

Created by the refactoring checker.

consider-using-sys-exit / R1722

Message emitted:

Consider using sys.exit()

Description:

Instead of using exit() or quit(), consider using the sys.exit().

Problematic code:

if __name__ == "__main__":

user = input("Enter user name: ")
print(f"Hello, {user}")
exit(0) # [consider-using-sys-exit]

Correct code:

import sys
if __name__ == "__main__":

user = input("Enter user name: ")
print(f"Hello, {user}")
sys.exit(0)

Created by the refactoring checker.

consider-using-ternary / R1706

Message emitted:

Consider using ternary (%s)

Description:

Used when one of known pre-python 2.5 ternary syntax is used.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the refactoring checker.

consider-using-tuple / R6102

Message emitted:

Consider using an in-place tuple instead of list

Description:

Only for style consistency! Emitted where an in-place defined ``list`` can be replaced by a ``tuple``. Due to optimizations by CPython, there is no performance benefit from it.

Problematic code:

for i in [1, 2, 3]:  # [consider-using-tuple]

print(i)

Correct code:

for i in (1, 2, 3):

print(i)

NOTE:

This message is emitted by the optional 'code_style' checker which requires the pylint.extensions.code_style plugin to be loaded.

Created by the code_style checker.

consider-using-with / R1732

Message emitted:

Consider using 'with' for resource-allocating operations

Description:

Emitted if a resource-allocating assignment or call may be replaced by a 'with' block. By using 'with' the release of the allocated resources is ensured even in the case of an exception.

Problematic code:

file = open("apple.txt", "r", encoding="utf8")  # [consider-using-with]
contents = file.read()
file.close()
worst = open("banana.txt", "r", encoding="utf8").read()  # [consider-using-with]

Correct code:

with open("apple.txt", "r", encoding="utf8") as file:

contents = file.read() with open("banana.txt", "r", encoding="utf8") as f:
best = f.read()

Additional details:

Calling write() without using the with keyword or calling close() might result in the arguments of write() not being completely written to the disk, even if the program exits successfully.

This message applies to callables of Python's stdlib which can be replaced by a with statement. It is suppressed in the following cases:

  • the call is located inside a context manager
  • the call result is returned from the enclosing function
  • the call result is used in a with statement itself

Related links:

  • Python doc: Reading and writing files
  • PEP 343
  • Context managers in Python by John Lekberg
  • Rationale

Created by the refactoring checker.

cyclic-import / R0401

Message emitted:

Cyclic import (%s)

Description:

Used when a cyclic import between two or more modules is detected.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the imports checker.

duplicate-code / R0801

Message emitted:

Similar lines in %s files %s

Description:

Indicates that a set of similar lines has been detected among multiple file. This usually means that the code should be refactored to avoid this duplication.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the similarities checker.

else-if-used / R5501

Message emitted:

Consider using "elif" instead of "else" then "if" to remove one indentation level

Description:

Used when an else statement is immediately followed by an if statement and does not contain statements that would be unrelated to it.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'else_if_used' checker which requires the pylint.extensions.check_elif plugin to be loaded.

Created by the else_if_used checker.

empty-comment / R2044

Message emitted:

Line with empty comment

Description:

Used when a # symbol appears on a line not followed by an actual comment

Problematic code:

# +1:[empty-comment]
#
# +1:[empty-comment]
x = 0  #

Correct code:

# comment
x = 0  # comment

NOTE:

This message is emitted by the optional 'empty-comment' checker which requires the pylint.extensions.empty_comment plugin to be loaded.

Created by the empty-comment checker.

inconsistent-return-statements / R1710

Message emitted:

Either all return statements in a function should return an expression, or none of them should.

Description:

According to PEP8, if any return statement returns an expression, any return statements where no value is returned should explicitly state this as return None, and an explicit return statement should be present at the end of the function (if reachable)

Problematic code:

def get_the_answer(value: str) -> str | None:  # [inconsistent-return-statements]

if value:
return value

Correct code:

def get_the_answer(value: str) -> str | None:

if value:
return value
return None

Created by the refactoring checker.

literal-comparison / R0123

Message emitted:

In '%s', use '%s' when comparing constant literals not '%s' ('%s')

Description:

Used when comparing an object to a literal, which is usually what you do not want to do, since you can compare to a different literal than what was expected altogether.

Problematic code:

def is_an_orange(fruit):

return fruit is "orange" # [literal-comparison]

Correct code:

def is_an_orange(fruit):

return fruit == "orange"

Related links:

Comparison operations in Python

Created by the basic checker.

no-classmethod-decorator / R0202

Message emitted:

Consider using a decorator instead of calling classmethod

Description:

Used when a class method is defined without using the decorator syntax.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the classes checker.

no-else-break / R1723

Message emitted:

Unnecessary "%s" after "break", %s

Description:

Used in order to highlight an unnecessary block of code following an if containing a break statement. As such, it will warn when it encounters an else following a chain of ifs, all of them containing a break statement.

Problematic code:

def next_seven_elements(iterator):

for i, item in enumerate(iterator):
if i == 7: # [no-else-break]
break
else:
yield item

Correct code:

def next_seven_elements(iterator):

for i, item in enumerate(iterator):
if i == 7:
break
yield item

Created by the refactoring checker.

no-else-continue / R1724

Message emitted:

Unnecessary "%s" after "continue", %s

Description:

Used in order to highlight an unnecessary block of code following an if containing a continue statement. As such, it will warn when it encounters an else following a chain of ifs, all of them containing a continue statement.

Problematic code:

def even_number_under(n: int):

for i in range(n):
if i%2 == 1: # [no-else-continue]
continue
else:
yield i

Correct code:

def even_number_under(n: int):

for i in range(n):
if i%2 == 1:
continue
yield i

Created by the refactoring checker.

no-else-raise / R1720

Message emitted:

Unnecessary "%s" after "raise", %s

Description:

Used in order to highlight an unnecessary block of code following an if containing a raise statement. As such, it will warn when it encounters an else following a chain of ifs, all of them containing a raise statement.

Problematic code:

def integer_sum(a: int, b: int) -> int:

if not (isinstance(a, int) and isinstance(b, int)): # [no-else-raise]
raise ValueError('Function supports only integer parameters.')
else:
return a + b

Correct code:

def integer_sum(a: int, b: int) -> int:

if not (isinstance(a, int) and isinstance(b, int)):
raise ValueError('Function supports only integer parameters.')
return a + b

Created by the refactoring checker.

no-else-return / R1705

Message emitted:

Unnecessary "%s" after "return", %s

Description:

Used in order to highlight an unnecessary block of code following an if containing a return statement. As such, it will warn when it encounters an else following a chain of ifs, all of them containing a return statement.

Problematic code:

def compare_numbers(a: int, b: int) -> int:

if a == b: # [no-else-return]
return 0
elif a < b:
return -1
else:
return 1

Correct code:

def compare_numbers(a: int, b: int) -> int:

if a == b:
return 0
if a < b:
return -1
return 1

Created by the refactoring checker.

no-self-use / R6301

Message emitted:

Method could be a function

Description:

Used when a method doesn't use its bound instance, and so could be written as a function.

Problematic code:

class Person:

def developer_greeting(self): # [no-self-use]
print("Greetings developer!")
def greeting_1(self): # [no-self-use]
print("Hello!")
def greeting_2(self): # [no-self-use]
print("Hi!")

Correct code:

"""If a function is not using any class attribute it can be a @staticmethod, or a function outside the class."""
def developer_greeting():

print("Greetings developer!") class Person:
name = "Paris"
def greeting_1(self):
print(f"Hello from {self.name} !")
@staticmethod
def greeting_2():
print("Hi!")

NOTE:

This message is emitted by the optional 'no_self_use' checker which requires the pylint.extensions.no_self_use plugin to be loaded.

Created by the no_self_use checker.

no-staticmethod-decorator / R0203

Message emitted:

Consider using a decorator instead of calling staticmethod

Description:

Used when a static method is defined without using the decorator syntax.

Problematic code:

class Worm:

def bore(self):
pass
bore = staticmethod(bore) # [no-staticmethod-decorator]

Correct code:

class Worm:

@staticmethod
def bore(self):
pass

Created by the classes checker.

property-with-parameters / R0206

Message emitted:

Cannot have defined parameters for properties

Description:

Used when we detect that a property also has parameters, which are useless, given that properties cannot be called with additional arguments.

Problematic code:

class Worm:

@property
def bore(self, depth): # [property-with-parameters]
pass

Correct code:

class Worm:

@property
def bore(self):
"""Property accessed with '.bore'."""
pass
def bore_with_depth(depth):
"""Function called with .bore_with_depth(depth)."""
pass

Created by the classes checker.

redefined-argument-from-local / R1704

Message emitted:

Redefining argument with the local name %r

Description:

Used when a local name is redefining an argument, which might suggest a potential error. This is taken in account only for a handful of name binding operations, such as for iteration, with statement assignment and exception handler assignment.

Problematic code:

def show(host_id=10.11):

for host_id, host in [[12.13, 'Venus'], [14.15, 'Mars']]: # [redefined-argument-from-local]
print(host_id, host)

Correct code:

def show(host_id=10.11):

for inner_host_id, host in [[12.13, 'Venus'], [14.15, 'Mars']]:
print(host_id, inner_host_id, host)

Created by the refactoring checker.

redefined-variable-type / R0204

Message emitted:

Redefinition of %s type from %s to %s

Description:

Used when the type of a variable changes inside a method or a function.

Problematic code:

x = 1
x = "2"  # [redefined-variable-type]

Correct code:

x = 1
x = 2

NOTE:

This message is emitted by the optional 'multiple_types' checker which requires the pylint.extensions.redefined_variable_type plugin to be loaded.

Created by the multiple_types checker.

simplifiable-condition / R1726

Message emitted:

Boolean condition '%s' may be simplified to '%s'

Description:

Emitted when a boolean condition is able to be simplified.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the refactoring checker.

simplifiable-if-expression / R1719

Message emitted:

The if expression can be replaced with %s

Description:

Used when an if expression can be replaced with 'bool(test)' or simply 'test' if the boolean cast is implicit.

Problematic code:

FLYING_THINGS = ["bird", "plane", "superman", "this example"]
def is_flying_thing(an_object):

return True if an_object in FLYING_THINGS else False # [simplifiable-if-expression] def is_not_flying_thing(an_object):
return False if an_object in FLYING_THINGS else True # [simplifiable-if-expression]

Correct code:

FLYING_THINGS = ["bird", "plane", "superman", "this example"]
def is_flying_thing(an_object):

return an_object in FLYING_THINGS def is_not_flying_thing(an_object):
return an_object not in FLYING_THINGS

Related links:

Simplifying an 'if' statement with bool()

Created by the refactoring checker.

simplifiable-if-statement / R1703

Message emitted:

The if statement can be replaced with %s

Description:

Used when an if statement can be replaced with 'bool(test)'.

Problematic code:

FLYING_THINGS = ["bird", "plane", "superman", "this example"]
def is_flying_animal(an_object):

if isinstance(an_object, Animal) and an_object in FLYING_THINGS: # [simplifiable-if-statement]
is_flying = True
else:
is_flying = False
return is_flying

Correct code:

FLYING_THINGS = ["bird", "plane", "superman", "this example"]
def is_flying_animal(an_object):

is_flying = isinstance(an_object, Animal) and an_object.name in FLYING_THINGS
return is_flying

Created by the refactoring checker.

simplify-boolean-expression / R1709

Message emitted:

Boolean expression may be simplified to %s

Description:

Emitted when redundant pre-python 2.5 ternary syntax is used.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the refactoring checker.

stop-iteration-return / R1708

Message emitted:

Do not raise StopIteration in generator, use return statement instead

Description:

According to PEP479, the raise of StopIteration to end the loop of a generator may lead to hard to find bugs. This PEP specify that raise StopIteration has to be replaced by a simple return statement

Problematic code:

def fruit_generator():

for fruit in ["apple", "banana"]:
yield fruit
raise StopIteration # [stop-iteration-return] def two_fruits_generator(fruits):
for fruit in fruits:
yield fruit, next(fruits) # [stop-iteration-return] def two_good_fruits_generator(fruits):
for fruit in fruits:
if not fruit.is_tasty():
continue
while True:
next_fruit = next(fruits) # [stop-iteration-return]
if next_fruit.is_tasty():
yield fruit, next_fruit
break

Correct code:

def fruit_generator():

"""The example is simple enough you don't need an explicit return."""
for fruit in ["apple", "banana"]:
yield fruit def two_fruits_generator(fruits):
"""Catching the StopIteration."""
for fruit in fruits:
try:
yield fruit, next(fruits)
except StopIteration:
print("Sorry there is only one fruit left.")
yield fruit, None def two_good_fruits_generator(fruits):
"""A return can be used to end the iterator early, but not a StopIteration."""
for fruit in fruits:
if not fruit.is_tasty():
continue
while True:
next_fruit = next(fruits, None)
if next_fruit is None:
print("Sorry there is only one fruit left.")
yield fruit, None
# We reached the end of the 'fruits' generator but raising a
# StopIteration instead of returning would create a RuntimeError
return
if next_fruit.is_tasty():
yield fruit, next_fruit
break

Additional details:

It's possible to give a default value to next or catch the StopIteration, or return directly. A StopIteration cannot be propagated from a generator.

Related links:

PEP 479

Created by the refactoring checker.

super-with-arguments / R1725

Message emitted:

Consider using Python 3 style super() without arguments

Description:

Emitted when calling the super() builtin with the current class and instance. On Python 3 these arguments are the default and they can be omitted.

Problematic code:

class Fruit:

pass class Orange(Fruit):
def __init__(self):
super(Orange, self).__init__() # [super-with-arguments]

Correct code:

class Fruit:

pass class Orange(Fruit):
def __init__(self):
super().__init__()

Created by the refactoring checker.

too-complex / R1260

Message emitted:

%s is too complex. The McCabe rating is %d

Description:

Used when a method or function is too complex based on McCabe Complexity Cyclomatic

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

NOTE:

This message is emitted by the optional 'design' checker which requires the pylint.extensions.mccabe plugin to be loaded.

Created by the design checker.

too-few-public-methods / R0903

Message emitted:

Too few public methods (%s/%s)

Description:

Used when class has too few public methods, so be sure it's really worth it.

Problematic code:

class Worm:  # [too-few-public-methods]

def __init__(self, name: str, fruit_of_residence: Fruit):
self.name = name
self.fruit_of_residence = fruit_of_residence
def bore(self):
print(f"{self.name} is boring into {self.fruit_of_residence}")

Correct code:

import dataclasses
class Worm:

def __init__(self, name: str, fruit_of_residence: Fruit):
self.name = name
self.fruit_of_residence = fruit_of_residence
def bore(self):
print(f"{self.name} is boring into {self.fruit_of_residence}")
def wiggle(self):
print(f"{self.name} wiggle around wormily.") # or @dataclasses.dataclass class Worm:
name:str
fruit_of_residence: Fruit def bore(worm: Worm):
print(f"{worm.name} is boring into {worm.fruit_of_residence}") # or def bore(fruit: Fruit, worm_name: str):
print(f"{worm_name} is boring into {fruit}")

Created by the design checker.

too-many-ancestors / R0901

Message emitted:

Too many ancestors (%s/%s)

Description:

Used when class has too many parent classes, try to reduce this to get a simpler (and so easier to use) class.

Problematic code:

class Animal: ...
class BeakyAnimal(Animal): ...
class FurryAnimal(Animal): ...
class Swimmer(Animal): ...
class EggLayer(Animal): ...
class VenomousAnimal(Animal): ...
class ProtectedSpecie(Animal): ...
class BeaverTailedAnimal(Animal): ...
class Vertebrate(Animal): ...
# max of 7 by default, can be configured
# each edge of a diamond inheritance counts
class Playtypus(  # [too-many-ancestors]

BeakyAnimal,
FurryAnimal,
Swimmer,
EggLayer,
VenomousAnimal,
ProtectedSpecie,
BeaverTailedAnimal,
Vertebrate, ):
pass

Correct code:

class Animal:

beaver_tailed: bool
can_swim: bool
has_beak: bool
has_fur: bool
has_vertebrae: bool
lays_egg: bool
protected_specie: bool
venomous: bool class Invertebrate(Animal):
has_vertebrae = False class Vertebrate(Animal):
has_vertebrae = True class Mammal(Vertebrate):
has_beak = False
has_fur = True
lays_egg = False
venomous = False class Playtypus(Mammal):
beaver_tailed = True
can_swim = True
has_beak = True
lays_egg = False
protected_specie = True
venomous = True

Created by the design checker.

too-many-arguments / R0913

Message emitted:

Too many arguments (%s/%s)

Description:

Used when a function or method takes too many arguments.

Problematic code:

def three_d_chess_move(  # [too-many-arguments]

x_white,
y_white,
z_white,
piece_white,
x_black,
y_black,
z_black,
piece_black,
x_blue,
y_blue,
z_blue,
piece_blue,
current_player, ):
pass

Correct code:

from dataclasses import dataclass
@dataclass
class ThreeDChessPiece:

x: int
y: int
z: int
type: str def three_d_chess_move(
white: ThreeDChessPiece,
black: ThreeDChessPiece,
blue: ThreeDChessPiece,
current_player, ):
pass

Created by the design checker.

too-many-boolean-expressions / R0916

Message emitted:

Too many boolean expressions in if statement (%s/%s)

Description:

Used when an if statement contains too many boolean expressions.

Problematic code:

def can_be_divided_by_two_and_are_not_zero(x, y, z):

# Maximum number of boolean expressions in an if statement (by default 5)
if (x and y and z) and (x % 2 == 0 and y % 2 == 0 and z % 2 == 0): # [too-many-boolean-expressions]
pass

Correct code:

def can_be_divided_by_two_and_are_not_zero(x, y, z):

if all(i and i%2==0 for i in [x, y, z]):
pass

Created by the design checker.

too-many-branches / R0912

Message emitted:

Too many branches (%s/%s)

Description:

Used when a function or method has too many branches, making it hard to follow.

Problematic code:

def num_to_word(x):  # [too-many-branches]

if x == 0:
return "zero"
elif x == 1:
return "one"
elif x == 2:
return "two"
elif x == 3:
return "three"
elif x == 4:
return "four"
elif x == 5:
return "five"
elif x == 6:
return "six"
elif x == 7:
return "seven"
elif x == 8:
return "eight"
elif x == 9:
return "nine"
else:
return None

Correct code:

def num_to_word(x):

return {
0: "zero",
1: "one",
2: "two",
3: "three",
4: "for",
5: "fie",
6: "six",
7: "seven",
8: "eight",
9: "nine",
}.get(x)

Created by the design checker.

too-many-instance-attributes / R0902

Message emitted:

Too many instance attributes (%s/%s)

Description:

Used when class has too many instance attributes, try to reduce this to get a simpler (and so easier to use) class.

Problematic code:

class Fruit:  # [too-many-instance-attributes]

def __init__(self):
# max of 7 attributes by default, can be configured
self.worm_name = "Jimmy"
self.worm_type = "Codling Moths"
self.worm_color = "light brown"
self.fruit_name = "Little Apple"
self.fruit_color = "Bright red"
self.fruit_vitamins = ["A", "B1"]
self.fruit_antioxidants = None
self.secondary_worm_name = "Kim"
self.secondary_worm_type = "Apple maggot"
self.secondary_worm_color = "Whitish"

Correct code:

import dataclasses
@dataclasses.dataclass
class Worm:

name: str
type: str
color: str class Fruit:
def __init__(self):
self.name = "Little Apple"
self.color = "Bright red"
self.vitamins = ["A", "B1"]
self.antioxidants = None
self.worms = [
Worm(name="Jimmy", type="Codling Moths", color="light brown"),
Worm(name="Kim", type="Apple maggot", color="Whitish"),
]

Created by the design checker.

too-many-locals / R0914

Message emitted:

Too many local variables (%s/%s)

Description:

Used when a function or method has too many local variables.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the design checker.

too-many-nested-blocks / R1702

Message emitted:

Too many nested blocks (%s/%s)

Description:

Used when a function or a method has too many nested blocks. This makes the code less understandable and maintainable.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the refactoring checker.

too-many-public-methods / R0904

Message emitted:

Too many public methods (%s/%s)

Description:

Used when class has too many public methods, try to reduce this to get a simpler (and so easier to use) class.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the design checker.

too-many-return-statements / R0911

Message emitted:

Too many return statements (%s/%s)

Description:

Used when a function or method has too many return statement, making it hard to follow.

Problematic code:

def to_string(x):  # [too-many-return-statements]

# max of 6 by default, can be configured
if x == 1:
return 'This is one.'
if x == 2:
return 'This is two.'
if x == 3:
return 'This is three.'
if x == 4:
return 'This is four.'
if x == 5:
return 'This is five.'
if x == 6:
return 'This is six.'
if x == 7:
return 'This is seven.'

Correct code:

NUMBERS_TO_STRINGS = {

1: 'one',
2: 'two',
3: 'three',
4: 'four',
5: 'five',
6: 'six',
7: 'seven' } def to_string(x):
return f'This is {NUMBERS_TO_STRINGS.get(x)}.'

Created by the design checker.

too-many-statements / R0915

Message emitted:

Too many statements (%s/%s)

Description:

Used when a function or method has too many statements. You should then split it in smaller functions / methods.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the design checker.

trailing-comma-tuple / R1707

Message emitted:

Disallow trailing comma tuple

Description:

In Python, a tuple is actually created by the comma symbol, not by the parentheses. Unfortunately, one can actually create a tuple by misplacing a trailing comma, which can lead to potential weird bugs in your code. You should always use parentheses explicitly for creating a tuple.

Problematic code:

COMPASS = "north", "south", "east", "west",  # [trailing-comma-tuple]

Correct code:

COMPASS = ("north", "south", "east", "west")

Created by the refactoring checker.

unnecessary-comprehension / R1721

Message emitted:

Unnecessary use of a comprehension, use %s instead.

Description:

Instead of using an identity comprehension, consider using the list, dict or set constructor. It is faster and simpler.

Problematic code:

NUMBERS = [1, 1, 2, 2, 3, 3]
UNIQUE_NUMBERS = {number for number in NUMBERS}  # [unnecessary-comprehension]

Correct code:

NUMBERS = [1, 1, 2, 2, 3, 3]
UNIQUE_NUMBERS = set(NUMBERS)

Created by the refactoring checker.

unnecessary-dict-index-lookup / R1733

Message emitted:

Unnecessary dictionary index lookup, use '%s' instead

Description:

Emitted when iterating over the dictionary items (key-item pairs) and accessing the value by index lookup. The value can be accessed directly instead.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the refactoring checker.

unnecessary-list-index-lookup / R1736

Message emitted:

Unnecessary list index lookup, use '%s' instead

Description:

Emitted when iterating over an enumeration and accessing the value by index lookup. The value can be accessed directly instead.

Problematic code:

letters = ['a', 'b', 'c']
for index, letter in enumerate(letters):

print(letters[index]) # [unnecessary-list-index-lookup]

Correct code:

letters = ['a', 'b', 'c']
for index, letter in enumerate(letters):

print(letter)

Created by the refactoring checker.

use-a-generator / R1729

Message emitted:

Use a generator instead '%s(%s)'

Description:

Comprehension inside of 'any', 'all', 'max', 'min' or 'sum' is unnecessary. A generator would be sufficient and faster.

Problematic code:

from random import randint
all([randint(-5, 5) > 0 for _ in range(10)])  # [use-a-generator]
any([randint(-5, 5) > 0 for _ in range(10)])  # [use-a-generator]

Correct code:

from random import randint
all(randint(-5, 5) > 0 for _ in range(10))
any(randint(-5, 5) > 0 for _ in range(10))

Additional details:

By using a generator you can cut the execution tree and exit directly at the first element that is False for all or True for any instead of calculating all the elements. Except in the worst possible case where you still need to evaluate everything (all values are True for all or all values are false for any) performance will be better.

Related links:

  • PEP 289 – Generator Expressions
  • Benchmark and discussion during initial implementation

Created by the refactoring checker.

use-dict-literal / R1735

Message emitted:

Consider using {} instead of dict()

Description:

Emitted when using dict() to create an empty dictionary instead of the literal {}. The literal is faster as it avoids an additional function call.

Problematic code:

empty_dict = dict()  # [use-dict-literal]

Correct code:

empty_dict = {}

Created by the refactoring checker.

use-list-literal / R1734

Message emitted:

Consider using [] instead of list()

Description:

Emitted when using list() to create an empty list instead of the literal []. The literal is faster as it avoids an additional function call.

Problematic code:

empty_list = list()  # [use-list-literal]

Correct code:

empty_list = []

Created by the refactoring checker.

use-set-for-membership / R6201

Message emitted:

Consider using set for membership test

Description:

Membership tests are more efficient when performed on a lookup optimized datatype like ``sets``.

Problematic code:

def fruit_is_dangerous_for_cat(fruit: str) -> bool:

"""This list is only a silly example, don't make decision regarding your cat diet based on it."""
return fruit in ["cherry", "grapes"] # [use-set-for-membership]

Correct code:

def fruit_is_dangerous_for_cat(fruit: str) -> bool:

"""This list is only a silly example, don't make decision regarding your cat diet based on it."""
return fruit in {"cherry", "grapes"}

NOTE:

This message is emitted by the optional 'set_membership' checker which requires the pylint.extensions.set_membership plugin to be loaded.

Created by the set_membership checker.

useless-object-inheritance / R0205

Message emitted:

Class %r inherits from object, can be safely removed from bases in python3

Description:

Used when a class inherit from object, which under python3 is implicit, hence can be safely removed from bases.

Problematic code:

class Banana(object):  # [useless-object-inheritance]

...

Correct code:

class Banana:

...

Created by the classes checker.

useless-return / R1711

Message emitted:

Useless return at end of function or method

Description:

Emitted when a single "return" or "return None" statement is found at the end of function or method definition. This statement can safely be removed because Python will implicitly return None

Problematic code:

import sys
def print_python_version():  # [useless-return]

print(sys.version)
return None

Correct code:

import sys
def print_python_version():

print(sys.version)

Created by the refactoring checker.

All renamed messages in the refactor category:

"old-no-self-use has been renamed. The new message can be found at:

"old-simplifiable-if-statement has been renamed. The new message can be found at:

"old-too-many-nested-blocks has been renamed. The new message can be found at:

All messages in the information category:

bad-inline-option / I0010

Message emitted:

Unable to consider inline option %r

Description:

Used when an inline option is either badly formatted or can't be used inside modules.

Problematic code:

# 2:[bad-inline-option]
# pylint: disable line-too-long

Correct code:

# pylint: disable=line-too-long

Created by the main checker.

c-extension-no-member / I1101

Message emitted:

%s %r has no %r member%s, but source is unavailable. Consider adding this module to extension-pkg-allow-list if you want to perform analysis based on run-time introspection of living objects.

Description:

Used when a variable is accessed for non-existent member of C extension. Due to unavailability of source static analysis is impossible, but it may be performed by introspecting living objects in run-time.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the typecheck checker.

deprecated-pragma / I0022

Message emitted:

Pragma "%s" is deprecated, use "%s" instead

Description:

Some inline pylint options have been renamed or reworked, only the most recent form should be used. NOTE:skip-all is only available with pylint >= 0.26

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

Message emitted:

Ignoring entire file

Description:

Used to inform that the file will not be checked

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

Message emitted:

Locally disabling %s (%s)

Description:

Used when an inline option disables a message or a messages category.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

Message emitted:

Unable to run raw checkers on built-in module %s

Description:

Used to inform that a built-in module has not been checked using the raw checkers.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

Message emitted:

Suppressed %s (from line %d)

Description:

A message was triggered on a line, but suppressed explicitly by a disable= comment in the file. This message is not generated for messages that are ignored due to configuration settings.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

use-symbolic-message-instead / I0023

Message emitted:

%s

Description:

Used when a message is enabled or disabled by id.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the miscellaneous checker.

useless-suppression / I0021

Message emitted:

Useless suppression of %s

Description:

Reported when a message is explicitly disabled for a line or a block of code, but never triggered.

Correct code:

# This is a placeholder for correct code for this message.

Additional details:

You can help us make the doc better by contributing !

Created by the main checker.

All renamed messages in the information category:

"deprecated-disable-all has been renamed. The new message can be found at:

In order to control messages, pylint accepts the following values:

  • a symbolic message: no-member, undefined-variable etc.
  • a numerical ID: E1101, E1102 etc.
  • The name of the group of checks. You can grab those with pylint --list-groups. For example, you can disable / enable all the checks related to type checking, with typecheck or all the checks related to variables with variables
  • Corresponding category of the checks
  • C convention related checks
  • R refactoring related checks
  • W various warnings
  • E errors, for probable bugs in the code
  • F fatal, if an error occurred which prevented pylint from doing further processing.
All the checks with all

This describes how the pragma controls operate at a code level.

The pragma controls can disable / enable:

All the violations on a single line
a, b = ... # pylint: disable=unbalanced-tuple-unpacking
All the violations on the following line
# pylint: disable-next=unbalanced-tuple-unpacking
a, b = ...
All the violations in a single scope
def test():

# Disable all the no-member violations in this function
# pylint: disable=no-member
...
All the violations in a block. For instance, each separate branch of an if statement is considered a separate block, as in the following example:
def meth5(self):

# pylint: disable=no-member
# no error
print(self.bla)
if self.blop:
# pylint: enable=no-member
# enable all no-members for this block
print(self.blip)
else:
# This is affected by the scope disable
print(self.blip)
# pylint: enable=no-member
print(self.blip)
if self.blop:
# pylint: disable=no-member
# disable all no-members for this block
print(self.blip)
else:
# This emits a violation
print(self.blip)
If the violation occurs on a block starting line, then it applies only to that line
if self.blop: # pylint: disable=no-member; applies only to this line

# Here we get an error
print(self.blip) else:
# error
print(self.blip)

Here's an example with all these rules in a single place:

"""pylint option block-disable"""
__revision__ = None
class Foo(object):

"""block-disable test"""
def __init__(self):
pass
def meth1(self, arg):
"""this issues a message"""
print(self)
def meth2(self, arg):
"""and this one not"""
# pylint: disable=unused-argument
print(self\
+ "foo")
def meth3(self):
"""test one line disabling"""
# no error
print(self.bla) # pylint: disable=no-member
# error
print(self.blop)
def meth4(self):
"""test re-enabling"""
# pylint: disable=no-member
# no error
print(self.bla)
print(self.blop)
# pylint: enable=no-member
# error
print(self.blip)
def meth5(self):
"""test IF sub-block re-enabling"""
# pylint: disable=no-member
# no error
print(self.bla)
if self.blop:
# pylint: enable=no-member
# error
print(self.blip)
else:
# no error
print(self.blip)
# no error
print(self.blip)
def meth6(self):
"""test TRY/EXCEPT sub-block re-enabling"""
# pylint: disable=no-member
# no error
print(self.bla)
try:
# pylint: enable=no-member
# error
print(self.blip)
except UndefinedName: # pylint: disable=undefined-variable
# no error
print(self.blip)
# no error
print(self.blip)
def meth7(self):
"""test one line block opening disabling"""
if self.blop: # pylint: disable=no-member
# error
print(self.blip)
else:
# error
print(self.blip)
# error
print(self.blip)
def meth8(self):
"""test late disabling"""
# error
print(self.blip)
# pylint: disable=no-member
# no error
print(self.bla)
print(self.blop)
def meth9(self):
"""test next line disabling"""
# no error
# pylint: disable-next=no-member
print(self.bla)
# error
print(self.blop)

As pylint gets better and false positives are removed, disables that became useless can accumulate and clutter the code. In order to clean them you can enable the useless-suppression warning.

Pylint can emit various messages. These are categorized according to categories corresponding to bit-encoded exit codes:

  • Fatal (1)
  • Error (2)
  • Warning (4)
  • Convention (8)
  • Refactor (16)
  • Information (NA)

An overview of these messages can be found in Messages overview

pylint has an advanced message control for its checks, offering the ability to enable / disable a message either from the command line or from the configuration file, as well as from the code itself.

For more detail see Messages control

Pylint is highly configurable. There are a lot of options to follow the needs of various projects and a lot of checks to activate if they suit your style.

You can generate a sample configuration file with --generate-toml-config or --generate-rcfile. Every option present on the command line before this will be included in the file

For example:

pylint --disable=bare-except,invalid-name --class-rgx='[A-Z][a-z]+' --generate-toml-config

In practice, it is often better to create a minimal configuration file which only contains configuration overrides. For all other options, Pylint will use its default values.

Main Checker

--analyse-fallback-blocks

Analyse import fallback blocks. This can be used to support both Python 2 and 3 compatible code, which means that the block might have code that exists only in one or another interpreter, leading to false positives when analysed.

Default: False

--confidence

Only show warnings with the listed confidence levels. Leave empty to show all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, UNDEFINED.

Default: ['HIGH', 'CONTROL_FLOW', 'INFERENCE', 'INFERENCE_FAILURE', 'UNDEFINED']

--disable

Disable the message, report, category or checker with the given id(s). You can either give multiple identifiers separated by comma (,) or put this option multiple times (only on the command line, not in the configuration file where it should appear only once). You can also use "--disable=all" to disable everything first and then re-enable specific checks. For example, if you want to run only the similarities checker, you can use "--disable=all --enable=similarities". If you want to run only the classes checker, but have no Warning level messages displayed, use "--disable=all --enable=classes --disable=W".

Default: ()

--enable

Enable the message, report, category or checker with the given id(s). You can either give multiple identifier separated by comma (,) or put this option multiple time (only on the command line, not in the configuration file where it should appear only once). See also the "--disable" option for examples.

Default: ()

--evaluation

Python expression which should return a score less than or equal to 10. You have access to the variables 'fatal', 'error', 'warning', 'refactor', 'convention', and 'info' which contain the number of messages in each category, as well as 'statement' which is the total number of statements analyzed. This score is used by the global evaluation report (RP0004).

Default: max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))

--exit-zero

Always return a 0 (non-error) status code, even if lint errors are found. This is primarily useful in continuous integration scripts.

Default: False

--extension-pkg-allow-list

A comma-separated list of package or module names from where C extensions may be loaded. Extensions are loading into the active Python interpreter and may run arbitrary code.

Default: []

--extension-pkg-whitelist

A comma-separated list of package or module names from where C extensions may be loaded. Extensions are loading into the active Python interpreter and may run arbitrary code. (This is an alternative name to extension-pkg-allow-list for backward compatibility.)

Default: []

--fail-on

Return non-zero exit code if any of these messages/categories are detected, even if score is above --fail-under value. Syntax same as enable. Messages specified are enabled, while categories only check already-enabled messages.

Default: ""

--fail-under

Specify a score threshold under which the program will exit with error.

Default: 10

--from-stdin

Interpret the stdin as a python script, whose filename needs to be passed as the module_or_package argument.

Default: False

--ignore

Files or directories to be skipped. They should be base names, not paths.

Default: ('CVS',)

--ignore-paths

Add files or directories matching the regular expressions patterns to the ignore-list. The regex matches against paths and can be in Posix or Windows format. Because '' represents the directory delimiter on Windows systems, it can't be used as an escape character.

Default: []

--ignore-patterns

Files or directories matching the regular expression patterns are skipped. The regex matches against base names, not paths. The default value ignores Emacs file locks

Default: (re.compile('^\\.#'),)

--ignored-modules

List of module names for which member attributes should not be checked (useful for modules/projects where namespaces are manipulated during runtime and thus existing member attributes cannot be deduced by static analysis). It supports qualified module names, as well as Unix pattern matching.

Default: ()

--jobs

Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the number of processors available to use, and will cap the count on Windows to avoid hangs.

Default: 1

--limit-inference-results

Control the amount of potential inferred values when inferring a single object. This can help the performance when dealing with large functions or complex, nested conditions.

Default: 100

--load-plugins

List of plugins (as comma separated values of python module names) to load, usually to register additional checkers.

Default: ()

--msg-template

Template used to display messages. This is a python new-style format string used to format the message information. See doc for all details.

Default: ""

--output-format

Set the output format. Available formats are text, parseable, colorized, json and msvs (visual studio). You can also give a reporter class, e.g. mypackage.mymodule.MyReporterClass.

Default: text

--persistent

Pickle collected data for later comparisons.

Default: True

--py-version

Minimum Python version to use for version dependent checks. Will default to the version used to run pylint.

Default: (3, 10)

--recursive

Discover python modules and packages in the file system subtree.

Default: False

--reports

Tells whether to display a full report or only the messages.

Default: False

--score

Activate the evaluation score.

Default: True

--suggestion-mode

When enabled, pylint would attempt to guess common misconfiguration and emit user-friendly hints instead of false-positive error messages.

Default: True

--unsafe-load-any-extension

Allow loading of arbitrary C extensions. Extensions are imported into the active Python interpreter and may run arbitrary code.

Default: False

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.main]
analyse-fallback-blocks = false
confidence = ["HIGH", "CONTROL_FLOW", "INFERENCE", "INFERENCE_FAILURE", "UNDEFINED"]
# disable =
# enable =
evaluation = "max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))"
exit-zero = false
extension-pkg-allow-list = []
extension-pkg-whitelist = []
fail-on = []
fail-under = 10
from-stdin = false
ignore = ["CVS"]
ignore-paths = []
ignore-patterns = ["^\\.#"]
ignored-modules = []
jobs = 1
limit-inference-results = 100
load-plugins = []
msg-template = ""
# output-format =
persistent = true
py-version = [3, 10]
recursive = false
reports = false
score = true
suggestion-mode = true
unsafe-load-any-extension = false

Basic Checker

--argument-naming-style

Naming style matching correct argument names.

Default: snake_case

--argument-rgx

Regular expression matching correct argument names. Overrides argument-naming-style. If left empty, argument names will be checked with the set naming style.

Default: None

--attr-naming-style

Naming style matching correct attribute names.

Default: snake_case

--attr-rgx

Regular expression matching correct attribute names. Overrides attr-naming-style. If left empty, attribute names will be checked with the set naming style.

Default: None

--bad-names

Bad variable names which should always be refused, separated by a comma.

Default: ('foo', 'bar', 'baz', 'toto', 'tutu', 'tata')

--bad-names-rgxs

Bad variable names regexes, separated by a comma. If names match any regex, they will always be refused

Default: ""

--class-attribute-naming-style

Naming style matching correct class attribute names.

Default: any

--class-attribute-rgx

Regular expression matching correct class attribute names. Overrides class-attribute-naming-style. If left empty, class attribute names will be checked with the set naming style.

Default: None

--class-const-naming-style

Naming style matching correct class constant names.

Default: UPPER_CASE

--class-const-rgx

Regular expression matching correct class constant names. Overrides class-const-naming-style. If left empty, class constant names will be checked with the set naming style.

Default: None

--class-naming-style

Naming style matching correct class names.

Default: PascalCase

--class-rgx

Regular expression matching correct class names. Overrides class-naming-style. If left empty, class names will be checked with the set naming style.

Default: None

--const-naming-style

Naming style matching correct constant names.

Default: UPPER_CASE

--const-rgx

Regular expression matching correct constant names. Overrides const-naming-style. If left empty, constant names will be checked with the set naming style.

Default: None

--docstring-min-length

Minimum line length for functions/classes that require docstrings, shorter ones are exempt.

Default: -1

--function-naming-style

Naming style matching correct function names.

Default: snake_case

--function-rgx

Regular expression matching correct function names. Overrides function-naming-style. If left empty, function names will be checked with the set naming style.

Default: None

--good-names

Good variable names which should always be accepted, separated by a comma.

Default: ('i', 'j', 'k', 'ex', 'Run', '_')

--good-names-rgxs

Good variable names regexes, separated by a comma. If names match any regex, they will always be accepted

Default: ""

--include-naming-hint

Include a hint for the correct naming format with invalid-name.

Default: False

--inlinevar-naming-style

Naming style matching correct inline iteration names.

Default: any

--inlinevar-rgx

Regular expression matching correct inline iteration names. Overrides inlinevar-naming-style. If left empty, inline iteration names will be checked with the set naming style.

Default: None

--method-naming-style

Naming style matching correct method names.

Default: snake_case

--method-rgx

Regular expression matching correct method names. Overrides method-naming-style. If left empty, method names will be checked with the set naming style.

Default: None

--module-naming-style

Naming style matching correct module names.

Default: snake_case

--module-rgx

Regular expression matching correct module names. Overrides module-naming-style. If left empty, module names will be checked with the set naming style.

Default: None

--name-group

Colon-delimited sets of names that determine each other's naming style when the name regexes allow several styles.

Default: ()

--no-docstring-rgx

Regular expression which should only match function or class names that do not require a docstring.

Default: re.compile('^_')

--property-classes

List of decorators that produce properties, such as abc.abstractproperty. Add to this list to register other decorators that produce valid properties. These decorators are taken in consideration only for invalid-name.

Default: ('abc.abstractproperty',)

--typevar-rgx

Regular expression matching correct type variable names. If left empty, type variable names will be checked with the set naming style.

Default: None

--variable-naming-style

Naming style matching correct variable names.

Default: snake_case

--variable-rgx

Regular expression matching correct variable names. Overrides variable-naming-style. If left empty, variable names will be checked with the set naming style.

Default: None

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.basic]
argument-naming-style = "snake_case"
# argument-rgx =
attr-naming-style = "snake_case"
# attr-rgx =
bad-names = ["foo", "bar", "baz", "toto", "tutu", "tata"]
bad-names-rgxs = []
class-attribute-naming-style = "any"
# class-attribute-rgx =
class-const-naming-style = "UPPER_CASE"
# class-const-rgx =
class-naming-style = "PascalCase"
# class-rgx =
const-naming-style = "UPPER_CASE"
# const-rgx =
docstring-min-length = -1
function-naming-style = "snake_case"
# function-rgx =
good-names = ["i", "j", "k", "ex", "Run", "_"]
good-names-rgxs = []
include-naming-hint = false
inlinevar-naming-style = "any"
# inlinevar-rgx =
method-naming-style = "snake_case"
# method-rgx =
module-naming-style = "snake_case"
# module-rgx =
name-group = []
no-docstring-rgx = "^_"
property-classes = ["abc.abstractproperty"]
# typevar-rgx =
variable-naming-style = "snake_case"
# variable-rgx =

Classes Checker

--check-protected-access-in-special-methods

Warn about protected attribute access inside special methods

Default: False

--defining-attr-methods

List of method names used to declare (i.e. assign) instance attributes.

Default: ('__init__', '__new__', 'setUp', '__post_init__')

--exclude-protected

List of member names, which should be excluded from the protected access warning.

Default: ('_asdict', '_fields', '_replace', '_source', '_make')

--valid-classmethod-first-arg

List of valid names for the first argument in a class method.

Default: ('cls',)

--valid-metaclass-classmethod-first-arg

List of valid names for the first argument in a metaclass class method.

Default: ('cls',)

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.classes]
check-protected-access-in-special-methods = false
defining-attr-methods = ["__init__", "__new__", "setUp", "__post_init__"]
exclude-protected = ["_asdict", "_fields", "_replace", "_source", "_make"]
valid-classmethod-first-arg = ["cls"]
valid-metaclass-classmethod-first-arg = ["cls"]

Design Checker

--exclude-too-few-public-methods

List of regular expressions of class ancestor names to ignore when counting public methods (see R0903)

Default: []

--ignored-parents

List of qualified class names to ignore when counting class parents (see R0901)

Default: ()

--max-args

Maximum number of arguments for function / method.

Default: 5

--max-attributes

Maximum number of attributes for a class (see R0902).

Default: 7

--max-bool-expr

Maximum number of boolean expressions in an if statement (see R0916).

Default: 5

--max-branches

Maximum number of branch for function / method body.

Default: 12

--max-complexity

McCabe complexity cyclomatic threshold

Default: 10

--max-locals

Maximum number of locals for function / method body.

Default: 15

--max-parents

Maximum number of parents for a class (see R0901).

Default: 7

--max-public-methods

Maximum number of public methods for a class (see R0904).

Default: 20

--max-returns

Maximum number of return / yield for function / method body.

Default: 6

--max-statements

Maximum number of statements in function / method body.

Default: 50

--min-public-methods

Minimum number of public methods for a class (see R0903).

Default: 2

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.design]
exclude-too-few-public-methods = []
ignored-parents = []
max-args = 5
max-attributes = 7
max-bool-expr = 5
max-branches = 12
max-complexity = 10
max-locals = 15
max-parents = 7
max-public-methods = 20
max-returns = 6
max-statements = 50
min-public-methods = 2

Method_args Checker

--timeout-methods

List of qualified names (i.e., library.method) which require a timeout parameter e.g. 'requests.api.get,requests.api.post'

Default: ('requests.api.delete', 'requests.api.get', 'requests.api.head', 'requests.api.options', 'requests.api.patch', 'requests.api.post', 'requests.api.put', 'requests.api.request')

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.method_args]
timeout-methods = ["requests.api.delete", "requests.api.get", "requests.api.head", "requests.api.options", "requests.api.patch", "requests.api.post", "requests.api.put", "requests.api.request"]

Exceptions Checker

--overgeneral-exceptions

Exceptions that will emit a warning when caught.

Default: ('BaseException', 'Exception')

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.exceptions]
overgeneral-exceptions = ["BaseException", "Exception"]

Format Checker

--expected-line-ending-format

Expected format of line ending, e.g. empty (any line ending), LF or CRLF.

Default: ""

--ignore-long-lines

Regexp for a line that is allowed to be longer than the limit.

Default: ^\s*(# )?<?https?://\S+>?$

--indent-after-paren

Number of spaces of indent required inside a hanging or continued line.

Default: 4

--indent-string

String used as indentation unit. This is usually " " (4 spaces) or "t" (1 tab).

Default: `` ``

--max-line-length

Maximum number of characters on a single line.

Default: 100

--max-module-lines

Maximum number of lines in a module.

Default: 1000

--single-line-class-stmt

Allow the body of a class to be on the same line as the declaration if body contains single statement.

Default: False

--single-line-if-stmt

Allow the body of an if to be on the same line as the test if there is no else.

Default: False

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.format]
expected-line-ending-format = ""
ignore-long-lines = "^\\s*(# )?<?https?://\\S+>?$"
indent-after-paren = 4
indent-string = "    "
max-line-length = 100
max-module-lines = 1000
single-line-class-stmt = false
single-line-if-stmt = false

Imports Checker

--allow-any-import-level

List of modules that can be imported at any level, not just the top level one.

Default: ()

--allow-wildcard-with-all

Allow wildcard imports from modules that define __all__.

Default: False

--deprecated-modules

Deprecated modules which should not be used, separated by a comma.

Default: ()

--ext-import-graph

Output a graph (.gv or any supported image format) of external dependencies to the given file (report RP0402 must not be disabled).

Default: ""

--import-graph

Output a graph (.gv or any supported image format) of all (i.e. internal and external) dependencies to the given file (report RP0402 must not be disabled).

Default: ""

--int-import-graph

Output a graph (.gv or any supported image format) of internal dependencies to the given file (report RP0402 must not be disabled).

Default: ""

--known-standard-library

Force import order to recognize a module as part of the standard compatibility libraries.

Default: ()

--known-third-party

Force import order to recognize a module as part of a third party library.

Default: ('enchant',)

--preferred-modules

Couples of modules and preferred modules, separated by a comma.

Default: ()

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.imports]
allow-any-import-level = []
allow-wildcard-with-all = false
deprecated-modules = []
ext-import-graph = ""
import-graph = ""
int-import-graph = ""
known-standard-library = []
known-third-party = ["enchant"]
preferred-modules = []

Logging Checker

--logging-format-style

The type of string formatting that logging methods do. `old` means using % formatting, `new` is for `{}` formatting.

Default: old

--logging-modules

Logging modules to check that the string format arguments are in logging function parameter format.

Default: ('logging',)

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.logging]
logging-format-style = "old"
logging-modules = ["logging"]

Miscellaneous Checker

--notes

List of note tags to take in consideration, separated by a comma.

Default: ('FIXME', 'XXX', 'TODO')

--notes-rgx

Regular expression of note tags to take in consideration.

Default: ""

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.miscellaneous]
notes = ["FIXME", "XXX", "TODO"]
notes-rgx = ""

Refactoring Checker

--max-nested-blocks

Maximum number of nested blocks for function / method body

Default: 5

--never-returning-functions

Complete name of functions that never returns. When checking for inconsistent-return-statements if a never returning function is called then it will be considered as an explicit return statement and no message will be printed.

Default: ('sys.exit', 'argparse.parse_error')

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.refactoring]
max-nested-blocks = 5
never-returning-functions = ["sys.exit", "argparse.parse_error"]

Similarities Checker

--ignore-comments

Comments are removed from the similarity computation

Default: True

--ignore-docstrings

Docstrings are removed from the similarity computation

Default: True

--ignore-imports

Imports are removed from the similarity computation

Default: True

--ignore-signatures

Signatures are removed from the similarity computation

Default: True

--min-similarity-lines

Minimum lines number of a similarity.

Default: 4

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.similarities]
ignore-comments = true
ignore-docstrings = true
ignore-imports = true
ignore-signatures = true
min-similarity-lines = 4

Spelling Checker

--max-spelling-suggestions

Limits count of emitted suggestions for spelling mistakes.

Default: 4

--spelling-dict

Spelling dictionary name. Available dictionaries: none. To make it work, install the 'python-enchant' package.

Default: ""

--spelling-ignore-comment-directives

List of comma separated words that should be considered directives if they appear at the beginning of a comment and should not be checked.

Default: fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:

--spelling-ignore-words

List of comma separated words that should not be checked.

Default: ""

--spelling-private-dict-file

A path to a file that contains the private dictionary; one word per line.

Default: ""

--spelling-store-unknown-words

Tells whether to store unknown words to the private dictionary (see the --spelling-private-dict-file option) instead of raising a message.

Default: n

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.spelling]
max-spelling-suggestions = 4
spelling-dict = ""
spelling-ignore-comment-directives = "fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:"
spelling-ignore-words = ""
spelling-private-dict-file = ""
spelling-store-unknown-words = false

String Checker

--check-quote-consistency

This flag controls whether inconsistent-quotes generates a warning when the character used as a quote delimiter is used inconsistently within a module.

Default: False

--check-str-concat-over-line-jumps

This flag controls whether the implicit-str-concat should generate a warning on implicit string concatenation in sequences defined over several lines.

Default: False

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.string]
check-quote-consistency = false
check-str-concat-over-line-jumps = false

Typecheck Checker

--contextmanager-decorators

List of decorators that produce context managers, such as contextlib.contextmanager. Add to this list to register other decorators that produce valid context managers.

Default: ['contextlib.contextmanager']

--generated-members

List of members which are set dynamically and missed by pylint inference system, and so shouldn't trigger E1101 when accessed. Python regular expressions are accepted.

Default: ()

--ignore-mixin-members

Tells whether missing members accessed in mixin class should be ignored. A class is considered mixin if its name matches the mixin-class-rgx option.

Default: True

--ignore-none

Tells whether to warn about missing members when the owner of the attribute is inferred to be None.

Default: True

--ignore-on-opaque-inference

This flag controls whether pylint should warn about no-member and similar checks whenever an opaque object is returned when inferring. The inference can return multiple potential results while evaluating a Python object, but some branches might not be evaluated, which results in partial inference. In that case, it might be useful to still emit no-member and other checks for the rest of the inferred objects.

Default: True

--ignored-checks-for-mixins

List of symbolic message names to ignore for Mixin members.

Default: ['no-member', 'not-async-context-manager', 'not-context-manager', 'attribute-defined-outside-init']

--ignored-classes

List of class names for which member attributes should not be checked (useful for classes with dynamically set attributes). This supports the use of qualified names.

Default: ('optparse.Values', 'thread._local', '_thread._local', 'argparse.Namespace')

--missing-member-hint

Show a hint with possible names when a member name was not found. The aspect of finding the hint is based on edit distance.

Default: True

--missing-member-hint-distance

The minimum edit distance a name should have in order to be considered a similar match for a missing member name.

Default: 1

--missing-member-max-choices

The total number of similar names that should be taken in consideration when showing a hint for a missing member.

Default: 1

--mixin-class-rgx

Regex pattern to define which classes are considered mixins.

Default: .*[Mm]ixin

--signature-mutators

List of decorators that change the signature of a decorated function.

Default: []

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.typecheck]
contextmanager-decorators = ["contextlib.contextmanager"]
generated-members = []
ignore-mixin-members = true
ignore-none = true
ignore-on-opaque-inference = true
ignored-checks-for-mixins = ["no-member", "not-async-context-manager", "not-context-manager", "attribute-defined-outside-init"]
ignored-classes = ["optparse.Values", "thread._local", "_thread._local", "argparse.Namespace"]
missing-member-hint = true
missing-member-hint-distance = 1
missing-member-max-choices = 1
mixin-class-rgx = ".*[Mm]ixin"
signature-mutators = []

Variables Checker

--additional-builtins

List of additional names supposed to be defined in builtins. Remember that you should avoid defining new builtins when possible.

Default: ()

--allow-global-unused-variables

Tells whether unused global variables should be treated as a violation.

Default: True

--allowed-redefined-builtins

List of names allowed to shadow builtins

Default: ()

--callbacks

List of strings which can identify a callback function by name. A callback name must start or end with one of those strings.

Default: ('cb_', '_cb')

--dummy-variables-rgx

A regular expression matching the name of dummy variables (i.e. expected to not be used).

Default: _+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_

--ignored-argument-names

Argument names that match this expression will be ignored.

Default: re.compile('_.*|^ignored_|^unused_')

--init-import

Tells whether we should check for unused import in __init__ files.

Default: False

--redefining-builtins-modules

List of qualified module names which can have objects that can redefine builtins.

Default: ('six.moves', 'past.builtins', 'future.builtins', 'builtins', 'io')

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.variables]
additional-builtins = []
allow-global-unused-variables = true
allowed-redefined-builtins = []
callbacks = ["cb_", "_cb"]
dummy-variables-rgx = "_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_"
ignored-argument-names = "_.*|^ignored_|^unused_"
init-import = false
redefining-builtins-modules = ["six.moves", "past.builtins", "future.builtins", "builtins", "io"]

Broad_try_clause Checker

--max-try-statements

Maximum number of statements allowed in a try clause

Default: 1

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.broad_try_clause]
max-try-statements = 1

Code_style Checker

--max-line-length-suggestions

Max line length for which to sill emit suggestions. Used to prevent optional suggestions which would get split by a code formatter (e.g., black). Will default to the setting for ``max-line-length``.

Default: 0

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.code_style]
max-line-length-suggestions = 0

Deprecated_builtins Checker

--bad-functions

List of builtins function names that should not be used, separated by a comma

Default: ['map', 'filter']

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.deprecated_builtins]
bad-functions = ["map", "filter"]

Parameter_documentation Checker

--accept-no-param-doc

Whether to accept totally missing parameter documentation in the docstring of a function that has parameters.

Default: True

--accept-no-raise-doc

Whether to accept totally missing raises documentation in the docstring of a function that raises an exception.

Default: True

--accept-no-return-doc

Whether to accept totally missing return documentation in the docstring of a function that returns a statement.

Default: True

--accept-no-yields-doc

Whether to accept totally missing yields documentation in the docstring of a generator.

Default: True

--default-docstring-type

If the docstring type cannot be guessed the specified docstring type will be used.

Default: default

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.parameter_documentation]
accept-no-param-doc = true
accept-no-raise-doc = true
accept-no-return-doc = true
accept-no-yields-doc = true
default-docstring-type = "default"

Typing Checker

--runtime-typing

Set to ``no`` if the app / library does **NOT* need to support runtime introspection of type annotations. If you use type annotations exclusively for type checking of an application, you're probably fine. For libraries, evaluate if some users want to access the type hints at runtime first, e.g., through typing.get_type_hints. Applies to Python versions 3.7 - 3.9*

Default: True

Note: Only tool.pylint is required, the section title is not. These are the default values.

[tool.pylint.typing]
runtime-typing = true

Pylint checkers can provide three set of features:

  • options that control their execution,
  • messages that they can raise,
  • reports that they can generate.

Below is a list of all checkers and their features.

Verbatim name of the checker is async.

Async context manager '%s' doesn't implement __aenter__ and __aexit__. Used when an async context manager is used with an object that does not implement the async context management protocol. This message can't be emitted when using Python < 3.5.
Yield inside async function Used when an yield or yield from statement is found inside an async function. This message can't be emitted when using Python < 3.5.

Verbatim name of the checker is basic.

See also basic checker's options' documentation

%r not properly in loop Used when break or continue keywords are used outside a loop.
%s already defined line %s Used when a function / class / method is redefined.
'continue' not supported inside 'finally' clause Emitted when the continue keyword is found inside a finally clause, which is a SyntaxError.
Abstract class %r with abstract methods instantiated Used when an abstract class with abc.ABCMeta as metaclass has abstract methods and is instantiated.
Can use starred expression only in assignment target Emitted when a star expression is not used in an assignment target.
Duplicate argument name %s in function definition Duplicate argument names in function definitions are syntax errors.
Explicit return in __init__ Used when the special class method __init__ has an explicit return value.
More than one starred expression in assignment Emitted when there are more than one starred expressions (*x) in an assignment. This is a SyntaxError.
Name %r is nonlocal and global Emitted when a name is both nonlocal and global.
Name %r is used prior to global declaration Emitted when a name is used prior a global declaration, which results in an error since Python 3.6. This message can't be emitted when using Python < 3.6.
Return outside function Used when a "return" statement is found outside a function or method.
Return with argument inside generator Used when a "return" statement with an argument is found outside in a generator function or method (e.g. with some "yield" statements). This message can't be emitted when using Python >= 3.3.
Starred assignment target must be in a list or tuple Emitted when a star expression is used as a starred assignment target.
The first reversed() argument is not a sequence Used when the first argument to reversed() builtin isn't a sequence (does not implement __reversed__, nor __getitem__ and __len__
Use of the non-existent %s operator Used when you attempt to use the C-style pre-increment or pre-decrement operator -- and ++, which doesn't exist in Python.
Yield outside function Used when a "yield" statement is found outside a function or method.
__init__ method is a generator Used when the special class method __init__ is turned into a generator by a yield in its body.
format function is not called on str Emitted when format function is not called on str object. e.g doing print("value: {}").format(123) instead of print("value: {}".format(123)). This might not be what the user intended to do.
nonlocal name %s found without binding Emitted when a nonlocal variable does not have an attached name somewhere in the parent scopes
%s statement in finally block may swallow exception Used when a break or a return statement is found inside the finally clause of a try...finally block: the exceptions raised in the try clause will be silently swallowed instead of being re-raised.
Assert called on a 2-item-tuple. Did you mean 'assert x,y'? A call of assert on a tuple will always evaluate to true if the tuple is not empty, and will always evaluate to false if it is.
Assert statement has a string literal as its first argument. The assert will %s fail. Used when an assert statement has a string literal as its first argument, which will cause the assert to always pass.
Assigning the same variable %r to itself Emitted when we detect that a variable is assigned to itself
Comparing against a callable, did you omit the parenthesis? This message is emitted when pylint detects that a comparison with a callable was made, which might suggest that some parenthesis were omitted, resulting in potential unwanted behaviour.
Comparison %s should be %s Used when an expression is compared to NaN values like numpy.NaN and float('nan').
Dangerous default value %s as argument Used when a mutable value as list or dictionary is detected in a default value for an argument.
Duplicate key %r in dictionary Used when a dictionary expression binds the same key multiple times.
Duplicate value %r in set This message is emitted when a set contains the same value two or more times.
Else clause on loop without a break statement, remove the else and de-indent all the code inside it Loops should only have an else clause if they can exit early with a break statement, otherwise the statements under else should be on the same scope as the loop itself.
Expression "%s" is assigned to nothing Used when an expression that is not a function call is assigned to nothing. Probably something else was intended.
Following "as" with another context manager looks like a tuple. Emitted when a with statement component returns multiple values and uses name binding with as only for a part of those values, as in with ctx() as a, b. This can be misleading, since it's not clear if the context manager returns a tuple or if the node without a name binding is another context manager.
Lambda may not be necessary Used when the body of a lambda expression is a function call on the same argument list as the lambda itself; such lambda expressions are in all but a few cases replaceable with the function being called in the body of the lambda.
Redeclared variable %r in assignment Emitted when we detect that a variable was redeclared in the same assignment.
Statement seems to have no effect Used when a statement doesn't have (or at least seems to) any effect.
String statement has no effect Used when a string is used as a statement (which of course has no effect). This is a particular case of W0104 with its own message so you can easily disable it if you're using those strings as documentation, instead of comments.
Unnecessary pass statement Used when a "pass" statement that can be avoided is encountered.
Unreachable code Used when there is some code behind a "return" or "raise" statement, which will never be accessed.
Use of eval Used when you use the "eval" function, to discourage its usage. Consider using ast.literal_eval for safely evaluating strings containing Python expressions from untrusted sources.
Use of exec Raised when the 'exec' statement is used. It's dangerous to use this function for a user input, and it's also slower than actual code in general. This doesn't mean you should never use it, but you should consider alternatives first and restrict the functions available.
Using a conditional statement with a constant value Emitted when a conditional statement (If or ternary if) uses a constant value for its test. This might not be what the user intended to do.
Using a conditional statement with potentially wrong function or method call due to missing parentheses Emitted when a conditional statement (If or ternary if) seems to wrongly call a function due to missing parentheses
Comparison between constants: '%s %s %s' has a constant value When two literals are compared with each other the result is a constant. Using the constant directly is both easier to read and more performant. Initializing 'True' and 'False' this way is not required since Python 2.3.
In '%s', use '%s' when comparing constant literals not '%s' ('%s') Used when comparing an object to a literal, which is usually what you do not want to do, since you can compare to a different literal than what was expected altogether.
Redundant comparison - %s Used when something is compared against itself.
%s name "%s" doesn't conform to %s Used when the name doesn't conform to naming rules associated to its type (constant, variable, class...).
Comparison %s should be %s Used when an expression is compared to singleton values like True, False or None.
Disallowed name "%s" Used when the name matches bad-names or bad-names-rgxs- (unauthorized names).
Empty %s docstring Used when a module, function, class or method has an empty docstring (it would be too easy ;).
Missing class docstring Used when a class has no docstring. Even an empty class must have a docstring.
Missing function or method docstring Used when a function or method has no docstring. Some special methods like __init__ do not require a docstring.
Missing module docstring Used when a module has no docstring. Empty modules do not require a docstring.
Type variable name does not reflect variance%s Emitted when a TypeVar name doesn't reflect its type variance. According to PEP8, it is recommended to add suffixes '_co' and '_contra' to the variables used to declare covariant or contravariant behaviour respectively. Invariant (default) variables do not require a suffix. The message is also emitted when invariant variables do have a suffix.
TypeVar cannot be both covariant and contravariant Emitted when both the "covariant" and "contravariant" keyword arguments are set to "True" in a TypeVar.
TypeVar name "%s" does not match assigned variable name "%s" Emitted when a TypeVar is assigned to a variable that does not match its name argument.
Use isinstance() rather than type() for a typecheck. The idiomatic way to perform an explicit typecheck in Python is to use isinstance(x, Y) rather than type(x) == Y, type(x) is Y. Though there are unusual situations where these give different results.

Statistics by type

Verbatim name of the checker is classes.

See also classes checker's options' documentation

Access to member %r before its definition line %s Used when an instance member is accessed before it's actually assigned.
An attribute defined in %s line %s hides this method Used when a class defines a method which is hidden by an instance attribute from an ancestor class or set by some client code.
Assigning to attribute %r not defined in class slots Used when assigning to an attribute not defined in the class slots.
Duplicate bases for class %r Duplicate use of base classes in derived classes raise TypeErrors.
Extending inherited Enum class "%s" Used when a class tries to extend an inherited Enum class. Doing so will raise a TypeError at runtime.
Inconsistent method resolution order for class %r Used when a class has an inconsistent method resolution order.
Inheriting %r, which is not a class. Used when a class inherits from something which is not a class.
Invalid __class__ object Used when an invalid object is assigned to a __class__ property. Only a class is permitted.
Invalid __slots__ object Used when an invalid __slots__ is found in class. Only a string, an iterable or a sequence is permitted.
Invalid object %r in __slots__, must contain only non empty strings Used when an invalid (non-string) object occurs in __slots__.
Method %r has no argument Used when a method which should have the bound instance as first argument has no argument defined.
Method %r should have "self" as first argument Used when a method has an attribute different the "self" as first argument. This is considered as an error since this is a so common convention that you shouldn't break it!
The special method %r expects %s param(s), %d %s given Emitted when a special method was defined with an invalid number of parameters. If it has too few or too many, it might not work at all.
Value %r in slots conflicts with class variable Used when a value in __slots__ conflicts with a class variable, property or method.
__bool__ does not return bool Used when a __bool__ method returns something which is not a bool
__bytes__ does not return bytes Used when a __bytes__ method returns something which is not bytes
__format__ does not return str Used when a __format__ method returns something which is not a string
__getnewargs__ does not return a tuple Used when a __getnewargs__ method returns something which is not a tuple
__getnewargs_ex__ does not return a tuple containing (tuple, dict) Used when a __getnewargs_ex__ method returns something which is not of the form tuple(tuple, dict)
__hash__ does not return int Used when a __hash__ method returns something which is not an integer
__index__ does not return int Used when an __index__ method returns something which is not an integer
__iter__ returns non-iterator Used when an __iter__ method returns something which is not an iterable (i.e. has no __next__ method)
__len__ does not return non-negative integer Used when a __len__ method returns something which is not a non-negative integer
__length_hint__ does not return non-negative integer Used when a __length_hint__ method returns something which is not a non- negative integer
__repr__ does not return str Used when a __repr__ method returns something which is not a string
__str__ does not return str Used when a __str__ method returns something which is not a string
%s %s %r method Used when a method has a different number of arguments than in the implemented interface or in an overridden method. Extra arguments with default values are ignored.
%s %s %r method Used when a method parameter has a different name than in the implemented interface or in an overridden method.
Access to a protected member %s of a client class Used when a protected member (i.e. class member with a name beginning with an underscore) is access outside the class or a descendant of the class where it's defined.
Attribute %r defined outside __init__ Used when an instance attribute is defined outside the __init__ method.
Class %r is a subclass of a class decorated with typing.final: %r Used when a class decorated with typing.final has been subclassed.
Method %r is abstract in class %r but is not overridden Used when an abstract method (i.e. raise NotImplementedError) is not overridden in concrete class.
Method %r overrides a method decorated with typing.final which is defined in class %r Used when a method decorated with typing.final has been overridden.
Method %r was expected to be %r, found it instead as %r Used when we detect that a method was overridden in a way that does not match its base class which could result in potential bugs at runtime.
Redefined slots %r in subclass Used when a slot is re-defined in a subclass.
Signature differs from %s %r method Used when a method signature is different than in the implemented interface or in an overridden method.
Static method with %r as first argument Used when a static method has "self" or a value specified in valid- classmethod-first-arg option or valid-metaclass-classmethod-first-arg option as first argument.
Super call without brackets Used when a call to super does not have brackets and thus is not an actual call and does not work as expected.
Unused private member `%s.%s` Emitted when a private member of a class is defined but not used.
Useless parent or super() delegation in method %r Used whenever we can detect that an overridden method is useless, relying on parent or super() delegation to do the same thing as another method from the MRO.
__init__ method from a non direct base class %r is called Used when an __init__ method is called on a class which is not in the direct ancestors for the analysed class.
__init__ method from base class %r is not called Used when an ancestor class method has an __init__ method which is not called by a derived class.
Cannot have defined parameters for properties Used when we detect that a property also has parameters, which are useless, given that properties cannot be called with additional arguments.
Class %r inherits from object, can be safely removed from bases in python3 Used when a class inherit from object, which under python3 is implicit, hence can be safely removed from bases.
Consider using a decorator instead of calling classmethod Used when a class method is defined without using the decorator syntax.
Consider using a decorator instead of calling staticmethod Used when a static method is defined without using the decorator syntax.
Class __slots__ should be a non-string iterable Used when a class __slots__ is a simple string, rather than an iterable.
Class method %s should have %s as first argument Used when a class method has a first argument named differently than the value specified in valid-classmethod-first-arg option (default to "cls"), recommended to easily differentiate them from regular instance methods.
Metaclass class method %s should have %s as first argument Used when a metaclass class method has a first argument named differently than the value specified in valid-metaclass-classmethod-first-arg option (default to "mcs"), recommended to easily differentiate them from regular instance methods.
Metaclass method %s should have %s as first argument Used when a metaclass method has a first argument named differently than the value specified in valid-classmethod-first-arg option (default to "cls"), recommended to easily differentiate them from regular instance methods.
Unable to check methods signature (%s / %s) Used when Pylint has been unable to check methods signature compatibility for an unexpected reason. Please report this kind if you don't make sense of it.

Design checker

Verbatim name of the checker is design.

See also design checker's options' documentation

Design checker Messages

Too few public methods (%s/%s) Used when class has too few public methods, so be sure it's really worth it.
Too many ancestors (%s/%s) Used when class has too many parent classes, try to reduce this to get a simpler (and so easier to use) class.
Too many arguments (%s/%s) Used when a function or method takes too many arguments.
Too many boolean expressions in if statement (%s/%s) Used when an if statement contains too many boolean expressions.
Too many branches (%s/%s) Used when a function or method has too many branches, making it hard to follow.
Too many instance attributes (%s/%s) Used when class has too many instance attributes, try to reduce this to get a simpler (and so easier to use) class.
Too many local variables (%s/%s) Used when a function or method has too many local variables.
Too many public methods (%s/%s) Used when class has too many public methods, try to reduce this to get a simpler (and so easier to use) class.
Too many return statements (%s/%s) Used when a function or method has too many return statement, making it hard to follow.
Too many statements (%s/%s) Used when a function or method has too many statements. You should then split it in smaller functions / methods.

Verbatim name of the checker is exceptions.

See also exceptions checker's options' documentation

Bad except clauses order (%s) Used when except clauses are not in the correct order (from the more specific to the more generic). If you don't fix the order, some exceptions may not be caught by the most specific handler.
Catching an exception which doesn't inherit from Exception: %s Used when a class which doesn't inherit from Exception is used as an exception in an except clause.
Exception cause set to something which is not an exception, nor None Used when using the syntax "raise ... from ...", where the exception cause is not an exception, nor None.
NotImplemented raised - should raise NotImplementedError Used when NotImplemented is raised instead of NotImplementedError
Raising %s while only classes or instances are allowed Used when something which is neither a class nor an instance is raised (i.e. a TypeError will be raised).
Raising a new style class which doesn't inherit from BaseException Used when a new style class which doesn't inherit from BaseException is raised.
The raise statement is not inside an except clause Used when a bare raise is not used inside an except clause. This generates an error, since there are no active exceptions to be reraised. An exception to this rule is represented by a bare raise inside a finally clause, which might work, as long as an exception is raised inside the try block, but it is nevertheless a code smell that must not be relied upon.
Catching previously caught exception type %s Used when an except catches a type that was already caught by a previous handler.
Catching too general exception %s Used when an except catches a too general exception, possibly burying unrelated errors.
Consider explicitly re-raising using %s'%s from %s' Python's exception chaining shows the traceback of the current exception, but also of the original exception. When you raise a new exception after another exception was caught it's likely that the second exception is a friendly re- wrapping of the first exception. In such cases raise from provides a better link between the two tracebacks in the final error.
Exception arguments suggest string formatting might be intended Used when passing multiple arguments to an exception constructor, the first of them a string literal containing what appears to be placeholders intended for formatting
Exception to catch is the result of a binary "%s" operation Used when the exception to catch is of the form "except A or B:". If intending to catch multiple, rewrite as "except (A, B):"
Invalid exception operation. %s Used when an operation is done against an exception, but the operation is not valid for the exception in question. Usually emitted when having binary operations between exceptions in except handlers.
No exception type(s) specified Used when an except clause doesn't specify exceptions type to catch.
The except handler raises immediately Used when an except handler uses raise as its first or only operator. This is useless because it raises back the exception immediately. Remove the raise operator or the entire try-except-raise block!

Verbatim name of the checker is format.

See also format checker's options' documentation

Bad indentation. Found %s %s, expected %s Used when an unexpected number of indentation's tabulations or spaces has been found.
Unnecessary semicolon Used when a statement is ended by a semi-colon (";"), which isn't necessary (that's python, not C ;).
Final newline missing Used when the last line in a file is missing a newline.
line-too-long (C0301)
Line too long (%s/%s) Used when a line is longer than a given number of characters.
Mixed line endings LF and CRLF Used when there are mixed (LF and CRLF) newline signs in a file.
More than one statement on a single line Used when more than on statement are found on the same line.
Too many lines in module (%s/%s) Used when a module has too many lines, reducing its readability.
Trailing newlines Used when there are trailing blank lines in a file.
Trailing whitespace Used when there is whitespace between the end of a line and the newline.
Unexpected line ending format. There is '%s' while it should be '%s'. Used when there is different newline than expected.
Unnecessary parens after %r keyword Used when a single item in parentheses follows an if, for, or other keyword.

Verbatim name of the checker is imports.

See also imports checker's options' documentation

Attempted relative import beyond top-level package Used when a relative import tries to access too many levels in the current package.
Unable to import %s Used when pylint has been unable to import a module.
Deprecated module %r A module marked as deprecated is imported.
Module import itself Used when a module is importing itself.
Prefer importing %r instead of %r Used when a module imported has a preferred replacement module.
Reimport %r (imported line %s) Used when a module is reimported multiple times.
Wildcard import %s Used when from module import * is detected.
__future__ import is not the first non docstring statement Python 2.5 and greater require __future__ import to be the first non docstring statement in the module.
Cyclic import (%s) Used when a cyclic import between two or more modules is detected.
Use 'from %s import %s' instead Emitted when a submodule of a package is imported and aliased with the same name, e.g., instead of import concurrent.futures as futures use from concurrent import futures.
%s should be placed before %s Used when PEP8 import order is not respected (standard imports first, then third-party libraries, then local imports).
Import "%s" should be placed at the top of the module Used when code and imports are mixed.
Import alias does not rename original package Used when an import alias is same as original package, e.g., using import numpy as numpy instead of import numpy as np.
Import outside toplevel (%s) Used when an import statement is used anywhere other than the module toplevel. Move this import to the top of the file.
Imports from package %s are not grouped Used when imports are not grouped by packages.
Multiple imports on one line (%s) Used when import statement importing multiple modules is detected.

External dependencies
Modules dependencies graph

Lambda-Expressions checker

Verbatim name of the checker is lambda-expressions.

Lambda-Expressions checker Messages

Lambda expression assigned to a variable. Define a function using the "def" keyword instead. Used when a lambda expression is assigned to variable rather than defining a standard function with the "def" keyword.
Lambda expression called directly. Execute the expression inline instead. Used when a lambda expression is directly called rather than executing its contents inline.

Verbatim name of the checker is logging.

See also logging checker's options' documentation

Logging format string ends in middle of conversion specifier Used when a logging statement format string terminates before the end of a conversion specifier.
Not enough arguments for logging format string Used when a logging format string is given too few arguments.
Too many arguments for logging format string Used when a logging format string is given too many arguments.
Unsupported logging format character %r (%#02x) at index %d Used when an unsupported format character is used in a logging statement format string.
Use %s formatting in logging functions Used when a logging statement has a call form of "logging.<logging method>(format_string.format(format_args...))". Use another type of string formatting instead. You can use % formatting but leave interpolation to the logging function by passing the parameters as arguments. If logging-fstring- interpolation is disabled then you can use fstring formatting. If logging- not-lazy is disabled then you can use % formatting as normal.
Use %s formatting in logging functions Used when a logging statement has a call form of "logging.<logging method>(f"...")".Use another type of string formatting instead. You can use % formatting but leave interpolation to the logging function by passing the parameters as arguments. If logging-format-interpolation is disabled then you can use str.format. If logging-not-lazy is disabled then you can use % formatting as normal.
Use %s formatting in logging functions Used when a logging statement has a call form of "logging.<logging method>(format_string % (format_args...))". Use another type of string formatting instead. You can use % formatting but leave interpolation to the logging function by passing the parameters as arguments. If logging-fstring- interpolation is disabled then you can use fstring formatting. If logging- format-interpolation is disabled then you can use str.format.

Verbatim name of the checker is method_args.

See also method_args checker's options' documentation

Missing timeout argument for method '%s' can cause your program to hang indefinitely Used when a method needs a 'timeout' parameter in order to avoid waiting for a long time. If no timeout is specified explicitly the default value is used. For example for 'requests' the program will never time out (i.e. hang indefinitely).

Verbatim name of the checker is metrics.

Raw metrics

Verbatim name of the checker is miscellaneous.

See also miscellaneous checker's options' documentation

Used when a warning note as FIXME or XXX is detected.
Used when a message is enabled or disabled by id.

Verbatim name of the checker is modified_iteration.

Iterated dict '%s' is being modified inside for loop body, iterate through a copy of it instead. Emitted when items are added or removed to a dict being iterated through. Doing so raises a RuntimeError.
Iterated set '%s' is being modified inside for loop body, iterate through a copy of it instead. Emitted when items are added or removed to a set being iterated through. Doing so raises a RuntimeError.
Iterated list '%s' is being modified inside for loop body, consider iterating through a copy of it instead. Emitted when items are added or removed to a list being iterated through. Doing so can result in unexpected behaviour, that is why it is preferred to use a copy of the list.

Verbatim name of the checker is newstyle.

Bad first argument %r given to super() Used when another argument than the current class is given as first argument of the super builtin.

Nonascii-Checker checker

Verbatim name of the checker is nonascii-checker.

Nonascii-Checker checker Messages

%s name "%s" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers, not file names. Some editors don't support non-ASCII file names properly. Even though Python supports UTF-8 files since Python 3.5 this isn't recommended for interoperability. Further reading: - https://peps.python.org/pep-0489/#export-hook-name - https://peps.python.org/pep-0672/#confusing-features - https://bugs.python.org/issue20485
%s name "%s" contains a non-ASCII character, consider renaming it. Used when the name contains at least one non-ASCII unicode character. See https://peps.python.org/pep-0672/#confusing-features for a background why this could be bad. If your programming guideline defines that you are programming in English, then there should be no need for non ASCII characters in Python Names. If not you can simply disable this check.
%s name "%s" contains a non-ASCII character, use an ASCII-only alias for import. Used when the name contains at least one non-ASCII unicode character. See https://peps.python.org/pep-0672/#confusing-features for a background why this could be bad. If your programming guideline defines that you are programming in English, then there should be no need for non ASCII characters in Python Names. If not you can simply disable this check.

Verbatim name of the checker is refactoring.

See also refactoring checker's options' documentation

Boolean condition '%s' may be simplified to '%s' Emitted when a boolean condition is able to be simplified.
Boolean condition '%s' will always evaluate to '%s' Emitted when a boolean condition can be simplified to a constant value.
Boolean expression may be simplified to %s Emitted when redundant pre-python 2.5 ternary syntax is used.
Consider merging these comparisons with 'in' by using '%s %sin (%s)'. Use a set instead if elements are hashable. To check if a variable is equal to one of many values, combine the values into a set or tuple and check if the variable is contained "in" it instead of checking for equality against each of the values. This is faster and less verbose.
Consider merging these isinstance calls to isinstance(%s, (%s)) Used when multiple consecutive isinstance calls can be merged into one.
Consider using '%s' instead of unnecessary if block Using the max builtin instead of a conditional improves readability and conciseness.
Consider using '%s' instead of unnecessary if block Using the min builtin instead of a conditional improves readability and conciseness.
Consider using 'with' for resource-allocating operations Emitted if a resource-allocating assignment or call may be replaced by a 'with' block. By using 'with' the release of the allocated resources is ensured even in the case of an exception.
Consider using Python 3 style super() without arguments Emitted when calling the super() builtin with the current class and instance. On Python 3 these arguments are the default and they can be omitted.
Consider using [] instead of list() Emitted when using list() to create an empty list instead of the literal []. The literal is faster as it avoids an additional function call.
Consider using a dictionary comprehension Emitted when we detect the creation of a dictionary using the dict() callable and a transient list. Although there is nothing syntactically wrong with this code, it is hard to read and can be simplified to a dict comprehension. Also it is faster since you don't need to create another transient list
Consider using a generator instead '%s(%s)' If your container can be large using a generator will bring better performance.
Consider using a set comprehension Although there is nothing syntactically wrong with this code, it is hard to read and can be simplified to a set comprehension. Also it is faster since you don't need to create another transient list
Consider using dict.get for getting values from a dict if a key is present or a default if not Using the builtin dict.get for getting a value from a dictionary if a key is present or a default if not, is simpler and considered more idiomatic, although sometimes a bit slower
Consider using str.join(sequence) for concatenating strings from an iterable Using str.join(sequence) is faster, uses less memory and increases readability compared to for-loop iteration.
Consider using sys.exit() Instead of using exit() or quit(), consider using the sys.exit().
Consider using ternary (%s) Used when one of known pre-python 2.5 ternary syntax is used.
Consider using tuple unpacking for swapping variables You do not have to use a temporary variable in order to swap variables. Using "tuple unpacking" to directly swap variables makes the intention more clear.
Consider using {} instead of dict() Emitted when using dict() to create an empty dictionary instead of the literal {}. The literal is faster as it avoids an additional function call.
Disallow trailing comma tuple In Python, a tuple is actually created by the comma symbol, not by the parentheses. Unfortunately, one can actually create a tuple by misplacing a trailing comma, which can lead to potential weird bugs in your code. You should always use parentheses explicitly for creating a tuple.
Do not raise StopIteration in generator, use return statement instead According to PEP479, the raise of StopIteration to end the loop of a generator may lead to hard to find bugs. This PEP specify that raise StopIteration has to be replaced by a simple return statement
Either all return statements in a function should return an expression, or none of them should. According to PEP8, if any return statement returns an expression, any return statements where no value is returned should explicitly state this as return None, and an explicit return statement should be present at the end of the function (if reachable)
Redefining argument with the local name %r Used when a local name is redefining an argument, which might suggest a potential error. This is taken in account only for a handful of name binding operations, such as for iteration, with statement assignment and exception handler assignment.
Simplify chained comparison between the operands This message is emitted when pylint encounters boolean operation like "a < b and b < c", suggesting instead to refactor it to "a < b < c"
The if expression can be replaced with %s Used when an if expression can be replaced with 'bool(test)' or simply 'test' if the boolean cast is implicit.
The if statement can be replaced with %s Used when an if statement can be replaced with 'bool(test)'.
Too many nested blocks (%s/%s) Used when a function or a method has too many nested blocks. This makes the code less understandable and maintainable.
Unnecessary "%s" after "break", %s Used in order to highlight an unnecessary block of code following an if containing a break statement. As such, it will warn when it encounters an else following a chain of ifs, all of them containing a break statement.
Unnecessary "%s" after "continue", %s Used in order to highlight an unnecessary block of code following an if containing a continue statement. As such, it will warn when it encounters an else following a chain of ifs, all of them containing a continue statement.
Unnecessary "%s" after "raise", %s Used in order to highlight an unnecessary block of code following an if containing a raise statement. As such, it will warn when it encounters an else following a chain of ifs, all of them containing a raise statement.
Unnecessary "%s" after "return", %s Used in order to highlight an unnecessary block of code following an if containing a return statement. As such, it will warn when it encounters an else following a chain of ifs, all of them containing a return statement.
Unnecessary dictionary index lookup, use '%s' instead Emitted when iterating over the dictionary items (key-item pairs) and accessing the value by index lookup. The value can be accessed directly instead.
Unnecessary list index lookup, use '%s' instead Emitted when iterating over an enumeration and accessing the value by index lookup. The value can be accessed directly instead.
Unnecessary use of a comprehension, use %s instead. Instead of using an identity comprehension, consider using the list, dict or set constructor. It is faster and simpler.
Use a generator instead '%s(%s)' Comprehension inside of 'any', 'all', 'max', 'min' or 'sum' is unnecessary. A generator would be sufficient and faster.
Useless return at end of function or method Emitted when a single "return" or "return None" statement is found at the end of function or method definition. This statement can safely be removed because Python will implicitly return None
'%s' can be simplified to '%s' as an empty sequence is falsey Used when Pylint detects that collection literal comparison is being used to check for emptiness; Use implicit booleaness instead of a collection classes; empty collections are considered as false
Consider changing "%s" to "%s" Used when a boolean expression contains an unneeded negation.
Consider iterating the dictionary directly instead of calling .keys() Emitted when the keys of a dictionary are iterated through the .keys() method or when .keys() is used for a membership check. It is enough to iterate through the dictionary itself, for key in dictionary. For membership checks, if key in dictionary is faster.
Consider iterating with .items() Emitted when iterating over the keys of a dictionary and accessing the value by index lookup. Both the key and value can be accessed by iterating using the .items() method of the dictionary instead.
Consider using enumerate instead of iterating with range and len Emitted when code that iterates with range and len is encountered. Such code can be simplified by using the enumerate builtin.
Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty Used when Pylint detects that len(sequence) is being used without explicit comparison inside a condition to determine if a sequence is empty. Instead of coercing the length to a boolean, either rely on the fact that empty sequences are false or compare the length against a scalar.
Formatting a regular string which could be a f-string Used when we detect a string that is being formatted with format() or % which could potentially be a f-string. The use of f-strings is preferred. Requires Python 3.6 and py-version >= 3.6.
Use %s instead Emitted when accessing only the first or last element of str.split(). The first and last element can be accessed by using str.split(sep, maxsplit=1)[0] or str.rsplit(sep, maxsplit=1)[-1] instead.
Use a sequence type when iterating over values When iterating over values, sequence types (e.g., lists, tuples, ranges) are more efficient than sets.

Verbatim name of the checker is similarities.

See also similarities checker's options' documentation

Similar lines in %s files Indicates that a set of similar lines has been detected among multiple file. This usually means that the code should be refactored to avoid this duplication.

Duplication

Verbatim name of the checker is spelling.

See also spelling checker's options' documentation

Invalid characters %r in a docstring Used when a word in docstring cannot be checked by enchant.
Wrong spelling of a word '%s' in a comment: Used when a word in comment is not spelled correctly.
Wrong spelling of a word '%s' in a docstring: Used when a word in docstring is not spelled correctly.

Verbatim name of the checker is stdlib.

%s does not support %s type argument Env manipulation functions support only string type arguments. See https://docs.python.org/3/library/os.html#os.getenv.
"%s" is not a valid mode for open. Python supports: r, w, a[, x] modes with b, +, and U (only with r) options. See https://docs.python.org/3/library/functions.html#open
%s default type is %s. Expected str or None. Env manipulation functions return None or str values. Supplying anything different as a default may cause bugs. See https://docs.python.org/3/library/os.html#os.getenv.
'lru_cache(maxsize=None)' or 'cache' will keep all method args alive indefinitely, including 'self' By decorating a method with lru_cache or cache the 'self' argument will be linked to the function and therefore never garbage collected. Unless your instance will never need to be garbage collected (singleton) it is recommended to refactor code to avoid this pattern or add a maxsize to the cache. The default value for maxsize is 128.
Leaving functions creating breakpoints in production code is not recommended Calls to breakpoint(), sys.breakpointhook() and pdb.set_trace() should be removed from code that is not actively being debugged.
Redundant use of %s with constant value %r The first argument of assertTrue and assertFalse is a condition. If a constant is passed as parameter, that condition will be always true. In this case a warning should be emitted.
Using copy.copy(os.environ). Use os.environ.copy() instead. os.environ is not a dict object but proxy object, so shallow copy has still effects on original object. See https://bugs.python.org/issue15373 for reference.
Using datetime.time in a boolean context. Using datetime.time in a boolean context can hide subtle bugs when the time they represent matches midnight UTC. This behaviour was fixed in Python 3.5. See https://bugs.python.org/issue13936 for reference. This message can't be emitted when using Python >= 3.5.
Using deprecated argument %s of method %s() The argument is marked as deprecated and will be removed in the future.
Using deprecated class %s of module %s The class is marked as deprecated and will be removed in the future.
Using deprecated decorator %s() The decorator is marked as deprecated and will be removed in the future.
Using deprecated method %s() The method is marked as deprecated and will be removed in the future.
Using open without explicitly specifying an encoding It is better to specify an encoding when opening documents. Using the system default implicitly can create problems on other operating systems. See https://peps.python.org/pep-0597/
Using preexec_fn keyword which may be unsafe in the presence of threads The preexec_fn parameter is not safe to use in the presence of threads in your application. The child process could deadlock before exec is called. If you must use it, keep it trivial! Minimize the number of libraries you call into. See https://docs.python.org/3/library/subprocess.html#popen-constructor
Using subprocess.run without explicitly set `check` is not recommended. The check parameter should always be used with explicitly set check keyword to make clear what the error-handling behavior is. See https://docs.python.org/3/library/subprocess.html#subprocess.run
threading.Thread needs the target function The warning is emitted when a threading.Thread class is instantiated without the target function being passed. By default, the first parameter is the group param, not the target param.

Verbatim name of the checker is string.

See also string checker's options' documentation

Argument %r does not match format type %r Used when a type required by format string is not suitable for actual argument type
Expected mapping for format string, not %s Used when a format string that uses named conversion specifiers is used with an argument that is not a mapping.
Format string ends in middle of conversion specifier Used when a format string terminates before the end of a conversion specifier.
Missing key %r in format string dictionary Used when a format string that uses named conversion specifiers is used with a dictionary that doesn't contain all the keys required by the format string.
Mixing named and unnamed conversion specifiers in format string Used when a format string contains both named (e.g. '%(foo)d') and unnamed (e.g. '%d') conversion specifiers. This is also used when a named conversion specifier contains * for the minimum field width and/or precision.
Not enough arguments for format string Used when a format string that uses unnamed conversion specifiers is given too few arguments
Suspicious argument in %s.%s call The argument to a str.{l,r,}strip call contains a duplicate character,
Too many arguments for format string Used when a format string that uses unnamed conversion specifiers is given too many arguments.
Unsupported format character %r (%#02x) at index %d Used when an unsupported format character is used in a format string.
Anomalous Unicode escape in byte string: '%s'. String constant might be missing an r or u prefix. Used when an escape like u is encountered in a byte string where it has no effect.
Anomalous backslash in string: '%s'. String constant might be missing an r prefix. Used when a backslash is in a literal string but not as an escape.
Duplicate string formatting argument %r, consider passing as named argument Used when we detect that a string formatting is repeating an argument instead of using named string arguments
Format string contains both automatic field numbering and manual field specification Used when a PEP 3101 format string contains both automatic field numbering (e.g. '{}') and manual field specification (e.g. '{0}').
Format string dictionary key should be a string, not %s Used when a format string that uses named conversion specifiers is used with a dictionary whose keys are not all strings.
Implicit string concatenation found in %s String literals are implicitly concatenated in a literal iterable definition : maybe a comma is missing ?
Invalid format string Used when a PEP 3101 format string is invalid.
Missing format attribute %r in format specifier %r Used when a PEP 3101 format string uses an attribute specifier ({0.length}), but the argument passed for formatting doesn't have that attribute.
Missing keyword argument %r for format string Used when a PEP 3101 format string that uses named fields doesn't receive one or more required keywords.
Quote delimiter %s is inconsistent with the rest of the file Quote delimiters are not used consistently throughout a module (with allowances made for avoiding unnecessary escaping).
The u prefix for strings is no longer necessary in Python >=3.0 Used when we detect a string with a u prefix. These prefixes were necessary in Python 2 to indicate a string was Unicode, but since Python 3.0 strings are Unicode by default.
Unused format argument %r Used when a PEP 3101 format string that uses named fields is used with an argument that is not required by the format string.
Unused key %r in format string dictionary Used when a format string that uses named conversion specifiers is used with a dictionary that contains keys not required by the format string.
Using an f-string that does not have any interpolated variables Used when we detect an f-string that does not use any interpolation variables, in which case it can be either a normal string or a bug in the code.
Using formatting for a string that does not have any interpolated variables Used when we detect a string that does not have any interpolation variables, in which case it can be either a normal string without formatting or a bug in the code.
Using invalid lookup key %r in format specifier %r Used when a PEP 3101 format string uses a lookup specifier ({a[1]}), but the argument passed for formatting doesn't contain or doesn't have that key as an attribute.

Verbatim name of the checker is threading.

'%s()' directly created in 'with' has no effect Used when a new lock instance is created by using with statement which has no effect. Instead, an existing instance should be used to acquire lock.

Verbatim name of the checker is typecheck.

See also typecheck checker's options' documentation

%r does not support item assignment Emitted when an object does not support item assignment (i.e. doesn't define __setitem__ method).
%r does not support item deletion Emitted when an object does not support item deletion (i.e. doesn't define __delitem__ method).
Emitted when a unary operand is used on an object which does not support this type of operation.
Emitted when a binary arithmetic operation between two operands is not supported.
%s %r has no %r member%s Used when a variable is accessed for a nonexistent member.
%s is not callable Used when an object being called has been inferred to a non callable object.
'%s' is unhashable and can't be used as a %s in a %s Emitted when a dict key or set member is not hashable (i.e. doesn't define __hash__ method).
'await' should be used within an async function Emitted when await is used outside an async function.
Argument %r passed by position and keyword in %s call Used when a function call would result in assigning multiple values to a function parameter, one value from a positional argument and one from a keyword argument.
Assigning result of a function call, where the function has no return Used when an assignment is done on a function call but the inferred function doesn't return anything.
Assigning result of a function call, where the function returns None Used when an assignment is done on a function call but the inferred function returns nothing but None.
Context manager '%s' doesn't implement __enter__ and __exit__. Used when an instance in a with statement doesn't implement the context manager protocol(__enter__/__exit__).
Got multiple values for keyword argument %r in function call Emitted when a function call got multiple values for a keyword.
Invalid metaclass %r used Emitted whenever we can detect that a class is using, as a metaclass, something which might be invalid for using as a metaclass.
Missing mandatory keyword argument %r in %s call Used when a function call does not pass a mandatory keyword-only argument.
No value for argument %s in %s call Used when a function call passes too few arguments.
Non-iterable value %s is used in an iterating context Used when a non-iterable value is used in place where iterable is expected
Non-mapping value %s is used in a mapping context Used when a non-mapping value is used in place where mapping is expected
Sequence index is not an int, slice, or instance with __index__ Used when a sequence type is indexed with an invalid type. Valid types are ints, slices, and objects with an __index__ method.
Slice index is not an int, None, or instance with __index__ Used when a slice index is not an integer, None, or an object with an __index__ method.
Too many positional arguments for %s call Used when a function call passes too many positional arguments.
Unexpected keyword argument %r in %s call Used when a function call passes a keyword argument that doesn't correspond to one of the function's parameter names.
Unpacking a dictionary in iteration without calling .items() Emitted when trying to iterate through a dict without calling .items()
Value '%s' doesn't support membership test Emitted when an instance in membership test expression doesn't implement membership protocol (__contains__/__iter__/__getitem__).
Value '%s' is unsubscriptable Emitted when a subscripted value doesn't support subscription (i.e. doesn't define __getitem__ method or __class_getitem__ for a class).
Keyword argument before variable positional arguments list in the definition of %s function When defining a keyword argument before variable positional arguments, one can end up in having multiple values passed for the aforementioned parameter in case the method is called with keyword arguments.
Non-string value assigned to __name__ Emitted when a non-string value is assigned to __name__
Positional arguments appear to be out of order Emitted when the caller's argument names fully match the parameter names in the function signature but do not have the same order.
Second argument of isinstance is not a type Emitted when the second argument of an isinstance call is not a type.
%s %r has no %r member%s, but source is unavailable. Consider adding this module to extension-pkg-allow-list if you want to perform analysis based on run-time introspection of living objects. Used when a variable is accessed for non-existent member of C extension. Due to unavailability of source static analysis is impossible, but it may be performed by introspecting living objects in run-time.

Verbatim name of the checker is unicode_checker.

Contains control characters that can permit obfuscated code executed differently than displayed bidirectional unicode are typically not displayed characters required to display right-to-left (RTL) script (i.e. Chinese, Japanese, Arabic, Hebrew, ...) correctly. So can you trust this code? Are you sure it displayed correctly in all editors? If you did not write it or your language is not RTL, remove the special characters, as they could be used to trick you into executing code, that does something else than what it looks like. More Information: https://en.wikipedia.org/wiki/Bidirectional_text https://trojansource.codes/
Invalid unescaped character backspace, use "b" instead. Moves the cursor back, so the character after it will overwrite the character before.
Invalid unescaped character carriage-return, use "r" instead. Moves the cursor to the start of line, subsequent characters overwrite the start of the line.
Invalid unescaped character esc, use "x1B" instead. Commonly initiates escape codes which allow arbitrary control of the terminal.
Invalid unescaped character nul, use "0" instead. Mostly end of input for python.
Invalid unescaped character sub, use "x1A" instead. Ctrl+Z "End of text" on Windows. Some programs (such as type) ignore the rest of the file after it.
Invalid unescaped character zero-width-space, use "u200B" instead. Invisible space character could hide real code execution.
UTF-16 and UTF-32 aren't backward compatible. Use UTF-8 instead For compatibility use UTF-8 instead of UTF-16/UTF-32. See also https://bugs.python.org/issue1503789 for a history of this issue. And https://softwareengineering.stackexchange.com/questions/102205/should- utf-16-be-considered-harmful for some possible problems when using UTF-16 for instance.
PEP8 recommends UTF-8 as encoding for Python files PEP8 recommends UTF-8 default encoding for Python files. See https://peps.python.org/pep-0008/#source-file-encoding

Unnecessary-Dunder-Call checker

Verbatim name of the checker is unnecessary-dunder-call.

Unnecessary-Dunder-Call checker Messages

Unnecessarily calls dunder method %s. %s. Used when a dunder method is manually called instead of using the corresponding function/method/operator.

Verbatim name of the checker is unnecessary_ellipsis.

Unnecessary ellipsis constant Used when the ellipsis constant is encountered and can be avoided. A line of code consisting of an ellipsis is unnecessary if there is a docstring on the preceding line or if there is a statement in the same scope.

Verbatim name of the checker is unsupported_version.

F-strings are not supported by all versions included in the py-version setting Used when the py-version set by the user is lower than 3.6 and pylint encounters a f-string.
typing.final is not supported by all versions included in the py-version setting Used when the py-version set by the user is lower than 3.8 and pylint encounters a typing.final decorator.

Verbatim name of the checker is variables.

See also variables checker's options' documentation

Attempting to unpack a non-sequence%s Used when something which is not a sequence is used in an unpack assignment
Invalid format for __all__, must be tuple or list Used when __all__ has an invalid format.
Invalid index for iterable length Emitted when an index used on an iterable goes beyond the length of that iterable.
Invalid object %r in __all__, must contain only strings Used when an invalid (non-string) object occurs in __all__.
No name %r in module %r Used when a name cannot be found in a module.
Undefined variable %r Used when an undefined variable is accessed.
Undefined variable name %r in __all__ Used when an undefined variable name is referenced in __all__.
Using variable %r before assignment Emitted when a local variable is accessed before its assignment took place. Assignments in try blocks are assumed not to have occurred when evaluating associated except/finally blocks. Assignments in except blocks are assumed not to have occurred when evaluating statements outside the block, except when the associated try block contains a return statement.
Cell variable %s defined in loop A variable used in a closure is defined in a loop. This will result in all closures using the same value for the closed-over variable.
Global variable %r undefined at the module level Used when a variable is defined through the "global" statement but the variable is not defined in the module scope.
Invalid assignment to %s in method Invalid assignment to self or cls in instance or class method respectively.
Possible unbalanced tuple unpacking with sequence%s: left side has %d label(s), right side has %d value(s) Used when there is an unbalanced tuple unpacking in assignment
Possibly unused variable %r Used when a variable is defined but might not be used. The possibility comes from the fact that locals() might be used, which could consume or not the said variable
Redefining built-in %r Used when a variable or function override a built-in.
Redefining name %r from outer scope (line %s) Used when a variable's name hides a name defined in an outer scope or except handler.
Unused %s Used when an imported module or variable is not used.
Unused argument %r Used when a function or method argument is not used.
Unused import(s) %s from wildcard import of %s Used when an imported module or variable is not used from a 'from X import *' style import.
Unused variable %r Used when a variable is defined but not used.
Using global for %r but no assignment is done Used when a variable is defined through the "global" statement but no assignment to this variable is done.
Using possibly undefined loop variable %r Used when a loop variable (i.e. defined by a for loop or a list comprehension or a generator expression) is used outside the loop.
Using the global statement Used when you use the "global" statement to update a global variable. Pylint just try to discourage this usage. That doesn't mean you cannot use it !
Using the global statement at the module level Used when you use the "global" statement at the module level since it has no effect

Pylint provides the following optional plugins:

  • Deprecated Builtins checker
  • Broad Try Clause checker
  • Else If Used checker
  • Code Style checker
  • Compare-To-Zero checker
  • Comparison-Placement checker
  • Confusing Elif checker
  • Consider Ternary Expression checker
  • Parameter Documentation checker
  • Docstyle checker
  • Empty-Comment checker
  • Compare-To-Empty-String checker
  • Eq-Without-Hash checker
  • Consider-Using-Any-Or-All checker
  • Design checker
  • No Self Use checker
  • Overlap-Except checker
  • Import-Private-Name checker
  • Redefined-Loop-Name checker
  • Multiple Types checker
  • Set Membership checker
  • Typing checker
  • While Used checker

You can activate any or all of these extensions by adding a load-plugins line to the MAIN section of your .pylintrc, for example:

load-plugins=pylint.extensions.docparams,pylint.extensions.docstyle

This checker is provided by pylint.extensions.broad_try_clause. Verbatim name of the checker is broad_try_clause.

See also broad_try_clause checker's options' documentation

Try clause contains too many statements.

This checker is provided by pylint.extensions.code_style. Verbatim name of the checker is code_style.

Checkers that can improve code consistency. As such they don't necessarily provide a performance benefit and are often times opinionated.

See also code_style checker's options' documentation

Consider using an in-place tuple instead of list Only for style consistency! Emitted where an in-place defined list can be replaced by a tuple. Due to optimizations by CPython, there is no performance benefit from it.
Consider using namedtuple or dataclass for dictionary values Emitted when dictionary values can be replaced by namedtuples or dataclass instances.
Use '%s' instead Emitted when an if assignment is directly followed by an if statement and both can be combined by using an assignment expression :=. Requires Python 3.8 and py-version >= 3.8.

Compare-To-Empty-String checker

This checker is provided by pylint.extensions.emptystring. Verbatim name of the checker is compare-to-empty-string.

Compare-To-Empty-String checker Messages

Avoid comparisons to empty string Used when Pylint detects comparison to an empty string constant.

Compare-To-Zero checker

This checker is provided by pylint.extensions.comparetozero. Verbatim name of the checker is compare-to-zero.

Compare-To-Zero checker Messages

Avoid comparisons to zero Used when Pylint detects comparison to a 0 constant.

Comparison-Placement checker

This checker is provided by pylint.extensions.comparison_placement. Verbatim name of the checker is comparison-placement.

Comparison-Placement checker Messages

Comparison should be %s Used when the constant is placed on the left side of a comparison. It is usually clearer in intent to place it in the right hand side of the comparison.

This checker is provided by pylint.extensions.confusing_elif. Verbatim name of the checker is confusing_elif.

Consecutive elif with differing indentation level, consider creating a function to separate the inner elif Used when an elif statement follows right after an indented block which itself ends with if or elif. It may not be ovious if the elif statement was willingly or mistakenly unindented. Extracting the indented if statement into a separate function might avoid confusion and prevent errors.

Consider-Using-Any-Or-All checker

This checker is provided by pylint.extensions.for_any_all. Verbatim name of the checker is consider-using-any-or-all.

Consider-Using-Any-Or-All checker Messages

`for` loop could be `%s` A for loop that checks for a condition and return a bool can be replaced with any or all.

This checker is provided by pylint.extensions.consider_ternary_expression. Verbatim name of the checker is consider_ternary_expression.

Consider rewriting as a ternary expression Multiple assign statements spread across if/else blocks can be rewritten with a single assignment and ternary expression

This checker is provided by pylint.extensions.bad_builtin. Verbatim name of the checker is deprecated_builtins.

This used to be the bad-builtin core checker, but it was moved to an extension instead. It can be used for finding prohibited used builtins, such as map or filter, for which other alternatives exists.

If you want to control for what builtins the checker should warn about, you can use the bad-functions option:

$ pylint a.py --load-plugins=pylint.extensions.bad_builtin --bad-functions=apply,reduce
...

See also deprecated_builtins checker's options' documentation

Used builtin function %s Used when a disallowed builtin function is used (see the bad-function option). Usual disallowed functions are the ones like map, or filter , where Python offers now some cleaner alternative like list comprehension.

Design checker

This checker is provided by pylint.extensions.mccabe. Verbatim name of the checker is design.

You can now use this plugin for finding complexity issues in your code base.

Activate it through pylint --load-plugins=pylint.extensions.mccabe. It introduces a new warning, too-complex, which is emitted when a code block has a complexity higher than a preestablished value, which can be controlled through the max-complexity option, such as in this example:

$ cat a.py
def f10():

"""McCabe rating: 11"""
myint = 2
if myint == 5:
return myint
elif myint == 6:
return myint
elif myint == 7:
return myint
elif myint == 8:
return myint
elif myint == 9:
return myint
elif myint == 10:
if myint == 8:
while True:
return True
elif myint == 8:
with myint:
return 8
else:
if myint == 2:
return myint
return myint
return myint $ pylint a.py --load-plugins=pylint.extensions.mccabe R:1: 'f10' is too complex. The McCabe rating is 11 (too-complex) $ pylint a.py --load-plugins=pylint.extensions.mccabe --max-complexity=50 $

See also design checker's options' documentation

Design checker Messages

%s is too complex. The McCabe rating is %d Used when a method or function is too complex based on McCabe Complexity Cyclomatic

This checker is provided by pylint.extensions.docstyle. Verbatim name of the checker is docstyle.

Bad docstring quotes in %s, expected """, given %s Used when a docstring does not have triple double quotes.
First line empty in %s docstring Used when a blank line is found at the beginning of a docstring.

This checker is provided by pylint.extensions.check_elif. Verbatim name of the checker is else_if_used.

Consider using "elif" instead of "else" then "if" to remove one indentation level Used when an else statement is immediately followed by an if statement and does not contain statements that would be unrelated to it.

Empty-Comment checker

This checker is provided by pylint.extensions.empty_comment. Verbatim name of the checker is empty-comment.

Empty-Comment checker Messages

Line with empty comment Used when a # symbol appears on a line not followed by an actual comment

Eq-Without-Hash checker

This checker is provided by pylint.extensions.eq_without_hash. Verbatim name of the checker is eq-without-hash.

Eq-Without-Hash checker Messages

Implementing __eq__ without also implementing __hash__ Used when a class implements __eq__ but not __hash__. Objects get None as their default __hash__ implementation if they also implement __eq__.

Import-Private-Name checker

This checker is provided by pylint.extensions.private_import. Verbatim name of the checker is import-private-name.

Import-Private-Name checker Messages

Imported private %s (%s) Used when a private module or object prefixed with _ is imported. PEP8 guidance on Naming Conventions states that public attributes with leading underscores should be considered private.

This checker is provided by pylint.extensions.redefined_variable_type. Verbatim name of the checker is multiple_types.

Redefinition of %s type from %s to %s Used when the type of a variable changes inside a method or a function.

This checker is provided by pylint.extensions.no_self_use. Verbatim name of the checker is no_self_use.

Method could be a function Used when a method doesn't use its bound instance, and so could be written as a function.

Overlap-Except checker

This checker is provided by pylint.extensions.overlapping_exceptions. Verbatim name of the checker is overlap-except.

Overlap-Except checker Messages

Overlapping exceptions (%s) Used when exceptions in handler overlap or are identical

This checker is provided by pylint.extensions.docparams. Verbatim name of the checker is parameter_documentation.

If you document the parameters of your functions, methods and constructors and their types systematically in your code this optional component might be useful for you. Sphinx style, Google style, and Numpy style are supported. (For some examples, see https://pypi.org/project/sphinxcontrib-napoleon/ .)

You can activate this checker by adding the line:

load-plugins=pylint.extensions.docparams

to the MAIN section of your .pylintrc.

This checker verifies that all function, method, and constructor docstrings include documentation of the

  • parameters and their types
  • return value and its type
  • exceptions raised

and can handle docstrings in

Sphinx style (param, type, return, rtype, raise / except):
def function_foo(x, y, z):

'''function foo ...
:param x: bla x
:type x: int
:param y: bla y
:type y: float
:param int z: bla z
:return: sum
:rtype: float
:raises OSError: bla
'''
return x + y + z
or the Google style (Args:, Returns:, Raises:):
def function_foo(x, y, z):

'''function foo ...
Args:
x (int): bla x
y (float): bla y
z (int): bla z
Returns:
float: sum
Raises:
OSError: bla
'''
return x + y + z
or the Numpy style (Parameters, Returns, Raises):
def function_foo(x, y, z):

'''function foo ...
Parameters
----------
x: int
bla x
y: float
bla y
z: int
bla z
Returns
-------
float
sum
Raises
------
OSError
bla
'''
return x + y + z

You'll be notified of missing parameter documentation but also of naming inconsistencies between the signature and the documentation which often arise when parameters are renamed automatically in the code, but not in the documentation. Note: by default docstrings of private and magic methods are not checked. To change this behaviour (for example, to also check __init__) add no-docstring-rgx=^(?!__init__$)_ to the BASIC section of your .pylintrc.

Constructor parameters can be documented in either the class docstring or the __init__ docstring, but not both:

class ClassFoo(object):

'''Sphinx style docstring foo
:param float x: bla x
:param y: bla y
:type y: int
'''
def __init__(self, x, y):
pass class ClassBar(object):
def __init__(self, x, y):
'''Google style docstring bar
Args:
x (float): bla x
y (int): bla y
'''
pass

In some cases, having to document all parameters is a nuisance, for instance if many of your functions or methods just follow a common interface. To remove this burden, the checker accepts missing parameter documentation if one of the following phrases is found in the docstring:

  • For the other parameters, see
  • For the parameters, see

(with arbitrary whitespace between the words). Please add a link to the docstring defining the interface, e.g. a superclass method, after "see":

def callback(x, y, z):

'''Sphinx style docstring for callback ...
:param x: bla x
:type x: int
For the other parameters, see
:class:`MyFrameworkUsingAndDefiningCallback`
'''
return x + y + z def callback(x, y, z):
'''Google style docstring for callback ...
Args:
x (int): bla x
For the other parameters, see
:class:`MyFrameworkUsingAndDefiningCallback`
'''
return x + y + z

Naming inconsistencies in existing parameter and their type documentations are still detected.

See also parameter_documentation checker's options' documentation

"%s" differing in parameter documentation Please check parameter names in declarations.
"%s" differing in parameter type documentation Please check parameter names in type declarations.
"%s" has constructor parameters documented in class and __init__ Please remove parameter declarations in the class or constructor.
"%s" missing in parameter documentation Please add parameter declarations for all parameters.
"%s" missing in parameter type documentation Please add parameter type declarations for all parameters.
"%s" not documented as being raised Please document exceptions for all raised exception types.
"%s" useless ignored parameter documentation Please remove the ignored parameter documentation.
"%s" useless ignored parameter type documentation Please remove the ignored parameter type documentation.
Missing any documentation in "%s" Please add parameter and/or type documentation.
Missing return documentation Please add documentation about what this method returns.
Missing return type documentation Please document the type returned by this method.
Missing yield documentation Please add documentation about what this generator yields.
Missing yield type documentation Please document the type yielded by this method.
Redundant returns documentation Please remove the return/rtype documentation from this method.
Redundant yields documentation Please remove the yields documentation from this method.

Redefined-Loop-Name checker

This checker is provided by pylint.extensions.redefined_loop_name. Verbatim name of the checker is redefined-loop-name.

Redefined-Loop-Name checker Messages

Redefining %r from loop (line %s) Used when a loop variable is overwritten in the loop body.

This checker is provided by pylint.extensions.set_membership. Verbatim name of the checker is set_membership.

Consider using set for membership test Membership tests are more efficient when performed on a lookup optimized datatype like sets.

This checker is provided by pylint.extensions.typing. Verbatim name of the checker is typing.

Find issue specifically related to type annotations.

See also typing checker's options' documentation

'NoReturn' inside compound types is broken in 3.7.0 / 3.7.1 typing.NoReturn inside compound types is broken in Python 3.7.0 and 3.7.1. If not dependent on runtime introspection, use string annotation instead. E.g. Callable[..., 'NoReturn']. https://bugs.python.org/issue34921
'collections.abc.Callable' inside Optional and Union is broken in 3.9.0 / 3.9.1 (use 'typing.Callable' instead) collections.abc.Callable inside Optional and Union is broken in Python 3.9.0 and 3.9.1. Use typing.Callable for these cases instead. https://bugs.python.org/issue42965
'%s' is deprecated, use '%s' instead Emitted when a deprecated typing alias is used.
'%s' will be deprecated with PY39, consider using '%s' instead%s Only emitted if 'runtime-typing=no' and a deprecated typing alias is used in a type annotation context in Python 3.7 or 3.8.
Consider using alternative Union syntax instead of '%s'%s Emitted when 'typing.Union' or 'typing.Optional' is used instead of the alternative Union syntax 'int | None'.

This checker is provided by pylint.extensions.while_used. Verbatim name of the checker is while_used.

Used `while` loop Unbounded while loops can often be rewritten as bounded for loops.

You can call Pylint, epylint, symilar and pyreverse from another Python program thanks to their APIs:

from pylint import run_pylint, run_epylint, run_pyreverse, run_symilar
run_pylint("--disable=C", "myfile.py")
run_epylint(...)
run_pyreverse(...)
run_symilar(...)

You can use the run_pylint function, which is the same function called by the command line (using sys.argv). You can supply arguments yourself:

from pylint import run_pylint
run_pylint(argv=["--disable=line-too-long", "myfile.py"])

You can also use pylint.lint.Run directly if you want to do something that can't be done using only pylint's command line options. Here's the basic example:

from pylint.lint import Run
Run(argv=["--disable=line-too-long", "myfile.py"])

With Run it is possible to invoke pylint programmatically with a reporter initialized with a custom stream:

from io import StringIO
from pylint.lint import Run
from pylint.reporters.text import TextReporter
pylint_output = StringIO()  # Custom open stream
reporter = TextReporter(pylint_output)
Run(["test_file.py"], reporter=reporter, exit=False)
print(pylint_output.getvalue())  # Retrieve and print the text report

The reporter can accept any stream object as as parameter. In this example, the stream outputs to a file:

from pylint.lint import Run
from pylint.reporters.text import TextReporter
with open("report.out", "w") as f:

reporter = TextReporter(f)
Run(["test_file.py"], reporter=reporter, exit=False)

This would be useful to capture pylint output in an open stream which can be passed onto another program.

If your program expects that the files being linted might be edited between runs, you will need to clear pylint's inference cache:

from pylint.lint import pylinter
pylinter.MANAGER.clear_cache()

To silently run epylint on a module_name.py module, and get its standard output and error:

from pylint import epylint as lint
(pylint_stdout, pylint_stderr) = lint.py_run('module_name.py', return_std=True)

It is also possible to include additional Pylint options in the first argument to py_run:

from pylint import epylint as lint
(pylint_stdout, pylint_stderr) = lint.py_run('module_name.py --disable C0114', return_std=True)

The options --msg-template="{path}:{line}: {category} ({msg_id}, {symbol}, {obj}) {msg}" and --reports=n are set implicitly inside the epylint module.

You can find some simple examples in the distribution (custom.py , custom_raw.py and deprecation_checker.py).

There are three kinds of checkers:

  • Raw checkers, which analyse each module as a raw file stream.
  • Token checkers, which analyse a file using the list of tokens that represent the source code in the file.
  • AST checkers, which work on an AST representation of the module.

The AST representation is provided by the astroid library. astroid adds additional information and methods over ast in the standard library, to make tree navigation and code introspection easier.

Let's implement a checker to make sure that all return nodes in a function return a unique constant. Firstly we will need to fill in some required boilerplate:

import astroid
from astroid import nodes
from typing import TYPE_CHECKING, Optional
from pylint.checkers import BaseChecker
if TYPE_CHECKING:

from pylint.lint import PyLinter class UniqueReturnChecker(BaseChecker):
name = "unique-returns"
msgs = {
"W0001": (
"Returns a non-unique constant.",
"non-unique-returns",
"All constants returned in a function should be unique.",
),
}
options = (
(
"ignore-ints",
{
"default": False,
"type": "yn",
"metavar": "<y or n>",
"help": "Allow returning non-unique integers",
},
),
)

So far we have defined the following required components of our checker:

section for the checker, when options have been provided.
in your code, the problems being displayed to the user through messages. The message dictionary should specify what messages the checker is going to emit. See Defining a Message for the details about defining a new message.

We have also defined an optional component of the checker. The options list defines any user configurable options. It has the following format:

options = (

("option-symbol", {"argparse-like-kwarg": "value"}), )
The option-symbol is a unique name for the option. This is used on the command line and in config files. The hyphen is replaced by an underscore when used in the checker, similarly to how you would use argparse.Namespace:
if not self.linter.config.ignore_ints:

...

Next we'll track when we enter and leave a function.

def __init__(self, linter: Optional["PyLinter"] = None) -> None:

super().__init__(linter)
self._function_stack = [] def visit_functiondef(self, node: nodes.FunctionDef) -> None:
self._function_stack.append([]) def leave_functiondef(self, node: nodes.FunctionDef) -> None:
self._function_stack.pop()

In the constructor we initialise a stack to keep a list of return nodes for each function. An AST checker is a visitor, and should implement visit_<lowered class name> or leave_<lowered class name> methods for the nodes it's interested in. In this case we have implemented visit_functiondef and leave_functiondef to add a new list of return nodes for this function, and to remove the list of return nodes when we leave the function.

Finally we'll implement the check. We will define a visit_return function, which is called with an .astroid.nodes.Return node.

We'll need to be able to figure out what attributes an .astroid.nodes.Return` node has available. We can use ``astroid.extract_node for this:

>>> node = astroid.extract_node("return 5")
>>> node
<Return l.1 at 0x7efe62196390>
>>> help(node)
>>> node.value
<Const.int l.1 at 0x7efe62196ef0>

We could also construct a more complete example:

>>> node_a, node_b = astroid.extract_node("""
... def test():
...     if True:
...         return 5 #@
...     return 5 #@
... """)
>>> node_a.value
<Const.int l.4 at 0x7efe621a74e0>
>>> node_a.value.value
5
>>> node_a.value.value == node_b.value.value
True

For astroid.extract_node, you can use #@ at the end of a line to choose which statements will be extracted into nodes.

For more information on astroid.extract_node, see the astroid documentation.

Now we know how to use the astroid node, we can implement our check.

def visit_return(self, node: nodes.Return) -> None:

if not isinstance(node.value, nodes.Const):
return
for other_return in self._function_stack[-1]:
if node.value.value == other_return.value.value and not (
self.config.ignore_ints and node.value.pytype() == int
):
self.add_message("non-unique-returns", node=node)
self._function_stack[-1].append(node)

Once we have established that the source code has failed our check, we use ~.BaseChecker.add_message to emit our failure message.

Finally, we need to register the checker with pylint. Add the register function to the top level of the file.

def register(linter: "PyLinter") -> None:

"""This required method auto registers the checker during initialization.
:param linter: The linter to register the checker to.
"""
linter.register_checker(UniqueReturnChecker(linter))

We are now ready to debug and test our checker!

It is very simple to get to a point where we can use pdb. We'll need a small test case. Put the following into a Python file:

def test():

if True:
return 5
return 5 def test2():
if True:
return 1
return 5

After inserting pdb into our checker and installing it, we can run pylint with only our checker:

$ pylint --load-plugins=my_plugin --disable=all --enable=non-unique-returns test.py
(Pdb)

Now we can debug our checker!

NOTE:

my_plugin refers to a module called my_plugin.py. This module can be made available to pylint by putting this module's parent directory in your PYTHONPATH environment variable or by adding the my_plugin.py file to the pylint/checkers directory if running from source.

Pylint message is defined using the following format:

msgs = {

"E0401": ( # message id
"Unable to import %s", # template of displayed message
"import-error", # message symbol
"Used when pylint has been unable to import a module.", # Message description
{ # Additional parameters:
# message control support for the old names of the messages:
"old_names": [("F0401", "old-import-error")]
"minversion": (3, 5), # No check under this version
"maxversion": (3, 7), # No check above this version
},
),

The message is then formatted using the args parameter from add_message i.e. in self.add_message("import-error", args=module_we_cant_import, node=importnode), the value in module_we_cant_import say patglib will be interpolled and the final result will be: Unable to import patglib

  • The message-id should be a 4-digit number, prefixed with a message category. There are multiple message categories, these being C, W, E, F, R, standing for Convention, Warning, Error, Fatal and Refactoring. The 4 digits should not conflict with existing checkers and the first 2 digits should consistent across the checker (except shared messages).
  • The displayed-message is used for displaying the message to the user, once it is emitted.
  • The message-symbol is an alias of the message id and it can be used wherever the message id can be used.
  • The message-help is used when calling pylint --help-msg.

Optionally message can contain optional extra options:

  • The old_names option permits to change the message id or symbol of a message without breaking the message control used on the old messages by users. The option is specified as a list of tuples (message-id, old-message-symbol) e.g. {"old_names": [("F0401", "old-import-error")]}. The symbol / msgid association must be unique so if you're changing the message id the symbol also need to change and you can generally use the old- prefix for that.
  • The minversion or maxversion options specify minimum or maximum version of python relevant for this message. The option value is specified as tuple with major version number as first number and minor version number as second number e.g. {"minversion": (3, 5)}
  • The shared option enables sharing message between multiple checkers. As mentioned previously, normally the message cannot be shared between multiple checkers. To allow having message shared between multiple checkers, the shared option must be set to True.

BaseChecker has two methods get_map_data and reduce_map_data that permit to parallelize the checks when used with the -j option. If a checker actually needs to reduce data it should define get_map_data as returning something different than None and let its reduce_map_data handle a list of the types returned by get_map_data.

An example can be seen by looking at pylint/checkers/similar.py.

Pylint is very well suited to test driven development. You can implement the template of the checker, produce all of your test cases and check that they fail, implement the checker, then check that all of your test cases work.

Pylint provides a pylint.testutils.CheckerTestCase to make test cases very simple. We can use the example code that we used for debugging as our test cases.

import my_plugin
import pylint.testutils
class TestUniqueReturnChecker(pylint.testutils.CheckerTestCase):

CHECKER_CLASS = my_plugin.UniqueReturnChecker
def test_finds_non_unique_ints(self):
func_node, return_node_a, return_node_b = astroid.extract_node("""
def test(): #@
if True:
return 5 #@
return 5 #@
""")
self.checker.visit_functiondef(func_node)
self.checker.visit_return(return_node_a)
with self.assertAddsMessages(
pylint.testutils.MessageTest(
msg_id="non-unique-returns",
node=return_node_b,
),
):
self.checker.visit_return(return_node_b)
def test_ignores_unique_ints(self):
func_node, return_node_a, return_node_b = astroid.extract_node("""
def test(): #@
if True:
return 1 #@
return 5 #@
""")
with self.assertNoMessages():
self.checker.visit_functiondef(func_node)
self.checker.visit_return(return_node_a)
self.checker.visit_return(return_node_b)

Once again we are using astroid.extract_node to construct our test cases. pylint.testutils.CheckerTestCase has created the linter and checker for us, we simply simulate a traversal of the AST tree using the nodes that we are interested in.

Pylint provides support for writing two types of extensions. First, there is the concept of checkers, which can be used for finding problems in your code. Secondly, there is also the concept of transform plugin, which represents a way through which the inference and the capabilities of Pylint can be enhanced and tailored to a particular module, library of framework.

In general, a plugin is a module which should have a function register, which takes an instance of pylint.lint.PyLinter as input.

A plugin can optionally define a function, load_configuration, which takes an instance of pylint.lint.PyLinter as input. This function is called after Pylint loads configuration from configuration file and command line interface. This function should load additional plugin specific configuration to Pylint.

So a basic hello-world plugin can be implemented as:

# Inside hello_plugin.py
from typing import TYPE_CHECKING
import astroid
if TYPE_CHECKING:

from pylint.lint import PyLinter def register(linter: "PyLinter") -> None:
"""This required method auto registers the checker during initialization.
:param linter: The linter to register the checker to.
"""
print('Hello world')

We can run this plugin by placing this module in the PYTHONPATH and invoking pylint as:

$ pylint -E --load-plugins hello_plugin foo.py
Hello world

We can extend hello-world plugin to ignore some specific names using load_configuration function:

# Inside hello_plugin.py
from typing import TYPE_CHECKING
import astroid
if TYPE_CHECKING:

from pylint.lint import PyLinter def register(linter: "PyLinter") -> None:
"""This required method auto registers the checker during initialization.
:param linter: The linter to register the checker to.
"""
print('Hello world') def load_configuration(linter):
name_checker = get_checker(linter, NameChecker)
# We consider as good names of variables Hello and World
name_checker.config.good_names += ('Hello', 'World')
# We ignore bin directory
linter.config.black_list += ('bin',)

Depending if we need a transform plugin or a checker, this might not be enough. For the former, this is enough to declare the module as a plugin, but in the case of the latter, we need to register our checker with the linter object, by calling the following inside the register function:

linter.register_checker(OurChecker(linter))

For more information on writing a checker see How to Write a Checker.

Pylint is a static analysis tool and Python is a dynamically typed language. So there will be cases where Pylint cannot analyze files properly (this problem can happen in statically typed languages also if reflection or dynamic evaluation is used).

The plugins are a way to tell Pylint how to handle such cases, since only the user would know what needs to be done. They are usually operating on the AST level, by modifying or changing it in a way which can ease its understanding by Pylint.

Let us run Pylint on a module from the Python source: warnings.py and see what happens:

amitdev$ pylint -E Lib/warnings.py
E:297,36: Instance of 'WarningMessage' has no 'message' member (no-member)
E:298,36: Instance of 'WarningMessage' has no 'filename' member (no-member)
E:298,51: Instance of 'WarningMessage' has no 'lineno' member (no-member)
E:298,64: Instance of 'WarningMessage' has no 'line' member (no-member)

Did we catch a genuine error? Let's open the code and look at WarningMessage class:

class WarningMessage(object):

"""Holds the result of a single showwarning() call."""
_WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
"line")
def __init__(self, message, category, filename, lineno, file=None,
line=None):
local_values = locals()
for attr in self._WARNING_DETAILS:
setattr(self, attr, local_values[attr])
self._category_name = category.__name__ if category else None
def __str__(self):
...

Ah, the fields (message, category etc) are not defined statically on the class. Instead they are added using setattr. Pylint would have a tough time figuring this out.

We can write a transform plugin to tell Pylint how to analyze this properly.

One way to fix our example with a plugin would be to transform the WarningMessage class, by setting the attributes so that Pylint can see them. This can be done by registering a transform function. We can transform any node in the parsed AST like Module, Class, Function etc. In our case we need to transform a class. It can be done so:

from typing import TYPE_CHECKING
import astroid
if TYPE_CHECKING:

from pylint.lint import PyLinter def register(linter: "PyLinter") -> None:
"""This required method auto registers the checker during initialization.
:param linter: The linter to register the checker to.
"""
pass def transform(cls):
if cls.name == 'WarningMessage':
import warnings
for f in warnings.WarningMessage._WARNING_DETAILS:
cls.locals[f] = [astroid.ClassDef(f, None)] astroid.MANAGER.register_transform(astroid.ClassDef, transform)

Let's go through the plugin. First, we need to register a class transform, which is done via the register_transform function in MANAGER. It takes the node type and function as parameters. We need to change a class, so we use astroid.ClassDef. We also pass a transform function which does the actual transformation.

transform function is simple as well. If the class is WarningMessage then we add the attributes to its locals (we are not bothered about type of attributes, so setting them as class will do. But we could set them to any type we want). That's it.

Note: We don't need to do anything in the register function of the plugin since we are not modifying anything in the linter itself.

Lets run Pylint with this plugin and see:

amitdev$ pylint -E --load-plugins warning_plugin Lib/warnings.py
amitdev$

All the false positives associated with WarningMessage are now gone. This is just an example, any code transformation can be done by plugins.

See astroid/brain for real life examples of transform plugins.

The two main classes in pylint.lint are .pylint.lint.Run and .pylint.lint.PyLinter.

The .pylint.lint.Run object is responsible for starting up pylint. It does some basic checking of the given command line options to find the initial hook to run, find the config file to use, and find which plugins have been specified. It can then create the main .pylint.lint.PyLinter instance and initialise it with the config file and plugins that were discovered when preprocessing the command line options. Finally the .pylint.lint.Run object launches any child linters for parallel jobs, and starts the linting process.

The .pylint.lint.PyLinter is responsible for coordinating the linting process. It parses the configuration and provides it for the checkers and other plugins, it handles the messages emitted by the checkers, it handles the output reporting, and it launches the checkers.

All of the default pylint checkers exist in pylint.checkers. This is where most of pylint's brains exist. Most checkers are AST based and so use astroid. pylint.checkers.utils provides a large number of utility methods for dealing with astroid.

The contributor guide will help you if you want to contribute to pylint itself.

Want to contribute to pylint? There's a lot of things you can do. Here's a list of links you can check depending on what you want to do:

  • Asking a question on discord, or on github
  • Opening an issue
  • Making the documentation better
  • Making the error message better
  • Reproducing bugs and confirming that issues are valid
  • Investigating or debugging complicated issues
  • Designing or specifying a solution
  • Giving your opinion on ongoing discussion
  • Fixing bugs and crashes
  • Fixing false positives
  • Creating new features or fixing false negatives
  • Reviewing pull requests

If you are a pylint maintainer there's also:

  • Triaging issues
  • Labeling issues that do not have an actionable label yet
  • Preparing the next patch release
  • Checking stale pull requests status

Got a change for Pylint? Below are a few steps you should take to make sure your patch gets accepted:

  • We recommend using Python 3.8 or higher for development of Pylint as it gives you access to the latest ast parser.
  • Install the dev dependencies, see Contributor installation.
  • Use our test suite and write new tests, see Testing pylint.
  • Create a news fragment with towncrier create <IssueNumber>.<type> which will be included in the changelog. <type> can be one of: new_check, removed_check, extension, false_positive, false_negative, bugfix, other, internal. If necessary you can write details or offer examples on how the new change is supposed to work.
  • Document your change, if it is a non-trivial one.
  • If you used multiple emails or multiple names when contributing, add your mails and preferred name in the script/.contributors_aliases.json file.
  • Write a comprehensive commit message
  • Relate your change to an issue in the tracker if such an issue exists (see Closing issues via commit messages of the GitHub documentation for more information on this)
  • Send a pull request from GitHub (see About pull requests for more insight about this topic)

  • Read the Technical Reference. It gives a short walk through of the pylint codebase and will help you identify where you will need to make changes for what you are trying to implement.
  • astroid.extract_node is your friend. Most checkers are AST based, so you will likely need to interact with astroid. A short example of how to use astroid.extract_node is given here.
  • When fixing a bug for a specific check, search the code for the warning message to find where the warning is raised, and therefore where the logic for that code exists.
  • When adding a new checker class you can use the get_unused_message_id_category.py script in ./script to get a message id that is not used by any of the other checkers.

You can use the makefile in the doc directory with make html to build the documentation. To test smaller changes you can consider build-html, which skips some checks but will be faster:

$ cd doc
$ make install-dependencies
$ make build-html

We're reusing generated files for speed, use make clean when you want to start from scratch.

Choose depending on the kind of change you're doing:

In patch release (1.2.3), we only fix false positives and crashes.
In minor releases (1.2.0), we add checks, remove checks, drop python interpreters past end of life, upgrade astroid minor/major versions and fix false negatives.
In major releases (1.0.0) we change everything else (pylint options, json output, dev API...) while still trying to minimize disruption.

Pylint is very well tested and has a high code coverage. New contributions are not accepted unless they include tests.

Pylint is developed using the git distributed version control system.

You can clone Pylint using

git clone https://github.com/PyCQA/pylint

Before you start testing your code, you need to install your source-code package locally. Suppose you just cloned pylint with the previous git clone command. To set up your environment for testing, open a terminal and run:

cd pylint
python3 -m venv venv
source venv/bin/activate
pip install -r requirements_test_min.txt

This ensures your testing environment is similar to Pylint's testing environment on GitHub.

Optionally (Because there's an auto-fix if you open a merge request): We have pre-commit hooks which should take care of the autoformatting for you before each commit. To enable it, run pre-commit install in the pylint root directory.

If you're testing new changes in astroid you need to also clone astroid and install with an editable installation alongside pylint as follows:

# Suppose you're in the pylint directory
git clone https://github.com/PyCQA/astroid.git
python3 -m pip install -e astroid/

You're now using the local astroid in pylint and can control the version with git for example:

cd astroid/
git switch my-astroid-dev-branch

Since we use pytest to run the tests, you can also use it on its own. We do recommend using the tox command though:

pytest pylint -k test_functional

You can use pytest directly. If you want to run tests on a specific portion of the code with pytest and your local python version:

python3 -m pytest

Everything in tests/message with coverage for the relevant code (require pytest-cov):

python3 -m pytest tests/message/ --cov=pylint.message
coverage html

Only the functional test "missing_kwoa_py3":

python3 -m pytest "tests/test_functional.py::test_functional[missing_kwoa_py3]"

You can also optionally install tox and run our tests using the tox package, as in:

python -m tox
python -m tox -epy38 # for Python 3.8 suite only
python -m tox -epylint # for running Pylint over Pylint's codebase
python -m tox -eformatting # for running formatting checks over Pylint's codebase

It's usually a good idea to run tox with --recreate. This flag tells tox to re-download all dependencies before running the tests. This can be important when a new version of astroid or any of the other dependencies has been published:

python -m tox --recreate # The entire tox environment will be recreated
python -m tox --recreate -e py310 # The python 3.10 tox environment will be recreated

To run only a specific test suite, use a pattern for the test filename (without the .py extension), as in:

python -m tox -e py310 -- -k test_functional
python -m tox -e py310 -- -k  \*func\*
python -m tox --recreate -e py310 -- -k test_functional # With recreation of the environment

Pylint also uses what we refer to as primer tests. These are tests that are run automatically in our Continuous Integration and check whether any changes in Pylint lead to crashes or fatal errors on the stdlib and a selection of external repositories.

To run the primer tests you can add either --primer-stdlib or --primer-external to the pytest command. If you want to only run the primer you can add either of their marks, for example:

pytest -m primer_stdlib --primer-stdlib

The external primer can be run with:

pytest -m primer_external_batch_one --primer-external # Runs batch one

The list of repositories is created on the basis of three criteria: 1) projects need to use a diverse range of language features, 2) projects need to be well maintained and 3) projects should not have a codebase that is too repetitive. This guarantees a good balance between speed of our CI and finding potential bugs.

You can find the latest list of repositories and any relevant code for these tests in the tests/primer directory.

Pylint uses three types of tests: unittests, functional tests and primer tests.

  • unittests can be found in pylint/tests. Unless you're working on pylint's internal you're probably not going to have to write any.
  • Global functional tests can be found in the pylint/tests/functional. They are mainly used to test whether Pylint emits the correct messages.
  • Configuration's functional tests can be found in the pylint/tests/config/functional. They are used to test Pylint's configuration loading.
  • Primer tests you can suggest a new external repository to check but there's nothing to do most of the time.

Most other tests reside in the '/pylint/test' directory. These unittests can be used to test almost all functionality within Pylint. A good step before writing any new unittests is to look at some tests that test a similar funcitionality. This can often help write new tests.

If your new test requires any additional files you can put those in the /pylint/test/regrtest_data directory. This is the directory we use to store any data needed for the unittests.

These are residing under /pylint/test/functional and they are formed of multiple components. First, each Python file is considered to be a test case and it should be accompanied by a .txt file, having the same name, with the messages that are supposed to be emitted by the given test file.

In the Python file, each line for which Pylint is supposed to emit a message has to be annotated with a comment in the form # [message_symbol], as in:

a, b, c = 1 # [unbalanced-tuple-unpacking]

If multiple messages are expected on the same line, then this syntax can be used:

a, b, c = 1.test # [unbalanced-tuple-unpacking, no-member]

You can also use # +n: [ with n an integer if the above syntax would make the line too long or other reasons:

# +1: [empty-comment]
#

If you need special control over Pylint's configuration, you can also create a .rc file, which can have sections of Pylint's configuration. The .rc file can also contain a section [testoptions] to pass options for the functional test runner. The following options are currently supported:

  • "min_pyver": Minimal python version required to run the test
  • "max_pyver": Python version from which the test won't be run. If the last supported version is 3.9 this setting should be set to 3.10.
  • "min_pyver_end_position": Minimal python version required to check the end_line and end_column attributes of the message
  • "requires": Packages required to be installed locally to run the test
  • "except_implementations": List of python implementations on which the test should not run
  • "exclude_platforms": List of operating systems on which the test should not run

Functional test file locations

For existing checkers, new test cases should preferably be appended to the existing test file. For new checkers, a new file new_checker_message.py should be created (Note the use of underscores). This file should then be placed in the test/functional/n sub-directory.

Some additional notes:

  • If the checker is part of an extension the test should go in test/functional/ext/extension_name
  • If the test is a regression test it should go in test/r/regression or test/r/regression_02. The file name should start with regression_.
  • For some sub-directories, such as test/functional/u, there are additional sub-directories (test/functional/u/use). Please check if your test file should be placed in any of these directories. It should be placed there if the sub-directory name matches the word before the first underscore of your test file name.

The folder structure is enforced when running the test suite, so you might be directed to put the file in a different sub-directory.

Running and updating functional tests

During development, it's sometimes helpful to run all functional tests in your current environment in order to have faster feedback. Run from Pylint root directory with:

python tests/test_functional.py

You can use all the options you would use for pytest, for example -k "test_functional[len_checks]". Furthermore, if required the .txt file with expected messages can be regenerated based on the the current output by appending --update-functional-output to the command line:

python tests/test_functional.py --update-functional-output -k "test_functional[len_checks]"

To test the different ways to configure Pylint there is also a small functional test framework for configuration files. These tests can be found in the '/pylint/test/config' directory.

To create a new test create a new file with an unused name in the directory of that type of configuration file. Subsequently add a filename.result.json file with 'filename' being the same name as your configuration file. This file should record what the configuration should be compared to the standard configuration.

For example, if the configuration should add a warning to the list of disabled messages and you changed the configuration for job to 10 instead of the default 1 the .json file should include:

"functional_append": {

"disable": [["a-message-to-be-added"],] } "jobs": 10,

Similarly if a message should be removed you can add the following to the .json file:

"functional_remove": {

"disable": [["a-message-to-be-removed"],] }

If a configuration is incorrect and should lead to a crash or warning being emitted you can specify this by adding a .out file. This file should have the following name name_of_configuration_testfile.error_code.out. So, if your test is called bad_configuration.toml and should exit with exit code 2 the .out file should be named bad_configuration.2.out. The content of the .out file should have a similar pattern as a normal Pylint output. Note that the module name should be {abspath} and the file name {relpath}.

To analyse the performance of Pylint we recommend to use the cProfile module from stdlib. Together with the pstats module this should give you all the tools you need to profile a Pylint run and see which functions take how long to run.

The documentation for both modules can be found at cProfile.

To profile a run of Pylint over itself you can use the following code and run it from the base directory. Note that cProfile will create a document called stats that is then read by pstats. The human-readable output will be stored by pstats in ./profiler_stats. It will be sorted by cumulative time:

import cProfile
import pstats
import sys
sys.argv = ["pylint", "pylint"]
cProfile.run("from pylint import __main__", "stats")
with open("profiler_stats", "w", encoding="utf-8") as file:

stats = pstats.Stats("stats", stream=file)
stats.sort_stats("cumtime")
stats.print_stats()

You can also interact with the stats object by sorting or restricting the output. For example, to only print functions from the pylint module and sort by cumulative time you could use:

import cProfile
import pstats
import sys
sys.argv = ["pylint", "pylint"]
cProfile.run("from pylint import __main__", "stats")
with open("profiler_stats", "w", encoding="utf-8") as file:

stats = pstats.Stats("stats", stream=file)
stats.sort_stats("cumtime")
stats.print_stats("pylint/pylint")

Lastly, to profile a run over your own module or code you can use:

import cProfile
import pstats
import sys
sys.argv = ["pylint", "your_dir/your_file"]
cProfile.run("from pylint import __main__", "stats")
with open("profiler_stats", "w", encoding="utf-8") as file:

stats = pstats.Stats("stats", stream=file)
stats.sort_stats("cumtime")
stats.print_stats()

The documentation of the pstats module discusses other possibilities to interact with the profiling output.

To analyse the performance of specific checker within Pylint we can use the human-readable output created by pstats.

If you search in the profiler_stats file for the file name of the checker you will find all functional calls from functions within the checker. Let's say we want to check the visit_importfrom method of the variables checker:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
622    0.006    0.000    8.039    0.013 /MY_PROGRAMMING_DIR/pylint/pylint/checkers/variables.py:1445(visit_importfrom)

The previous line tells us that this method was called 622 times during the profile and we were inside the function itself for 6 ms in total. The time per call is less than a millisecond (0.006 / 622) and thus is displayed as being 0.

Often you are more interested in the cumulative time (per call). This refers to the time spent within the function and any of the functions it called or the functions they called (etc.). In our example, the visit_importfrom method and all of its child-functions took a little over 8 seconds to exectute, with an execution time of 0.013 ms per call.

You can also search the profiler_stats for an individual function you want to check. For example _analyse_fallback_blocks, a function called by visit_importfrom in the variables checker. This allows more detailed analysis of specific functions:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
1    0.000    0.000    0.000    0.000 /MY_PROGRAMMING_DIR/pylint/pylint/checkers/variables.py:1511(_analyse_fallback_blocks)

Often you might want to create a visual representation of your profiling stats. A good tool to do this is gprof2dot. This tool can create a .dot file from the profiling stats created by cProfile and pstats. You can then convert the .dot file to a .png file with one of the many converters found online.

You can read the gprof2dot documentation for installation instructions for your specific environment.

Another option would be snakeviz.

So, you want to release the X.Y.Z version of pylint ?

Before releasing a major or minor version check if there are any unreleased commits on the maintenance branch. If so, release a last patch release first. See Releasing a patch version.

  • Write the Summary -- Release highlights in doc/whatsnew and upgrade the release date.
  • Install the release dependencies: pip3 install -r requirements_test.txt
  • Bump the version and release by using tbump X.Y.0 --no-push --no-tag. (For example: tbump 2.4.0 --no-push --no-tag)
  • Check the commit created with git show amend the commit if required.
  • Create a new What's new in Pylint X.Y+1 document. Add it to doc/index.rst. Take a look at the examples from doc/whatsnew. Commit that with git commit -am "wip".
  • Move the main branch up to a dev version with tbump:
tbump X.Y+1.0-dev0 --no-tag --no-push  # You can interrupt after the first step
git commit -am "Upgrade the version to x.y+1.0-dev0 following x.y.0 release"

For example:

tbump 2.5.0-dev0 --no-tag --no-push
git commit -am "Upgrade the version to 2.5.0-dev0 following 2.4.0 release"

Check the commit, fixup the 'wip' commit with the what's new then push to a release branch

  • Open a merge request with the two commits (no one can push directly on main)
  • After the merge, recover the merged commits on main and tag the first one (the version should be X.Y.Z) as vX.Y.Z (For example: v2.4.0)
  • Push the tag.
  • Release the version on GitHub with the same name as the tag and copy and paste the appropriate changelog in the description. This triggers the PyPI release.
  • Delete the maintenance/X.Y-1.x branch. (For example: maintenance/2.3.x)
  • Create a maintenance/X.Y.x (For example: maintenance/2.4.x from the v2.4.0 tag.)
  • Close the current milestone and create the new ones (For example: close 2.4.0, create 2.4.1 and 2.6.0)
  • Hide and deactivate all the patch releases for the previous minor release on readthedoc, except the last one. (For example: hide v2.4.0, v2.4.1, v2.4.2 and keep only v2.4.3)

Whenever a commit on main should be released in a patch release on the current maintenance branch we cherry-pick the commit from main.

  • During the merge request on main, make sure that the changelog is for the patch version X.Y-1.Z'. (For example: v2.3.5)
  • After the PR is merged on main cherry-pick the commits on the release-branch-X.Y-1.Z' branch created from maintenance/X.Y-1.x then cherry-pick the commit from the main branch. (For example: release-branch-2.3.5 from maintenance/2.3.x)
  • Remove the "need backport" label from cherry-picked issues
  • Release a patch version

We release patch versions when a crash or a bug is fixed on the main branch and has been cherry-picked on the maintenance branch.

  • Install the release dependencies: pip3 install -r requirements_test.txt
  • Bump the version and release by using tbump X.Y-1.Z --no-push. (For example: tbump 2.3.5 --no-push)
  • Check the result visually with git show.
  • Open a merge request of release-X.Y-1.Z' in maintenance/X.Y.x (For example: release-2.3.5-branch in maintenance/2.3.x) to run the CI tests for this branch.
  • Create and push the tag.
  • Release the version on GitHub with the same name as the tag and copy and paste the changelog from the ReadtheDoc generated documentation from the pull request pipeline in the description. This triggers the PyPI release.
  • Merge the maintenance/X.Y.x branch on the main branch. The main branch should have the changelog for X.Y-1.Z+1 (For example v2.3.6). This merge is required so pre-commit autoupdate works for pylint.
  • Fix version conflicts properly, or bump the version to X.Y.0-devZ (For example: 2.4.0-dev6) before pushing on the main branch
  • Close the current milestone and create the new one (For example: close 2.3.5, create 2.3.6)

We move issues that were not done to the next milestone and block releases only if there are any open issues labelled as blocker.

pyreverse analyzes your source code and generates package and class diagrams.

It supports output to .dot/.gv, .vcg, .puml/.plantuml (PlantUML) and .mmd/.html (MermaidJS) file formats. If Graphviz (or the dot command) is installed, all output formats supported by Graphviz can be used as well. In this case, pyreverse first generates a temporary .gv file, which is then fed to Graphviz to generate the final image.

To run pyreverse, use:

pyreverse [options] <packages>

<packages> can also be a single Python module. To see a full list of the available options, run:

pyreverse -h

Example diagrams generated with the .puml output format are shown below.

[image: Class diagram generated by pyreverse] [image]

[image: Package diagram generated by pyreverse] [image]

In many cases creating a single diagram depicting all classes in the project yields a rather unwieldy, giant diagram. While limiting the input path to a single package or module can already help greatly to narrow down the scope, the -c option provides another way to create a class diagram focusing on a single class and its collaborators. For example, running:

pyreverse -ASmy -c pylint.checkers.classes.ClassChecker pylint

will generate the full class and package diagrams for pylint, but will additionally generate a file pylint.checkers.classes.ClassChecker.dot: [image: Package diagram generated by pyreverse] [image]

The console script symilar finds copy pasted blocks in a set of files. It provides a command line interface to the Similar class, which includes the logic for Pylint's duplicate-code message. It can be invoked with:

symilar [-d|--duplicates min_duplicated_lines] [-i|--ignore-comments] [--ignore-docstrings] [--ignore-imports] [--ignore-signatures] file1...

All files that shall be checked have to be passed in explicitly, e.g.:

symilar foo.py, bar.py, subpackage/spam.py, subpackage/eggs.py

symilar produces output like the following:

17 similar lines in 2 files
==tests/data/clientmodule_test.py:3
==tests/data/suppliermodule_test.py:12

class Ancestor:
""" Ancestor method """
__implements__ = (Interface,)
cls_member = DoNothing()
def __init__(self, value):
local_variable = 0
self.attr = 'this method shouldn\'t have a docstring'
self.__value = value
def get_value(self):
""" nice docstring ;-) """
return self.__value
def set_value(self, value):
self.__value = value
return 'this method shouldn\'t have a docstring' TOTAL lines=58 duplicates=17 percent=29.31

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

What's New in Pylint 2.16

:Release:2.16 :Date: TBA

Summary -- Release highlights

What's New in Pylint 2.15

2.15
2022-08-26

Summary -- Release highlights

In pylint 2.15.0, we added a new check missing-timeout to warn of default timeout values that could cause a program to be hanging indefinitely.

We improved pylint's handling of namespace packages. More packages should be linted without resorting to using the --recursive=y option.

We still welcome any community effort to help review, integrate, and add good/bad examples to the doc for https://github.com/PyCQA/pylint/issues/5953`_. This should be doable without any pylint or astroid knowledge, so this is the perfect entrypoint if you want to contribute to pylint or open source without any experience with our code!

Internally, we changed the way we generate the release notes, thanks to DudeNr33. There will be no more conflict resolution to do in the changelog, and every contributor rejoice.

Marc Byrne became a maintainer, welcome to the team !

What's new in Pylint 2.15.10?

Release date: 2023-01-09

False Positives Fixed

  • Fix use-sequence-for-iteration when unpacking a set with *.

    Closes #5788 (#5788)

  • Fix false positive assigning-non-slot when a class attribute is re-assigned.

    Closes #6001 (#6001)

  • Fixes used-before-assignment false positive when the walrus operator is used in a ternary operator.

    Closes #7779 (#7779)

  • Prevent used-before-assignment when imports guarded by if TYPE_CHECKING are guarded again when used.

    Closes #7979 (#7979)

Other Bug Fixes

Using custom braces in msg-template will now work properly.

Closes #5636 (#5636)

What's new in Pylint 2.15.9?

Release date: 2022-12-17

False Positives Fixed

Fix false-positive for used-before-assignment in pattern matching with a guard.

Closes #5327 (#5327)

Other Bug Fixes

  • Pylint will no longer deadlock if a parallel job is killed but fail immediately instead.

    Closes #3899 (#3899)

  • When pylint exit due to bad arguments being provided the exit code will now be the expected 32.

    Refs #7931 (#7931)

  • Fixes a ModuleNotFound exception when running pylint on a Django project with the pylint_django plugin enabled.

    Closes #7938 (#7938)

What's new in Pylint 2.15.8?

Release date: 2022-12-05

False Positives Fixed

  • Document a known false positive for useless-suppression when disabling line-too-long in a module with only comments and no code.

    Closes #3368 (#3368)

  • Fix logging-fstring-interpolation false positive raised when logging and f-string with %s formatting.

    Closes #4984 (#4984)

  • Fixes false positive abstract-method on Protocol classes.

    Closes #7209 (#7209)

  • Fix missing-param-doc false positive when function parameter has an escaped underscore.

    Closes #7827 (#7827)

  • multiple-statements no longer triggers for function stubs using inlined ....

    Closes #7860 (#7860)

What's new in Pylint 2.15.7?

Release date: 2022-11-27

False Positives Fixed

  • Fix deprecated-method false positive when alias for method is similar to name of deprecated method.

    Closes #5886 (#5886)

  • Fix a false positive for used-before-assignment for imports guarded by typing.TYPE_CHECKING later used in variable annotations.

    Closes #7609 (#7609)

Other Bug Fixes

  • Pylint will now filter duplicates given to it before linting. The output should be the same whether a file is given/discovered multiple times or not.

    Closes #6242, #4053 (#6242)

  • Fixes a crash in stop-iteration-return when the next builtin is called without arguments.

    Closes #7828 (#7828)

What's new in Pylint 2.15.6?

Release date: 2022-11-19

False Positives Fixed

  • Fix false positive for unhashable-member when subclassing dict and using the subclass as a dictionary key.

    Closes #7501 (#7501)

  • unnecessary-list-index-lookup will not be wrongly emitted if enumerate is called with start.

    Closes #7682 (#7682)

  • Don't warn about stop-iteration-return when using next() over itertools.cycle.

    Closes #7765 (#7765)

Other Bug Fixes

  • Messages sent to reporter are now copied so a reporter cannot modify the message sent to other reporters.

    Closes #7214 (#7214)

  • Fixes edge case of custom method named next raised an astroid error.

    Closes #7610 (#7610)

  • Fix crash that happened when parsing files with unexpected encoding starting with 'utf' like utf13.

    Closes #7661 (#7661)

  • Fix a crash when a child class with an __init__ method inherits from a parent class with an __init__ class attribute.

    Closes #7742 (#7742)

What's new in Pylint 2.15.5?

Release date: 2022-10-21

False Positives Fixed

Fix a false positive for simplify-boolean-expression when multiple values are inferred for a constant.

Closes #7626 (#7626)

Other Bug Fixes

  • Remove __index__ dunder method call from unnecessary-dunder-call check.

    Closes #6795 (#6795)

  • Fixed a multi-processing crash that prevents using any more than 1 thread on MacOS.

    The returned module objects and errors that were cached by the linter plugin loader cannot be reliably pickled. This means that dill would throw an error when attempting to serialise the linter object for multi-processing use.

    Closes #7635. (#7635)

Other Changes

  • Add a keyword-only compare_constants argument to safe_infer.

    Refs #7626 (#7626)

  • Sort --generated-rcfile output.

    Refs #7655 (#7655)

What's new in Pylint 2.15.4?

Release date: 2022-10-10

False Positives Fixed

Fix the message for unnecessary-dunder-call for __aiter__ and __aneext__. Also only emit the warning when py-version >= 3.10.

Closes #7529 (#7529)

Other Bug Fixes

  • Fix bug in detecting unused-variable when iterating on variable.

    Closes #3044 (#3044)

  • Fixed handling of -- as separator between positional arguments and flags. This was not actually fixed in 2.14.5.

    Closes #7003, Refs #7096 (#7003)

  • Report no-self-argument rather than no-method-argument for methods with variadic arguments.

    Closes #7507 (#7507)

  • Fixed an issue where syntax-error couldn't be raised on files with invalid encodings.

    Closes #7522 (#7522)

  • Fix false positive for redefined-outer-name when aliasing typing e.g. as t and guarding imports under t.TYPE_CHECKING.

    Closes #7524 (#7524)

  • Fixed a crash of the modified_iterating checker when iterating on a set defined as a class attribute.

    Closes #7528 (#7528)

  • Fix bug in scanning of names inside arguments to typing.Literal. See https://peps.python.org/pep-0586/#literals-enums-and-forward-references for details.

    Refs #3299 (#3299)

Other Changes

Add method name to the error messages of no-method-argument and no-self-argument.

Closes #7507 (#7507)

What's new in Pylint 2.15.3?

Release date: 2022-09-19

  • Fixed a crash in the unhashable-member checker when using a lambda as a dict key.

    Closes #7453 (#7453)

  • Fix a crash in the modified-iterating-dict checker involving instance attributes.

    Closes #7461 (#7461)

  • invalid-class-object does not crash anymore when __class__ is assigned alongside another variable.

    Closes #7467 (#7467)

  • Fix false positive for global-variable-not-assigned when a global variable is re-assigned via an ImportFrom node.

    Closes #4809 (#4809)

  • Fix false positive for undefined-loop-variable in for-else loops that use a function having a return type annotation of NoReturn or Never.

    Closes #7311 (#7311)

  • --help-msg now accepts a comma-separated list of message IDs again.

    Closes #7471 (#7471)

What's new in Pylint 2.15.2?

Release date: 2022-09-07

  • Fixed a case where custom plugins specified by command line could silently fail.

    Specifically, if a plugin relies on the init-hook option changing sys.path before it can be imported, this will now emit a bad-plugin-value message. Before this change, it would silently fail to register the plugin for use, but would load any configuration, which could have unintended effects.

    Fixes part of #7264. (#7264)

  • Fix used-before-assignment for functions/classes defined in type checking guard.

    Closes #7368 (#7368)

  • Update modified_iterating checker to fix a crash with for loops on empty list.

    Closes #7380 (#7380)

  • The docparams extension now considers typing in Numpy style docstrings as "documentation" for the missing-param-doc message.

    Refs #7398 (#7398)

  • Fix false positive for unused-variable and unused-import when a name is only used in a string literal type annotation.

    Closes #3299 (#3299)

  • Fix false positive for too-many-function-args when a function call is assigned to a class attribute inside the class where the function is defined.

    Closes #6592 (#6592)

  • Fix used-before-assignment for functions/classes defined in type checking guard.

    Closes #7368 (#7368)

  • Fix ignored files being linted when passed on stdin.

    Closes #4354 (#4354)

  • missing-return-doc, missing-raises-doc and missing-yields-doc now respect the no-docstring-rgx option.

    Closes #4743 (#4743)

  • Don't crash on OSError in config file discovery.

    Closes #7169 (#7169)

  • disable-next is now correctly scoped to only the succeeding line.

    Closes #7401 (#7401)

  • Update modified_iterating checker to fix a crash with for loops on empty list.

    Closes #7380 (#7380)

What's new in Pylint 2.15.1?

Release date: 2022-09-06

This is a "github only release", it was mistakenly released as 2.16.0-dev on pypi. Replaced by 2.15.2.

What's new in Pylint 2.15.0?

Added new checker missing-timeout to warn of default timeout values that could cause a program to be hanging indefinitely.

Refs #6780 (#6780)

False Positives Fixed

  • Don't report super-init-not-called for abstract __init__ methods.

    Closes #3975 (#3975)

  • Don't report unsupported-binary-operation on Python <= 3.9 when using the | operator with types, if one has a metaclass that overloads __or__ or __ror__ as appropriate.

    Closes #4951 (#4951)

  • Don't report no-value-for-parameter for dataclasses fields annotated with KW_ONLY.

    Closes #5767 (#5767)

  • Fixed inference of Enums when they are imported under an alias.

    Closes #5776 (#5776)

  • Prevent false positives when accessing PurePath.parents by index (not slice) on Python 3.10+.

    Closes #5832 (#5832)

  • unnecessary-list-index-lookup is now more conservative to avoid potential false positives.

    Closes #6896 (#6896)

  • Fix double emitting trailing-whitespace for multi-line docstrings.

    Closes #6936 (#6936)

  • import-error now correctly checks for contextlib.suppress guards on import statements.

    Closes #7270 (#7270)

  • Fix false positive for no-self-argument/no-method-argument when a staticmethod is applied to a function but uses a different name.

    Closes #7300 (#7300)

  • Fix undefined-loop-variable with break and continue statements in else blocks.

    Refs #7311 (#7311)

  • Improve default TypeVar name regex. Disallow names prefixed with T. E.g. use AnyStrT instead of TAnyStr.

    Refs #7322 (#7322 https://github.com/PyCQA/pylint/issues/7322`_)

  • Emit used-before-assignment when relying on a name that is reimported later in a function.

    Closes #4624 (#4624)

  • Emit used-before-assignment for self-referencing named expressions (:=) lacking prior assignments.

    Closes #5653 (#5653)

  • Emit used-before-assignment for self-referencing assignments under if conditions.

    Closes #6643 (#6643)

  • Emit modified-iterating-list and analogous messages for dicts and sets when iterating literals, or when using the del keyword.

    Closes #6648 (#6648)

  • Emit used-before-assignment when calling nested functions before assignment.

    Closes #6812 (#6812)

  • Emit nonlocal-without-binding when a nonlocal name has been assigned at a later point in the same scope.

    Closes #6883 (#6883)

  • Emit using-constant-test when testing the truth value of a variable or call result holding a generator.

    Closes #6909 (#6909)

  • Rename unhashable-dict-key to unhashable-member and emit when creating sets and dicts, not just when accessing dicts.

    Closes #7034, Closes #7055 (#7034)

Other Bug Fixes

  • Fix a failure to lint packages with __init__.py contained in directories lacking __init__.py.

    Closes #1667 (#1667)

  • Fixed a syntax-error crash that was not handled properly when the declared encoding of a file was utf-9.

    Closes #3860 (#3860)

  • Fix a crash in the not-callable check when there is ambiguity whether an instance is being incorrectly provided to __new__().

    Closes #7109 (#7109)

  • Fix crash when regex option raises a re.error exception.

    Closes #7202 (#7202)

  • Fix undefined-loop-variable from walrus in comprehension test.

    Closes #7222 (#7222)

  • Check for <cwd> before removing first item from sys.path in modify_sys_path.

    Closes #7231 (#7231)

  • Fix sys.path pollution in parallel mode.

    Closes #7246 (#7246)

  • Prevent useless-parent-delegation for delegating to a builtin written in C (e.g. Exception.__init__) with non-self arguments.

    Closes #7319 (#7319)

Other Changes

  • bad-exception-context has been renamed to bad-exception-cause as it is about the cause and not the context.

    Closes #3694 (#3694)

  • The message for literal-comparison is now more explicit about the problem and the solution.

    Closes #5237 (#5237)

  • useless-super-delegation has been renamed to useless-parent-delegation in order to be more generic.

    Closes #6953 (#6953)

  • Pylint now uses towncrier for changelog generation.

    Refs #6974 (#6974)

  • Update astroid to 2.12.

    Refs #7153 (#7153)

  • Fix crash when a type-annotated __slots__ with no value is declared.

    Closes #7280 (#7280)

  • Fixed an issue where it was impossible to update functional tests output when the existing output was impossible to parse. Instead of raising an error we raise a warning message and let the functional test fail with a default value.

    Refs #6891 (#6891)

  • pylint.testutils.primer is now a private API.

    Refs #6905 (#6905)

  • We changed the way we handle the changelog internally by using towncrier. If you're a contributor you won't have to fix merge conflicts in the changelog anymore.

    Closes #6974 (#6974)

  • Pylint is now using Scorecards to implement security recommendations from the OpenSSF. This is done in order to secure our supply chains using a combination of automated tooling and best practices, most of which were already implemented before.

    Refs #7267 (#7267)

What's New in Pylint 2.14

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

With 2.14 pylint only supports Python version 3.7.2 and above.

We introduced several new checks among which duplicate-value for sets, comparison-of-constants, and checks related to lambdas. We removed no-init and made no-self-use optional as they were too opinionated. We also added an option to generate a toml configuration: --generate-toml-config.

We migrated to argparse from optparse and refactored the configuration handling thanks to Daniël van Noord. On the user side it should change the output of the --help command, and some inconsistencies and bugs should disappear. The behavior between options set in a config file versus on the command line will be more consistent. For us, it will permit to maintain this part of the code easily in the future and anticipate optparse's removal in Python 3.12.

As a result of the refactor there are a lot of internal deprecations. If you're a library maintainer that depends on pylint, please verify that you're ready for pylint 3.0 by activating deprecation warnings.

We continued the integration of pylint-error and are now at 33%!. We still welcome any community effort to help review, integrate, and add good/bad examples https://github.com/PyCQA/pylint/issues/5953`_. This should be doable without any pylint or astroid knowledge, so this is the perfect entrypoint if you want to contribute to pylint or open source without any experience with our code!

New checkers

  • Added new checker comparison-of-constants.

    Closes #6076

  • Added new checker typevar-name-mismatch: TypeVar must be assigned to a variable with the same name as its name argument.

    Closes #5224

  • invalid-enum-extension: Used when a class tries to extend an inherited Enum class.

    Closes #5501

  • Added new checker typevar-double-variance: The "covariant" and "contravariant" keyword arguments cannot both be set to "True" in a TypeVar.

    Closes #5895

  • Add new check unnecessary-dunder-call for unnecessary dunder method calls.

    Closes #5936

  • unnecessary-lambda-assignment: Lambda expression assigned to a variable. Define a function using the "def" keyword instead. unnecessary-direct-lambda-call: Lambda expression called directly. Execute the expression inline instead.

    Closes #5976

  • potential-index-error: Emitted when the index of a list or tuple exceeds its length. This checker is currently quite conservative to avoid false positives. We welcome suggestions for improvements.

    Closes #578

  • Added new checker unnecessary-list-index-lookup for indexing into a list while iterating over enumerate().

    Closes #4525

  • Added new message called duplicate-value which identifies duplicate values inside sets.

    Closes #5880

  • Added the super-without-brackets checker, raised when a super call is missing its brackets.

    Closes #4008

Removed checkers

  • The no-init (W0232) warning has been removed. It's ok to not have an __init__ in a class.

    Closes #2409

  • Removed the assign-to-new-keyword message as there are no new keywords in the supported Python versions any longer.

    Closes #4683

  • Moved no-self-use check to optional extension. You now need to explicitly enable this check using load-plugins=pylint.extensions.no_self_use.

    Closes #5502

RedefinedLoopNameChecker
Added optional extension redefined-loop-name to emit messages when a loop variable is redefined in the loop body.

Closes #5072

DocStringStyleChecker
Re-enable checker bad-docstring-quotes for Python <= 3.7.

Closes #6087

NoSelfUseChecker
Added no-self-use check, previously enabled by default.

Closes #5502

Other Changes

  • Started ignoring underscore as a local variable for too-many-locals.

    Closes #6488

  • Pylint can now be installed with an extra-require called spelling (pip install pylint[spelling]). This will add pyenchant to pylint's dependencies. You will still need to install the requirements for pyenchant (the enchant library and any dictionaries) yourself. You will also need to set the spelling-dict option.

    Refs #6462

  • Improved wording of the message of deprecated-module

    Closes #6169

  • Pylint now requires Python 3.7.2 or newer to run.

    Closes #4301

  • We made a greater effort to reraise failures stemming from the astroid library as AstroidError, with the effect that pylint emits astroid-error rather than merely fatal. Regardless, please report any such issues you encounter!
  • We have improved our recognition of inline disable and enable comments. It is now possible to disable bad-option-value inline (as long as you disable it before the bad option value is raised, i.e. disable=bad-option-value,bad-message not disable=bad-message,bad-option-value ) as well as certain other previously unsupported messages.

    Closes #3312

  • The main checker name is now main instead of master. The configuration does not need to be updated as sections' name are optional.

    Closes #5467

  • Update invalid-slots-object message to show bad object rather than its inferred value.

    Closes #6101

  • Fixed a crash in the not-an-iterable checker involving multiple starred expressions inside a call.

    Closes #6372

  • Fixed a crash in the unused-private-member checker involving chained private attributes.

    Closes #6709

  • Disable spellchecking of mypy rule names in ignore directives.

    Closes #5929

  • implicit-str-concat will now be raised on calls like open("myfile.txt" "a+b") too.

    Closes #6441

  • Fix a failure to respect inline disables for fixme occurring on the last line of a module when pylint is launched with --enable=fixme.
  • Removed the broken generate-man option.

    Closes #5283 Closes #1887

  • Fixed failure to enable deprecated-module after a disable=all by making ImportsChecker solely responsible for emitting deprecated-module instead of sharing responsibility with StdlibChecker. (This could have led to double messages.)
  • Added the generate-toml-config option.

    Refs #5462

  • bad-option-value will be emitted whenever a configuration value or command line invocation includes an unknown message.

    Closes #4324

  • Added the unrecognized-option message. Raised if we encounter any unrecognized options.

    Closes #5259

  • Fix false negative for bad-string-format-type if the value to be formatted is passed in as a variable holding a constant.
  • The concept of checker priority has been removed.
  • The cache-max-size-none checker has been renamed to method-cache-max-size-none.

    Closes #5670

  • The method-cache-max-size-none checker will now also check functools.cache.

    Closes #5670

  • BaseChecker classes now require the linter argument to be passed.
  • The set_config_directly decorator has been removed.
  • Don't report useless-super-delegation for the __hash__ method in classes that also override the __eq__ method.

    Closes #3934

  • Fix falsely issuing useless-suppression on the wrong-import-position checker.

    Closes #5219

  • Fixed false positive no-member for Enums with self-defined members.

    Closes #5138

  • Fix false negative for no-member when attempting to assign an instance attribute to itself without any prior assignment.

    Closes #1555

  • Changed message type from redefined-outer-name to redefined-loop-name (optional extension) for redefinitions of outer loop variables by inner loops.

    Closes #5608

  • By default the similarity checker will now ignore imports and ignore function signatures when computing duplication. If you want to keep the previous behaviour set ignore-imports and ignore-signatures to False.
  • Pylint now expands the user path (i.e. ~ to home/yusef/) and expands environment variables (i.e. home/$USER/$project to home/yusef/pylint for USER=yusef and project=pylint) for pyreverse's output-directory, import-graph, ext-import-graph, int-import-graph options, and the spell checker's spelling-private-dict-file option.

    Refs #6493

  • Don't emit unsubscriptable-object for string annotations. Pylint doesn't check if class is only generic in type stubs only.

    Closes #4369 and #6523

  • Fix pyreverse crash RuntimeError: dictionary changed size during iteration

    Refs #6612

  • Fix syntax for return type annotations in MermaidJS diagrams produced with pyreverse.

    Closes #6467

  • Fix type annotations of class and instance attributes using the alternative union syntax in pyreverse diagrams.
  • Fix bug where it writes a plain text error message to stdout, invalidating output formats.

    Closes #6597

  • The refactoring checker now also raises 'consider-using-a-generator' messages for max(), min() and sum().

    Refs #6595

  • Update ranges for using-constant-test and missing-parentheses-for-call-in-test error messages.
  • Don't emit no-member inside type annotations with from __future__ import annotations.

    Closes #6594

  • Fix unexpected-special-method-signature false positive for __init_subclass__ methods with one or more arguments.

    Closes #6644

  • The ignore-mixin-members option has been deprecated. You should now use the new ignored-checks-for-mixins option.

    Closes #5205

  • interfaces.implements has been deprecated and will be removed in 3.0. Please use standard inheritance patterns instead of __implements__.

    Refs #2287

  • All Interface classes in pylint.interfaces have been deprecated. You can subclass the respective normal classes to get the same behaviour. The __implements__ functionality was based on a rejected PEP from 2001: https://peps.python.org/pep-0245/

    Closes #2287

  • MapReduceMixin has been deprecated. BaseChecker now implements get_map_data and reduce_map_data. If a checker actually needs to reduce data it should define get_map_data as returning something different than None and let its reduce_map_data handle a list of the types returned by get_map_data. An example can be seen by looking at pylint/checkers/similar.py.
  • The config attribute of BaseChecker has been deprecated. You can use checker.linter.config to access the global configuration object instead of a checker-specific object.

    Refs #5392

  • The level attribute of BaseChecker has been deprecated: everything is now displayed in --help, all the time.

    Refs #5392

  • The set_option method of BaseChecker has been deprecated. You can use checker.linter.set_option to set an option on the global configuration object instead of a checker-specific object.

    Refs #5392

  • The options_providers attribute of ArgumentsManager has been deprecated.

    Refs #5392

  • Fix saving of persistent data files in environments where the user's cache directory and the linted file are on a different drive.

    Closes #6394

  • The method-cache-max-size-none checker will now also check functools.cache.
  • The config attribute of PyLinter is now of the argparse.Namespace type instead of optparse.Values.

    Refs #5392

  • UnsupportedAction has been deprecated.

    Refs #5392

  • OptionsManagerMixIn has been deprecated.

    Refs #5392

  • OptionParser has been deprecated.

    Refs #5392

  • Option has been deprecated.

    Refs #5392

  • OptionsProviderMixIn has been deprecated.

    Refs #5392

  • ConfigurationMixIn has been deprecated.
  • The option_groups attribute of PyLinter has been deprecated.

    Refs #5392

  • get_global_config has been deprecated. You can now access all global options from checker.linter.config.

    Refs #5392

  • OptionsManagerMixIn has been replaced with ArgumentsManager. ArgumentsManager is considered private API and most methods that were public on OptionsManagerMixIn have now been deprecated and will be removed in a future release.

    Refs #5392

  • OptionsProviderMixIn has been replaced with ArgumentsProvider. ArgumentsProvider is considered private API and most methods that were public on OptionsProviderMixIn have now been deprecated and will be removed in a future release.

    Refs #5392

  • pylint.pyreverse.ASTWalker has been removed, as it was only used internally by a single child class.

    Refs #6712

  • pyreverse: Resolving and displaying implemented interfaces that are defined by the __implements__ attribute has been deprecated and will be removed in 3.0.

    Refs #6713

  • is_class_subscriptable_pep585_with_postponed_evaluation_enabled has been deprecated. Use is_postponed_evaluation_enabled(node) and is_node_in_type_annotation_context(node) instead.

    Refs #6536

Full changelog

What's New in Pylint 2.14.5?

Release date: 2022-07-17

  • Fixed a crash in the undefined-loop-variable check when enumerate() is used in a ternary expression.

    Closes #7131

  • Fixed handling of -- as separator between positional arguments and flags.

    Closes #7003

  • Fixed the disabling of fixme and its interaction with useless-suppression.
  • Allow lists of default values in parameter documentation for Numpy style.

    Closes #4035

What's New in Pylint 2.14.4?

Release date: 2022-06-29

  • The differing-param-doc check was triggered by positional only arguments.

    Closes #6950

  • Fixed an issue where scanning . directory recursively with --ignore-path=^path/to/dir is not ignoring the path/to/dir directory.

    Closes #6964

  • Fixed regression that didn't allow quoted init-hooks in option files.

    Closes #7006

  • Fixed a false positive for modified-iterating-dict when updating an existing key.

    Closes #6179

  • Fixed an issue where many-core Windows machines (>~60 logical processors) would hang when using the default jobs count.

    Closes #6965

  • Fixed an issue with the recognition of setup.cfg files. Only .cfg files that are exactly named setup.cfg require section names that start with pylint..

    Closes #3630

  • Don't report import-private-name for relative imports.

    Closes #7078

What's New in Pylint 2.14.3?

Release date: 2022-06-18

  • Fixed two false positives for bad-super-call for calls that refer to a non-direct parent.

    Closes #4922, Closes #2903

  • Fixed a false positive for useless-super-delegation for subclasses that specify the number of of parameters against a parent that uses a variadic argument.

    Closes #2270

  • Allow suppressing undefined-loop-variable and undefined-variable without raising useless-suppression.
  • Fixed false positive for undefined-variable for __class__ in inner methods.

    Closes #4032

What's New in Pylint 2.14.2?

Release date: 2022-06-15

  • Fixed a false positive for unused-variable when a function returns an argparse.Namespace object.

    Closes #6895

  • Avoided raising an identical undefined-loop-variable message twice on the same line.
  • Don't crash if lint.run._query_cpu() is run within a Kubernetes Pod, that has only a fraction of a cpu core assigned. Just go with one process then.

    Closes #6902

  • Fixed a false positive in consider-using-f-string if the left side of a % is not a string.

    Closes #6689

  • Fixed a false positive in unnecessary-list-index-lookup and unnecessary-dict-index-lookup when the subscript is updated in the body of a nested loop.

    Closes #6818

  • Fixed an issue with multi-line init-hook options which did not record the line endings.

    Closes #6888

  • Fixed a false positive for used-before-assignment when a try block returns but an except handler defines a name via type annotation.
  • --errors-only no longer enables previously disabled messages. It was acting as "emit all and only error messages" without being clearly documented that way.

    Closes #6811

What's New in Pylint 2.14.1?

Release date: 2022-06-06

  • Avoid reporting unnecessary-dict-index-lookup or unnecessary-list-index-lookup when the index lookup is part of a destructuring assignment.

    Closes #6788

  • Fixed parsing of unrelated options in tox.ini.

    Closes #6800

  • Fixed a crash when linting __new__() methods that return a call expression.

    Closes #6805

  • Don't crash if we can't find the user's home directory.

    Closes #6802

  • Fixed false positives for unused-import when aliasing typing e.g. as t and guarding imports under t.TYPE_CHECKING.

    Closes #3846

  • Fixed a false positive regression in 2.13 for used-before-assignment where it is safe to rely on a name defined only in an except block because the else block returned.

    Closes #6790

  • Fixed the use of abbreviations for some special options on the command line.

    Closes #6810

  • Fix a crash in the optional pylint.extensions.private_import extension.

    Closes #6624

  • bad-option-value (E0012) is now a warning unknown-option-value (W0012). Deleted messages that do not exist anymore in pylint now raise useless-option-value (R0022) instead of bad-option-value. This allows to distinguish between genuine typos and configuration that could be cleaned up. Existing message disables for bad-option-value will still work on both new messages.

    Refs #6794

What's New in Pylint 2.14.0?

Release date: 2022-06-01

  • The refactoring checker now also raises 'consider-using-generator' messages for max(), min() and sum().

    Refs #6595

  • We have improved our recognition of inline disable and enable comments. It is now possible to disable bad-option-value inline (as long as you disable it before the bad option value is raised, i.e. disable=bad-option-value,bad-message not disable=bad-message,bad-option-value ) as well as certain other previously unsupported messages.

    Closes #3312

  • Fixed a crash in the unused-private-member checker involving chained private attributes.

    Closes #6709

  • Added new checker comparison-of-constants.

    Closes #6076

  • pylint.pyreverse.ASTWalker has been removed, as it was only used internally by a single child class.

    Refs #6712

  • pyreverse: Resolving and displaying implemented interfaces that are defined by the __implements__ attribute has been deprecated and will be removed in 3.0.

    Refs #6713

  • Fix syntax for return type annotations in MermaidJS diagrams produced with pyreverse.

    Closes #6467

  • Fix type annotations of class and instance attributes using the alternative union syntax in pyreverse diagrams.
  • Fix unexpected-special-method-signature false positive for __init_subclass__ methods with one or more arguments.

    Closes #6644

  • Started ignoring underscore as a local variable for too-many-locals.

    Closes #6488

  • Improved wording of the message of deprecated-module

    Closes #6169

  • Pylint now requires Python 3.7.2 or newer to run.

    Closes #4301

  • BaseChecker classes now require the linter argument to be passed.
  • Fix a failure to respect inline disables for fixme occurring on the last line of a module when pylint is launched with --enable=fixme.
  • Update invalid-slots-object message to show bad object rather than its inferred value.

    Closes #6101

  • The main checker name is now main instead of master. The configuration does not need to be updated as sections' name are optional.

    Closes #5467

  • Don't report useless-super-delegation for the __hash__ method in classes that also override the __eq__ method.

    Closes #3934

  • Added new checker typevar-name-mismatch: TypeVar must be assigned to a variable with the same name as its name argument.

    Closes #5224

  • Pylint can now be installed with an extra-require called spelling (pip install pylint[spelling]). This will add pyenchant to pylint's dependencies. You will still need to install the requirements for pyenchant (the enchant library and any dictionaries) yourself. You will also need to set the spelling-dict option.

    Refs #6462

  • Removed the assign-to-new-keyword message as there are no new keywords in the supported Python versions any longer.

    Closes #4683

  • Fixed a crash in the not-an-iterable checker involving multiple starred expressions inside a call.

    Closes #6372

  • Fixed a crash in the docparams extension involving raising the result of a function.
  • Fixed failure to enable deprecated-module after a disable=all by making ImportsChecker solely responsible for emitting deprecated-module instead of sharing responsibility with StdlibChecker. (This could have led to double messages.)
  • The no-init (W0232) warning has been removed. It's ok to not have an __init__ in a class.

    Closes #2409

  • The config attribute of BaseChecker has been deprecated. You can use checker.linter.config to access the global configuration object instead of a checker-specific object.

    Refs #5392

  • The level attribute of BaseChecker has been deprecated: everything is now displayed in --help, all the time.

    Refs #5392

  • The options_providers attribute of ArgumentsManager has been deprecated.

    Refs #5392

  • The option_groups attribute of PyLinter has been deprecated.

    Refs #5392

  • All Interface classes in pylint.interfaces have been deprecated. You can subclass the respective normal classes to get the same behaviour. The __implements__ functionality was based on a rejected PEP from 2001: https://peps.python.org/pep-0245/

    Closes #2287

  • The set_option method of BaseChecker has been deprecated. You can use checker.linter.set_option to set an option on the global configuration object instead of a checker-specific object.

    Refs #5392

  • implicit-str-concat will now be raised on calls like open("myfile.txt" "a+b") too.

    Closes #6441

  • The config attribute of PyLinter is now of the argparse.Namespace type instead of optparse.Values.

    Refs #5392

  • MapReduceMixin has been deprecated. BaseChecker now implements get_map_data and reduce_map_data. If a checker actually needs to reduce data it should define get_map_data as returning something different than None and let its reduce_map_data handle a list of the types returned by get_map_data. An example can be seen by looking at pylint/checkers/similar.py.
  • UnsupportedAction has been deprecated.

    Refs #5392

  • OptionsManagerMixIn has been deprecated.

    Refs #5392

  • OptionParser has been deprecated.

    Refs #5392

  • Option has been deprecated.

    Refs #5392

  • OptionsProviderMixIn has been deprecated.

    Refs #5392

  • ConfigurationMixIn has been deprecated.

    Refs #5392

  • get_global_config has been deprecated. You can now access all global options from checker.linter.config.

    Refs #5392

  • OptionsManagerMixIn has been replaced with ArgumentsManager. ArgumentsManager is considered private API and most methods that were public on OptionsManagerMixIn have now been deprecated and will be removed in a future release.

    Refs #5392

  • OptionsProviderMixIn has been replaced with ArgumentsProvider. ArgumentsProvider is considered private API and most methods that were public on OptionsProviderMixIn have now been deprecated and will be removed in a future release.

    Refs #5392

  • interfaces.implements has been deprecated and will be removed in 3.0. Please use standard inheritance patterns instead of __implements__.

    Refs #2287

  • invalid-enum-extension: Used when a class tries to extend an inherited Enum class.

    Closes #5501

  • Added the unrecognized-option message. Raised if we encounter any unrecognized options.

    Closes #5259

  • Added new checker typevar-double-variance: The "covariant" and "contravariant" keyword arguments cannot both be set to "True" in a TypeVar.

    Closes #5895

  • Re-enable checker bad-docstring-quotes for Python <= 3.7.

    Closes #6087

  • Removed the broken generate-man option.

    Closes #5283 Closes #1887

  • Fix false negative for bad-string-format-type if the value to be formatted is passed in as a variable holding a constant.
  • Add new check unnecessary-dunder-call for unnecessary dunder method calls.

    Closes #5936 Closes #6074

  • The cache-max-size-none checker has been renamed to method-cache-max-size-none.

    Closes #5670

  • The method-cache-max-size-none checker will now also check functools.cache.

    Closes #5670

  • unnecessary-lambda-assignment: Lambda expression assigned to a variable. Define a function using the "def" keyword instead. unnecessary-direct-lambda-call: Lambda expression called directly. Execute the expression inline instead.

    Closes #5976

  • potential-index-error: Emitted when the index of a list or tuple exceeds its length. This checker is currently quite conservative to avoid false positives. We welcome suggestions for improvements.

    Closes #578

  • Added optional extension redefined-loop-name to emit messages when a loop variable is redefined in the loop body.

    Closes #5072

  • Changed message type from redefined-outer-name to redefined-loop-name (optional extension) for redefinitions of outer loop variables by inner loops.

    Closes #5608

  • The ignore-mixin-members option has been deprecated. You should now use the new ignored-checks-for-mixins option.

    Closes #5205

  • bad-option-value will be emitted whenever a configuration value or command line invocation includes an unknown message.

    Closes #4324

  • Avoid reporting superfluous-parens on expressions using the is not operator.

    Closes #5930

  • Added the super-without-brackets checker, raised when a super call is missing its brackets.

    Closes #4008

  • Added the generate-toml-config option.

    Refs #5462

  • Added new checker unnecessary-list-index-lookup for indexing into a list while iterating over enumerate().

    Closes #4525

  • Fix falsely issuing useless-suppression on the wrong-import-position checker.

    Closes #5219

  • Fixed false positive no-member for Enums with self-defined members.

    Closes #5138

  • Fix false negative for no-member when attempting to assign an instance attribute to itself without any prior assignment.

    Closes #1555

  • The concept of checker priority has been removed.
  • Add a new command line option --minimal-messages-config for pytest, which disables all irrelevant messages when running the functional tests.
  • duplicate-argument-name now only raises once for each set of duplicated arguments.
  • Fix bug where specifically enabling just await-outside-async was not possible.
  • The set_config_directly decorator has been removed.
  • Added new message called duplicate-value which identifies duplicate values inside sets.

    Closes #5880

  • Pylint now expands the user path (i.e. ~ to home/yusef/) and expands environment variables (i.e. home/$USER/$project to home/yusef/pylint for USER=yusef and project=pylint) for pyreverse's output-directory, import-graph, ext-import-graph, int-import-graph options, and the spell checker's spelling-private-dict-file option.

    Refs #6493

  • Created NoSelfUseChecker extension and moved the no-self-use check. You now need to explicitly enable this check using load-plugins=pylint.extensions.no_self_use.

    Closes #5502

  • Fix saving of persistent data files in environments where the user's cache directory and the linted file are on a different drive.

    Closes #6394

  • Don't emit unsubscriptable-object for string annotations. Pylint doesn't check if class is only generic in type stubs only.

    Closes #4369 and #6523

  • Fix pyreverse crash RuntimeError: dictionary changed size during iteration

    Refs #6612

  • Fix bug where it writes a plain text error message to stdout, invalidating output formats.

    Closes #6597

  • is_class_subscriptable_pep585_with_postponed_evaluation_enabled has been deprecated. Use is_postponed_evaluation_enabled(node) and is_node_in_type_annotation_context(node) instead.

    Refs #6536

  • Update ranges for using-constant-test and missing-parentheses-for-call-in-test error messages.
  • Don't emit no-member inside type annotations with from __future__ import annotations.

    Closes #6594

What's New in Pylint 2.13

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

In 2.13, we introduced a new check to deal with unicode security issues. On top of that a lot of work was done inside the unicode checker by @CarliJoy. We also introduced a new check when importing private name and for unnecessary ellipsis among other.

We fixed long standing issues related to duplicate code that could not be disabled, line numbers that were not accurate some of the time, and added the ability to lint all files in a directory without specifying each one. One of the most anticipated issue from the repository. Thank you @matusvalo !

A lot of undefined-variables and used-before-assignment issues were resolved thanks to @jacobtylerwalls.

We started integrating pylint-error the documentation created by @vald-phoenix a developer from Hlyniane, Ukraine. We hope he's doing well despite the current situation. The deployment is set up but there's still a lot to do so we welcome any community effort help to review, integrate, and add good/bad examples. This should be doable without any pylint or astroid knowledge, so this is the perfect entrypoint if you want to contribute to pylint without investing any time learning the internals.

This release is the last one to support interpreter below 3.7.2, 3.6 end of life was reached in december 2021.

New checkers

Added several checkers to deal with unicode security issues (see Trojan Sources and PEP 672 for details) that also concern the readability of the code. In detail the following checks were added:
  • bad-file-encoding checks that the file is encoded in UTF-8 as suggested by PEP8. UTF-16 and UTF-32 are not supported by Python at the moment. If this ever changes invalid-unicode-codec checks that they aren't used, to allow for backwards compatibility.
  • bidirectional-unicode checks for bidirectional unicode characters that could make code execution different than what the user expects.
  • invalid-character-backspace, invalid-character-carriage-return, invalid-character-sub, invalid-character-esc, invalid-character-zero-width-space and invalid-character-nul to check for possibly harmful unescaped characters.

Closes #5281

  • unnecessary-ellipsis: Emitted when the ellipsis constant is used unnecessarily.

    Closes #5460

  • Added new checker typevar-name-missing-variance. Emitted when a covariant or contravariant TypeVar does not end with _co or _contra respectively or when a TypeVar is not either but has a suffix.
  • Add modified-iterating-list, modified-iterating-dict, and modified-iterating-set, emitted when items are added to or removed from respectively a list, dictionary or set being iterated through.

    Closes #5348

  • Add checker redefined-slots-in-subclass: Emitted when a slot is redefined in a subclass.

    Closes #5617

It now ensures __all__ Python names are ASCII and also properly checks the names of imports (non-ascii-module-import) as well as file names (non-ascii-file-name) and emits their respective new warnings.

Non ASCII characters could be homoglyphs (look alike characters) and hard to enter on a non specialized keyboard. See Confusable Characters in PEP 672

Added cache-max-size-none checker with checks for the use of functools.lru_cache on class methods with a maxsize of None. This is unrecommended as it creates memory leaks by never letting the instance get garbage collected.

Closes #5670 Clsoes #6180

Removed checkers

Removed the deprecated check_docs extension. You can use the docparams checker to get the checks previously included in check_docs.

Closes #5322

  • New extension import-private-name: indicate imports of external private packages and objects (prefixed with _). It can be loaded using load-plugins=pylint.extensions.private_import.

    Closes #5463

  • Pyreverse - add output in mermaid-js format and html which is an mermaid js diagram with html boilerplate
  • TypingChecker
DocstringParameterChecker
Fixed incorrect classification of Numpy-style docstring as Google-style docstring for docstrings with property setter documentation. Docstring classification is now based on the highest amount of matched sections instead of the order in which the docstring styles were tried.
DocStringStyleChecker
Disable checker bad-docstring-quotes for Python <= 3.7, because in these versions the line numbers for decorated functions and classes are not reliable which interferes with the checker.

Closes #3077

Other Changes

  • Include testing_pylintrc in source and wheel distributions.

    Closes #6028

  • Fix false positive for unused-import when disabling both used-before-assignment and undefined-variable.

    Closes #6089

  • Fix false positive for unnecessary-ellipsis when using an ellipsis as a default argument.

    Closes #5973

  • Add missing dunder methods to unexpected-special-method-signature check.
  • No longer emit no-member in for loops that reference self if the binary operation that started the for loop uses a self that is encapsulated in tuples or lists.

    Refs PyCQA/astroid#1360 Closes #4826

  • Fix matching --notes options that end in a non-word character.

    Closes #5840

  • The line numbering for messages related to function arguments is now more accurate. This can require some message disables to be relocated to updated positions.
were renamed from W1601 and W1602 to W2601 and W2602. Disables using these msgids will break. This is done in order to restore consistency with the already existing msgids for apply-builtin and basestring-builtin from the now deleted python 3K+ checker. There is now a check that we're not using existing msgids or symbols from deleted checkers.

Closes #5729

  • Add --recursive option to allow recursive discovery of all modules and packages in subtree. Running pylint with --recursive=y option will check all discovered .py files and packages found inside subtree of directory provided as parameter to pylint.

    Closes #352

  • Updated the position of messages for class and function definitions to no longer cover the complete definition. Only the def or class + the name of the class/function are covered.

    Closes #5466

  • Reinstated checks from the python3 checker that are still useful for python 3 (eq-without-hash). This is now in the pylint.extensions.eq_without_hash optional extension.

    Closes #5025

  • Fix false-negative for assignment-from-none checker with list.sort() method.

    Closes #5722

  • Fix unused-private-member false positive when accessing private methods through property.

    Closes #4756

  • Fixed crash from arguments-differ and arguments-renamed when methods were defined outside the top level of a class.

    Closes #5648

  • Better warning messages for useless else or elif when a function returns early.

    Closes #5614

  • Asterisks are no longer required in Sphinx and Google style parameter documentation for missing-param-doc and are parsed correctly.

    Closes #5815 Closes #5406

  • Fixed an AstroidError in 2.13.0 raised by the `duplicate-code` checker with ignore-imports or ignore-signatures enabled.

    Closes #6301

  • Use the tomli package instead of toml to parse .toml files.

    Closes #5885

  • Fixed false positive consider-using-dict-comprehension when creating a dict using a list of tuples where key AND value vary depending on the same condition.

    Closes #5588

  • When run in parallel mode pylint now pickles the data passed to subprocesses with the dill package. The dill package has therefore been added as a dependency.
  • Fixed false positive for global-variable-undefined when global is used with a class name

    Closes #3088

  • Fixed crash on properties and inherited class methods when comparing them for equality against an empty dict.

    Closes #5646

  • By default, pylint does no longer take files starting with .# into account. Those are considered Emacs file locks. This behavior can be reverted by redefining the ignore-patterns option.

    Closes #367

  • Fix super-init-not-called when parent or self is a Protocol

    Closes #4790

  • The issue template for crashes is now created for crashes which were previously not covered by this mechanism.

    Closes #5668

  • An astroid issue where symlinks were not being taken into account was fixed

    Closes #1470 Closes #3499 Closes #4302 Closes #4798 Closes #5081

  • Fix false negative for undefined-variable and related variable messages when the same undefined variable is used as a type annotation and is accessed multiple times, or is used as a default argument to a function.

    Closes #5399

  • Emit used-before-assignment instead of undefined-variable when attempting to access unused type annotations.

    Closes #5713

  • Fixed an issue where ungrouped-imports could not be disabled without raising useless-suppression.

    Refs #2366

  • Fixed a crash on __init__ nodes when the attribute was previously uninferable due to a cache limit size. This limit can be hit when the inheritance pattern of a class (and therefore of the __init__ attribute) is very large.

    Closes #5679

  • Fixed extremely long processing of long lines with comma's.

    Closes #5483

  • Fix false positive super-init-not-called for classes that inherit their init from a parent.

    Closes #4941

  • Fix false positives for used-before-assignment from using named expressions in a ternary operator test and using that expression as a call argument.

    Closes #5177, #5212

  • Fixed crash with recursion error for inference of class attributes that referenced the class itself.

    Closes #5408 RefsPyCQA/astroid#1392

  • Fixed false positive for unused-argument when a method overridden in a subclass does nothing with the value of a keyword-only argument.

    Closes #5771 RefsPyCQA/astroid#1382

  • Optimize parsing of long lines when missing-final-newline is enabled.

    Closes #5724

  • Fix false positive for used-before-assignment from a class definition nested under a function subclassing a class defined outside the function.

    Closes #4590

  • Fix unnecessary_dict_index_lookup false positive when deleting a dictionary's entry.

    Closes #4716

  • Fix false positive for used-before-assignment when an except handler shares a name with a test in a filtered comprehension.

    Closes #5817

  • Fix a crash in unused-private-member checker when analyzing code using type(self) in bound methods.

    Closes #5569

  • Fix crash in unnecessary-dict-index-lookup checker if the output of items() is assigned to a 1-tuple.

    Closes #5504

  • Fixed crash with slots assignments and annotated assignments.

    Closes #5479

  • Fixed a crash in unspecified-encoding checker when providing None to the mode argument of an open() call.

    Closes #5731

  • Fixed a crash involving a NewType named with an f-string.

    Closes #5770 RefsPyCQA/astroid#1400

  • Improved bad-open-mode message when providing None to the mode argument of an open() call.

    Closes #5733

  • Fix false negative for consider-iterating-dictionary during membership checks encapsulated in iterables or not in checks

    Closes #5323

  • Allow disabling duplicate-code with a disable comment when running through pylint.

    Closes #214

  • Fix false positive for undefined-variable when namedtuple class attributes are used as return annotations.

    Closes #5568

  • Added confidence level CONTROL_FLOW for warnings relying on assumptions about control flow.
  • used-before-assignment now considers that assignments in a try block may not have occurred when the except or finally blocks are executed.

    Closes #85, #2615

  • Fixed false negative for used-before-assignment when a conditional or context manager intervened before the try statement that suggested it might fail.

    Closes #4045

  • Fixed false negative for used-before-assignment in finally blocks if an except handler did not define the assignment that might have failed in the try block.
  • Fix a false positive for assigning-non-slot when the slotted class defined __setattr__.

    Closes #3793

  • Fixed a false positive for invalid-class-object when the object being assigned to the __class__ attribute is uninferable.
  • Added a testutil extra require to the packaging, as gitpython should not be a dependency all the time but is still required to use the primer helper code in pylint.testutil. You can install it with pip install pylint[testutil].

    Closes #5486

  • Fixed a false positive for used-before-assignment when a named expression appears as the first value in a container.

    Closes #5112

  • Fixed false positive for used-before-assignment with self-referential type annotation in conditional statements within class methods.

    Closes #5499

  • used-before-assignment now assumes that assignments in except blocks may not have occurred and warns accordingly.

    Closes #4761

  • When evaluating statements after an except block, used-before-assignment assumes that assignments in the except blocks took place if the corresponding try block contained a return statement.

    Closes #5500

  • Fixed a false negative for used-before-assignment when some but not all except handlers defined a name relied upon after an except block when the corresponding try block contained a return statement.

    Closes #5524

  • When evaluating statements in the else clause of a loop, used-before-assignment assumes that assignments in the except blocks took place if the except handlers constituted the only ways for the loop to finish without breaking early.

    Closes #5683

  • used-before-assignment now checks names in try blocks.
  • Fixed false positive with used-before-assignment for assignment expressions in lambda statements.

    Closes #5360, #3877

  • Improve invalid-name check for TypeVar names. The accepted pattern can be customized with --typevar-rgx.

    Closes #3401

  • Fixed a false positive (affecting unreleased development) for used-before-assignment involving homonyms between filtered comprehensions and assignments in except blocks.

    Closes #5586

  • Fixed crash on list comprehensions that used type as inner variable name.

    Closes #5461

  • Fixed crash in use-maxsplit-arg checker when providing the sep argument to str.split() by keyword.

    Closes #5737

  • Fix false positive for unused-variable for a comprehension variable matching an outer scope type annotation.

    Closes #5326

  • Fix false negative for undefined-variable for a variable used multiple times in a comprehension matching an unused outer scope type annotation.

    Closes #5654

  • Require Python 3.6.2 to run pylint.

    Closes #5065

  • Fixed crash on uninferable decorators on Python 3.6 and 3.7
  • Emit redefined-outer-name when a nested except handler shadows an outer one.

    Closes #4434 Closes #5370

  • encoding can now be supplied as a positional argument to calls that open files without triggering unspecified-encoding.

    Closes #5638

  • Fatal errors now emit a score of 0.0 regardless of whether the linted module contained any statements

    Closes #5451

  • fatal was added to the variables permitted in score evaluation expressions.
  • The default score evaluation now uses a floor of 0.

    Closes #2399

  • Fix comparison-with-callable false positive for callables that raise, such as typing constants.

    Closes #5557

  • When invoking pylint, epylint, symilar or pyreverse by importing them in a python file you can now pass an argv keyword besides patching sys.argv.

    Closes #5320

  • The PyLinter class will now be initialized with a TextReporter as its reporter if none is provided.
  • Fix false positive not-callable with attributes that alias NamedTuple

    Fixes part of #1730

  • The testutils for unittests now accept end_lineno and end_column. Tests without these will trigger a DeprecationWarning.
  • arguments-differ will no longer complain about method redefinitions with extra parameters that have default values.

    Closes #1556, #5338

  • Disables for deprecated-module and similar warnings for stdlib features deprecated in newer versions of Python no longer raise useless-suppression when linting with older Python interpreters where those features are not yet deprecated.
  • Importing the deprecated stdlib module xml.etree.cElementTree now emits deprecated_module.

    Closes #5862

  • Importing the deprecated stdlib module distutils now emits deprecated_module on Python 3.10+.
  • Fixed false positive unexpected-keyword-arg for decorators.

    Closes #258

  • missing-raises-doc will now check the class hierarchy of the raised exceptions
def my_function():

"""My function.
Raises:
Exception: if something fails
"""
raise ValueError

Closes #4955

  • Fixed false positive for unused-variable when a nonlocal name is assigned as part of a multi-name assignment.

    Closes #3781

  • Fix false positive - Allow unpacking of self in a subclass of typing.NamedTuple.

    Closes #5312

  • Fixed false negative unpacking-non-sequence when value is an empty list.

    Closes #5707

  • Fixed false positive for global-variable-not-assigned when the del statement is used

    Closes #5333

  • Fix type hints in class diagrams generated by pyreverse for class methods and methods returning None.
  • Output better error message if unsupported file formats are used with pyreverse.

    Closes #5950

  • Fixed false positive for unused-argument when a nonlocal name is used in a nested function that is returned without being called by its parent.

    Closes #5187

  • Avoid emitting raising-bad-type when there is inference ambiguity on the variable being raised.

    Closes #2793

  • Fix false positive for superfluous-parens for patterns like "return (a or b) in iterable".

    Closes #5803

  • Fix a crash in the unsupported-membership-test checker when assigning multiple constants to class attributes including __iter__ via unpacking.

    Closes #6366

  • Fix false positive for used-before-assignment for assignments taking place via nonlocal declarations after an earlier type annotation.

    Closes #5394

  • Fixed a false positive for unused-variable when a builtin specified in --additional-builtins is given a type annotation.

    Closes #6388

  • Fix false positive for 'nonexistent-operator' when repeated '-' are separated (e.g. by parens).

    Closes #5769

  • Fix a false positive for undefined-loop-variable when the else of a for loop raises or returns.

    Closes #5971

  • Only raise not-callable when all the inferred values of a property are not callable.

    Closes #5931

  • Fix false positive for unused-variable for classes inside functions and where a metaclass is provided via a call.

    Closes #4020

  • Avoid reporting superfluous-parens on expressions using the is not operator.

    Closes #5930

  • Fix a false positive for undefined-loop-variable for a variable used in a lambda inside the first of multiple loops.

    Closes #6419

  • Fix false positive for unsubscriptable-object in Python 3.8 and below for statements guarded by if TYPE_CHECKING.

    Closes #3979

  • Fix a crash when accessing __code__ and assigning it to a variable.

    Closes #6539

  • Fix a crash when linting a file that passes an integer mode= to open

    Closes #6414

  • Fix false positives for no-name-in-module and import-error for numpy.distutils and pydantic.

    Closes #6497

  • Fix IndexError crash in uninferable_final_decorators method.

    Refs #6531

  • Fix a crash in unnecessary-dict-index-lookup when subscripting an attribute.

    Closes #6557

  • Fix a false positive for undefined-loop-variable when using enumerate().

    Closes #6593

Full changelog

What's New in Pylint 2.13.9?

Release date: 2022-05-13

  • Respect ignore configuration options with --recursive=y.

    Closes #6471

  • Fix false positives for no-name-in-module and import-error for numpy.distutils and pydantic.

    Closes #6497

  • Fix IndexError crash in uninferable_final_decorators method.

    Refs #6531

  • Fix a crash in unnecessary-dict-index-lookup when subscripting an attribute.

    Closes #6557

  • Fix a crash when accessing __code__ and assigning it to a variable.

    Closes #6539

  • Fix a false positive for undefined-loop-variable when using enumerate().

    Closes #6593

What's New in Pylint 2.13.8?

Release date: 2022-05-02

  • Fix a false positive for undefined-loop-variable for a variable used in a lambda inside the first of multiple loops.

    Closes #6419

  • Fix a crash when linting a file that passes an integer mode= to open

    Closes #6414

  • Avoid reporting superfluous-parens on expressions using the is not operator.

    Closes #5930

  • Fix a false positive for undefined-loop-variable when the else of a for loop raises or returns.

    Closes #5971

  • Fix false positive for unused-variable for classes inside functions and where a metaclass is provided via a call.

    Closes #4020

  • Fix false positive for unsubscriptable-object in Python 3.8 and below for statements guarded by if TYPE_CHECKING.

    Closes #3979

What's New in Pylint 2.13.7?

Release date: 2022-04-20

Fix a crash caused by using the new config from 2.14.0 in 2.13.x code.

Closes #6408

What's New in Pylint 2.13.6?

Release date: 2022-04-20

  • Fix a crash in the unsupported-membership-test checker when assigning multiple constants to class attributes including __iter__ via unpacking.

    Closes #6366

  • Asterisks are no longer required in Sphinx and Google style parameter documentation for missing-param-doc and are parsed correctly.

    Closes #5815 Closes #5406

  • Fixed a false positive for unused-variable when a builtin specified in --additional-builtins is given a type annotation.

    Closes #6388

  • Fixed an AstroidError in 2.13.0 raised by the duplicate-code checker with ignore-imports or ignore-signatures enabled.

    Closes #6301

What's New in Pylint 2.13.5?

Release date: 2022-04-06

  • Fix false positive regression in 2.13.0 for used-before-assignment for homonyms between variable assignments in try/except blocks and variables in subscripts in comprehensions.

    Closes #6069 Closes #6136

  • lru-cache-decorating-method has been renamed to cache-max-size-none and will only be emitted when maxsize is None.

    Closes #6180

  • Fix false positive for unused-import when disabling both used-before-assignment and undefined-variable.

    Closes #6089

  • Narrow the scope of the unnecessary-ellipsis checker to: * functions & classes which contain both a docstring and an ellipsis. * A body which contains an ellipsis nodes.Expr node & at least one other statement.
  • Fix false positive for used-before-assignment for assignments taking place via nonlocal declarations after an earlier type annotation.

    Closes #5394

  • Fix crash for redefined-slots-in-subclass when the type of the slot is not a const or a string.

    Closes #6100

  • Only raise not-callable when all the inferred values of a property are not callable.

    Closes #5931

  • Fix a false negative for subclassed-final-class when a set of other messages were disabled.

What's New in Pylint 2.13.4?

Release date: 2022-03-31

  • Fix false positive regression in 2.13.0 for used-before-assignment for homonyms between variable assignments in try/except blocks and variables in a comprehension's filter.

    Closes #6035

  • Include testing_pylintrc in source and wheel distributions.

    Closes #6028

  • Fix crash in super-init-not-called checker when using ctypes.Union.

    Closes #6027

  • Fix crash for unnecessary-ellipsis checker when an ellipsis is used inside of a container or a lambda expression.

    Closes #6036 Closes #6037 Closes #6048

What's New in Pylint 2.13.3?

Release date: 2022-03-29

  • Fix false positive for unnecessary-ellipsis when using an ellipsis as a default argument.

    Closes #5973

  • Fix crash involving unbalanced tuple unpacking.

    Closes #5998

  • Fix false positive for 'nonexistent-operator' when repeated '-' are separated (e.g. by parens).

    Closes #5769

What's New in Pylint 2.13.2?

Release date: 2022-03-27

  • Fix crash when subclassing a namedtuple.

    Closes #5982

  • Fix false positive for superfluous-parens for patterns like "return (a or b) in iterable".

    Closes #5803

  • Fix a false negative regression in 2.13.0 where protected-access was not raised on functions.

    Closes #5989

  • Better error messages in case of crash if pylint can't write the issue template.

    Refs #5987

What's New in Pylint 2.13.1?

Release date: 2022-03-26

  • Fix a regression in 2.13.0 where used-before-assignment was emitted for the usage of a nonlocal in a try block.

    Closes #5965

  • Avoid emitting raising-bad-type when there is inference ambiguity on the variable being raised.

    Closes #2793

  • Loosen TypeVar default name pattern a bit to allow names with multiple uppercase characters. E.g. HVACModeT or IPAddressT.

    Closes #5981

  • Fixed false positive for unused-argument when a nonlocal name is used in a nested function that is returned without being called by its parent.

    Closes #5187

  • Fix program crash for modified_iterating-list/set/dict when the list/dict/set being iterated through is a function call.

    Closes #5969

  • Don't emit broken-noreturn and broken-collections-callable errors inside if TYPE_CHECKING blocks.

What's New in Pylint 2.13.0?

Release date: 2022-03-24

  • Add missing dunder methods to unexpected-special-method-signature check.
  • No longer emit no-member in for loops that reference self if the binary operation that started the for loop uses a self that is encapsulated in tuples or lists.

    Refs PyCQA/astroid#1360 Closes #4826

  • Output better error message if unsupported file formats are used with pyreverse.

    Closes #5950

  • Fix pyreverse diagrams type hinting for classmethods and staticmethods.
  • Fix pyreverse diagrams type hinting for methods returning None.
  • Fix matching --notes options that end in a non-word character.

    Closes #5840

  • Updated the position of messages for class and function definitions to no longer cover the complete definition. Only the def or class + the name of the class/function are covered.

    Closes #5466

were renamed from W1601 and W1602 to W2601 and W2602. Disabling using these msgids will break. This is done in order to restore consistency with the already existing msgids for apply-builtin and basestring-builtin from the now deleted python 3K+ checker. There is now a check that we're not using existing msgids or symbols from deleted checkers.

Closes #5729

  • The line numbering for messages related to function arguments is now more accurate. This can require some message disables to be relocated to updated positions.
  • Add --recursive option to allow recursive discovery of all modules and packages in subtree. Running pylint with --recursive=y option will check all discovered .py files and packages found inside subtree of directory provided as parameter to pylint.

    Closes #352

  • Add modified-iterating-list, modified-iterating-dict and modified-iterating-set, emitted when items are added to or removed from respectively a list, dictionary or set being iterated through.

    Closes #5348

  • Fix false-negative for assignment-from-none checker using list.sort() method.

    Closes #5722

  • New extension import-private-name: indicate imports of external private packages and objects (prefixed with _). It can be loaded using load-plugins=pylint.extensions.private_import.

    Closes #5463

  • Fixed crash from arguments-differ and arguments-renamed when methods were defined outside the top level of a class.

    Closes #5648

  • Removed the deprecated check_docs extension. You can use the docparams checker to get the checks previously included in check_docs.

    Closes #5322

  • Added a testutil extra require to the packaging, as gitpython should not be a dependency all the time but is still required to use the primer helper code in pylint.testutil. You can install it with pip install pylint[testutil].

    Closes #5486

  • Reinstated checks from the python3 checker that are still useful for python 3 (eq-without-hash). This is now in the pylint.extensions.eq_without_hash optional extension.

    Closes #5025

  • Fixed an issue where ungrouped-imports could not be disabled without raising useless-suppression.

    Refs #2366

  • Added several checkers to deal with unicode security issues (see Trojan Sources and PEP 672 for details) that also concern the readability of the code. In detail the following checks were added:
  • bad-file-encoding checks that the file is encoded in UTF-8 as suggested by PEP8. UTF-16 and UTF-32 are not supported by Python at the moment. If this ever changes invalid-unicode-codec checks that they aren't used, to allow for backwards compatibility.
  • bidirectional-unicode checks for bidirectional unicode characters that could make code execution different than what the user expects.
  • invalid-character-backspace, invalid-character-carriage-return, invalid-character-sub, invalid-character-esc, invalid-character-zero-width-space and invalid-character-nul to check for possibly harmful unescaped characters.

Closes #5281

  • Use the tomli package instead of toml to parse .toml files.

    Closes #5885

  • Fix false positive - Allow unpacking of self in a subclass of typing.NamedTuple.

    Closes #5312

  • Fixed false negative unpacking-non-sequence when value is an empty list.

    Closes #5707

  • Better warning messages for useless else or elif when a function returns early.

    Closes #5614

  • Fixed false positive consider-using-dict-comprehension when creating a dict using a list of tuples where key AND value vary depending on the same condition.

    Closes #5588

  • Fixed false positive for global-variable-undefined when global is used with a class name

    Closes #3088

  • Fixed false positive for unused-variable when a nonlocal name is assigned as part of a multi-name assignment.

    Closes #3781

  • Fixed a crash in unspecified-encoding checker when providing None to the mode argument of an open() call.

    Closes #5731

  • Fixed a crash involving a NewType named with an f-string.

    Closes #5770 Ref PyCQA/astroid#1400

  • Improved bad-open-mode message when providing None to the mode argument of an open() call.

    Closes #5733

  • Added lru-cache-decorating-method checker with checks for the use of functools.lru_cache on class methods. This is unrecommended as it creates memory leaks by never letting the instance getting garbage collected.

    Closes #5670

  • Fixed crash with recursion error for inference of class attributes that referenced the class itself.

    Closes #5408 Ref PyCQA/astroid#1392

  • Fixed false positive for unused-argument when a method overridden in a subclass does nothing with the value of a keyword-only argument.

    Closes #5771 Ref PyCQA/astroid#1382

  • The issue template for crashes is now created for crashes which were previously not covered by this mechanism.

    Closes #5668

It now ensures __all__ Python names are ASCII and also properly checks the names of imports (non-ascii-module-import) as well as file names (non-ascii-file-name) and emits their respective new warnings.

Non ASCII characters could be homoglyphs (look alike characters) and hard to enter on a non specialized keyboard. See Confusable Characters in PEP 672

  • When run in parallel mode pylint now pickles the data passed to subprocesses with the dill package. The dill package has therefore been added as a dependency.
  • An astroid issue where symlinks were not being taken into account was fixed

    Closes #1470 Closes #3499 Closes #4302 Closes #4798 Closes #5081

  • Fix a crash in unused-private-member checker when analyzing code using type(self) in bound methods.

    Closes #5569

  • Optimize parsing of long lines when missing-final-newline is enabled.

    Closes #5724

  • Fix false positives for used-before-assignment from using named expressions in a ternary operator test and using that expression as a call argument.

    Closes #5177, #5212

  • Fix false positive for undefined-variable when namedtuple class attributes are used as return annotations.

    Closes #5568

  • Fix false negative for undefined-variable and related variable messages when the same undefined variable is used as a type annotation and is accessed multiple times, or is used as a default argument to a function.

    Closes #5399

  • Pyreverse - add output in mermaidjs format
  • Emit used-before-assignment instead of undefined-variable when attempting to access unused type annotations.

    Closes #5713

  • Added confidence level CONTROL_FLOW for warnings relying on assumptions about control flow.
  • used-before-assignment now considers that assignments in a try block may not have occurred when the except or finally blocks are executed.

    Closes #85, #2615

  • Fixed false negative for used-before-assignment when a conditional or context manager intervened before the try statement that suggested it might fail.

    Closes #4045

  • Fixed false negative for used-before-assignment in finally blocks if an except handler did not define the assignment that might have failed in the try block.
  • Fixed extremely long processing of long lines with comma's.

    Closes #5483

  • Fixed crash on properties and inherited class methods when comparing them for equality against an empty dict.

    Closes #5646

  • Fixed a false positive for assigning-non-slot when the slotted class defined __setattr__.

    Closes #3793

  • Fixed a false positive for invalid-class-object when the object being assigned to the __class__ attribute is uninferable.
  • Fixed false positive for used-before-assignment with self-referential type annotation in conditional statements within class methods.

    Closes #5499

  • Add checker redefined-slots-in-subclass: Emitted when a slot is redefined in a subclass.

    Closes #5617

  • Fixed false positive for global-variable-not-assigned when the del statement is used

    Closes #5333

  • By default, pylint does no longer take files starting with .# into account. Those are considered Emacs file locks. See https://www.gnu.org/software/emacs/manual/html_node/elisp/File-Locks.html. This behavior can be reverted by redefining the ignore-patterns option.

    Closes #367

  • Fixed a false positive for used-before-assignment when a named expression appears as the first value in a container.

    Closes #5112

  • used-before-assignment now assumes that assignments in except blocks may not have occurred and warns accordingly.

    Closes #4761

  • When evaluating statements after an except block, used-before-assignment assumes that assignments in the except blocks took place if the corresponding try block contained a return statement.

    Closes #5500

  • Fixed a false negative for used-before-assignment when some but not all except handlers defined a name relied upon after an except block when the corresponding try block contained a return statement.

    Closes #5524

  • When evaluating statements in the else clause of a loop, used-before-assignment assumes that assignments in the except blocks took place if the except handlers constituted the only ways for the loop to finish without breaking early.

    Closes #5683

  • used-before-assignment now checks names in try blocks.
  • Fixed false positive with used-before-assignment for assignment expressions in lambda statements.

    Closes #5360, #3877

  • Fixed a false positive (affecting unreleased development) for used-before-assignment involving homonyms between filtered comprehensions and assignments in except blocks.

    Closes #5586

  • Fixed crash with slots assignments and annotated assignments.

    Closes #5479

  • Fixed crash on list comprehensions that used type as inner variable name.

    Closes #5461

  • Fixed crash in use-maxsplit-arg checker when providing the sep argument to str.split() by keyword.

    Closes #5737

  • Fix false positive for unused-variable for a comprehension variable matching an outer scope type annotation.

    Closes #5326

  • Fix false negative for undefined-variable for a variable used multiple times in a comprehension matching an unused outer scope type annotation.

    Closes #5654

  • Some files in pylint.testutils were deprecated. In the future imports should be done from the pylint.testutils.functional namespace directly.
  • Fixed false positives for no-value-for-parameter with variadic positional arguments.

    Closes #5416

  • safe_infer no longer makes an inference when given two function definitions with differing numbers of arguments.

    Closes #3675

  • Fix comparison-with-callable false positive for callables that raise, such as typing constants.

    Closes #5557

  • Fixed a crash on __init__ nodes when the attribute was previously uninferable due to a cache limit size. This limit can be hit when the inheritance pattern of a class (and therefore of the __init__ attribute) is very large.

    Closes #5679

  • Fix false positive for used-before-assignment from a class definition nested under a function subclassing a class defined outside the function.

    Closes #4590

  • Fix unnecessary_dict_index_lookup false positive when deleting a dictionary's entry.

    Closes #4716

  • Fix false positive for used-before-assignment when an except handler shares a name with a test in a filtered comprehension.

    Closes #5817

  • Fix crash in unnecessary-dict-index-lookup checker if the output of items() is assigned to a 1-tuple.

    Closes #5504

  • When invoking pylint, epylint, symilar or pyreverse by importing them in a python file you can now pass an argv keyword besides patching sys.argv.

    Closes #5320

  • The PyLinter class will now be initialized with a TextReporter as its reporter if none is provided.
  • Fix super-init-not-called when parent or self is a Protocol

    Closes #4790

  • Fix false positive not-callable with attributes that alias NamedTuple

    Fixes part of #1730

  • Emit redefined-outer-name when a nested except handler shadows an outer one.

    Closes #4434 Closes #5370

  • Fix false positive super-init-not-called for classes that inherit their init from a parent.

    Closes #4941

  • encoding can now be supplied as a positional argument to calls that open files without triggering unspecified-encoding.

    Closes #5638

  • Fatal errors now emit a score of 0.0 regardless of whether the linted module contained any statements

    Closes #5451

  • fatal was added to the variables permitted in score evaluation expressions.
  • The default score evaluation now uses a floor of 0.

    Closes #2399

  • Fix false negative for consider-iterating-dictionary during membership checks encapsulated in iterables or not in checks

    Closes #5323

  • Fixed crash on uninferable decorators on Python 3.6 and 3.7
  • Add checker unnecessary-ellipsis: Emitted when the ellipsis constant is used unnecessarily.

    Closes #5460

  • Disable checker bad-docstring-quotes for Python <= 3.7, because in these versions the line numbers for decorated functions and classes are not reliable which interferes with the checker.

    Closes #3077

  • Fixed incorrect classification of Numpy-style docstring as Google-style docstring for docstrings with property setter documentation. Docstring classification is now based on the highest amount of matched sections instead of the order in which the docstring styles were tried.
  • Fixed detection of arguments-differ when superclass static methods lacked a @staticmethod decorator.

    Closes #5371

  • TypingChecker
  • The testutils for unittests now accept end_lineno and end_column. Tests without these will trigger a DeprecationWarning.
  • arguments-differ will no longer complain about method redefinitions with extra parameters that have default values.

    Closes #1556, #5338

  • Fixed false positive unexpected-keyword-arg for decorators.

    Closes #258

  • Importing the deprecated stdlib module xml.etree.cElementTree now emits deprecated_module.

    Closes #5862

  • Disables for deprecated-module and similar warnings for stdlib features deprecated in newer versions of Python no longer raise useless-suppression when linting with older Python interpreters where those features are not yet deprecated.
  • Importing the deprecated stdlib module distutils now emits deprecated_module on Python 3.10+.
  • missing-raises-doc will now check the class hierarchy of the raised exceptions
def my_function():

"""My function.
Raises:
Exception: if something fails
"""
raise ValueError

Closes #4955

  • Disable spellchecking of mypy rule names in ignore directives.

    Closes #5929

  • Allow disabling duplicate-code with a disable comment when running through pylint.

    Closes #214

  • Improve invalid-name check for TypeVar names. The accepted pattern can be customized with --typevar-rgx.

    Closes #3401

  • Added new checker typevar-name-missing-variance. Emitted when a covariant or contravariant TypeVar does not end with _co or _contra respectively or when a TypeVar is not either but has a suffix.
  • Allow usage of mccabe 0.7.x release

    Closes #5878

  • Fix unused-private-member false positive when accessing private methods through property.

    Closes #4756

What's New in Pylint 2.12

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

In 2.12, we introduced a new option py-version that permits to analyse code for a python version that may differ from your current python interpreter. This does not affect all checkers but permits, for example, to check for python 3.5 code smells (using f-string's) while using pylint with python 3.6. The minimum version to run pylint is now 3.6.2, while the last working version for python 3.6.0 and 3.6.1 was pylint 2.9.3.

On top of fixing a lot of false positives and bugs, we also added new default checks, like use-implicit-booleaness-not-comparison, overridden-final-method, and useless-with-lock. There's also better check for TOML configurations.

Lastly, in addition to the information we already had about start line and start column, we introduced new information about the end line and end column of messages. This will permit to have more precise visual clue in IDE like in pylint for vs-code. The default will stay the same to not break compatibility but it can be retrieved by adding end_line and end_column to the --msg-template option. For better result stick to python 3.8+.

The checker for Yoda conditions is now an extension, you might want to enable it if you were relying on this check. There's also a new extension checker, consider-using-any-or-all that detects for loops that could be replaced by any or all, entirely contributed by @areveny, welcome to the team !

New checkers

Added missing-any-param-doc triggered when a function has neither parameter nor parameter type documentation. Undocumented parameters are now being properly identified. A warning might start to appear unexpectedly if missing-param-doc and missing-type-doc were disabled, as a new message missing-any-param-doc will be emitted instead.

Closes #3799

  • Added overridden-final-method: Emitted when a method which is annotated with typing.final is overridden
  • Added subclassed-final-class: Emitted when a class which is annotated with typing.final is subclassed

    Closes #3197

  • Created new UnsupportedVersionChecker checker class that includes checks for features not supported by all versions indicated by a py-version.
Added using-f-string-in-unsupported-version checker. Issued when py-version is set to a version that does not support f-strings (< 3.6)
  • Added new checker use-implicit-booleaness-not-comparison: Emitted when collection literal comparison is being used to check for emptiness.

    Closes #4774

  • Added using-final-decorator-in-unsupported-version checker. Issued when py-version is set to a version that does not support typing.final (< 3.8)
  • Added new checker useless-with-lock to find incorrect usage of with statement and threading module locks. Emitted when with threading.Lock(): is used instead of with lock_instance:.

    Closes #5208

  • A new bad-configuration-section checker was added that will emit for misplaced option in pylint's top level namespace for toml configuration. Top-level dictionaries or option defined in the wrong section will still silently not be taken into account, which is tracked in a follow-up issue.

    Follow-up in #5259

  • MessageTest of the unittest testutil now requires the confidence attribute to match the expected value. If none is provided it is set to UNDEFINED.
  • add_message of the unittest testutil now actually handles the col_offset parameter and allows it to be checked against actual output in a test.

  • Added an optional extension consider-using-any-or-all: Emitted when a for loop only produces a boolean and could be replaced by any or all using a generator. Also suggests a suitable any/all statement if it is concise.

    Closes #5008

  • Moved misplaced-comparison-constant to its own extension comparison_placement. This checker was opinionated and now no longer a default. It can be reactived by adding pylint.extensions.comparison_placement to load-plugins in your config.

    Closes #1064

Other Changes

  • Fix install graphiz message which isn't needed for puml output format.
  • pylint no longer crashes when checking assignment expressions within if-statements

    Closes #5178

  • Added configuration option exclude-too-few-public-methods to allow excluding classes from the min-public-methods checker.

    Closes #3370

  • Fix accept-no-yields-doc and accept-no-return-doc not allowing missing yield or return documentation when a docstring is partially correct

    Closes #5223

  • Fix simplify-boolean-expression when condition can be inferred as False.

    Closes #5200

  • Fix exception when pyreverse parses property function of a class.
  • Improve and flatten unused-wildcard-import message

    Closes #3859

  • In length checker, len-as-condition has been renamed as use-implicit-booleaness-not-len in order to be consistent with use-implicit-booleaness-not-comparison.
  • Fixed protected-access for accessing of attributes and methods of inner classes

    Closes #3066

  • Update literal-comparison` checker to ignore tuple literals

    Closes #3031

  • The functional testutils now accept end_lineno and end_column. Expected output files without these will trigger a DeprecationWarning. Expected output files can be easily updated with the python tests/test_functional.py --update-functional-output command.
  • The functional testutils now correctly check the distinction between HIGH and UNDEFINED confidence. Expected output files without defined confidence levels will now trigger a DeprecationWarning. Expected output files can be easily updated with the python tests/test_functional.py --update-functional-output command.
  • The functional test runner now supports the option min_pyver_end_position to control on which python versions the end_lineno and end_column attributes should be checked. The default value is 3.8.
  • undefined-variable now correctly flags variables which only receive a type annotations and never get assigned a value

    Closes #5140

  • undefined-variable now correctly considers the line numbering and order of classes used in metaclass declarations

    Closes #4031

  • used-before-assignment now correctly considers references to classes as type annotation or default values in first-level methods

    Closes #3771

  • undefined-variable and unused-variable now correctly trigger for assignment expressions in functions defaults

    Refs #3688

  • self-cls-assignment now also considers tuple assignment
  • undefined-variable now correctly triggers for assignment expressions in if ... else statements This includes a basic form of control flow inference for if ... else statements using constant boolean values

    Closes #3688

  • Fix crash for unused-private-member when checking private members on __class__

    Closes #5261

  • Fix double emitting of not-callable on inferable properties

    Closes #4426

  • Support configuring mixin class pattern via mixin-class-rgx
  • Normalize the input to the ignore-paths option to allow both Posix and Windows paths

    Closes #5194

  • missing-param-doc now correctly parses asterisks for variable length and keyword parameters

    Closes #3733

  • missing-param-doc now correctly handles Numpy parameter documentation without explicit typing

    Closes #5222

  • The --jobs parameter now falls back to 1 if the host operating system does not have functioning shared semaphore implementation.

    Closes #5216

  • Crashes when a list is encountered in a toml configuration do not happen anymore.

    Closes #4580

  • Fix crash for protected-access on (outer) class traversal
  • Fix useless-super-delegation false positive when default keyword argument is a variable.
  • Make yn validator case insensitive, to allow for True and False in config files.
  • The last version compatible with python '3.6.0' and '3.6.1' is pylint '2.9.3'. We did not realize that when adding incompatible typing at the time, and all versions since are broken for this interpreter. 2.12.0 meta-information will permit to download pylint on those interpreters but the installation will fail and tell you to install '2.9.3' instead. pylint 2.12.1 will require python >= 3.6.2.

    Closes #5171 Follow-up in #5065

  • Added the --enable-all-extensions command line option. It will load all available extensions which can be listed by running --list-extensions
  • It is now recommended to do pylint development on Python 3.8 or higher. This allows using the latest ast parser.
  • All standard jobs in the pylint CI now run on Python 3.8 by default. We still support python 3.6 and 3.7 and run tests for those interpreters.
  • Fix crash on open() calls when the mode argument is not a simple string.

    Fixes part of #5321

  • Add ability to add end_line and end_column to the --msg-template option. With the standard TextReporter this will add the line and column number of the end of a node to the output of Pylint. If these numbers are unknown, they are represented by an empty string.
  • Introduced primer tests and a configuration tests framework. The helper classes available in pylint/testutil/ are still unstable and might be modified in the near future.

    Closes #4412 #5287

  • Add endLine and endColumn keys to output of JSONReporter.

    Closes #5380

  • Fix false negative for consider-iterating-dictionary during membership checks encapsulated in iterables or not in checks

    Closes #5323

Full changelog

What's New in Pylint 2.12.2?

Release date: 2021-11-25

  • Fixed a false positive for unused-import where everything was not analyzed properly inside typing guards.
  • Fixed a false-positive regression for used-before-assignment for typed variables in the body of class methods that reference the same class

    Closes #5342

  • Specified that the ignore-paths option considers "" to represent a windows directory delimiter instead of a regular expression escape character.
  • Fixed a crash with the ignore-paths option when invoking the option via the command line.

    Closes #5437

  • Fixed handling of Sphinx-style parameter docstrings with asterisks. These should be escaped with by prepending a "".

    Closes #5406

  • Add endLine and endColumn keys to output of JSONReporter.

    Closes #5380

  • Fixed handling of Google-style parameter specifications where descriptions are on the line following the parameter name. These were generating false positives for missing-param-doc.

    Closes #5452

  • Fix false negative for consider-iterating-dictionary during membership checks encapsulated in iterables or not in checks

    Closes #5323

  • unused-import now check all ancestors for typing guards

    Closes #5316

What's New in Pylint 2.12.1?

Release date: 2021-11-25

Require Python 3.6.2 to run pylint.

Closes #5065

What's New in Pylint 2.12.0?

Release date: 2021-11-24

  • Upgrade astroid to 2.9.0

    Closes #4982

  • Add ability to add end_line and end_column to the --msg-template option. With the standard TextReporter this will add the line and column number of the end of a node to the output of Pylint. If these numbers are unknown, they are represented by an empty string.
  • Introduced primer tests and a configuration tests framework. The helper classes available in pylint/testutil/ are still unstable and might be modified in the near future.

    Closes #4412 #5287

  • Fix install graphiz message which isn't needed for puml output format.
  • MessageTest of the unittest testutil now requires the confidence attribute to match the expected value. If none is provided it is set to UNDEFINED.
  • add_message of the unittest testutil now actually handles the col_offset parameter and allows it to be checked against actual output in a test.
  • Fix a crash in the check_elif extensions where an undetected if in a comprehension with an if statement within a f-string resulted in an out of range error. The checker no longer relies on counting if statements anymore and uses known if statements locations instead. It should not crash on badly parsed if statements anymore.
  • Fix simplify-boolean-expression when condition can be inferred as False.

    Closes #5200

  • Fix exception when pyreverse parses property function of a class.
  • The functional testutils now accept end_lineno and end_column. Expected output files without these will trigger a DeprecationWarning. Expected output files can be easily updated with the python tests/test_functional.py --update-functional-output command.
  • The functional testutils now correctly check the distinction between HIGH and UNDEFINED confidence. Expected output files without defined confidence levels will now trigger a DeprecationWarning. Expected output files can be easily updated with the python tests/test_functional.py --update-functional-output command.
  • The functional test runner now supports the option min_pyver_end_position to control on which python versions the end_lineno and end_column attributes should be checked. The default value is 3.8.
  • Fix accept-no-yields-doc and accept-no-return-doc not allowing missing yield or return documentation when a docstring is partially correct

    Closes #5223

  • Add an optional extension consider-using-any-or-all : Emitted when a for loop only produces a boolean and could be replaced by any or all using a generator. Also suggests a suitable any or all statement.

    Closes #5008

  • Properly identify parameters with no documentation and add new message called missing-any-param-doc

    Closes #3799

  • Add checkers overridden-final-method & subclassed-final-class

    Closes #3197

  • Fixed protected-access for accessing of attributes and methods of inner classes

    Closes #3066

  • Added support for ModuleNotFoundError (import-error and no-name-in-module). ModuleNotFoundError inherits from ImportError and was added in Python 3.6
  • undefined-variable now correctly flags variables which only receive a type annotations and never get assigned a value

    Closes #5140

  • undefined-variable now correctly considers the line numbering and order of classes used in metaclass declarations

    Closes #4031

  • used-before-assignment now correctly considers references to classes as type annotation or default values in first-level methods

    Closes #3771

  • undefined-variable and unused-variable now correctly trigger for assignment expressions in functions defaults

    Refs #3688

  • undefined-variable now correctly triggers for assignment expressions in if ... else statements This includes a basic form of control flow inference for if ... else statements using constant boolean values

    Closes #3688

  • Added the --enable-all-extensions command line option. It will load all available extensions which can be listed by running --list-extensions
  • Fix bug with importing namespace packages with relative imports

    Closes #2967 and #5131

  • Improve and flatten unused-wildcard-import message

    Closes #3859

  • In length checker, len-as-condition has been renamed as use-implicit-booleaness-not-len in order to be consistent with use-implicit-booleaness-not-comparison.
  • Created new UnsupportedVersionChecker checker class that includes checks for features not supported by all versions indicated by a py-version.
Added using-f-string-in-unsupported-version checker. Issued when py-version is set to a version that does not support f-strings (< 3.6)
  • Fix useless-super-delegation false positive when default keyword argument is a variable.
  • Properly emit duplicate-key when Enum members are duplicate dictionary keys

    Closes #5150

  • Use py-version setting for alternative union syntax check (PEP 604), instead of the Python interpreter version.
  • Subclasses of dict are regarded as reversible by the bad-reversed-sequence checker (Python 3.8 onwards).

    Closes #4981

  • Support configuring mixin class pattern via mixin-class-rgx
  • Added new checker use-implicit-booleaness-not-comparison: Emitted when collection literal comparison is being used to check for emptiness.

    Closes #4774

  • missing-param-doc now correctly parses asterisks for variable length and keyword parameters

    Closes #3733

  • missing-param-doc now correctly handles Numpy parameter documentation without explicit typing

    Closes #5222

  • pylint no longer crashes when checking assignment expressions within if-statements

    Closes #5178

  • Update literal-comparison` checker to ignore tuple literals

    Closes #3031

  • Normalize the input to the ignore-paths option to allow both Posix and Windows paths

    Closes #5194

  • Fix double emitting of not-callable on inferable properties

    Closes #4426

  • self-cls-assignment now also considers tuple assignment
  • Fix missing-function-docstring not being able to check __init__ and other magic methods even if the no-docstring-rgx setting was set to do so
  • Added using-final-decorator-in-unsupported-version checker. Issued when py-version is set to a version that does not support typing.final (< 3.8)
  • Added configuration option exclude-too-few-public-methods to allow excluding classes from the min-public-methods checker.

    Closes #3370

  • The --jobs parameter now fallbacks to 1 if the host operating system does not have functioning shared semaphore implementation.

    Closes #5216

  • Fix crash for unused-private-member when checking private members on __class__

    Closes #5261

  • Crashes when a list is encountered in a toml configuration do not happen anymore.

    Closes #4580

  • Moved misplaced-comparison-constant to its own extension comparison_placement. This checker was opinionated and now no longer a default. It can be reactived by adding pylint.extensions.comparison_placement to load-plugins in your config.

    Closes #1064

  • A new bad-configuration-section checker was added that will emit for misplaced option in pylint's top level namespace for toml configuration. Top-level dictionaries or option defined in the wrong section will still silently not be taken into account, which is tracked in a follow-up issue.

    Follow-up in #5259

  • Fix crash for protected-access on (outer) class traversal
  • Added new checker useless-with-lock to find incorrect usage of with statement and threading module locks. Emitted when with threading.Lock(): is used instead of with lock_instance:.

    Closes #5208

  • Make yn validator case insensitive, to allow for True and False in config files.
  • Fix crash on open() calls when the mode argument is not a simple string.

    Fixes part of #5321

  • Inheriting from a class that implements __class_getitem__ no longer raises inherit-non-class.
  • Pyreverse - Add the project root directory to sys.path

    Closes #2479

  • Don't emit consider-using-f-string if py-version is set to Python < 3.6. f-strings were added in Python 3.6

    Closes #5019

  • Fix regression for unspecified-encoding with pathlib.Path.read_text()

    Closes #5029

  • Don't emit consider-using-f-string if the variables to be interpolated include a backslash
  • Fixed false positive for cell-var-from-loop when variable is used as the default value for a keyword-only parameter.

    Closes #5012

  • Fix false-positive undefined-variable with Lambda, IfExp, and assignment expression.
  • Fix false-positive useless-suppression for wrong-import-order

    Closes #2366

  • Fixed toml dependency issue

    Closes #5066

  • Fix false-positive useless-suppression for line-too-long

    Closes #4212

  • Fixed invalid-name not checking parameters of overwritten base object methods

    Closes #3614

  • Fixed crash in consider-using-f-string if format is not called

    Closes #5058

  • Fix crash with AssignAttr in if TYPE_CHECKING blocks.

    Closes #5111

  • Improve node information for invalid-name on function argument.
  • Prevent return type checkers being called on functions with ellipses as body

    Closes #4736

  • Add is_sys_guard and is_typing_guard helper functions from astroid to pylint.checkers.utils.
  • Fix regression on ClassDef inference

    Closes #5030 Closes #5036

  • Fix regression on Compare node inference

    Closes #5048

  • Fix false-positive isinstance-second-argument-not-valid-type with typing.Callable.

    Closes #3507 Closes #5087

  • It is now recommended to do pylint development on Python 3.8 or higher. This allows using the latest ast parser.
  • All standard jobs in the pylint CI now run on Python 3.8 by default. We still support python 3.6 and 3.7 and run tests for those interpreters.
  • TypingChecker
Fix false-negative for deprecated-typing-alias and consider-using-alias with typing.Type + typing.Callable.

What's New in Pylint 2.11

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

In 2.11, we added a new default checker to advise using f-string as it's the most efficient way of formatting strings right now. You can use pyupgrade or flynt to migrate your old % and format() automatically.

We added a new extension SetMembershipChecker that will advise the use of set for membership test, as it's more performant than lists or tuples. The CodeStyleChecker also got some love, check it out if you're not already using it.

We fixed some long standing bugs, false positives, or false negatives and we added small quality of life options like min-similarity-lines that disable the duplication check when set to 0.

Under the hood the code for both pylint and astroid is progressively more typed, which could be helpful to you if you're using them as libraries. In order for this new typing to make more sense and stay simple, we deprecated some functions or type that will be removed in the next major version. This is an ongoing effort.

The future possible-forgotten-f-prefix check still had too much false positives, and is delayed again. Check the possible-forgotten-f-prefix issue if you want to provide knowledge or use case :)

New checkers

Added consider-using-f-string: Emitted when .format() or '%' is being used to format a string.

Closes #3592

Removed checkers

The python3 porting mode checker and it's py3k option were removed. You can still find it in older pylint versions.

Added new extension SetMembershipChecker with use-set-for-membership check: Emitted when using an in-place defined list or tuple to do a membership test. sets are better optimized for that.

Closes #4776

Added consider-using-assignment-expr: Emitted when an assignment is directly followed by an if statement and both can be combined by using an assignment expression :=. Requires Python 3.8

Closes #4862

Other Changes

  • Added py-version config key (if [MAIN] section). Used for version dependent checks. Will default to whatever Python version pylint is executed with.
  • The invalid-name message is now more detailed when using multiple naming style regexes.
  • Fix false positive for consider-using-with if a context manager is assigned to a variable in different paths of control flow (e. g. if-else clause).

    Closes #4751

  • Fix false positive for function-redefined for simple type annotations

    Closes #4936

  • Fix false positive for protected-access if a protected member is used in type hints of function definitions
  • Fix false positive dict-iter-missing-items for dictionaries only using tuples as keys

    Closes #3282

  • The unspecified-encoding checker now also checks calls to pathlib.Path().read_text() and pathlib.Path().write_text()

    Closes #4945

  • Fix false positive superfluous-parens for tuples created with inner tuples

    Closes #4907

  • Fix false positive unused-private-member for accessing attributes in a class using cls

    Closes #4849

  • Extended consider-using-in check to work for attribute access.
  • Setting min-similarity-lines to 0 now makes the similarty checker stop checking for duplicate code

    Closes #4901

  • Fix a bug where pylint complained if the cache's parent directory does not exist

    Closes #4900

  • The global-variable-not-assigned checker now catches global variables that are never reassigned in a local scope and catches (reassigned) functions

    Closes #1375 Closes #330

  • The consider-iterating-dictionary checker now also considers membership checks

    Closes #4069

Full changelog

What's New in Pylint 2.11.1?

Release date: 2021-09-16

unspecified-encoding now checks the encoding of pathlib.Path() correctly

Closes #5017

What's New in Pylint 2.11.0?

Release date: 2021-09-16

  • The python3 porting mode checker and it's py3k option were removed. You can still find it in older pylint versions.
  • raising-bad-type is now properly emitted when raising a string
  • Added new extension SetMembershipChecker with use-set-for-membership check: Emitted when using an in-place defined list or tuple to do a membership test. sets are better optimized for that.

    Closes #4776

  • Added py-version config key (if [MASTER] section). Used for version dependent checks. Will default to whatever Python version pylint is executed with.
  • CodeStyleChecker: Added consider-using-assignment-expr: Emitted when an assignment is directly followed by an if statement and both can be combined by using an assignment expression :=. Requires Python 3.8

    Closes #4862

  • Added consider-using-f-string: Emitted when .format() or '%' is being used to format a string.

    Closes #3592

  • Fix false positive for consider-using-with if a context manager is assigned to a variable in different paths of control flow (e. g. if-else clause).

    Closes #4751

  • https is now preferred in the documentation and http://pylint.pycqa.org correctly redirect to https://pylint.pycqa.org

    Closes #3802

  • Fix false positive for function-redefined for simple type annotations

    Closes #4936

  • Fix false positive for protected-access if a protected member is used in type hints of function definitions
  • Fix false positive dict-iter-missing-items for dictionaries only using tuples as keys

    Closes #3282

  • The unspecified-encoding checker now also checks calls to pathlib.Path().read_text() and pathlib.Path().write_text()

    Closes #4945

  • Fix false positive superfluous-parens for tuples created with inner tuples

    Closes #4907

  • Fix false positive unused-private-member for accessing attributes in a class using cls

    Closes #4849

  • Fix false positive unused-private-member for private staticmethods accessed in classmethods.

    Closes #4849

  • Extended consider-using-in check to work for attribute access.
  • Setting min-similarity-lines to 0 now makes the similarty checker stop checking for duplicate code

    Closes #4901

  • Fix a bug where pylint complained if the cache's parent directory does not exist

    Closes #4900

  • The global-variable-not-assigned checker now catches global variables that are never reassigned in a local scope and catches (reassigned) functions

    Closes #1375 Closes #330

  • Fix false positives for invalid-all-format that are lists or tuples at runtime

    Closes #4711

  • Fix no-self-use and docparams extension for async functions and methods.
  • Add documentation for pyreverse and symilar

    Closes #4616

  • Non symbolic messages with the wrong capitalisation now correctly trigger use-symbolic-message-instead

    Closes #5000

  • The consider-iterating-dictionary checker now also considers membership checks

    Closes #4069

  • The invalid-name message is now more detailed when using multiple naming style regexes.

What's New In Pylint 2.10

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

In 2.10, we added several new default check, like unspecified-encoding, forgotten-debug-statement or use-dict-literal. There's also a few opinionated optional one. You can now forbid while loop or profess your exclusive love of ternary expressions publicly. We promise you hours of arguing fun with your whole team if you add those to your configuration.

We've also fixed some long standing bugs, false positives, or missing options like ignore-signature that will now work on inner function's signatures.

A new option to disable the next line, disable-next, has been added. It's also possible to export colored diagrams, and plantuml diagram using pyreverse. PYLINT_HOME is now XDG_CACHE_HOME if not set.

The performance of the similarity checker has been improved, as well as several small performance fixes.

We're going to continue working on improving performance during 2.11. We're also going to finalize a new possible-forgotten-f-prefix check that had too much false positives at release time. Check the possible-forgotten-f-prefix issue if you want to provide knowledge or use case :)

New checkers

  • Added unspecified-encoding: Emitted when open() is called without specifying an encoding

    Closes #3826

  • Added use-list-literal: Emitted when list() is called with no arguments instead of using []

    Closes #4365

  • Added use-dict-literal: Emitted when dict() is called with no arguments instead of using {}

    Closes #4365

  • Added forgotten-debug-statement: Emitted when breakpoint, pdb.set_trace or sys.breakpointhook calls are found

    Closes #3692

  • Added use-sequence-for-iteration: Emitted when iterating over an in-place defined set.
  • Added format-string-without-interpolation checker: Emitted when formatting is applied to a string without any variables to be replaced

    Closes #4042

  • Added redundant-u-string-prefix checker: Emitted when the u prefix is added to a string

    Closes #4102

CodeStyleChecker
  • Limit consider-using-tuple to be emitted only for in-place defined lists.
  • Emit consider-using-tuple even if list contains a starred expression.
  • Added optional extension consider-ternary-expression: Emitted whenever a variable is assigned in both branches of an if/else block.

    Closes # 4366

  • Added optional extension while-used: Emitted whenever a while loop is used.

    Closes # 4367

Other Changes

  • pyreverse now permit to produce colored generated diagram by using the colorized option.
  • Pyreverse - add output in PlantUML format
  • consider-using-with is no longer triggered if a context manager is returned from a function.
  • pylint does not crash with a traceback anymore when a file is problematic. It creates a template text file for opening an issue on the bug tracker instead. The linting can go on for other non problematic files instead of being impossible.
  • Pyreverse - Show class has-a relationships inferred from type-hints
  • Performance of the Similarity checker has been improved.
  • Added time.clock to deprecated functions/methods for python 3.3
  • Added ignored-parents option to the design checker to ignore specific classes from the too-many-ancestors check (R0901).
  • Don't emit no-member error if guarded behind if statement.

    Refs #1162 Closes #1990 Closes #4168

  • Fix false positives for superfluous-parens with walrus operator, ternary operator and inside list comprehension.

    Closes #2818 Closes #3249 Closes #3608 Closes #4346

  • Refactor of --list-msgs & --list-msgs-enabled: both options now show whether messages are emittable with the current interpreter.

    Closes #4778

  • Fix false negative for used-before-assignment when the variable is assigned in an exception handler, but used outside of the handler.

    Closes #626

  • Added disable-next option: allows using # pylint: disable-next=msgid to disable a message for the following line

    Closes #1682

  • Fixed cell-var-from-loop checker: handle cell variables in comprehensions within functions, and function default argument expressions. Also handle basic variable shadowing.

    Closes #2846 Closes #3107

  • Fixed bug with cell-var-from-loop checker: it no longer has false negatives when both unused-variable and used-before-assignment are disabled.
  • Class methods' signatures are now ignored the same way as functions' with similarities "ignore-signatures" option enabled

    Closes #4653

Full changelog

What's New in Pylint 2.10.2?

Release date: 2021-08-21

  • We now use platformdirs instead of appdirs since the latter is not maintained.

    Closes #4886

  • Fix a crash in the checker raising shallow-copy-environ when failing to infer on copy.copy

    Closes #4891

What's New in Pylint 2.10.1?

Release date: 2021-08-20

pylint does not crash when PYLINT_HOME does not exist.

Closes #4883

What's New in Pylint 2.10.0?

Release date: 2021-08-20

  • pyreverse: add option to produce colored output.

    Closes #4488

  • pyreverse: add output in PlantUML format.

    Closes #4498

  • consider-using-with is no longer triggered if a context manager is returned from a function.

    Closes #4748

  • pylint does not crash with a traceback anymore when a file is problematic. It creates a template text file for opening an issue on the bug tracker instead. The linting can go on for other non problematic files instead of being impossible.
  • pyreverse: Show class has-a relationships inferred from the type-hint

    Closes #4744

  • Fixed a crash when importing beyond the top level package during import-error message creation

    Closes #4775

  • Added ignored-parents option to the design checker to ignore specific classes from the too-many-ancestors check (R0901).

    Fixes part of #3057

  • Added unspecified-encoding: Emitted when open() is called without specifying an encoding

    Closes #3826

  • Improved the Similarity checker performance. Fix issue with --min-similarity-lines used with --jobs.

    Closes #4120 Closes #4118

  • Don't emit no-member error if guarded behind if statement.

    Refs #1162 Closes #1990 Closes #4168

  • The default for PYLINTHOME is now the standard XDG_CACHE_HOME, and pylint now uses appdirs.

    Closes #3878

  • Added use-list-literal: Emitted when list() is called with no arguments instead of using []

    Closes #4365

  • Added use-dict-literal: Emitted when dict() is called with no arguments instead of using {}

    Closes #4365

  • Added optional extension consider-ternary-expression: Emitted whenever a variable is assigned in both branches of an if/else block.

    Closes # 4366

  • Added optional extension while-used: Emitted whenever a while loop is used.

    Closes # 4367

  • Added forgotten-debug-statement: Emitted when breakpoint, pdb.set_trace or sys.breakpointhook calls are found

    Closes #3692

  • Fix false-positive of unused-private-member when using nested functions in a class

    Closes #4673

  • Fix crash for unused-private-member that occurred with nested attributes.

    Closes #4755

  • Fix a false positive for unused-private-member with class names

    Closes #4681

  • Fix false positives for superfluous-parens with walrus operator, ternary operator and inside list comprehension.

    Closes #2818 Closes #3249 Closes #3608 Closes #4346

  • Added format-string-without-interpolation checker: Emitted when formatting is applied to a string without any variables to be replaced

    Closes #4042

  • Refactor of --list-msgs & --list-msgs-enabled: both options now show whether messages are emittable with the current interpreter.

    Closes #4778

  • Fix false negative for used-before-assignment when the variable is assigned in an exception handler, but used outside of the handler.

    Closes #626

  • Added disable-next option: allows using # pylint: disable-next=msgid to disable a message for the following line

    Closes #1682

  • Added redundant-u-string-prefix checker: Emitted when the u prefix is added to a string

    Closes #4102

  • Fixed cell-var-from-loop checker: handle cell variables in comprehensions within functions, and function default argument expressions. Also handle basic variable shadowing.

    Closes #2846 Closes #3107

  • Fixed bug with cell-var-from-loop checker: it no longer has false negatives when both unused-variable and used-before-assignment are disabled.
  • Fix false positive for invalid-all-format if the list or tuple builtin functions are used

    Closes #4711

  • Config files can now contain environment variables

    Closes #3839

  • Fix false-positive used-before-assignment with an assignment expression in a Return node

    Closes #4828

  • Added use-sequence-for-iteration: Emitted when iterating over an in-place defined set.
  • CodeStyleChecker
  • Limit consider-using-tuple to be emitted only for in-place defined lists.
  • Emit consider-using-tuple even if list contains a starred expression.
  • Ignore decorators lines by similarities checker when ignore signatures flag enabled

    Closes #4839

  • Allow true and false values in pylintrc for better compatibility with toml config.
  • Class methods' signatures are ignored the same way as functions' with similarities "ignore-signatures" option enabled

    Closes #4653

  • Improve performance when inferring Call nodes, by utilizing caching.
  • Improve error message for invalid-metaclass when the node is an Instance.

What's New In Pylint 2.9

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

Pylint is now compatible with python 3.10.

A lot of new checks have been added, some non-opinionated performance warnings like use-maxsplit-arg, some consensual style warnings like unnecessary-dict-index-lookup or new deprecation checks.

We're aiming to reduce pylint noise for first time users and making some new checks optional is a step in that direction. In order to do that we created an optional code style checker that can be loaded using pylint.extensions.code_style with the load-plugins options. More than ever, if as a veteran you want the most checks you can possibly get, you should check the list of pylint extensions..

New checkers

  • deprecated-decorator: Emitted when deprecated decorator is used.
  • consider-using-dict-items: Emitted when iterating over dictionary keys and then indexing the same dictionary with the key within loop body.
  • use-maxsplit-arg: Emitted either when accessing only the first or last element of str.split().
  • An ignore_signatures option has been added to the similarity checker. It will permits to reduce false positives when multiple functions have the same parameters.
  • unnecessary-dict-index-lookup: Emitted when iterating over dictionary items (key-value pairs) and accessing the value by index lookup.
  • consider-using-from-import: Emitted when a submodule/member of a package is imported and aliased with the same name.
  • New checker unused-private-member: Emitted when a private member (i.e., starts with __) of a class is defined but not used.
  • New checker invalid-class-object: Emitted when a non-class is assigned to a __class__ attribute.
  • invalid-all-format: Emitted when __all__ has an invalid format, i.e. isn't a tuple or list.
  • New checker await-outside-async: Emitted when await is used outside an async function.
  • Add new extension CodeStyleChecker. It includes checkers that can improve code consistency. As such they don't necessarily provide a performance benefit and are often times opinionated.
  • consider-using-tuple: Emitted when an in-place defined list or set can be replaced by a tuple.
  • consider-using-namedtuple-or-dataclass: Emitted when dictionary values can be replaced by namedtuples or dataclass instances.

Other Changes

  • Fix false-positive consider-using-with (R1732) if a ternary conditional is used together with with
  • Fix false-positive consider-using-with (R1732) if contextlib.ExitStack takes care of calling the __exit__ method
  • Add type annotations to pyreverse dot files
  • Pylint's tags are now the standard form vX.Y.Z and not pylint-X.Y.Z anymore.
  • Fix false-positive too-many-ancestors when inheriting from builtin classes, especially from the collections.abc module
  • The output messages for arguments-differ error message have been customized based on the different error cases.
  • New option --fail-on=<msg ids> to return non-zero exit codes regardless of fail-under value.
  • A new error called arguments-renamed has been created, which identifies any changes at the parameter names of overridden functions. It aims to separate the functionality of arguments-differ.
  • Fix incompatibility with Python 3.6.0 caused by typing.Counter and typing.NoReturn usage
  • Allow comma-separated list in output-format and separate output files for each specified format. Each output file can be defined after a semicolon for example : --output-format=json:myfile.json,colorized
  • The using-constant-test checker now detects constant tests consisting of list literals like [] and [1, 2, 3].
  • ignore-paths configuration directive has been added. Defined regex patterns are matched against file path.
  • Added handling of floating point values when parsing configuration from pyproject.toml
  • Fix false positive useless-type-doc on ignored argument using pylint.extensions.docparams when a function was typed using pep484 but not inside the docstring.
  • Fix missing support for detecting deprecated aliases to existing functions/methods. functions/methods.
  • Added various deprecated functions/methods for python 3.10, 3.7, 3.6 and 3.3
  • No longer emit consider-using-with for ThreadPoolExecutor and ProcessPoolExecutor as they have legitimate use cases without a with block.
  • Fix crash if a callable returning a context manager was assigned to a list or dict item

Full changelog

What's New in Pylint 2.9.6?

Release date: 2021-07-28

Fix a false positive undefined-variable when variable name in decoration matches function argument

Closes #3791

What's New in Pylint 2.9.5?

Release date: 2021-07-21

  • Fix a crash when there would be a 'TypeError object does not support item assignment' in the code we parse.

    Closes #4439

  • Fix crash if a callable returning a context manager was assigned to a list or dict item

    Closes #4732

  • Fix a crash when an AttributeInferenceError was not handled properly when failing to infer the real name of an import in astroid.

    Closes #4692

What's New in Pylint 2.9.4?

Release date: 2021-07-20

  • Added time.clock to deprecated functions/methods for python 3.3
  • Fix bug in which --fail-on can return a zero exit code even when the specified issue is present

    Closes #4296 Closes #3363

  • Fix hard failure when handling missing attribute in a class with duplicated bases

    Closes #4687

  • Fix false-positive consider-using-with (R1732) if a ternary conditional is used together with with

    Closes #4676

  • Fix false-positive deprecated-module when relative import uses deprecated module name.

    Closes #4629

  • Fix false-positive consider-using-with (R1732) if contextlib.ExitStack takes care of calling the __exit__ method

    Closes #4654

  • Fix a false positive for unused-private-member when mutating a private attribute with cls

    Closes #4657

  • Fix ignored empty functions by similarities checker with "ignore-signatures" option enabled

    Closes #4652

  • Fix false-positive of use-maxsplit-arg when index is incremented in a loop

    Closes #4664

  • Don't emit cyclic-import message if import is guarded by typing.TYPE_CHECKING.

    Closes #3525

  • Fix false-positive not-callable with alternative TypedDict syntax

    Closes #4715

  • Clarify documentation for consider-using-from-import
  • Don't emit unreachable warning for empty generator functions

    Closes #4698

  • Don't emit import-error, no-name-in-module, and ungrouped-imports for imports guarded by sys.version_info or typing.TYPE_CHECKING.

    Closes #3285 Closes #3382

  • Fix invalid-overridden-method with nested property

    Closes #4368

  • Fix false-positive of unused-private-member when using __new__ in a class

    Closes #4668

  • No longer emit consider-using-with for ThreadPoolExecutor and ProcessPoolExecutor as they have legitimate use cases without a with block.

    Closes #4689

  • Fix crash when inferring variables assigned in match patterns

    Closes #4685

  • Fix a crash when a StopIteration was raised when inferring a faulty function in a context manager.

    Closes #4723

What's New in Pylint 2.9.3?

Release date: 2021-07-01

  • Fix a crash that happened when analysing empty function with docstring in the similarity checker.

    Closes #4648

  • The similarity checker no longer add three trailing whitespaces for empty lines in its report.

What's New in Pylint 2.9.2?

Release date: 2021-07-01

  • Fix a crash that happened when analysing code using type(self) to access a class attribute in the unused-private-member checker.

    Closes #4638

  • Fix a false positive for unused-private-member when accessing a private variable with self

    Closes #4644

  • Fix false-positive of unnecessary-dict-index-lookup and consider-using-dict-items for reassigned dict index lookups

    Closes #4630

What's New in Pylint 2.9.1?

Release date: 2021-06-30

Upgrade astroid to 2.6.2

Closes #4631 Closes #4633

What's New in Pylint 2.9.0?

Release date: 2021-06-29

  • Python 3.10 is now supported.
  • Add type annotations to pyreverse dot files

    Closes #1548

  • Fix missing support for detecting deprecated aliases to existing functions/methods.

    Closes #4618

  • astroid has been upgraded to 2.6.1
  • Added various deprecated functions/methods for python 3.10, 3.7, 3.6 and 3.3
  • Fix false positive useless-type-doc on ignored argument using pylint.extensions.docparams when a function was typed using pep484 but not inside the docstring.

    Closes #4117 Closes #4593

  • setuptools_scm has been removed and replaced by tbump in order to not have hidden runtime dependencies to setuptools
  • Fix a crash when a test function is decorated with @pytest.fixture and astroid can't infer the name of the decorator when using open without with.

    Closes #4612

  • Added deprecated-decorator: Emitted when deprecated decorator is used.

    Closes #4429

  • Added ignore-paths behaviour. Defined regex patterns are matched against full file path.

    Closes #2541

  • Fix false negative for consider-using-with if calls like open() were used outside of assignment expressions.
  • The warning for arguments-differ now signals explicitly the difference it detected by naming the argument or arguments that changed and the type of change that occurred.
  • Suppress consider-using-with inside context managers.

    Closes #4430

  • Added --fail-on option to return non-zero exit codes regardless of --fail-under value.
  • numversion tuple contains integers again to fix multiple pylint's plugins that relied on it

    Closes #4420

  • Fix false-positive too-many-ancestors when inheriting from builtin classes, especially from the collections.abc module

    Closes #4166 Closes #4415

  • Stdlib deprecated modules check is moved to stdlib checker. New deprecated modules are added.
  • Fix raising false-positive no-member on abstract properties
  • Created new error message called arguments-renamed which identifies any changes at the parameter names of overridden functions.

    Closes #3536

  • New checker consider-using-dict-items. Emitted when iterating over dictionary keys and then indexing the same dictionary with the key within loop body.

    Closes #3389

  • Don't emit import-error if import guarded behind if sys.version_info >= (x, x)
  • Fix incompatibility with Python 3.6.0 caused by typing.Counter and typing.NoReturn usage

    Closes #4412

  • New checker use-maxsplit-arg. Emitted either when accessing only the first or last element of str.split().

    Closes #4440

  • Add ignore_signatures to duplicate code checker

    Closes #3619

  • Fix documentation errors in "Block disables" paragraph of User Guide.
  • New checker unnecessary-dict-index-lookup. Emitted when iterating over dictionary items (key-value pairs) and accessing the value by index lookup.

    Closes #4470

  • New checker``consider-using-from-import``. Emitted when a submodule/member of a package is imported and aliased with the same name.

    Closes #2309

  • Allow comma-separated list in output-format and separate output files for each specified format.

    Closes #1798

  • Make using-constant-test detect constant tests consisting of list literals like [] and [1, 2, 3].
  • Improved error message of unnecessary-comprehension checker by providing code suggestion.

    Closes #4499

  • New checker unused-private-member. Emitted when a private member (i.e., starts with __) of a class is defined but not used.

    Closes #4483

  • Fix false negative of consider-using-enumerate when iterating over an attribute.

    Closes #3657

  • New checker invalid-class-object. Emitted when a non-class is assigned to a __class__ attribute.

    Closes #585

  • Fix a crash when a plugin from the configuration could not be loaded and raise an error 'bad-plugin-value' instead

    Closes #4555

  • Added handling of floating point values when parsing configuration from pyproject.toml

    Closes #4518

  • invalid-length-returned, now also works when nothing at all is returned following an upgrade in astroid.
  • logging-format-interpolation and logging-not-lazy, now works on logger class created from renamed logging import following an upgrade in astroid.
  • Fix false-positive no-member with generic base class

    Closes PyCQA/astroid#942

  • Fix assigning-non-slot false-positive with base that inherits from typing.Generic

    Closes #4509 Closes PyCQA/astroid#999

  • New checker invalid-all-format. Emitted when __all__ has an invalid format, i.e. isn't a tuple or list.
  • Fix false positive unused-variable and undefined-variable with Pattern Matching in Python 3.10
  • New checker await-outside-async. Emitted when await is used outside an async function.
  • Clarify documentation for typing extension.

    Closes #4545

  • Add new extension CodeStyleChecker. It includes checkers that can improve code consistency. As such they don't necessarily provide a performance benefit and are often times opinionated.
  • New checker consider-using-tuple. Emitted when an in-place defined list or set can be replaced by a tuple.
  • New checker consider-using-namedtuple-or-dataclass. Emitted when dictionary values can be replaced by namedtuples or dataclass instances.
  • Fix error that occurred when using slice as subscript for dict.
  • Reduce false-positives around inference of .value and .name properties on Enum subclasses, following an upgrade in astroid

    Closes #1932 Closes #2062

  • Fix issue with cached_property that caused invalid-overridden-method error when overriding a property.

    Closes #4023

  • Fix unused-import false positive for imported modules referenced in attribute lookups in type comments.

    Closes #4603

What's New In Pylint 2.8

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

The 'doc' extra-require has been removed. __pkginfo__` does not contain the package metadata anymore (except numversion, until 3.0). Meta-information are accessible with

`python from importlib import metadata metadata.metadata('pylint') ` Prefer that to an import from __pkginfo__.

New checkers

  • New refactoring message consider-using-with. This message is emitted if resource-allocating functions or methods of the standard library (like open() or threading.Lock.acquire()) that can be used as a context manager are called without a with block.
  • Add deprecated-argument check for deprecated arguments.
  • Add new extension ConfusingConsecutiveElifChecker. This optional checker emits a refactoring message (R5601 confusing-consecutive-elif) if if/elif statements with different indentation levels follow directly one after the other.
  • Add consider-using-min-max-builtin check for if statement which could be replaced by Python builtin min or max.
  • Add new extension TypingChecker. This optional checker can detect the use of deprecated typing aliases and can suggest the use of the alternative union syntax where possible. (For example, 'typing.Dict' can be replaced by 'dict', and 'typing.Unions' by '|', etc.) Make sure to check the config options if you plan on using it!
  • Add deprecated-class check for deprecated classes.

Other Changes

  • New option --output=<file> to output result to a file rather than printing to stdout.

    Closes #1070

  • Reduce usage of blacklist/whitelist terminology. Notably, extension-pkg-allow-list is an alternative to extension-pkg-whitelist and the message blacklisted-name is now emitted as disallowed-name. The previous names are accepted to maintain backward compatibility.
  • The packaging is now done via setuptools exclusively. doc, tests, man, elisp and Changelog are not packaged anymore - reducing the size of the package by 75%.
  • Updated astroid to 2.5.4
  • COPYING has been renamed to LICENSE for standardization.

Full changelog

What's New in Pylint 2.8.3?

Release date: 2021-05-31

Astroid has been pinned to 2.5.6 for the 2.8 branch.

Refs #4527

What's New in Pylint 2.8.2?

Release date: 2021-04-26

  • Keep __pkginfo__.numversion a tuple to avoid breaking pylint-django.

    Closes #4405

  • scm_setuptools has been added to the packaging.
  • Pylint's tags are now the standard form vX.Y.Z and not pylint-X.Y.Z anymore.
  • New warning message deprecated-class. This message is emitted if import or call deprecated class of the standard library (like collections.Iterable that will be removed in Python 3.10).

    Closes #4388

What's New in Pylint 2.8.1?

Release date: 2021-04-25

Add numversion back (temporarily) in __pkginfo__ because it broke Pylama and revert the unnecessary pylint.version breaking change.

Closes #4399

What's New in Pylint 2.8.0?

Release date: 2021-04-24

  • New refactoring message consider-using-with. This message is emitted if resource-allocating functions or methods of the standard library (like open() or threading.Lock.acquire()) that can be used as a context manager are called without a with block.

    Closes #3413

  • Resolve false positives on unused variables in decorator functions

    Closes #4252

  • Add new extension ConfusingConsecutiveElifChecker. This optional checker emits a refactoring message (R5601 confusing-consecutive-elif) if if/elif statements with different indentation levels follow directly one after the other.
  • New option --output=<file> to output result to a file rather than printing to stdout.

    Closes #1070

  • Use a prescriptive message for unidiomatic-typecheck

    Closes #3891

  • Apply const-naming-style to module constants annotated with typing.Final
  • The packaging is now done via setuptools exclusively. doc, tests, man, elisp and Changelog are not packaged anymore - reducing the size of the package by 75%.
  • Debian packaging is now (officially) done in https://salsa.debian.org/python-team/packages/pylint.
  • The 'doc' extra-require has been removed.
  • __pkginfo__ now only contain __version__ (also accessible with pylint.__version__), other meta-information are still accessible with from importlib import metadata;metadata.metadata('pylint').
  • COPYING has been renamed to LICENSE for standardization.
  • Fix false-positive used-before-assignment in function returns.

    Closes #4301

  • Updated astroid to 2.5.3

    Closes #2822, #4206, #4284

  • Add consider-using-min-max-builtin check for if statement which could be replaced by Python builtin min or max

    Closes #3406

  • Don't auto-enable postponed evaluation of type annotations with Python 3.10
  • Update astroid to 2.5.4
  • Add new extension TypingChecker. This optional checker can detect the use of deprecated typing aliases and can suggest the use of the alternative union syntax where possible. (For example, 'typing.Dict' can be replaced by 'dict', and 'typing.Unions' by '|', etc.) Make sure to check the config options if you plan on using it!
  • Reactivates old counts in report mode.

    Closes #3819

  • During detection of inconsistent-return-statements consider that assert False is a return node.

    Closes #4019

  • Run will not fail if score exactly equals config.fail_under.
  • Functions that never returns may declare NoReturn as type hints, so that inconsistent-return-statements is not emitted.

    Closes #4122, #4188

  • Improved protected access checks to allow access inside class methods

    Closes #1159

  • Fix issue with PEP 585 syntax and the use of collections.abc.Set
  • Fix issue that caused class variables annotated with typing.ClassVar to be identified as class constants. Now, class variables annotated with typing.Final are identified as such.

    Closes #4277

  • Continuous integration with read the doc has been added.

    Closes #3850

  • Don't show DuplicateBasesError for attribute access
  • Fix crash when checking setup.cfg for pylint config when there are non-ascii characters in there

    Closes #4328

  • Allow code flanked in backticks to be skipped by spellchecker

    Closes #4319

  • Allow Python tool directives (for black, flake8, zimports, isort, mypy, bandit, pycharm) at beginning of comments to be skipped by spellchecker

    Closes #4320

  • Fix issue that caused Emacs pylint to fail when used with tramp
  • Improve check for invalid PEP 585 syntax inside functions if postponed evaluation of type annotations is enabled
  • Improve check for invalid PEP 585 syntax as default function arguments

What's New In Pylint 2.7

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

  • Python 3.6+ is now required.
  • No more duplicate messages when using multiple jobs.
  • Handling of the new typing provided by mypy 0.8
  • Reduced the number of false positives in general
  • Reduced the occurrence of genuinely large recursion that went above system limit (See #3836, for a fix for pandas)

New checkers

  • Add nan-comparison check for comparison of NaN values
  • Add support to ignored-argument-names in DocstringParameterChecker and adds useless-param-doc and useless-type-doc messages.
  • Add empty-comment check for empty comments.
  • Add simplifiable-condition check for extraneous constants in conditionals using and/or.
  • Add condition-evals-to-constant check for conditionals using and/or that evaluate to a constant.
  • Add consider-using-generator check for the use of list comprehension inside any or all function.

Other Changes

  • Fix false positive for builtin-not-iterating when zip or map receives iterable
  • Fix linter multiprocessing pool shutdown which triggered warnings when ran in parallels with other pytest plugins.
  • Enums are now required to be named in UPPER_CASE by invalid-name.
  • Fix bug that lead to duplicate messages when using --jobs 2 or more.
  • Adds option check-protected-access-in-special-methods in the ClassChecker to activate/deactivate protected-access message emission for single underscore prefixed attribute in special methods.
  • inconsistent-return-statements message is now emitted if one of try/except statement is not returning explicitly while the other do.
  • Fix false positive message useless-super-delegation when default keyword argument is a dictionary.
  • Fix vulnerable regular expressions in pyreverse. The ambiguities of vulnerable regular expressions are removed, making the repaired regular expressions safer and faster matching.
  • len-as-conditions is now triggered only for classes that are inheriting directly from list, dict, or set and not implementing the __bool__ function, or from generators like range or list/dict/set comprehension. This should reduce the false positive for other classes, like pandas's DataFrame or numpy's Array.
  • Fixes duplicate code detection for --jobs=2+
  • New option allowed-redefined-builtins defines variable names allowed to shadow builtins.
  • Improved protected access checks to allow access inside class methods

Full changelog

What's New in Pylint 2.7.4?

Release date: 2021-03-30

  • Fix a problem with disabled msgid not being ignored

    Closes #4265

  • Fix issue with annotated class constants

    Closes #4264

What's New in Pylint 2.7.3?

Release date: 2021-03-29

  • Introduce logic for checking deprecated attributes in DeprecationMixin.
  • Reduce usage of blacklist/whitelist terminology. Notably, extension-pkg-allow-list is an alternative to extension-pkg-whitelist and the message blacklisted-name is now emitted as disallowed-name. The previous names are accepted to maintain backward compatibility.
  • Move deprecated checker to DeprecatedMixin

    Closes #4086

  • Bump astroid version to 2.5.2
  • Fix false positive for method-hidden when using private attribute and method

    Closes #3936

  • use-symbolic-message-instead now also works on legacy messages like C0111 (missing-docstring).
  • Remove unwanted print to stdout from _emit_no_member
  • Introduce a command-line option to specify pyreverse output directory

    Closes #4159

  • Fix issue with Enums and class-attribute-naming-style=snake_case

    Closes #4149

  • Add allowed-redefined-builtins option for fine tuning redefined-builtin check.

    Closes #3263

  • Fix issue when executing with python -m pylint

    Closes #4161

  • Exempt typing.TypedDict from too-few-public-methods check.

    Closes #4180

  • Fix false-positive no-member for typed annotations without default value.

    Closes #3167

  • Add --class-const-naming-style for Enum constants and class variables annotated with typing.ClassVar

    Closes #4181

  • Fix astroid.Inference error for undefined-variables with len()`

    Closes #4215

  • Fix column index on FIXME warning messages

    Closes #4218

  • Improve handling of assignment expressions, better edge case handling

    Closes #3763, #4238

  • Improve check if class is subscriptable PEP585
  • Fix documentation and filename handling of --import-graph
  • Fix false-positive for unused-import on class keyword arguments

    Closes #3202

  • Fix regression with plugins on PYTHONPATH if latter is cwd

    Closes #4252

What's New in Pylint 2.7.2?

Release date: 2021-02-28

  • Fix False Positive on Enum.__members__.items(), Enum.__members__.values, and Enum.__members__.keys

    Closes #4123

  • Properly strip dangerous sys.path entries (not just the first one)

    Closes #3636

  • Workflow and packaging improvements

What's New in Pylint 2.7.1?

Release date: 2021-02-23

  • Expose UnittestLinter in pylint.testutils
  • Don't check directories starting with '.' when using register_plugins

    Closes #4119

What's New in Pylint 2.7.0?

Release date: 2021-02-21

  • Introduce DeprecationMixin for reusable deprecation checks.

    Closes #4049

  • Fix false positive for builtin-not-iterating when map receives iterable

    Closes #4078

  • Python 3.6+ is now required.
  • Fix false positive for builtin-not-iterating when zip receives iterable
  • Add nan-comparison check for NaN comparisons
  • Bug fix for empty-comment message line number.

    Closes #4009

  • Only emit bad-reversed-sequence on dictionaries if below py3.8

    Closes #3940

  • Handle class decorators applied to function.

    Closes #3882

  • Add check for empty comments
  • Fix minor documentation issue in contribute.rst
  • Enums are now required to be named in UPPER_CASE by invalid-name.

    Closes #3834

  • Add missing checks for deprecated functions.
  • Postponed evaluation of annotations are now recognized by default if python version is above 3.10

    Closes #3992

  • Fix column metadata for anomalous backslash lints
  • Drop support for Python 3.5
  • Add support for pep585 with postponed evaluation

    Closes #3320

  • Check alternative union syntax - PEP 604

    Closes #4065

  • Fix multiple false positives with assignment expressions

    Closes #3347, #3953, #3865, #3275

  • Fix TypedDict inherit-non-class false-positive Python 3.9+

    Closes #1927

  • Fix issue with nested PEP 585 syntax
  • Fix issue with nested PEP 604 syntax
  • Fix a crash in undefined-variable caused by chained attributes in metaclass

    Closes #3742

  • Fix false positive for not-async-context-manager when contextlib.asynccontextmanager is used

    Closes #3862

  • Fix linter multiprocessing pool shutdown (triggered warnings when ran in parallels with other pytest plugins)

    Closes #3779

  • Fix a false-positive emission of no-self-use and unused-argument for methods of generic structural types (Protocol[T])

    Closes #3885

  • Fix bug that lead to duplicate messages when using --jobs 2 or more.

    Closes #3584

  • Adds option check-protected-access-in-special-methods in the ClassChecker to activate/deactivate protected-access message emission for single underscore prefixed attribute in special methods.

    Closes #3120

  • Fix vulnerable regular expressions in pyreverse

    Closes #3811

  • inconsistent-return-statements message is now emitted if one of try/except statement is not returning explicitly while the other do.

    Closes #3468

  • Fix useless-super-delegation false positive when default keyword argument is a dictionary.

    Closes #3773

  • Fix a crash when a specified config file does not exist
  • Add support to ignored-argument-names in DocstringParameterChecker and adds useless-param-doc and useless-type-doc messages.

    Closes #3800

  • Enforce docparams consistently when docstring is not present

    Closes #2738

  • Fix duplicate-code false positive when lines only contain whitespace and non-alphanumeric characters (e.g. parentheses, bracket, comma, etc.)
  • Improve lint message for singleton-comparison with bools
  • Fix spell-checker crash on indented docstring lines that look like # comments

    Closes #3786

  • Fix AttributeError in checkers/refactoring.py
  • Improve sphinx directives spelling filter
  • Fix a bug with postponed evaluation when using aliases for annotations.

    Closes #3798

  • Fix minor documentation issues
  • Improve the performance of the line length check.
  • Removed incorrect deprecation of inspect.getfullargspec
  • Fix signature-differs false positive for functions with variadics

    Closes #3737

  • Fix a crash in consider-using-enumerate when encountering range() without arguments

    Closes #3735

  • len-as-conditions is now triggered only for classes that are inheriting directly from list, dict, or set and not implementing the __bool__ function, or from generators like range or list/dict/set comprehension. This should reduce the false positives for other classes, like pandas's DataFrame or numpy's Array.

    Closes #1879

  • Fixes duplicate-errors not working with -j2+

    Closes #3314

  • generated-members now matches the qualified name of members

    Closes #2498

  • Add check for bool function to len-as-condition
  • Add simplifiable-condition check for extraneous constants in conditionals using and/or.
  • Add condition-evals-to-constant check for conditionals using and/or that evaluate to a constant.

    Closes #3407

  • Changed setup.py to work with distlib

    Closes #3555

  • New check: consider-using-generator

    This check warns when a comprehension is used inside an any or all function, since it is unnecessary and should be replaced by a generator instead. Using a generator would be less code and way faster.

    Closes #3165

  • Add Github Actions to replace Travis and AppVeyor in the future

What's New In Pylint 2.6

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

  • bad-continuation and bad-whitespace have been removed. black or another formatter can help you with this better than Pylint
  • Added support for isort 5

New checkers

  • Add super-with-arguments check for flagging instances of Python 2 style super calls.
  • Add raise-missing-from check for exceptions that should have a cause.

Other Changes

  • bad-continuation and bad-whitespace have been removed. black or another formatter can help you with this better than Pylint
  • The no-space-check option has been removed, it's no longer possible to consider empty line like a trailing-whitespace by using clever options.
  • mixed-indentation has been removed, it is no longer useful since TabError is included directly in python3
  • Fix superfluous-parens false-positive for the walrus operator
  • Add support for both isort 4 and isort 5. If you have pinned isort 4 in your projet requirements, nothing changes. If you use isort 5, though, note that the known-standard-library option is not interpreted the same in isort 4 and isort 5 (see the migration guide in isort documentation (no longer available) for further details). For compatibility's sake for most pylint users, the known-standard-library option in pylint now maps to extra-standard-library in isort 5. If you really want what known-standard-library now means in isort 5, you must disable the wrong-import-order check in pylint and run isort manually with a proper isort configuration file.

Full changelog

What's New in Pylint 2.6.1?

Release date: 2021-02-16

Astroid version has been set as < 2.5

Closes #4093

What's New in Pylint 2.6.0?

Release date: 2020-08-20

  • Fix various scope-related bugs in undefined-variable checker

    Closes #1082, #3434, #3461

  • bad-continuation and bad-whitespace have been removed, black or another formatter can help you with this better than Pylint

    Closes #246, #289, #638, #747, #1148, #1179, #1943, #2041, #2301, #2304, #2944, #3565

  • The no-space-check option has been removed. It's no longer possible to consider empty line like a trailing-whitespace by using clever options

    Closes #1368

  • missing-kwoa is no longer emitted when dealing with overload functions

    Closes #3655

  • mixed-indentation has been removed, it is no longer useful since TabError is included directly in python3

    Closes #2984 #3573

  • Add super-with-arguments check for flagging instances of Python 2 style super calls.
  • Add an faq detailing which messages to disable to avoid duplicates w/ other popular linters
  • Fix superfluous-parens false-positive for the walrus operator

    Closes #3383

  • Fix fail-under not accepting floats
  • Fix a bug with ignore-docstrings ignoring all lines in a module
  • Fix pre-commit config that could lead to undetected duplicate lines of code
  • Fix a crash in parallel mode when the module's filepath is not set

    Closes #3564

  • Add raise-missing-from check for exceptions that should have a cause.
  • Support both isort 4 and isort 5. If you have pinned isort 4 in your projet requirements, nothing changes. If you use isort 5, though, note that the known-standard-library option is not interpreted the same in isort 4 and isort 5 (see the migration guide in isort documentation for further details). For compatibility's sake for most pylint users, the known-standard-library option in pylint now maps to extra-standard-library in isort 5. If you really want what known-standard-library now means in isort 5, you must disable the wrong-import-order check in pylint and run isort manually with a proper isort configuration file.

    Closes #3722

  • Fix a crash caused by not guarding against InferenceError when calling infer_call_result

    Closes #3690

  • Fix a crash in parallel mode when the module's filepath is not set

    Closes #3564

What's New In Pylint 2.5

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

New checkers

A new check isinstance-second-argument-not-valid-type was added.
This check is emitted whenever pylint finds a call to the isinstance function with a second argument that is not a type. Such code is likely unintended as it will cause a TypeError to be thrown at runtime error.
A new check assert-on-string-literal was added.
This check is emitted whenever pylint finds an assert statement with a string literal as its first argument. Such assert statements are probably unintended as they will always pass.
A new check f-string-without-interpolation was added.
This check is emitted whenever pylint detects the use of an f-string without having any interpolated values in it, which means that the f-string can be a normal string.
Multiple checks for invalid return types of protocol functions were added:
  • invalid-bool-returned: __bool__ did not return a bool
  • invalid-index-returned: __index__ did not return an integer
  • invalid-repr-returned): __repr__ did not return a string
  • invalid-str-returned): __str__ did not return a string
  • invalid-bytes-returned): __bytes__ did not return a string
  • invalid-hash-returned): __hash__ did not return an integer
  • invalid-length-hint-returned): __length_hint__ did not return a non-negative integer
  • invalid-format-returned): __format__ did not return a string
  • invalid-getnewargs-returned): __getnewargs__ did not return a tuple
  • invalid-getnewargs-ex-returned): __getnewargs_ex__ did not return a tuple of the form (tuple, dict)
A new check inconsistent-quotes was added.
This check is emitted when quotes delimiters (" and ') are not used consistently throughout a module. It allows avoiding unnecessary escaping, allowing, for example, "Don't error" in a module in which single-quotes otherwise delimit strings so that the single quote in Don't doesn't need to be escaped.
A new check non-str-assignment-to-dunder-name was added to ensure that only strings are assigned to __name__ attributes.

Other Changes

  • Configuration can be read from a setup.cfg or pyproject.toml file in the current directory. A setup.cfg must prepend pylintrc section names with pylint., for example [pylint.MESSAGES CONTROL]. A pyproject.toml file must prepend section names with tool.pylint., for example [tool.pylint.'MESSAGES CONTROL']. These files can also be passed in on the command line.
  • Add new good-names-rgx and bad-names-rgx to enable permitting or disallowing of names via regular expressions

    To enable better handling of permitted/disallowed names, we added two new config options: good-names-rgxs: a comma- separated list of regexes, that if a name matches will be exempt of naming-checking. bad-names-rgxs: a comma- separated list of regexes, that if a name matches will be always marked as a disallowed name.

  • Mutable collections.* are now flagged as dangerous defaults.
  • Add new --fail-under flag for setting the threshold for the score to fail overall tests. If the score is over the fail-under threshold, pylint will complete SystemExit with value 0 to indicate no errors.
  • Added a new option notes-rgx to make fixme warnings more flexible. Now either notes or notes-rgx option can be used to detect fixme warnings.
  • Non-ASCII characters are now allowed by invalid-name.
  • pylint no longer emits invalid-name for non-constants found at module level.

    Pylint was considering all module level variables as constants, which is not what PEP 8 is actually mandating.

  • A new check non-ascii-name was added to detect identifiers with non-ASCII characters.
  • Overloaded typing functions no longer trigger no-self-use, unused-argument, missing-docstring and similar checks that assumed that overloaded functions are normal functions.
  • python -m pylint can no longer be made to import files from the local directory.
  • A new command --list-extensions was added.

    This command lists all extensions present in pylint.extensions.

  • Various false positives have been fixed which you can read more about in the Changelog files.
  • Multiple types of string formatting are allowed in logging functions.

The logging-fstring-interpolation message has been brought back to allow multiple types of string formatting to be used. The type of formatting to use is chosen through enabling and disabling messages rather than through the logging-format-style option. The fstr value of the logging-format-style option is not valid.

Full changelog

What's New in Pylint 2.5.3?

Release date: 2020-06-8

  • Fix a regression where disable comments that have checker names with numbers in them are not parsed correctly

    Closes #3666

  • property-with-parameters properly handles abstract properties

    Closes #3600

  • continue-in-finally no longer emitted on Python 3.8 where it's now valid

    Closes #3612

  • Fix a regression where messages with dash are not fully parsed

    Closes #3604

  • In a TOML configuration file, it's now possible to use rich (non-string) types, such as list, integer or boolean instead of strings. For example, one can now define a list of message identifiers to enable like this:
enable = [

"use-symbolic-message-instead",
"useless-suppression", ]

Closes #3538

  • Fix a regression where the score was not reported with multiple jobs

    Closes #3547

  • Protect against AttributeError when checking cell-var-from-loop

    Closes #3646

What's New in Pylint 2.5.2?

Release date: 2020-05-05

pylint.Run accepts do_exit as a deprecated parameter

Closes #3590

What's New in Pylint 2.5.1?

Release date: 2020-05-05

  • Fix a crash in method-hidden lookup for unknown base classes

    Closes #3527

  • Revert pylint.Run's exit parameter to do_exit

    This has been inadvertently changed several releases ago to do_exit.

    Closes #3533

  • no-value-for-parameter variadic detection has improved for assign statements

    Closes #3563

  • Allow package files to be properly discovered with multiple jobs

    Closes #3524

  • Allow linting directories without __init__.py which was a regression in 2.5.

    Closes #3528

What's New in Pylint 2.5.0?

Release date: 2020-04-27

  • Fix a false negative for undefined-variable when using class attribute in comprehension.

    Closes #3494

  • Fix a false positive for undefined-variable when using class attribute in decorator or as type hint.

    Closes #511 Closes #1976

  • Remove HTML quoting of messages in JSON output.

    Closes #2769

  • Adjust the invalid-name rule to work with non-ASCII identifiers and add the non-ascii-name rule.

    Closes #2725

  • Positional-only arguments are taken in account for useless-super-delegation
  • unidiomatic-typecheck is no longer emitted for in and not in operators

    Closes #3337

  • Positional-only argument annotations are taken in account for unused-import

    Closes #3462

  • Add a command to list available extensions.
  • Allow used variables to be properly consumed when different checks are enabled / disabled

    Closes #3445

  • Fix dangerous-default-value rule to account for keyword argument defaults

    Closes #3373

  • Fix a false positive of self-assigning-variable on tuple unpacking.

    Closes #3433

  • no-self-use is no longer emitted for typing stubs.

    Closes #3439

  • Fix a false positive for undefined-variable when __class__ is used

    Closes #3090

  • Emit invalid-name for variables defined in loops at module level.

    Closes #2695

  • Add a check for cases where the second argument to isinstance is not a type.

    Closes #3308

  • Add 'notes-rgx' option, to be used for fixme check.

    Closes #2874

  • function-redefined exempts function redefined on a condition.

    Closes #2410

  • typing.overload functions are exempted from docstring checks

    Closes #3350

  • Emit invalid-overridden-method for improper async def overrides.

    Closes #3355

  • Do not allow python -m pylint ... to import user code

    python -m pylint ... adds the current working directory as the first element of sys.path. This opens up a potential security hole where pylint will import user level code as long as that code resides in modules having the same name as stdlib or pylint's own modules.

    Closes #3386

  • Add dummy-variables-rgx option for _redeclared-assigned-name check.

    Closes #3341

  • Fixed graph creation for relative paths
  • Add a check for asserts on string literals.

    Closes #3284

  • not in is considered iterating context for some of the Python 3 porting checkers.
  • A new check inconsistent-quotes was added.
  • Add a check for non string assignment to __name__ attribute.

    Closes #583

  • __pow__, __imatmul__, __trunc__, __floor__, and __ceil__ are recognized as special method names.

    Closes #3281

  • Added errors for protocol functions when invalid return types are detected. E0304 (invalid-bool-returned): __bool__ did not return a bool E0305 (invalid-index-returned): __index__ did not return an integer E0306 (invalid-repr-returned): __repr__ did not return a string E0307 (invalid-str-returned): __str__ did not return a string E0308 (invalid-bytes-returned): __bytes__ did not return a string E0309 (invalid-hash-returned): __hash__ did not return an integer E0310 (invalid-length-hint-returned): __length_hint__ did not return a non-negative integer E0311 (invalid-format-returned): __format__ did not return a string E0312 (invalid-getnewargs-returned): __getnewargs__ did not return a tuple E0313 (invalid-getnewargs-ex-returned): __getnewargs_ex__ did not return a tuple of the form (tuple, dict)

    Closes #560

  • missing-*-docstring can look for __doc__ assignments.

    Closes #3301

  • undefined-variable can now find undefined loop iterables

    Closes #498

  • safe_infer can infer a value as long as all the paths share the same type.

    Closes #2503

  • Add a --fail-under <score> flag, also configurable in a .pylintrc file. If the final score is more than the specified score, it's considered a success and pylint exits with exitcode 0. Otherwise, it's considered a failure and pylint exits with its current exitcode based on the messages issued.

    Closes #2242

  • Don't emit line-too-long for multilines when disable=line-too-long comment stands at their end

    Closes #2957

  • Fixed an AttributeError caused by improper handling of dataclasses inference in pyreverse

    Closes #3256

  • Do not exempt bare except from undefined-variable and similar checks

    If a node was wrapped in a TryExcept, pylint was taking a hint from the except handler when deciding to emit or not a message. We were treating bare except as a fully fledged ignore but only the corresponding exceptions should be handled that way (e.g. NameError or ImportError)

    Closes #3235

  • No longer emit assignment-from-no-return when a function only raises an exception

    Closes #3218

  • Allow import aliases to exempt import-error when used in type annotations.

    Closes #3178

  • Ellipsis` is exempted from ``multiple-statements for function overloads.

    Closes #3224

  • No longer emit invalid-name for non-constants found at module level.

    Pylint was taking the following statement from PEP-8 too far, considering all module level variables as constants, which is not what the statement is saying:

    Constants are usually defined on a module level and written in all capital letters with underscores separating words.

    Closes #3111 Closes #3132

  • Allow implicit-str-concat-in-sequence to be emitted for string juxtaposition

    Closes #3030

  • implicit-str-concat-in-sequence was renamed implicit-str-concat
  • The json reporter no longer bypasses redirect_stdout.

    Closes #3227

  • Move NoFileError, OutputLine, FunctionalTestReporter, FunctionalTestFile, LintModuleTest and related methods from test_functional.py to pylint.testutils to help testing for 3rd party pylint plugins.
  • Can read config from a setup.cfg or pyproject.toml file.

    Closes #617

  • Fix exception-escape false positive with generators

    Closes #3128

  • inspect.getargvalues is no longer marked as deprecated.
  • A new check f-string-without-interpolation was added

    Closes #3190

  • Flag mutable collections.* utilities as dangerous defaults

    Closes #3183

  • docparams extension supports multiple types in raises sections.

    Multiple types can also be separated by commas in all valid sections.

    Closes #2729

  • Allow parallel linting when run under Prospector
  • Fixed false positives of method-hidden when a subclass defines the method that is being hidden.

    Closes #414

  • Python 3 porting mode is 30-50% faster on most codebases
  • Python 3 porting mode no longer swallows syntax errors

    Closes #2956

  • Pass the actual PyLinter object to sub processes to allow using custom PyLinter classes.

    PyLinter object (and all its members except reporter) needs to support pickling so the PyLinter object can be passed to worker processes.

  • Clean up setup.py

    Make pytest-runner a requirement only if running tests, similar to McCabe.

    Clean up the setup.py file, resolving a number of warnings around it.

  • Handle SyntaxError in files passed via --from-stdin option

    Pylint no longer outputs a traceback, if a file, read from stdin, contains a syntaxerror.

  • Fix uppercase style to disallow 3+ uppercase followed by lowercase.
  • Fixed undefined-variable and unused-import false positives when using a metaclass via an attribute.

    Closes #1603

  • Emit unused-argument for functions that partially uses their argument list before raising an exception.

    Closes #3246

  • Fixed broad_try_clause extension to check try/finally statements and to check for nested statements (e.g., inside of an if statement).
  • Recognize classes explicitly inheriting from abc.ABC or having an abc.ABCMeta metaclass as abstract. This makes them not trigger W0223.

    Closes #3098

  • Fix overzealous arguments-differ when overridden function uses variadics

    No message is emitted if the overriding function provides positional or keyword variadics in its signature that can feasibly accept and pass on all parameters given by the overridden function.

    Closes #1482 Closes #1553

  • Multiple types of string formatting are allowed in logging functions.

    The logging-fstring-interpolation message has been brought back to allow multiple types of string formatting to be used.

    Closes #3361

What's New In Pylint 2.4

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

New checkers

  • import-outside-toplevel

    This check warns when modules are imported from places other than a module toplevel, e.g. inside a function or a class.

  • Added a new check, consider-using-sys-exit

    This check is emitted when we detect that a quit() or exit() is invoked instead of sys.exit(), which is the preferred way of exiting in program.

    Closes #2925

  • Added a new check, arguments-out-of-order

    This check warns if you have arguments with names that match those in a function's signature but you are passing them in to the function in a different order.

    Closes #2975

  • Added new checks, no-else-break and no-else-continue

    These checks highlight unnecessary else and elif blocks after break and continue statements.

    Closes #2327

  • Added unnecessary-comprehension that detects unnecessary comprehensions.

    This check is emitted when pylint finds list-, set- or dict-comprehensions, that are unnecessary and can be rewritten with the list-, set- or dict-constructors.

    Closes #2905

  • Added a new check, invalid-overridden-method

    This check is emitted when we detect that a method is overridden as a property or a property is overridden as a method. This can indicate a bug in the application code that will trigger a runtime error.

    Closes #2670

  • Added a new check, redeclared-assigned-name

    This check is emitted when pylint detects that a name was assigned one or multiple times in the same assignment, which indicate a potential bug.

    Closes #2898

  • Added a new check, self-assigning-variable

    This check is emitted when we detect that a variable is assigned to itself, which might indicate a potential bug in the code application.

    For example, the following would raise this warning:

def new_a(attr, attr2):

a_inst = Aclass()
a_inst.attr2 = attr2
# should be: a_inst.attr = attr, but have a typo
attr = attr
return a_inst

Closes #2930

  • Added a new check property-with-parameters which detects when a property has more than a single argument.

    Closes #3006

  • Added subprocess-run-check to handle subprocess.run without explicitly set check keyword.

    Closes #2848

  • We added a new check message dict-iter-missing-items. This is emitted when trying to iterate through a dict in a for loop without calling its .items() method.

    Closes #2761

  • We added a new check message missing-parentheses-for-call-in-test. This is emitted in case a call to a function is made inside a test but it misses parentheses.
  • A new check class-variable-slots-conflict was added.

    This check is emitted when pylint finds a class variable that conflicts with a slot name, which would raise a ValueError at runtime.

    For example, the following would raise an error:

class A:

__slots__ = ('first', 'second')
first = 1
  • A new check preferred-module was added.

    This check is emitted when pylint finds an imported module that has a preferred replacement listed in preferred-modules.

    For example, you can set the preferred modules as xml:defusedxml,json:ujson to make pylint suggest using defusedxml instead of xml and ujson rather than json.

  • A new extension broad_try_clause was added.

    This extension enforces a configurable maximum number of statements inside of a try clause. This facilitates enforcing PEP 8's guidelines about try / except statements and the amount of code in the try clause.

    You can enable this extension using --load-plugins=pylint.extensions.broad_try_clause and you can configure the amount of statements in a try statement using --max-try-statements.

Other Changes

  • Don't emit protected-access when a single underscore prefixed attribute is used inside a special method

    Closes #1802

  • len-as-condition now only fires when a len(x) call is made without an explicit comparison.

    The message and description accompanying this checker has been changed reflect this new behavior, by explicitly asking to either rely on the fact that empty sequence are false or to compare the length with a scalar.

    OK:

if len(x) == 0:

pass while not len(x) == 0:
pass assert len(x) > 5, message

KO:

if not len(x):

pass while len(x) and other_cond:
pass assert len(x), message
  • A file is now read from stdin if the --from-stdin flag is used on the command line. In addition to the --from-stdin flag a (single) file name needs to be specified on the command line, which is needed for the report.
  • The checker for ungrouped imports is now more permissive.

The import can now be sorted alphabetically by import style. This makes pylint compatible with isort.

The following imports do not trigger an ungrouped-imports anymore

import unittest
import zipfile
from unittest import TestCase
from unittest.mock import MagicMock
The checker for missing return documentation is now more flexible.

The following does not trigger a missing-return-doc anymore

def my_func(self):

"""This is a docstring.
Returns
-------
:obj:`list` of :obj:`str`
List of strings
"""
return ["hi", "bye"] #@
signature-mutators CLI and config option was added.

With this option, users can choose to ignore too-many-function-args, unexpected-keyword-arg, and no-value-for-parameter for functions decorated with decorators that change the signature of a decorated function.

For example a test may want to make use of hypothesis. Adding hypothesis.extra.numpy.arrays to signature_mutators would mean that no-value-for-parameter would not be raised for:

@given(img=arrays(dtype=np.float32, shape=(3, 3, 3, 3)))
def test_image(img):

...
Allow the option of f-strings as a valid logging string formatting method.

logging-fstring--interpolation has been merged into logging-format-interpolation to allow the logging-format-style option to control which logging string format style is valid. To allow this, a new fstr value is valid for the logging-format-style option.

--list-msgs-enabled command was added.

When enabling/disabling several messages and groups in a config file, it can be unclear which messages are actually enabled and which are disabled. This new command produces the final resolved lists of enabled/disabled messages, sorted by symbol but with the ID provided for use with --help-msg.

Full changelog

What's New in Pylint 2.4.4?

Release date: 2019-11-13

  • Exempt all the names found in type annotations from unused-import

    The previous code was assuming that only typing names need to be exempted, but we need to do that for the rest of the type comment names as well.

    Closes #3112

  • Relax type import detection for names that do not come from the typing module

    Closes #3191

What's New in Pylint 2.4.3?

Release date: 2019-10-18

  • Fix an issue with unnecessary-comprehension in comprehensions with additional repacking of elements.

    Closes #3148

  • import-outside-toplevel is emitted for ImportFrom nodes as well.

    Closes #3175

  • Do not emit no-method-argument for functions using positional only args.

    Closes #3161

  • consider-using-sys-exit is no longer emitted when exit is imported in the local scope.

    Closes #3147

  • invalid-overridden-method takes abc.abstractproperty in account

    Closes #3150

  • Fixed missing-yield-type-doc getting incorrectly raised when a generator does not document a yield type but has a type annotation.

    Closes #3185

  • typing.overload functions are exempted from too-many-function-args

    Closes #3170

What's New in Pylint 2.4.2?

Release date: 2019-09-30

  • ignored-modules can skip submodules.

    Closes #3135

  • self-assigning-variable skips class level assignments.

    Closes #2930

  • consider-using-sys-exit is exempted when exit() is imported from sys

    Closes #3145

  • Exempt annotated assignments without variable from class-variable-slots-conflict

    Closes #3141

  • Fix utils.is_error to account for functions returning early.

    This fixes a false negative with unused-variable which was no longer triggered when a function raised an exception as the last instruction, but the body of the function still had unused variables.

    Closes #3028

What's New in Pylint 2.4.1?

Release date: 2019-09-25

  • Exempt type checking definitions defined in both clauses of a type checking guard

    Closes #3127

  • Exempt type checking definitions inside the type check guard

    In a7f236528bb3758886b97285a56f3f9ce5b13a99 we added basic support for emitting used-before-assignment if a variable was only defined inside a type checking guard (using TYPE_CHECKING variable from typing) Unfortunately that missed the case of using those type checking imports inside the guard itself, which triggered spurious used-before-assignment errors.

    Closes #3119

  • Require astroid >= 2.3 to avoid any compatibility issues.

What's New in Pylint 2.4.0?

Release date: 2019-09-24

  • New check: import-outside-toplevel

    This check warns when modules are imported from places other than a module toplevel, e.g. inside a function or a class.

  • Handle inference ambiguity for invalid-format-index

    Closes #2752

  • Removed Python 2 specific checks such as relative-import, invalid-encoded-data, missing-super-argument.
  • Support forward references for function-redefined check.

    Closes #2540

  • Handle redefinitions in case of type checking imports.

    Closes #2834

  • Added a new check, consider-using-sys-exit

    This check is emitted when we detect that a quit() or exit() is invoked instead of sys.exit(), which is the preferred way of exiting in program.

    Closes #2925

  • useless-suppression check now ignores cyclic-import suppressions, which could lead to false postiives due to incomplete context at the time of the check.

    Closes #3064

  • Added new checks, no-else-break and no-else-continue

    These checks highlight unnecessary else and elif blocks after break and continue statements.

    Closes #2327

  • Don't emit protected-access when a single underscore prefixed attribute is used inside a special method

    Closes #1802

  • Fix the "statement" values in the PyLinter's stats reports by module.
  • Added a new check, invalid-overridden-method

    This check is emitted when we detect that a method is overridden as a property or a property is overridden as a method. This can indicate a bug in the application code that will trigger a runtime error.

    Closes #2670

  • Added a new check, arguments-out-of-order

    This check warns if you have arguments with names that match those in a function's signature but you are passing them in to the function in a different order.

    Closes #2975

  • Added a new check, redeclared-assigned-name

    This check is emitted when pylint detects that a name was assigned one or multiple times in the same assignment, which indicate a potential bug.

    Closes #2898

  • Ignore lambda calls with variadic arguments without a context.

    Inferring variadic positional arguments and keyword arguments will result into empty Tuples and Dicts, which can lead in some cases to false positives with regard to no-value-for-parameter. In order to avoid this, until we'll have support for call context propagation, we're ignoring such cases if detected. We already did that for function calls, but the previous fix was not taking in consideration lambdas

    Closes #2918

  • Added a new check, self-assigning-variable. This check is emitted when we detect that a variable is assigned to itself, which might indicate a potential bug in the code application.

    Closes #2930

  • Added a new check, property-with-parameters.

    This check is emitted when we detect that a defined property also has parameters, which are useless.

    Closes #3006

  • Excluded protocol classes from a couple of checks.

    Closes #3002.

  • Add a check unnecessary-comprehension that detects unnecessary comprehensions.

    This check is emitted when pylint finds list-, set- or dict-comprehensions, that are unnecessary and can be rewritten with the list-, set- or dict-constructors.

    Closes #2905

  • Excluded PEP 526 instance and class variables from no-member.

    Closes #2945

  • Excluded attrs from too-few-public-methods check.

    Closes #2988.

  • unused-import emitted for the right import names in function scopes.

    Closes #2928

  • Dropped support for Python 3.4.
  • assignment-from-no-return not triggered for async methods.

    Closes #2902

  • Don't emit attribute-defined-outside-init for variables defined in setters.

    Closes #409

  • Syntax errors report the column number.

    Closes #2914

  • Support fully qualified typing imports for type annotations.

    Closes #2915

  • Exclude __dict__ from attribute-defined-outside-init
  • Fix pointer on spelling check when the error are more than one time in the same line.

    Closes #2895

  • Fix crash happening when parent of called object cannot be determined
  • Allow of in GoogleDocstring.re_multiple_type
  • Added subprocess-run-check to handle subrocess.run without explicitly set check keyword.

    Closes #2848

  • When we can't infer bare except handlers, skip try-except-raise

    Closes #2853

  • Handle more unnecessary-lambda cases when dealing with additional kwargs in wrapped calls

    Closes #2845

  • Better postponed evaluation of annotations handling

    Closes #2847

  • Support postponed evaluation of annotations for variable annotations.

    Closes #2838

  • epylint.py_run defaults to python in case the current executable is not a Python one.

    Closes #2837

  • Ignore raw docstrings when running Similarities checker with ignore-docstrings=yes option
  • Fix crash when calling inherit_from_std_ex on a class which is its own ancestor

    Closes #2680

  • Added a new check that warns the user if a function call is used inside a test but parentheses are missing.

    Closes #2658

  • len-as-condition now only fires when a len(x) call is made without an explicit comparison

    The message and description accompanying this checker has been changed reflect this new behavior, by explicitly asking to either rely on the fact that empty sequence are false or to compare the length with a scalar.

    Closes #2684

  • Add preferred-module checker that notify if an import has a replacement module that should be used.

    This check is emitted when pylint finds an imported module that has a preferred replacement listed in preferred-modules.

  • assigning-non-slot not emitted for classes with unknown base classes.

    Closes #2807

  • old-division is not emitted for non-Const nodes.

    Closes #2808

  • Added method arguments to the dot writer for pyreverse.

    Closes #2139

  • Support for linting file from stdin.

    IDEs may benefit from the support for linting from an in-memory file.

    Closes #1187

  • Added a new check class-variable-slots-conflict

    This check is emitted when pylint finds a class variable that conflicts with a slot name, which would raise a ValueError at runtime.

  • Added new check: dict-iter-missing-items (E1141)

    Closes #2761

  • Fix issue with pylint name in output of python -m pylint --version

    Closes #2764

  • Relicense logo material under the CC BY-SA 4.0 license.
  • Skip if expressions from f-strings for the check_elif checker

    Closes #2816

  • C0412 (ungrouped-import) is now compatible with isort.

    Closes #2806

  • Added new extension to detect too much code in a try clause

    Closes #2877

  • signature-mutators option was added. With this option, users can choose to ignore too-many-function-args, unexpected-keyword-arg, and no-value-for-parameter for functions decorated with decorators that change the signature of a decorated function.

    Closes #259

  • Fixed a pragma comment on its own physical line being ignored when part of a logical line with the previous physical line.

    Closes #199

  • Fixed false undefined-loop-variable for a function defined in the loop, that uses the variable defined in that loop.

    Closes #202

  • Fixed unused-argument and function-redefined getting raised for functions decorated with typing.overload.

    Closes #1581

  • Fixed a false positive with consider-using-dict-comprehension for constructions that can't be converted to a comprehension

    Closes #2963

  • Added __post_init__ to defining-attr-methods in order to avoid attribute-defined-outside-init in dataclasses.

    Closes #2581

  • Changed description of W0199 to use the term 2-item-tuple instead of 2-uple.
  • Allow a . as a prefix for Sphinx name resolution.
  • Checkers must now keep a 1 to 1 relationship between "msgid" (ie: C1234) and "symbol" (i.e. : human-readable-symbol)
  • In checkers, an old_names can now be used for multiple new messages and pylint is now a little faster

    It means if you do a partial old_names for a message definition an exception will tell you that you must rename the associated identification.

  • Allow the choice of f-strings as a valid way of formatting logging strings.

    Closes #2395

  • Added --list-msgs-enabled command to list all enabled and disabled messages given the current RC file and command line arguments.

What's New In Pylint 2.3

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

This release improves the performance of the 2.X series after it was affected by a performance regression a couple of releases ago.

New checkers

  • We added a new check message wrong-exception-operation. This is emitted when an operation is done against an exception, but the operation is not valid for the exception in question. Usually emitted when having binary operations between exceptions in except handlers.

    Closes #2494

  • We added a new no-else-raise warning similar to no-else-return

    Closes #2558

  • We added a new option check-str-concat-over-line-jumps to check implicit-str-concat-in-sequence over multiple lines.

Other Changes

Quite a lot of bug fixes and improvements went into this release, here's a handful of them. For the full changes, check the full changelog.

  • We no longer emit *-not-iterating checks for builtins consumed by itertools
  • We fixed some false positives for no-self-argument and unsubscriptable-object when using __class_getitem__ (new in Python 3.7)
  • pylint now supports Ellipsis as a synonym for pass statements.
  • fixme gets triggered only on comments.
  • pylint exempts starred unpacking from *-not-iterating Python 3 checks.
  • compare-to-zero is now less zealous by checking against equality and identity.

``yield from`` is exempted from ``-not-iterating`` Python 3 checks.

  • A false positive with not-async-context-manager caused by not understanding contextlib.asynccontextmanager was fixed.
  • We refactored bad-reversed-sequence to account for more objects that can define __reversed__.
  • no-member is now emitted for enums when they lack a member.
  • Plugins can now use the load_configuration() hook. This hook is executed after configuration is loaded to prevent overwriting plugin specific configuration via user-based configuration.
  • There's a new command line option list-groups for listing all the check groups pylint knows about. This is useful to know what groups you can disable or enable individually.

Full changelog

What's New in Pylint 2.3.0?

Release date: 2019-02-27

  • Protect against NonDeducibleTypeHierarchy when calling semi-private is_subtype

    astroid.helpers.is_subtype raises NonDeducibleTypeHierarchy when it cannot infer the base classes of the given types, but that makes sense in its context given that the method is mostly used to inform the inference process about the hierarchy of classes. Doesn't make that much sense for pylint itself, which is why we're handling the exception here, rather than in astroid

    Closes PyCQA/astroid#644

  • Added a new command line option list-groups for listing all the check groups pylint knows about.
  • Allow BaseException for emitting broad-except, just like Exception.

    Closes #2741

  • Fixed a crash that occurred for bad-str-strip-call when strip() received None

    Closes #2743

  • Don't emit *-not-iterating checks for builtins consumed by itertools

    Closes #2731

  • Fix a crash caused by iterating over Uninferable in a string formatting check.

    Closes #2727

  • Fixed false positives for no-self-argument and unsubscriptable-object when using __class_getitem__ (new in Python 3.7)

    Closes #2416

  • Support Ellipsis as a synonym for pass statements.

    Closes #2718

  • fixme gets triggered only on comments.

    Closes #2321

  • Fixed a false positive for unused-variable and nonlocal assignments

    Closes #2671

  • Added load_configuration() hook for plugins

    New optional hook for plugins is added: load_configuration(). This hook is executed after configuration is loaded to prevent overwriting plugin specific configuration via user-based configuration.

    Closes #2635

  • Fix missing-raises-doc false positive (W9006)

    Closes #1502

  • Exempt starred unpacking from *-not-iterating Python 3 checks

    Closes #2651

  • Make compare-to-zero less zealous by checking against equality and identity

    Closes #2645

  • Add no-else-raise warning (R1720)

    Closes #2558

  • Exempt yield from from *-not-iterating Python 3 checks.

    Closes #2643

  • Fix incorrect generation of no-else-return warnings (R1705)

    Fixed issue where if statements with nested if statements were incorrectly being flagged as no-else-return in some cases and not being flagged as no-else-return in other cases. Added tests for verification and updated pylint source files to eliminate newly exposed warnings.

  • Fix false positive with not-async-context-manager caused by not understanding contextlib.asynccontextmanager

    Closes #2440

  • Refactor bad-reversed-sequence to account for more objects that can define __reversed__

    One such object would be an enum class, for which __reversed__ yields each individual enum. As such, the check for bad-reversed-sequence needs to not differentiate between classes and instances when it comes for checking of __reversed__ presence.

    Closes #2598

  • Added wrong-exception-operation

    Used when an operation is done against an exception, but the operation is not valid for the exception in question. Usually emitted when having binary operations between exceptions in except handlers.

    Closes #2494

  • no-member is emitted for enums when they lack a member

    Previously we weren't doing this because we detected a __getattr__ implementation on the Enum class (and this check is skipped for classes with __getattr__), but that is fine for Enums, given that they are inferred in a customised way in astroid.

    Closes #2565

  • Generalize chained-comparison

    Previous version incorrectly detects a < b < c and b < d and fails to detect a < b < c and c < d.

  • Avoid popping __main__ when using multiple jobs

    Closes #2689

  • Add a new option 'check-str-concat-over-line-jumps' to check 'implicit-str-concat-in-sequence'
  • Fixes for the new style logging format linter.

    The number of arguments was not handled properly, leading to an always successful check.

  • Fix false positive not-callable for uninferable properties.
  • Fix false positive useless-else-on-loop if the break is deep in the else of an inner loop.
  • Minor improvements to the help text for a few options.

What's New In Pylint 2.2

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

New checkers

  • String checker now reports format string type mismatches.
  • duplicate-string-formatting-argument was added for detecting duplicate string formatting arguments that should be passed instead as named arguments.
  • logging-format-style is a new option for the logging checker for usage of str.format() style format strings in calls to loggers.

    It accepts two options: --logging-format-style=old for using % style formatting, which is the assumed default, and --logging-format-style=new for using {} style formatting.

  • implicit-str-concat-in-sequence detects string concatenation inside lists, sets & tuples.

    Example of code that would generate such warning:

woops = ('a', 'b' 'c')

Other Changes

  • try-except-raise checker now handles multilevel inheritance hirerachy for exceptions correctly.

    Closes #2484

  • Ignore import x.y.z as z cases for checker useless-import-alias.
  • unnecessary-pass is now also emitted when a function or class contains only docstring and pass statement, in which case, docstring is enough for empty definition.
  • Fix false positive undefined-variable and used-before-assignment with nonlocal keyword usage.
  • Fix exceptions being raised when one of the params is not a ClassDef for checkers.utils.is_subclass_of.
  • pylint now picks the latest value from the inferred values of the exception that gets raised, when looking for raising-non-exception. This helps when reusing a variable name for multiple types, since pylint was picking just the first inferred value, leading to spurious false positives.

    Closes #2431

  • pylint used to emit a not-an-iterable error when looking at coroutines built with asyncio.coroutine. This is no longer the case as we handle coroutines explicitly.

    Closes #996

  • pylint used to emit an unused-variable error if unused import was found in the function. Now instead of unused-variable, unused-import is emitted.

    Closes #2421

Full changelog

What's New in Pylint 2.2.2?

Release date: 2018-11-28

Change the logging-format-style to use name identifier instead of their corresponding Python identifiers

This is to prevent users having to think about escaping the default value for logging-format-style in the generated config file. Also our config parsing utilities don't quite support escaped values when it comes to choices detection, so this would have needed various hacks around that.

Closes #2614

What's New in Pylint 2.2.1?

Release date: 2018-11-27

Fix a crash caused by implicit-str-concat-in-sequence and multi-bytes characters.

Closes #2610

What's New in Pylint 2.2?

Release date: 2018-11-25

  • Consider range() objects for undefined-loop-variable leaking from iteration.

    Closes #2533

  • deprecated-method can use the attribute name for identifying a deprecated method
Previously we were using the fully qualified name, which we still do, but the fully qualified name for some unittest deprecated aliases leads to a generic deprecation function. Instead on relying on that, we now also rely on the attribute name, which should solve some false positives.
Closes #1653 Closes #1946
  • Fix compatibility with changes to stdlib tokenizer.
  • pylint is less eager to consume the whole line for pragmas

    Closes #2485

  • Obtain the correct number of CPUs for virtualized or containerized environments.

    Closes #2519

  • Change unbalanced-tuple-unpacking back to a warning.
It used to be a warning until a couple of years ago, after it was promoted to an error. But the check might be suggesting the wrong thing in some cases, for instance when checking against sys.argv which cannot be known at static analysis time. Given it might rely on potential unknown data, it's best to have it as a warning.
Closes #2522
  • Remove enumerate usage suggestion when defining __iter__ (C0200)

    Closes #2477

  • Emit too-many-starred-assignment only when the number of Starred nodes is per assignment elements

    Closes #2513

  • try-except-raise checker now handles multilevel inheritance hirerachy for exceptions correctly.

    Closes #2484

  • Add a new check, simplifiable-if-expression for expressions like True if cond else False.

    Closes #2487

  • too-few-public-methods is not reported for typing.NamedTuple

    Closes #2459

  • `too-few-public-methods is not reported for dataclasses created with options.

    Closes #2488

  • Remove wrong modules from 'bad-python3-import'.

    Closes #2453

  • The json reporter prints an empty list when no messages are emitted

    Closes #2446

  • Add a new check, duplicate-string-formatting-argument
This new check is emitted whenever a duplicate string formatting argument is found.
Closes #497
  • assignment-from-no-return is not emitted for coroutines.

    Closes #1715

  • Report format string type mismatches.
  • consider-using-ternary and simplified-boolean-expression no longer emit for sequence based checks

    Closes #2473

  • Handle AstroidSyntaxError when trying to import a module.

    Closes #2313

  • Allow __module__ to be redefined at a class level.

    Closes #2451

  • pylint used to emit an unused-variable error if unused import was found in the function. Now instead of unused-variable, unused-import is emitted.

    Closes #2421

  • Handle asyncio.coroutine when looking for not-an-iterable check.

    Closes #996

  • The locally-enabled check is gone.

    Closes #2442

  • Infer decorated methods when looking for method-hidden

    Closes #2369

  • Pick the latest value from the inferred values when looking for raising-non-exception

    Closes #2431

  • Extend the TYPE_CHECKING guard to TYPE_CHECKING name as well, not just the attribute

    Closes #2411

  • Ignore import x.y.z as z cases for checker useless-import-alias.

    Closes #2309

  • Fix false positive undefined-variable and used-before-assignment with nonlocal keyword usage.

    Closes #2049

  • Stop protected-access exception for missing class attributes
  • Don't emit assignment-from-no-return for decorated function nodes

    Closes #2385

  • unnecessary-pass is now also emitted when a function or class contains only docstring and pass statement.

    In Python, stubbed functions often have a body that contains just a single pass statement, indicating that the function doesn't do anything. However, a stubbed function can also have just a docstring, and function with a docstring and no body also does nothing.

    Closes #2208

  • duplicate-argument-name is emitted for more than one duplicate argument per function

    Closes #1712

  • Allow double indentation levels for more distinguishable indentations

    Closes #741

  • Consider tuples in exception handler for try-except-raise.

    Closes #2389

  • Fix astroid.ClassDef check in checkers.utils.is_subclass_of
  • Fix wildcard imports being ignored by the import checker
  • Fix external/internal distinction being broken in the import graph
  • Fix wildcard import check not skipping __init__.py

    Closes #2430

  • Add new option to logging checker, logging_format_style
  • Fix --ignore-imports to understand multi-line imports

    Closes #1422 Closes #2019

  • Add a new check 'implicit-str-concat-in-sequence' to spot string concatenation inside lists, sets & tuples.
  • literal-comparison is now emitted for 0 and 1 literals.

What's New In Pylint 2.1

From pylint's beginning to pylint 2.14.0 included, we had a changelog that contained all nontrivial changes to Pylint, including changes that were not user facing, i.e. change that might interest you only if you're a developer working on pylint or pylint plugins or an open-source historian.

From pylint 1.6.0 to 2.14.0, on top of the full changelog there was also a summary of (mostly user facing) changes.

Summary -- Release highlights

This release mostly includes fixes for bugs found after the launch of 2.0.

New checkers

A new check was added, misplaced-format-function.

This message is emitted when pylint detects that a format function is called on non str object. This can occur due to wrong placement of closing bracket, e.g

print('value: {}').format(123) # bad
print('value: {}'.format(123)) # good

Other Changes

  • try-except-raise check was demoted from an error to a warning, as part of issue #2323.
  • Correctly handle the new name of the Python implementation of the abc module.

    In Python 3.7, the abc module has both a C implementation as well as a Python one, but the Python implementation has a different file name that what pylint was expecting, resulting in some checks getting confused.

  • Modules with __getattr__ are exempted by default from no-member

    There's no easy way to figure out if a module has a particular member when the said module uses __getattr__, which is a new addition to Python 3.7. Instead we assume the safe thing to do, in the same way we do for classes, and skip those modules from checking.

  • invalid name is no longer triggered for function and attribute names longer than 30 characters. The upper limit was removed completely.
  • Fix false-positive undefined-variable for self referential class name in lamdbas
  • no-else-return also specifies the type of the branch that is causing the error.
  • Fixed inconsistent behaviour for bad-continuation on first line of file.
  • Fixed a bug where pylint was not able to disable certain messages on the last line through the global disable option.
  • pylint no longer emits useless-return when