diff --git a/site/ruff/contributing/index.html b/site/ruff/contributing/index.html index 18ff3023..65078575 100644 --- a/site/ruff/contributing/index.html +++ b/site/ruff/contributing/index.html @@ -1254,11 +1254,11 @@

Contributing to Ruff

Welcome! We're happy to have you here. Thank you in advance for your contribution to Ruff.

-
-

[!NOTE]

+
+

Note

This guide is for Ruff. If you're looking to contribute to ty, please see the ty contributing -guide.

-
+ guide.

+

The Basics

Ruff welcomes contributions in the form of pull requests.

For small changes (e.g., bug fixes), feel free to submit a PR.

@@ -1626,7 +1626,7 @@

CPython
cargo install hyperfine
 

To benchmark the release build:

-
cargo build --release && hyperfine --warmup 10 \
+
cargo build --release --bin ruff && hyperfine --warmup 10 \
   "./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ --no-cache -e" \
   "./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ -e"
 
@@ -1781,8 +1781,7 @@ 

Linux

Then convert the recorded profile

perf script -F +pid > /tmp/test.perf
 
-

You can now view the converted file with firefox profiler, with a -more in-depth guide here

+

You can now view the converted file with firefox profiler. To learn more about Firefox profiler, read the Firefox profiler profiling-guide.

An alternative is to convert the perf data to flamegraph.svg using flamegraph (cargo install flamegraph):

flamegraph --perfdata perf.data --no-inline
diff --git a/site/ruff/integrations/index.html b/site/ruff/integrations/index.html
index 3568d3df..bf47e0f9 100644
--- a/site/ruff/integrations/index.html
+++ b/site/ruff/integrations/index.html
@@ -1004,7 +1004,7 @@ 

GitLab CI/CD

stage: build interruptible: true image: - name: ghcr.io/astral-sh/ruff:0.11.10-alpine + name: ghcr.io/astral-sh/ruff:0.11.11-alpine before_script: - cd $CI_PROJECT_DIR - ruff --version @@ -1026,7 +1026,7 @@

pre-commit

Ruff can be used as a pre-commit hook via ruff-pre-commit:

- repo: https://github.com/astral-sh/ruff-pre-commit
   # Ruff version.
-  rev: v0.11.10
+  rev: v0.11.11
   hooks:
     # Run the linter.
     - id: ruff
@@ -1036,7 +1036,7 @@ 

pre-commit

To enable lint fixes, add the --fix argument to the lint hook:

- repo: https://github.com/astral-sh/ruff-pre-commit
   # Ruff version.
-  rev: v0.11.10
+  rev: v0.11.11
   hooks:
     # Run the linter.
     - id: ruff
@@ -1047,7 +1047,7 @@ 

pre-commit

To avoid running on Jupyter Notebooks, remove jupyter from the list of allowed filetypes:

- repo: https://github.com/astral-sh/ruff-pre-commit
   # Ruff version.
-  rev: v0.11.10
+  rev: v0.11.11
   hooks:
     # Run the linter.
     - id: ruff
diff --git a/site/ruff/requirements-insiders.txt b/site/ruff/requirements-insiders.txt
index f7759fb2..4b0f7df5 100644
--- a/site/ruff/requirements-insiders.txt
+++ b/site/ruff/requirements-insiders.txt
@@ -1,7 +1,8 @@
 PyYAML==6.0.2
-ruff==0.11.9
+ruff==0.11.10
 mkdocs==1.6.1
 mkdocs-material @ git+ssh://git@github.com/astral-sh/mkdocs-material-insiders.git@39da7a5e761410349e9a1b8abf593b0cdd5453ff
 mkdocs-redirects==1.2.2
 mdformat==0.7.22
 mdformat-mkdocs==4.1.2
+mkdocs-github-admonitions-plugin @ git+https://github.com/PGijsbers/admonitions.git#7343d2f4a92e4d1491094530ef3d0d02d93afbb7
diff --git a/site/ruff/requirements.txt b/site/ruff/requirements.txt
index 5d9b0541..e18d1ecf 100644
--- a/site/ruff/requirements.txt
+++ b/site/ruff/requirements.txt
@@ -1,7 +1,8 @@
 PyYAML==6.0.2
-ruff==0.11.9
+ruff==0.11.10
 mkdocs==1.6.1
 mkdocs-material==9.5.38
 mkdocs-redirects==1.2.2
 mdformat==0.7.22
 mdformat-mkdocs==4.1.2
+mkdocs-github-admonitions-plugin @ git+https://github.com/PGijsbers/admonitions.git#7343d2f4a92e4d1491094530ef3d0d02d93afbb7
diff --git a/site/ruff/rules/global-statement/index.html b/site/ruff/rules/global-statement/index.html
index a250f15f..d49fc25b 100644
--- a/site/ruff/rules/global-statement/index.html
+++ b/site/ruff/rules/global-statement/index.html
@@ -862,12 +862,13 @@ 

Example

def foo(): - print(var) - return 10 - + var = 10 + print(var) + return var -var = foo() -print(var) + +var = foo() +print(var)
diff --git a/site/ruff/rules/if-expr-with-true-false/index.html b/site/ruff/rules/if-expr-with-true-false/index.html index 677ab461..63c94115 100644 --- a/site/ruff/rules/if-expr-with-true-false/index.html +++ b/site/ruff/rules/if-expr-with-true-false/index.html @@ -852,6 +852,11 @@

Example

Use instead:

bool(a)
 
+

Fix safety

+

This fix is marked as unsafe because it may change the program’s behavior if the condition does not +return a proper Boolean. While the fix will try to wrap non-boolean values in a call to bool, +custom implementations of comparison functions like __eq__ can avoid the bool call and still +lead to altered behavior. Moreover, the fix may remove comments.

References

  • Python documentation: Truth Value Testing
  • diff --git a/site/ruff/rules/multiple-with-statements/index.html b/site/ruff/rules/multiple-with-statements/index.html index 8415250a..8b93c673 100644 --- a/site/ruff/rules/multiple-with-statements/index.html +++ b/site/ruff/rules/multiple-with-statements/index.html @@ -865,6 +865,9 @@

    Example

    with A() as a, B() as b:
         pass
     
    +

    Fix safety

    +

    This fix is marked as always unsafe unless preview mode is enabled, in which case it is always +marked as safe. Note that the fix is unavailable if it would remove comments (in either case).

    References

    • Python documentation: The with statement
    • diff --git a/site/ruff/rules/p-print/index.html b/site/ruff/rules/p-print/index.html index e6da2b9a..23a464a0 100644 --- a/site/ruff/rules/p-print/index.html +++ b/site/ruff/rules/p-print/index.html @@ -843,11 +843,12 @@

      p-print (T203)

      What it does

      Checks for pprint statements.

      Why is this bad?

      -

      Like print statements, pprint statements are useful in some situations -(e.g., debugging), but should typically be omitted from production code. -pprint statements can lead to the accidental inclusion of sensitive -information in logs, and are not configurable by clients, unlike logging -statements.

      +

      Like print statements, pprint statements used for debugging should +be omitted from production code. They can lead the accidental inclusion +of sensitive information in logs, and are not configurable by clients, +unlike logging statements.

      +

      pprint statements used to produce output as a part of a command-line +interface program are not typically a problem.

      Example

      import pprint
       
      @@ -863,7 +864,7 @@ 

      Example

      return dict_c

      Fix safety

      -

      This rule's fix is marked as unsafe, as it may remove pprint statements +

      This rule's fix is marked as unsafe, as it will remove pprint statements that are used beyond debugging purposes.

      diff --git a/site/ruff/rules/print/index.html b/site/ruff/rules/print/index.html index 3274f4df..bcc70e61 100644 --- a/site/ruff/rules/print/index.html +++ b/site/ruff/rules/print/index.html @@ -843,21 +843,32 @@

      print (T201)

      What it does

      Checks for print statements.

      Why is this bad?

      -

      print statements are useful in some situations (e.g., debugging), but -should typically be omitted from production code. print statements can -lead to the accidental inclusion of sensitive information in logs, and are -not configurable by clients, unlike logging statements.

      +

      print statements used for debugging should be omitted from production +code. They can lead the accidental inclusion of sensitive information in +logs, and are not configurable by clients, unlike logging statements.

      +

      print statements used to produce output as a part of a command-line +interface program are not typically a problem.

      Example

      -
      def add_numbers(a, b):
      -    print(f"The sum of {a} and {b} is {a + b}")
      -    return a + b
      +
      def sum_less_than_four(a, b):
      +    print(f"Calling sum_less_than_four")
      +    return a + b < 4
       
      -

      Use instead:

      -
      def add_numbers(a, b):
      -    return a + b
      +

      The automatic fix will remove the print statement entirely:

      +
      def sum_less_than_four(a, b):
      +    return a + b < 4
      +
      +

      To keep the line for logging purposes, instead use something like:

      +
      import logging
      +
      +logging.basicConfig(level=logging.INFO)
      +
      +
      +def sum_less_than_four(a, b):
      +    logging.debug("Calling sum_less_than_four")
      +    return a + b < 4
       

      Fix safety

      -

      This rule's fix is marked as unsafe, as it may remove print statements +

      This rule's fix is marked as unsafe, as it will remove print statements that are used beyond debugging purposes.

      diff --git a/site/ruff/rules/reimplemented-builtin/index.html b/site/ruff/rules/reimplemented-builtin/index.html index 7c7b172e..e7bb35ad 100644 --- a/site/ruff/rules/reimplemented-builtin/index.html +++ b/site/ruff/rules/reimplemented-builtin/index.html @@ -854,6 +854,8 @@

      Example

      Use instead:

      return any(predicate(item) for item in iterable)
       
      +

      Fix safety

      +

      This fix is always marked as unsafe because it might remove comments.

      References

      • Python documentation: any
      • diff --git a/site/ruff/search/search_index.json b/site/ruff/search/search_index.json index b57d391f..28b19954 100644 --- a/site/ruff/search/search_index.json +++ b/site/ruff/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"","title":"Ruff","text":"

        Docs | Playground

        An extremely fast Python linter and code formatter, written in Rust.

        Linting the CPython codebase from scratch.

        • \u26a1\ufe0f 10-100x faster than existing linters (like Flake8) and formatters (like Black)
        • \ud83d\udc0d Installable via pip
        • \ud83d\udee0\ufe0f pyproject.toml support
        • \ud83e\udd1d Python 3.13 compatibility
        • \u2696\ufe0f Drop-in parity with Flake8, isort, and Black
        • \ud83d\udce6 Built-in caching, to avoid re-analyzing unchanged files
        • \ud83d\udd27 Fix support, for automatic error correction (e.g., automatically remove unused imports)
        • \ud83d\udccf Over 800 built-in rules, with native re-implementations of popular Flake8 plugins, like flake8-bugbear
        • \u2328\ufe0f First-party editor integrations for VS Code and more
        • \ud83c\udf0e Monorepo-friendly, with hierarchical and cascading configuration

        Ruff aims to be orders of magnitude faster than alternative tools while integrating more functionality behind a single, common interface.

        Ruff can be used to replace Flake8 (plus dozens of plugins), Black, isort, pydocstyle, pyupgrade, autoflake, and more, all while executing tens or hundreds of times faster than any individual tool.

        Ruff is extremely actively developed and used in major open-source projects like:

        • Apache Airflow
        • Apache Superset
        • FastAPI
        • Hugging Face
        • Pandas
        • SciPy

        ...and many more.

        Ruff is backed by Astral. Read the launch post, or the original project announcement.

        "},{"location":"#testimonials","title":"Testimonials","text":"

        Sebasti\u00e1n Ram\u00edrez, creator of FastAPI:

        Ruff is so fast that sometimes I add an intentional bug in the code just to confirm it's actually running and checking the code.

        Nick Schrock, founder of Elementl, co-creator of GraphQL:

        Why is Ruff a gamechanger? Primarily because it is nearly 1000x faster. Literally. Not a typo. On our largest module (dagster itself, 250k LOC) pylint takes about 2.5 minutes, parallelized across 4 cores on my M1. Running ruff against our entire codebase takes .4 seconds.

        Bryan Van de Ven, co-creator of Bokeh, original author of Conda:

        Ruff is ~150-200x faster than flake8 on my machine, scanning the whole repo takes ~0.2s instead of ~20s. This is an enormous quality of life improvement for local dev. It's fast enough that I added it as an actual commit hook, which is terrific.

        Timothy Crosley, creator of isort:

        Just switched my first project to Ruff. Only one downside so far: it's so fast I couldn't believe it was working till I intentionally introduced some errors.

        Tim Abbott, lead developer of Zulip:

        This is just ridiculously fast... ruff is amazing.

        "},{"location":"configuration/","title":"Configuring Ruff","text":"

        Ruff can be configured through a pyproject.toml, ruff.toml, or .ruff.toml file.

        Whether you're using Ruff as a linter, formatter, or both, the underlying configuration strategy and semantics are the same.

        For a complete enumeration of the available configuration options, see Settings.

        If left unspecified, Ruff's default configuration is equivalent to:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Exclude a variety of commonly ignored directories.\nexclude = [\n    \".bzr\",\n    \".direnv\",\n    \".eggs\",\n    \".git\",\n    \".git-rewrite\",\n    \".hg\",\n    \".ipynb_checkpoints\",\n    \".mypy_cache\",\n    \".nox\",\n    \".pants.d\",\n    \".pyenv\",\n    \".pytest_cache\",\n    \".pytype\",\n    \".ruff_cache\",\n    \".svn\",\n    \".tox\",\n    \".venv\",\n    \".vscode\",\n    \"__pypackages__\",\n    \"_build\",\n    \"buck-out\",\n    \"build\",\n    \"dist\",\n    \"node_modules\",\n    \"site-packages\",\n    \"venv\",\n]\n\n# Same as Black.\nline-length = 88\nindent-width = 4\n\n# Assume Python 3.9\ntarget-version = \"py39\"\n\n[tool.ruff.lint]\n# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.\n# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or\n# McCabe complexity (`C901`) by default.\nselect = [\"E4\", \"E7\", \"E9\", \"F\"]\nignore = []\n\n# Allow fix for all enabled rules (when `--fix`) is provided.\nfixable = [\"ALL\"]\nunfixable = []\n\n# Allow unused variables when underscore-prefixed.\ndummy-variable-rgx = \"^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$\"\n\n[tool.ruff.format]\n# Like Black, use double quotes for strings.\nquote-style = \"double\"\n\n# Like Black, indent with spaces, rather than tabs.\nindent-style = \"space\"\n\n# Like Black, respect magic trailing commas.\nskip-magic-trailing-comma = false\n\n# Like Black, automatically detect the appropriate line ending.\nline-ending = \"auto\"\n\n# Enable auto-formatting of code examples in docstrings. Markdown,\n# reStructuredText code/literal blocks and doctests are all supported.\n#\n# This is currently disabled by default, but it is planned for this\n# to be opt-out in the future.\ndocstring-code-format = false\n\n# Set the line length limit used when formatting code snippets in\n# docstrings.\n#\n# This only has an effect when the `docstring-code-format` setting is\n# enabled.\ndocstring-code-line-length = \"dynamic\"\n
        # Exclude a variety of commonly ignored directories.\nexclude = [\n    \".bzr\",\n    \".direnv\",\n    \".eggs\",\n    \".git\",\n    \".git-rewrite\",\n    \".hg\",\n    \".ipynb_checkpoints\",\n    \".mypy_cache\",\n    \".nox\",\n    \".pants.d\",\n    \".pyenv\",\n    \".pytest_cache\",\n    \".pytype\",\n    \".ruff_cache\",\n    \".svn\",\n    \".tox\",\n    \".venv\",\n    \".vscode\",\n    \"__pypackages__\",\n    \"_build\",\n    \"buck-out\",\n    \"build\",\n    \"dist\",\n    \"node_modules\",\n    \"site-packages\",\n    \"venv\",\n]\n\n# Same as Black.\nline-length = 88\nindent-width = 4\n\n# Assume Python 3.9\ntarget-version = \"py39\"\n\n[lint]\n# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.\n# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or\n# McCabe complexity (`C901`) by default.\nselect = [\"E4\", \"E7\", \"E9\", \"F\"]\nignore = []\n\n# Allow fix for all enabled rules (when `--fix`) is provided.\nfixable = [\"ALL\"]\nunfixable = []\n\n# Allow unused variables when underscore-prefixed.\ndummy-variable-rgx = \"^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$\"\n\n[format]\n# Like Black, use double quotes for strings.\nquote-style = \"double\"\n\n# Like Black, indent with spaces, rather than tabs.\nindent-style = \"space\"\n\n# Like Black, respect magic trailing commas.\nskip-magic-trailing-comma = false\n\n# Like Black, automatically detect the appropriate line ending.\nline-ending = \"auto\"\n\n# Enable auto-formatting of code examples in docstrings. Markdown,\n# reStructuredText code/literal blocks and doctests are all supported.\n#\n# This is currently disabled by default, but it is planned for this\n# to be opt-out in the future.\ndocstring-code-format = false\n\n# Set the line length limit used when formatting code snippets in\n# docstrings.\n#\n# This only has an effect when the `docstring-code-format` setting is\n# enabled.\ndocstring-code-line-length = \"dynamic\"\n

        As an example, the following would configure Ruff to:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# 1. Enable flake8-bugbear (`B`) rules, in addition to the defaults.\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"B\"]\n\n# 2. Avoid enforcing line-length violations (`E501`)\nignore = [\"E501\"]\n\n# 3. Avoid trying to fix flake8-bugbear (`B`) violations.\nunfixable = [\"B\"]\n\n# 4. Ignore `E402` (import violations) in all `__init__.py` files, and in selected subdirectories.\n[tool.ruff.lint.per-file-ignores]\n\"__init__.py\" = [\"E402\"]\n\"**/{tests,docs,tools}/*\" = [\"E402\"]\n\n[tool.ruff.format]\n# 5. Use single quotes in `ruff format`.\nquote-style = \"single\"\n
        [lint]\n# 1. Enable flake8-bugbear (`B`) rules, in addition to the defaults.\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"B\"]\n\n# 2. Avoid enforcing line-length violations (`E501`)\nignore = [\"E501\"]\n\n# 3. Avoid trying to fix flake8-bugbear (`B`) violations.\nunfixable = [\"B\"]\n\n# 4. Ignore `E402` (import violations) in all `__init__.py` files, and in selected subdirectories.\n[lint.per-file-ignores]\n\"__init__.py\" = [\"E402\"]\n\"**/{tests,docs,tools}/*\" = [\"E402\"]\n\n[format]\n# 5. Use single quotes in `ruff format`.\nquote-style = \"single\"\n

        Linter plugin configurations are expressed as subsections, e.g.:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Add \"Q\" to the list of enabled codes.\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"Q\"]\n\n[tool.ruff.lint.flake8-quotes]\ndocstring-quotes = \"double\"\n
        [lint]\n# Add \"Q\" to the list of enabled codes.\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"Q\"]\n\n[lint.flake8-quotes]\ndocstring-quotes = \"double\"\n

        Ruff respects pyproject.toml, ruff.toml, and .ruff.toml files. All three implement an equivalent schema (though in the ruff.toml and .ruff.toml versions, the [tool.ruff] header and tool.ruff section prefix is omitted).

        For a complete enumeration of the available configuration options, see Settings.

        "},{"location":"configuration/#config-file-discovery","title":"Config file discovery","text":"

        Similar to ESLint, Ruff supports hierarchical configuration, such that the \"closest\" config file in the directory hierarchy is used for every individual file, with all paths in the config file (e.g., exclude globs, src paths) being resolved relative to the directory containing that config file.

        There are a few exceptions to these rules:

        1. In locating the \"closest\" pyproject.toml file for a given path, Ruff ignores any pyproject.toml files that lack a [tool.ruff] section.
        2. If a configuration file is passed directly via --config, those settings are used for all analyzed files, and any relative paths in that configuration file (like exclude globs or src paths) are resolved relative to the current working directory.
        3. If no config file is found in the filesystem hierarchy, Ruff will fall back to using a default configuration. If a user-specific configuration file exists at ${config_dir}/ruff/pyproject.toml, that file will be used instead of the default configuration, with ${config_dir} being determined via etcetera's native strategy, and all relative paths being again resolved relative to the current working directory.
        4. Any config-file-supported settings that are provided on the command-line (e.g., via --select) will override the settings in every resolved configuration file.

        Unlike ESLint, Ruff does not merge settings across configuration files; instead, the \"closest\" configuration file is used, and any parent configuration files are ignored. In lieu of this implicit cascade, Ruff supports an extend field, which allows you to inherit the settings from another config file, like so:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Extend the `pyproject.toml` file in the parent directory...\nextend = \"../pyproject.toml\"\n\n# ...but use a different line length.\nline-length = 100\n
        # Extend the `ruff.toml` file in the parent directory...\nextend = \"../ruff.toml\"\n\n# ...but use a different line length.\nline-length = 100\n

        All of the above rules apply equivalently to pyproject.toml, ruff.toml, and .ruff.toml files. If Ruff detects multiple configuration files in the same directory, the .ruff.toml file will take precedence over the ruff.toml file, and the ruff.toml file will take precedence over the pyproject.toml file.

        "},{"location":"configuration/#inferring-the-python-version","title":"Inferring the Python version","text":"

        When no discovered configuration specifies a target-version, Ruff will attempt to fall back to the minimum version compatible with the requires-python field in a nearby pyproject.toml. The rules for this behavior are as follows:

        1. If a configuration file is passed directly, Ruff does not attempt to infer a missing target-version.
        2. If a configuration file is found in the filesystem hierarchy, Ruff will infer a missing target-version from the requires-python field in a pyproject.toml file in the same directory as the found configuration.
        3. If we are using a user-level configuration from ${config_dir}/ruff/pyproject.toml, the requires-python field in the first pyproject.toml file found in an ancestor of the current working directory takes precedence over the target-version in the user-level configuration.
        4. If no configuration files are found, Ruff will infer the target-version from the requires-python field in the first pyproject.toml file found in an ancestor of the current working directory.

        Note that in these last two cases, the behavior of Ruff may differ depending on the working directory from which it is invoked.

        "},{"location":"configuration/#python-file-discovery","title":"Python file discovery","text":"

        When passed a path on the command-line, Ruff will automatically discover all Python files in that path, taking into account the exclude and extend-exclude settings in each directory's configuration file.

        Files can also be selectively excluded from linting or formatting by scoping the exclude setting to the tool-specific configuration tables. For example, the following would prevent ruff from formatting .pyi files, but would continue to include them in linting:

        pyproject.tomlruff.toml
        [tool.ruff.format]\nexclude = [\"*.pyi\"]\n
        [format]\nexclude = [\"*.pyi\"]\n

        By default, Ruff will also skip any files that are omitted via .ignore, .gitignore, .git/info/exclude, and global gitignore files (see: respect-gitignore).

        Files that are passed to ruff directly are always analyzed, regardless of the above criteria. For example, ruff check /path/to/excluded/file.py will always lint file.py.

        "},{"location":"configuration/#default-inclusions","title":"Default inclusions","text":"

        By default, Ruff will discover files matching *.py, *.pyi, *.ipynb, or pyproject.toml.

        To lint or format files with additional file extensions, use the extend-include setting. You can also change the default selection using the include setting.

        pyproject.tomlruff.toml
        [tool.ruff]\ninclude = [\"pyproject.toml\", \"src/**/*.py\", \"scripts/**/*.py\"]\n
        include = [\"pyproject.toml\", \"src/**/*.py\", \"scripts/**/*.py\"]\n

        Warning

        Paths provided to include must match files. For example, include = [\"src\"] will fail since it matches a directory.

        "},{"location":"configuration/#jupyter-notebook-discovery","title":"Jupyter Notebook discovery","text":"

        Ruff has built-in support for linting and formatting Jupyter Notebooks, which are linted and formatted by default on version 0.6.0 and higher.

        If you'd prefer to either only lint or only format Jupyter Notebook files, you can use the section-specific exclude option to do so. For example, the following would only lint Jupyter Notebook files and not format them:

        pyproject.tomlruff.toml
        [tool.ruff.format]\nexclude = [\"*.ipynb\"]\n
        [format]\nexclude = [\"*.ipynb\"]\n

        And, conversely, the following would only format Jupyter Notebook files and not lint them:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nexclude = [\"*.ipynb\"]\n
        [lint]\nexclude = [\"*.ipynb\"]\n

        You can completely disable Jupyter Notebook support by updating the extend-exclude setting:

        pyproject.tomlruff.toml
        [tool.ruff]\nextend-exclude = [\"*.ipynb\"]\n
        extend-exclude = [\"*.ipynb\"]\n

        If you'd like to ignore certain rules specifically for Jupyter Notebook files, you can do so by using the per-file-ignores setting:

        pyproject.tomlruff.toml
        [tool.ruff.lint.per-file-ignores]\n\"*.ipynb\" = [\"T20\"]\n
        [lint.per-file-ignores]\n\"*.ipynb\" = [\"T20\"]\n

        Some rules have different behavior when applied to Jupyter Notebook files. For example, when applied to .py files the module-import-not-at-top-of-file (E402) rule detect imports at the top of a file, but for notebooks it detects imports at the top of a cell. For a given rule, the rule's documentation will always specify if it has different behavior when applied to Jupyter Notebook files.

        "},{"location":"configuration/#command-line-interface","title":"Command-line interface","text":"

        Some configuration options can be provided or overridden via dedicated flags on the command line. This includes those related to rule enablement and disablement, file discovery, logging level, and more:

        $ ruff check path/to/code/ --select F401 --select F403 --quiet\n

        All other configuration options can be set via the command line using the --config flag, detailed below.

        "},{"location":"configuration/#the-config-cli-flag","title":"The --config CLI flag","text":"

        The --config flag has two uses. It is most often used to point to the configuration file that you would like Ruff to use, for example:

        $ ruff check path/to/directory --config path/to/ruff.toml\n

        However, the --config flag can also be used to provide arbitrary overrides of configuration settings using TOML <KEY> = <VALUE> pairs. This is mostly useful in situations where you wish to override a configuration setting that does not have a dedicated command-line flag.

        In the below example, the --config flag is the only way of overriding the dummy-variable-rgx configuration setting from the command line, since this setting has no dedicated CLI flag. The per-file-ignores setting could also have been overridden via the --per-file-ignores dedicated flag, but using --config to override the setting is also fine:

        $ ruff check path/to/file --config path/to/ruff.toml --config \"lint.dummy-variable-rgx = '__.*'\" --config \"lint.per-file-ignores = {'some_file.py' = ['F841']}\"\n

        Configuration options passed to --config are parsed in the same way as configuration options in a ruff.toml file. As such, options specific to the Ruff linter need to be prefixed with lint. (--config \"lint.dummy-variable-rgx = '__.*'\" rather than simply --config \"dummy-variable-rgx = '__.*'\"), and options specific to the Ruff formatter need to be prefixed with format..

        If a specific configuration option is simultaneously overridden by a dedicated flag and by the --config flag, the dedicated flag takes priority. In this example, the maximum permitted line length will be set to 90, not 100:

        $ ruff format path/to/file --line-length=90 --config \"line-length=100\"\n

        Specifying --config \"line-length=90\" will override the line-length setting from all configuration files detected by Ruff, including configuration files discovered in subdirectories. In this respect, specifying --config \"line-length=90\" has the same effect as specifying --line-length=90, which will similarly override the line-length setting from all configuration files detected by Ruff, regardless of where a specific configuration file is located.

        "},{"location":"configuration/#full-command-line-interface","title":"Full command-line interface","text":"

        See ruff help for the full list of Ruff's top-level commands:

        Ruff: An extremely fast Python linter and code formatter.\n\nUsage: ruff [OPTIONS] <COMMAND>\n\nCommands:\n  check    Run Ruff on the given files or directories\n  rule     Explain a rule (or all rules)\n  config   List or describe the available configuration options\n  linter   List all supported upstream linters\n  clean    Clear any caches in the current directory and any subdirectories\n  format   Run the Ruff formatter on the given files or directories\n  server   Run the language server\n  analyze  Run analysis over Python source code\n  version  Display Ruff's version\n  help     Print this message or the help of the given subcommand(s)\n\nOptions:\n  -h, --help     Print help\n  -V, --version  Print version\n\nLog levels:\n  -v, --verbose  Enable verbose logging\n  -q, --quiet    Print diagnostics, but nothing else\n  -s, --silent   Disable all logging (but still exit with status code \"1\" upon\n                 detecting diagnostics)\n\nGlobal options:\n      --config <CONFIG_OPTION>\n          Either a path to a TOML configuration file (`pyproject.toml` or\n          `ruff.toml`), or a TOML `<KEY> = <VALUE>` pair (such as you might\n          find in a `ruff.toml` configuration file) overriding a specific\n          configuration option. Overrides of individual settings using this\n          option always take precedence over all configuration files, including\n          configuration files that were also specified using `--config`\n      --isolated\n          Ignore all configuration files\n\nFor help with a specific command, see: `ruff help <command>`.\n

        Or ruff help check for more on the linting command:

        Run Ruff on the given files or directories\n\nUsage: ruff check [OPTIONS] [FILES]...\n\nArguments:\n  [FILES]...  List of files or directories to check [default: .]\n\nOptions:\n      --fix\n          Apply fixes to resolve lint violations. Use `--no-fix` to disable or\n          `--unsafe-fixes` to include unsafe fixes\n      --unsafe-fixes\n          Include fixes that may not retain the original intent of the code.\n          Use `--no-unsafe-fixes` to disable\n      --show-fixes\n          Show an enumeration of all fixed lint violations. Use\n          `--no-show-fixes` to disable\n      --diff\n          Avoid writing any fixed files back; instead, output a diff for each\n          changed file to stdout, and exit 0 if there are no diffs. Implies\n          `--fix-only`\n  -w, --watch\n          Run in watch mode by re-running whenever files change\n      --fix-only\n          Apply fixes to resolve lint violations, but don't report on, or exit\n          non-zero for, leftover violations. Implies `--fix`. Use\n          `--no-fix-only` to disable or `--unsafe-fixes` to include unsafe\n          fixes\n      --ignore-noqa\n          Ignore any `# noqa` comments\n      --output-format <OUTPUT_FORMAT>\n          Output serialization format for violations. The default serialization\n          format is \"full\" [env: RUFF_OUTPUT_FORMAT=] [possible values:\n          concise, full, json, json-lines, junit, grouped, github, gitlab,\n          pylint, rdjson, azure, sarif]\n  -o, --output-file <OUTPUT_FILE>\n          Specify file to write the linter output to (default: stdout) [env:\n          RUFF_OUTPUT_FILE=]\n      --target-version <TARGET_VERSION>\n          The minimum Python version that should be supported [possible values:\n          py37, py38, py39, py310, py311, py312, py313, py314]\n      --preview\n          Enable preview mode; checks will include unstable rules and fixes.\n          Use `--no-preview` to disable\n      --extension <EXTENSION>\n          List of mappings from file extension to language (one of `python`,\n          `ipynb`, `pyi`). For example, to treat `.ipy` files as IPython\n          notebooks, use `--extension ipy:ipynb`\n      --statistics\n          Show counts for every rule with at least one violation\n      --add-noqa\n          Enable automatic additions of `noqa` directives to failing lines\n      --show-files\n          See the files Ruff will be run against with the current settings\n      --show-settings\n          See the settings Ruff will use to lint a given Python file\n  -h, --help\n          Print help\n\nRule selection:\n      --select <RULE_CODE>\n          Comma-separated list of rule codes to enable (or ALL, to enable all\n          rules)\n      --ignore <RULE_CODE>\n          Comma-separated list of rule codes to disable\n      --extend-select <RULE_CODE>\n          Like --select, but adds additional rule codes on top of those already\n          specified\n      --per-file-ignores <PER_FILE_IGNORES>\n          List of mappings from file pattern to code to exclude\n      --extend-per-file-ignores <EXTEND_PER_FILE_IGNORES>\n          Like `--per-file-ignores`, but adds additional ignores on top of\n          those already specified\n      --fixable <RULE_CODE>\n          List of rule codes to treat as eligible for fix. Only applicable when\n          fix itself is enabled (e.g., via `--fix`)\n      --unfixable <RULE_CODE>\n          List of rule codes to treat as ineligible for fix. Only applicable\n          when fix itself is enabled (e.g., via `--fix`)\n      --extend-fixable <RULE_CODE>\n          Like --fixable, but adds additional rule codes on top of those\n          already specified\n\nFile selection:\n      --exclude <FILE_PATTERN>\n          List of paths, used to omit files and/or directories from analysis\n      --extend-exclude <FILE_PATTERN>\n          Like --exclude, but adds additional files and directories on top of\n          those already excluded\n      --respect-gitignore\n          Respect file exclusions via `.gitignore` and other standard ignore\n          files. Use `--no-respect-gitignore` to disable\n      --force-exclude\n          Enforce exclusions, even for paths passed to Ruff directly on the\n          command-line. Use `--no-force-exclude` to disable\n\nMiscellaneous:\n  -n, --no-cache\n          Disable cache reads [env: RUFF_NO_CACHE=]\n      --cache-dir <CACHE_DIR>\n          Path to the cache directory [env: RUFF_CACHE_DIR=]\n      --stdin-filename <STDIN_FILENAME>\n          The name of the file when passing it through stdin\n  -e, --exit-zero\n          Exit with status code \"0\", even upon detecting lint violations\n      --exit-non-zero-on-fix\n          Exit with a non-zero status code if any files were modified via fix,\n          even if no lint violations remain\n\nLog levels:\n  -v, --verbose  Enable verbose logging\n  -q, --quiet    Print diagnostics, but nothing else\n  -s, --silent   Disable all logging (but still exit with status code \"1\" upon\n                 detecting diagnostics)\n\nGlobal options:\n      --config <CONFIG_OPTION>\n          Either a path to a TOML configuration file (`pyproject.toml` or\n          `ruff.toml`), or a TOML `<KEY> = <VALUE>` pair (such as you might\n          find in a `ruff.toml` configuration file) overriding a specific\n          configuration option. Overrides of individual settings using this\n          option always take precedence over all configuration files, including\n          configuration files that were also specified using `--config`\n      --isolated\n          Ignore all configuration files\n

        Or ruff help format for more on the formatting command:

        Run the Ruff formatter on the given files or directories\n\nUsage: ruff format [OPTIONS] [FILES]...\n\nArguments:\n  [FILES]...  List of files or directories to format [default: .]\n\nOptions:\n      --check\n          Avoid writing any formatted files back; instead, exit with a non-zero\n          status code if any files would have been modified, and zero otherwise\n      --diff\n          Avoid writing any formatted files back; instead, exit with a non-zero\n          status code and the difference between the current file and how the\n          formatted file would look like\n      --extension <EXTENSION>\n          List of mappings from file extension to language (one of `python`,\n          `ipynb`, `pyi`). For example, to treat `.ipy` files as IPython\n          notebooks, use `--extension ipy:ipynb`\n      --target-version <TARGET_VERSION>\n          The minimum Python version that should be supported [possible values:\n          py37, py38, py39, py310, py311, py312, py313, py314]\n      --preview\n          Enable preview mode; enables unstable formatting. Use `--no-preview`\n          to disable\n  -h, --help\n          Print help (see more with '--help')\n\nMiscellaneous:\n  -n, --no-cache\n          Disable cache reads [env: RUFF_NO_CACHE=]\n      --cache-dir <CACHE_DIR>\n          Path to the cache directory [env: RUFF_CACHE_DIR=]\n      --stdin-filename <STDIN_FILENAME>\n          The name of the file when passing it through stdin\n      --exit-non-zero-on-format\n          Exit with a non-zero status code if any files were modified via\n          format, even if all files were formatted successfully\n\nFile selection:\n      --respect-gitignore\n          Respect file exclusions via `.gitignore` and other standard ignore\n          files. Use `--no-respect-gitignore` to disable\n      --exclude <FILE_PATTERN>\n          List of paths, used to omit files and/or directories from analysis\n      --force-exclude\n          Enforce exclusions, even for paths passed to Ruff directly on the\n          command-line. Use `--no-force-exclude` to disable\n\nFormat configuration:\n      --line-length <LINE_LENGTH>  Set the line-length\n\nEditor options:\n      --range <RANGE>  When specified, Ruff will try to only format the code in\n                       the given range.\n                       It might be necessary to extend the start backwards or\n                       the end forwards, to fully enclose a logical line.\n                       The `<RANGE>` uses the format\n                       `<start_line>:<start_column>-<end_line>:<end_column>`.\n\nLog levels:\n  -v, --verbose  Enable verbose logging\n  -q, --quiet    Print diagnostics, but nothing else\n  -s, --silent   Disable all logging (but still exit with status code \"1\" upon\n                 detecting diagnostics)\n\nGlobal options:\n      --config <CONFIG_OPTION>\n          Either a path to a TOML configuration file (`pyproject.toml` or\n          `ruff.toml`), or a TOML `<KEY> = <VALUE>` pair (such as you might\n          find in a `ruff.toml` configuration file) overriding a specific\n          configuration option. Overrides of individual settings using this\n          option always take precedence over all configuration files, including\n          configuration files that were also specified using `--config`\n      --isolated\n          Ignore all configuration files\n
        "},{"location":"configuration/#shell-autocompletion","title":"Shell autocompletion","text":"

        Ruff supports autocompletion for most shells. A shell-specific completion script can be generated by ruff generate-shell-completion <SHELL>, where <SHELL> is one of bash, elvish, fig, fish, powershell, or zsh.

        The exact steps required to enable autocompletion will vary by shell. For example instructions, see the Poetry or ripgrep documentation.

        As an example: to enable autocompletion for Zsh, run ruff generate-shell-completion zsh > ~/.zfunc/_ruff. Then add the following line to your ~/.zshrc file, if they're not already present:

        fpath+=~/.zfunc\nautoload -Uz compinit && compinit\n
        "},{"location":"contributing/","title":"Contributing to Ruff","text":"

        Welcome! We're happy to have you here. Thank you in advance for your contribution to Ruff.

        [!NOTE]

        This guide is for Ruff. If you're looking to contribute to ty, please see the ty contributing guide.

        "},{"location":"contributing/#the-basics","title":"The Basics","text":"

        Ruff welcomes contributions in the form of pull requests.

        For small changes (e.g., bug fixes), feel free to submit a PR.

        For larger changes (e.g., new lint rules, new functionality, new configuration options), consider creating an issue outlining your proposed change. You can also join us on Discord to discuss your idea with the community. We've labeled beginner-friendly tasks in the issue tracker, along with bugs and improvements that are ready for contributions.

        If you have suggestions on how we might improve the contributing documentation, let us know!

        "},{"location":"contributing/#prerequisites","title":"Prerequisites","text":"

        Ruff is written in Rust. You'll need to install the Rust toolchain for development.

        You'll also need Insta to update snapshot tests:

        cargo install cargo-insta\n

        You'll need uv (or pipx and pip) to run Python utility commands.

        You can optionally install pre-commit hooks to automatically run the validation checks when making a commit:

        uv tool install pre-commit\npre-commit install\n

        We recommend nextest to run Ruff's test suite (via cargo nextest run), though it's not strictly necessary:

        cargo install cargo-nextest --locked\n

        Throughout this guide, any usages of cargo test can be replaced with cargo nextest run, if you choose to install nextest.

        "},{"location":"contributing/#development","title":"Development","text":"

        After cloning the repository, run Ruff locally from the repository root with:

        cargo run -p ruff -- check /path/to/file.py --no-cache\n

        Prior to opening a pull request, ensure that your code has been auto-formatted, and that it passes both the lint and test validation checks:

        cargo clippy --workspace --all-targets --all-features -- -D warnings  # Rust linting\nRUFF_UPDATE_SCHEMA=1 cargo test  # Rust testing and updating ruff.schema.json\nuvx pre-commit run --all-files --show-diff-on-failure  # Rust and Python formatting, Markdown and Python linting, etc.\n

        These checks will run on GitHub Actions when you open your pull request, but running them locally will save you time and expedite the merge process.

        If you're using VS Code, you can also install the recommended rust-analyzer extension to get these checks while editing.

        Note that many code changes also require updating the snapshot tests, which is done interactively after running cargo test like so:

        cargo insta review\n

        If your pull request relates to a specific lint rule, include the category and rule code in the title, as in the following examples:

        • [flake8-bugbear] Avoid false positive for usage after continue (B031)
        • [flake8-simplify] Detect implicit else cases in needless-bool (SIM103)
        • [pycodestyle] Implement redundant-backslash (E502)

        Your pull request will be reviewed by a maintainer, which may involve a few rounds of iteration prior to merging.

        "},{"location":"contributing/#project-structure","title":"Project Structure","text":"

        Ruff is structured as a monorepo with a flat crate structure, such that all crates are contained in a flat crates directory.

        The vast majority of the code, including all lint rules, lives in the ruff_linter crate (located at crates/ruff_linter). As a contributor, that's the crate that'll be most relevant to you.

        At the time of writing, the repository includes the following crates:

        • crates/ruff_linter: library crate containing all lint rules and the core logic for running them. If you're working on a rule, this is the crate for you.
        • crates/ruff_benchmark: binary crate for running micro-benchmarks.
        • crates/ruff_cache: library crate for caching lint results.
        • crates/ruff: binary crate containing Ruff's command-line interface.
        • crates/ruff_dev: binary crate containing utilities used in the development of Ruff itself (e.g., cargo dev generate-all), see the cargo dev section below.
        • crates/ruff_diagnostics: library crate for the rule-independent abstractions in the lint diagnostics APIs.
        • crates/ruff_formatter: library crate for language agnostic code formatting logic based on an intermediate representation. The backend for ruff_python_formatter.
        • crates/ruff_index: library crate inspired by rustc_index.
        • crates/ruff_macros: proc macro crate containing macros used by Ruff.
        • crates/ruff_notebook: library crate for parsing and manipulating Jupyter notebooks.
        • crates/ruff_python_ast: library crate containing Python-specific AST types and utilities.
        • crates/ruff_python_codegen: library crate containing utilities for generating Python source code.
        • crates/ruff_python_formatter: library crate implementing the Python formatter. Emits an intermediate representation for each node, which ruff_formatter prints based on the configured line length.
        • crates/ruff_python_semantic: library crate containing Python-specific semantic analysis logic, including Ruff's semantic model. Used to resolve queries like \"What import does this variable refer to?\"
        • crates/ruff_python_stdlib: library crate containing Python-specific standard library data, e.g. the names of all built-in exceptions and which standard library types are immutable.
        • crates/ruff_python_trivia: library crate containing Python-specific trivia utilities (e.g., for analyzing indentation, newlines, etc.).
        • crates/ruff_python_parser: library crate containing the Python parser.
        • crates/ruff_wasm: library crate for exposing Ruff as a WebAssembly module. Powers the Ruff Playground.
        "},{"location":"contributing/#example-adding-a-new-lint-rule","title":"Example: Adding a new lint rule","text":"

        At a high level, the steps involved in adding a new lint rule are as follows:

        1. Determine a name for the new rule as per our rule naming convention (e.g., AssertFalse, as in, \"allow assert False\").

        2. Create a file for your rule (e.g., crates/ruff_linter/src/rules/flake8_bugbear/rules/assert_false.rs).

        3. In that file, define a violation struct (e.g., pub struct AssertFalse). You can grep for #[derive(ViolationMetadata)] to see examples.

        4. In that file, define a function that adds the violation to the diagnostic list as appropriate (e.g., pub(crate) fn assert_false) based on whatever inputs are required for the rule (e.g., an ast::StmtAssert node).

        5. Define the logic for invoking the diagnostic in crates/ruff_linter/src/checkers/ast/analyze (for AST-based rules), crates/ruff_linter/src/checkers/tokens.rs (for token-based rules), crates/ruff_linter/src/checkers/physical_lines.rs (for text-based rules), crates/ruff_linter/src/checkers/filesystem.rs (for filesystem-based rules), etc. For AST-based rules, you'll likely want to modify analyze/statement.rs (if your rule is based on analyzing statements, like imports) or analyze/expression.rs (if your rule is based on analyzing expressions, like function calls).

        6. Map the violation struct to a rule code in crates/ruff_linter/src/codes.rs (e.g., B011). New rules should be added in RuleGroup::Preview.

        7. Add proper testing for your rule.

        8. Update the generated files (documentation and generated code).

        To trigger the violation, you'll likely want to augment the logic in crates/ruff_linter/src/checkers/ast.rs to call your new function at the appropriate time and with the appropriate inputs. The Checker defined therein is a Python AST visitor, which iterates over the AST, building up a semantic model, and calling out to lint rule analyzer functions as it goes.

        If you need to inspect the AST, you can run cargo dev print-ast with a Python file. Grep for the Diagnostic::new invocations to understand how other, similar rules are implemented.

        Once you're satisfied with your code, add tests for your rule (see: rule testing), and regenerate the documentation and associated assets (like our JSON Schema) with cargo dev generate-all.

        Finally, submit a pull request, and include the category, rule name, and rule code in the title, as in:

        [pycodestyle] Implement redundant-backslash (E502)

        "},{"location":"contributing/#rule-naming-convention","title":"Rule naming convention","text":"

        Like Clippy, Ruff's rule names should make grammatical and logical sense when read as \"allow ${rule}\" or \"allow ${rule} items\", as in the context of suppression comments.

        For example, AssertFalse fits this convention: it flags assert False statements, and so a suppression comment would be framed as \"allow assert False\".

        As such, rule names should...

        • Highlight the pattern that is being linted against, rather than the preferred alternative. For example, AssertFalse guards against assert False statements.

        • Not contain instructions on how to fix the violation, which instead belong in the rule documentation and the fix_title.

        • Not contain a redundant prefix, like Disallow or Banned, which are already implied by the convention.

        When re-implementing rules from other linters, we prioritize adhering to this convention over preserving the original rule name.

        "},{"location":"contributing/#rule-testing-fixtures-and-snapshots","title":"Rule testing: fixtures and snapshots","text":"

        To test rules, Ruff uses snapshots of Ruff's output for a given file (fixture). Generally, there will be one file per rule (e.g., E402.py), and each file will contain all necessary examples of both violations and non-violations. cargo insta review will generate a snapshot file containing Ruff's output for each fixture, which you can then commit alongside your changes.

        Once you've completed the code for the rule itself, you can define tests with the following steps:

        1. Add a Python file to crates/ruff_linter/resources/test/fixtures/[linter] that contains the code you want to test. The file name should match the rule name (e.g., E402.py), and it should include examples of both violations and non-violations.

        2. Run Ruff locally against your file and verify the output is as expected. Once you're satisfied with the output (you see the violations you expect, and no others), proceed to the next step. For example, if you're adding a new rule named E402, you would run:

          cargo run -p ruff -- check crates/ruff_linter/resources/test/fixtures/pycodestyle/E402.py --no-cache --preview --select E402\n

          Note: Only a subset of rules are enabled by default. When testing a new rule, ensure that you activate it by adding --select ${rule_code} to the command.

        3. Add the test to the relevant crates/ruff_linter/src/rules/[linter]/mod.rs file. If you're contributing a rule to a pre-existing set, you should be able to find a similar example to pattern-match against. If you're adding a new linter, you'll need to create a new mod.rs file (see, e.g., crates/ruff_linter/src/rules/flake8_bugbear/mod.rs)

        4. Run cargo test. Your test will fail, but you'll be prompted to follow-up with cargo insta review. Run cargo insta review, review and accept the generated snapshot, then commit the snapshot file alongside the rest of your changes.

        5. Run cargo test again to ensure that your test passes.

        "},{"location":"contributing/#example-adding-a-new-configuration-option","title":"Example: Adding a new configuration option","text":"

        Ruff's user-facing settings live in a few different places.

        First, the command-line options are defined via the Args struct in crates/ruff/src/args.rs.

        Second, the pyproject.toml options are defined in crates/ruff_workspace/src/options.rs (via the Options struct), crates/ruff_workspace/src/configuration.rs (via the Configuration struct), and crates/ruff_workspace/src/settings.rs (via the Settings struct), which then includes the LinterSettings struct as a field.

        These represent, respectively: the schema used to parse the pyproject.toml file; an internal, intermediate representation; and the final, internal representation used to power Ruff.

        To add a new configuration option, you'll likely want to modify these latter few files (along with args.rs, if appropriate). If you want to pattern-match against an existing example, grep for dummy_variable_rgx, which defines a regular expression to match against acceptable unused variables (e.g., _).

        Note that plugin-specific configuration options are defined in their own modules (e.g., Settings in crates/ruff_linter/src/flake8_unused_arguments/settings.rs coupled with Flake8UnusedArgumentsOptions in crates/ruff_workspace/src/options.rs).

        Finally, regenerate the documentation and generated code with cargo dev generate-all.

        "},{"location":"contributing/#mkdocs","title":"MkDocs","text":"

        To preview any changes to the documentation locally:

        1. Install the Rust toolchain.

        2. Generate the MkDocs site with:

          uv run --no-project --isolated --with-requirements docs/requirements.txt scripts/generate_mkdocs.py\n
        3. Run the development server with:

          # For contributors.\nuvx --with-requirements docs/requirements.txt -- mkdocs serve -f mkdocs.public.yml\n\n# For members of the Astral org, which has access to MkDocs Insiders via sponsorship.\nuvx --with-requirements docs/requirements-insiders.txt -- mkdocs serve -f mkdocs.insiders.yml\n

        The documentation should then be available locally at http://127.0.0.1:8000/ruff/.

        "},{"location":"contributing/#release-process","title":"Release Process","text":"

        As of now, Ruff has an ad hoc release process: releases are cut with high frequency via GitHub Actions, which automatically generates the appropriate wheels across architectures and publishes them to PyPI.

        Ruff follows the semver versioning standard. However, as pre-1.0 software, even patch releases may contain non-backwards-compatible changes.

        "},{"location":"contributing/#creating-a-new-release","title":"Creating a new release","text":"
        1. Install uv: curl -LsSf https://astral.sh/uv/install.sh | sh

        2. Run ./scripts/release.sh; this command will:

          • Generate a temporary virtual environment with rooster
          • Generate a changelog entry in CHANGELOG.md
          • Update versions in pyproject.toml and Cargo.toml
          • Update references to versions in the README.md and documentation
          • Display contributors for the release
        3. The changelog should then be editorialized for consistency

          • Often labels will be missing from pull requests they will need to be manually organized into the proper section
          • Changes should be edited to be user-facing descriptions, avoiding internal details
        4. Highlight any breaking changes in BREAKING_CHANGES.md

        5. Run cargo check. This should update the lock file with new versions.

        6. Create a pull request with the changelog and version updates

        7. Merge the PR

        8. Run the release workflow with:

          • The new version number (without starting v)
        9. The release workflow will do the following:

          1. Build all the assets. If this fails (even though we tested in step 4), we haven't tagged or uploaded anything, you can restart after pushing a fix. If you just need to rerun the build, make sure you're re-running all the failed jobs and not just a single failed job.
          2. Upload to PyPI.
          3. Create and push the Git tag (as extracted from pyproject.toml). We create the Git tag only after building the wheels and uploading to PyPI, since we can't delete or modify the tag (#4468).
          4. Attach artifacts to draft GitHub release
          5. Trigger downstream repositories. This can fail non-catastrophically, as we can run any downstream jobs manually if needed.
        10. Verify the GitHub release:

          1. The Changelog should match the content of CHANGELOG.md
          2. Append the contributors from the scripts/release.sh script
        11. If needed, update the schemastore.

          1. One can determine if an update is needed when git diff old-version-tag new-version-tag -- ruff.schema.json returns a non-empty diff.
          2. Once run successfully, you should follow the link in the output to create a PR.
        12. If needed, update the ruff-lsp and ruff-vscode repositories and follow the release instructions in those repositories. ruff-lsp should always be updated before ruff-vscode.

          This step is generally not required for a patch release, but should always be done for a minor release.

        "},{"location":"contributing/#ecosystem-ci","title":"Ecosystem CI","text":"

        GitHub Actions will run your changes against a number of real-world projects from GitHub and report on any linter or formatter differences. You can also run those checks locally via:

        uvx --from ./python/ruff-ecosystem ruff-ecosystem check ruff \"./target/debug/ruff\"\nuvx --from ./python/ruff-ecosystem ruff-ecosystem format ruff \"./target/debug/ruff\"\n

        See the ruff-ecosystem package for more details.

        "},{"location":"contributing/#upgrading-rust","title":"Upgrading Rust","text":"
        1. Change the channel in ./rust-toolchain.toml to the new Rust version (<latest>)
        2. Change the rust-version in the ./Cargo.toml to <latest> - 2 (e.g. 1.84 if the latest is 1.86)
        3. Run cargo clippy --fix --allow-dirty --allow-staged to fix new clippy warnings
        4. Create and merge the PR
        5. Bump the Rust version in Ruff's conda forge recipe. See this PR for an example.
        6. Enjoy the new Rust version!
        "},{"location":"contributing/#benchmarking-and-profiling","title":"Benchmarking and Profiling","text":"

        We have several ways of benchmarking and profiling Ruff:

        • Our main performance benchmark comparing Ruff with other tools on the CPython codebase
        • Microbenchmarks which run the linter or the formatter on individual files. These run on pull requests.
        • Profiling the linter on either the microbenchmarks or entire projects

        Note When running benchmarks, ensure that your CPU is otherwise idle (e.g., close any background applications, like web browsers). You may also want to switch your CPU to a \"performance\" mode, if it exists, especially when benchmarking short-lived processes.

        "},{"location":"contributing/#cpython-benchmark","title":"CPython Benchmark","text":"

        First, clone CPython. It's a large and diverse Python codebase, which makes it a good target for benchmarking.

        git clone --branch 3.10 https://github.com/python/cpython.git crates/ruff_linter/resources/test/cpython\n

        Install hyperfine:

        cargo install hyperfine\n

        To benchmark the release build:

        cargo build --release && hyperfine --warmup 10 \\\n  \"./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ --no-cache -e\" \\\n  \"./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ -e\"\n\nBenchmark 1: ./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache\n  Time (mean \u00b1 \u03c3):     293.8 ms \u00b1   3.2 ms    [User: 2384.6 ms, System: 90.3 ms]\n  Range (min \u2026 max):   289.9 ms \u2026 301.6 ms    10 runs\n\nBenchmark 2: ./target/release/ruff ./crates/ruff_linter/resources/test/cpython/\n  Time (mean \u00b1 \u03c3):      48.0 ms \u00b1   3.1 ms    [User: 65.2 ms, System: 124.7 ms]\n  Range (min \u2026 max):    45.0 ms \u2026  66.7 ms    62 runs\n\nSummary\n  './target/release/ruff ./crates/ruff_linter/resources/test/cpython/' ran\n    6.12 \u00b1 0.41 times faster than './target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache'\n

        To benchmark against the ecosystem's existing tools:

        hyperfine --ignore-failure --warmup 5 \\\n  \"./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ --no-cache\" \\\n  \"pyflakes crates/ruff_linter/resources/test/cpython\" \\\n  \"autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython\" \\\n  \"pycodestyle crates/ruff_linter/resources/test/cpython\" \\\n  \"flake8 crates/ruff_linter/resources/test/cpython\"\n\nBenchmark 1: ./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache\n  Time (mean \u00b1 \u03c3):     294.3 ms \u00b1   3.3 ms    [User: 2467.5 ms, System: 89.6 ms]\n  Range (min \u2026 max):   291.1 ms \u2026 302.8 ms    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 2: pyflakes crates/ruff_linter/resources/test/cpython\n  Time (mean \u00b1 \u03c3):     15.786 s \u00b1  0.143 s    [User: 15.560 s, System: 0.214 s]\n  Range (min \u2026 max):   15.640 s \u2026 16.157 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 3: autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython\n  Time (mean \u00b1 \u03c3):      6.175 s \u00b1  0.169 s    [User: 54.102 s, System: 1.057 s]\n  Range (min \u2026 max):    5.950 s \u2026  6.391 s    10 runs\n\nBenchmark 4: pycodestyle crates/ruff_linter/resources/test/cpython\n  Time (mean \u00b1 \u03c3):     46.921 s \u00b1  0.508 s    [User: 46.699 s, System: 0.202 s]\n  Range (min \u2026 max):   46.171 s \u2026 47.863 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 5: flake8 crates/ruff_linter/resources/test/cpython\n  Time (mean \u00b1 \u03c3):     12.260 s \u00b1  0.321 s    [User: 102.934 s, System: 1.230 s]\n  Range (min \u2026 max):   11.848 s \u2026 12.933 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nSummary\n  './target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache' ran\n   20.98 \u00b1 0.62 times faster than 'autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython'\n   41.66 \u00b1 1.18 times faster than 'flake8 crates/ruff_linter/resources/test/cpython'\n   53.64 \u00b1 0.77 times faster than 'pyflakes crates/ruff_linter/resources/test/cpython'\n  159.43 \u00b1 2.48 times faster than 'pycodestyle crates/ruff_linter/resources/test/cpython'\n

        To benchmark a subset of rules, e.g. LineTooLong and DocLineTooLong:

        cargo build --release && hyperfine --warmup 10 \\\n  \"./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ --no-cache -e --select W505,E501\"\n

        You can run uv venv --project ./scripts/benchmarks, activate the venv and then run uv sync --project ./scripts/benchmarks to create a working environment for the above. All reported benchmarks were computed using the versions specified by ./scripts/benchmarks/pyproject.toml on Python 3.11.

        To benchmark Pylint, remove the following files from the CPython repository:

        rm Lib/test/bad_coding.py \\\n  Lib/test/bad_coding2.py \\\n  Lib/test/bad_getattr.py \\\n  Lib/test/bad_getattr2.py \\\n  Lib/test/bad_getattr3.py \\\n  Lib/test/badcert.pem \\\n  Lib/test/badkey.pem \\\n  Lib/test/badsyntax_3131.py \\\n  Lib/test/badsyntax_future10.py \\\n  Lib/test/badsyntax_future3.py \\\n  Lib/test/badsyntax_future4.py \\\n  Lib/test/badsyntax_future5.py \\\n  Lib/test/badsyntax_future6.py \\\n  Lib/test/badsyntax_future7.py \\\n  Lib/test/badsyntax_future8.py \\\n  Lib/test/badsyntax_future9.py \\\n  Lib/test/badsyntax_pep3120.py \\\n  Lib/test/test_asyncio/test_runners.py \\\n  Lib/test/test_copy.py \\\n  Lib/test/test_inspect.py \\\n  Lib/test/test_typing.py\n

        Then, from crates/ruff_linter/resources/test/cpython, run: time pylint -j 0 -E $(git ls-files '*.py'). This will execute Pylint with maximum parallelism and only report errors.

        To benchmark Pyupgrade, run the following from crates/ruff_linter/resources/test/cpython:

        hyperfine --ignore-failure --warmup 5 --prepare \"git reset --hard HEAD\" \\\n  \"find . -type f -name \\\"*.py\\\" | xargs -P 0 pyupgrade --py311-plus\"\n\nBenchmark 1: find . -type f -name \"*.py\" | xargs -P 0 pyupgrade --py311-plus\n  Time (mean \u00b1 \u03c3):     30.119 s \u00b1  0.195 s    [User: 28.638 s, System: 0.390 s]\n  Range (min \u2026 max):   29.813 s \u2026 30.356 s    10 runs\n
        "},{"location":"contributing/#microbenchmarks","title":"Microbenchmarks","text":"

        The ruff_benchmark crate benchmarks the linter and the formatter on individual files.

        You can run the benchmarks with

        cargo benchmark\n

        cargo benchmark is an alias for cargo bench -p ruff_benchmark --bench linter --bench formatter --

        "},{"location":"contributing/#benchmark-driven-development","title":"Benchmark-driven Development","text":"

        Ruff uses Criterion.rs for benchmarks. You can use --save-baseline=<name> to store an initial baseline benchmark (e.g., on main) and then use --benchmark=<name> to compare against that benchmark. Criterion will print a message telling you if the benchmark improved/regressed compared to that baseline.

        # Run once on your \"baseline\" code\ncargo bench -p ruff_benchmark -- --save-baseline=main\n\n# Then iterate with\ncargo bench -p ruff_benchmark -- --baseline=main\n
        "},{"location":"contributing/#pr-summary","title":"PR Summary","text":"

        You can use --save-baseline and critcmp to get a pretty comparison between two recordings. This is useful to illustrate the improvements of a PR.

        # On main\ncargo bench -p ruff_benchmark -- --save-baseline=main\n\n# After applying your changes\ncargo bench -p ruff_benchmark -- --save-baseline=pr\n\ncritcmp main pr\n

        You must install critcmp for the comparison.

        cargo install critcmp\n
        "},{"location":"contributing/#tips","title":"Tips","text":"
        • Use cargo bench -p ruff_benchmark <filter> to only run specific benchmarks. For example: cargo bench -p ruff_benchmark lexer to only run the lexer benchmarks.
        • Use cargo bench -p ruff_benchmark -- --quiet for a more cleaned up output (without statistical relevance)
        • Use cargo bench -p ruff_benchmark -- --quick to get faster results (more prone to noise)
        "},{"location":"contributing/#profiling-projects","title":"Profiling Projects","text":"

        You can either use the microbenchmarks from above or a project directory for benchmarking. There are a lot of profiling tools out there, The Rust Performance Book lists some examples.

        "},{"location":"contributing/#linux","title":"Linux","text":"

        Install perf and build ruff_benchmark with the profiling profile and then run it with perf

        cargo bench -p ruff_benchmark --no-run --profile=profiling && perf record --call-graph dwarf -F 9999 cargo bench -p ruff_benchmark --profile=profiling -- --profile-time=1\n

        You can also use the ruff_dev launcher to run ruff check multiple times on a repository to gather enough samples for a good flamegraph (change the 999, the sample rate, and the 30, the number of checks, to your liking)

        cargo build --bin ruff_dev --profile=profiling\nperf record -g -F 999 target/profiling/ruff_dev repeat --repeat 30 --exit-zero --no-cache path/to/cpython > /dev/null\n

        Then convert the recorded profile

        perf script -F +pid > /tmp/test.perf\n

        You can now view the converted file with firefox profiler, with a more in-depth guide here

        An alternative is to convert the perf data to flamegraph.svg using flamegraph (cargo install flamegraph):

        flamegraph --perfdata perf.data --no-inline\n
        "},{"location":"contributing/#mac","title":"Mac","text":"

        Install cargo-instruments:

        cargo install cargo-instruments\n

        Then run the profiler with

        cargo instruments -t time --bench linter --profile profiling -p ruff_benchmark -- --profile-time=1\n
        • -t: Specifies what to profile. Useful options are time to profile the wall time and alloc for profiling the allocations.
        • You may want to pass an additional filter to run a single test file

        Otherwise, follow the instructions from the linux section.

        "},{"location":"contributing/#cargo-dev","title":"cargo dev","text":"

        cargo dev is a shortcut for cargo run --package ruff_dev --bin ruff_dev. You can run some useful utils with it:

        • cargo dev print-ast <file>: Print the AST of a python file using Ruff's Python parser. For if True: pass # comment, you can see the syntax tree, the byte offsets for start and stop of each node and also how the : token, the comment and whitespace are not represented anymore:
        [\n    If(\n        StmtIf {\n            range: 0..13,\n            test: Constant(\n                ExprConstant {\n                    range: 3..7,\n                    value: Bool(\n                        true,\n                    ),\n                    kind: None,\n                },\n            ),\n            body: [\n                Pass(\n                    StmtPass {\n                        range: 9..13,\n                    },\n                ),\n            ],\n            orelse: [],\n        },\n    ),\n]\n
        • cargo dev print-tokens <file>: Print the tokens that the AST is built upon. Again for if True: pass # comment:
        0 If 2\n3 True 7\n7 Colon 8\n9 Pass 13\n14 Comment(\n    \"# comment\",\n) 23\n23 Newline 24\n
        • cargo dev print-cst <file>: Print the CST of a Python file using LibCST, which is used in addition to the RustPython parser in Ruff. For example, for if True: pass # comment, everything, including the whitespace, is represented:
        Module {\n    body: [\n        Compound(\n            If(\n                If {\n                    test: Name(\n                        Name {\n                            value: \"True\",\n                            lpar: [],\n                            rpar: [],\n                        },\n                    ),\n                    body: SimpleStatementSuite(\n                        SimpleStatementSuite {\n                            body: [\n                                Pass(\n                                    Pass {\n                                        semicolon: None,\n                                    },\n                                ),\n                            ],\n                            leading_whitespace: SimpleWhitespace(\n                                \" \",\n                            ),\n                            trailing_whitespace: TrailingWhitespace {\n                                whitespace: SimpleWhitespace(\n                                    \" \",\n                                ),\n                                comment: Some(\n                                    Comment(\n                                        \"# comment\",\n                                    ),\n                                ),\n                                newline: Newline(\n                                    None,\n                                    Real,\n                                ),\n                            },\n                        },\n                    ),\n                    orelse: None,\n                    leading_lines: [],\n                    whitespace_before_test: SimpleWhitespace(\n                        \" \",\n                    ),\n                    whitespace_after_test: SimpleWhitespace(\n                        \"\",\n                    ),\n                    is_elif: false,\n                },\n            ),\n        ),\n    ],\n    header: [],\n    footer: [],\n    default_indent: \"    \",\n    default_newline: \"\\n\",\n    has_trailing_newline: true,\n    encoding: \"utf-8\",\n}\n
        • cargo dev generate-all: Update ruff.schema.json, docs/configuration.md and docs/rules. You can also set RUFF_UPDATE_SCHEMA=1 to update ruff.schema.json during cargo test.
        • cargo dev generate-cli-help, cargo dev generate-docs and cargo dev generate-json-schema: Update just docs/configuration.md, docs/rules and ruff.schema.json respectively.
        • cargo dev generate-options: Generate a markdown-compatible table of all pyproject.toml options. Used for https://docs.astral.sh/ruff/settings/.
        • cargo dev generate-rules-table: Generate a markdown-compatible table of all rules. Used for https://docs.astral.sh/ruff/rules/.
        • cargo dev round-trip <python file or jupyter notebook>: Read a Python file or Jupyter Notebook, parse it, serialize the parsed representation and write it back. Used to check how good our representation is so that fixes don't rewrite irrelevant parts of a file.
        • cargo dev format_dev: See ruff_python_formatter README.md
        "},{"location":"contributing/#subsystems","title":"Subsystems","text":""},{"location":"contributing/#compilation-pipeline","title":"Compilation Pipeline","text":"

        If we view Ruff as a compiler, in which the inputs are paths to Python files and the outputs are diagnostics, then our current compilation pipeline proceeds as follows:

        1. File discovery: Given paths like foo/, locate all Python files in any specified subdirectories, taking into account our hierarchical settings system and any exclude options.

        2. Package resolution: Determine the \"package root\" for every file by traversing over its parent directories and looking for __init__.py files.

        3. Cache initialization: For every \"package root\", initialize an empty cache.

        4. Analysis: For every file, in parallel:

          1. Cache read: If the file is cached (i.e., its modification timestamp hasn't changed since it was last analyzed), short-circuit, and return the cached diagnostics.

          2. Tokenization: Run the lexer over the file to generate a token stream.

          3. Indexing: Extract metadata from the token stream, such as: comment ranges, # noqa locations, # isort: off locations, \"doc lines\", etc.

          4. Token-based rule evaluation: Run any lint rules that are based on the contents of the token stream (e.g., commented-out code).

          5. Filesystem-based rule evaluation: Run any lint rules that are based on the contents of the filesystem (e.g., lack of __init__.py file in a package).

          6. Logical line-based rule evaluation: Run any lint rules that are based on logical lines (e.g., stylistic rules).

          7. Parsing: Run the parser over the token stream to produce an AST. (This consumes the token stream, so anything that relies on the token stream needs to happen before parsing.)

          8. AST-based rule evaluation: Run any lint rules that are based on the AST. This includes the vast majority of lint rules. As part of this step, we also build the semantic model for the current file as we traverse over the AST. Some lint rules are evaluated eagerly, as we iterate over the AST, while others are evaluated in a deferred manner (e.g., unused imports, since we can't determine whether an import is unused until we've finished analyzing the entire file), after we've finished the initial traversal.

          9. Import-based rule evaluation: Run any lint rules that are based on the module's imports (e.g., import sorting). These could, in theory, be included in the AST-based rule evaluation phase \u2014 they're just separated for simplicity.

          10. Physical line-based rule evaluation: Run any lint rules that are based on physical lines (e.g., line-length).

          11. Suppression enforcement: Remove any violations that are suppressed via # noqa directives or per-file-ignores.

          12. Cache write: Write the generated diagnostics to the package cache using the file as a key.

        5. Reporting: Print diagnostics in the specified format (text, JSON, etc.), to the specified output channel (stdout, a file, etc.).

        "},{"location":"contributing/#import-categorization","title":"Import Categorization","text":"

        To understand Ruff's import categorization system, we first need to define two concepts:

        • \"Project root\": The directory containing the pyproject.toml, ruff.toml, or .ruff.toml file, discovered by identifying the \"closest\" such directory for each Python file. (If you're running via ruff --config /path/to/pyproject.toml, then the current working directory is used as the \"project root\".)
        • \"Package root\": The top-most directory defining the Python package that includes a given Python file. To find the package root for a given Python file, traverse up its parent directories until you reach a parent directory that doesn't contain an __init__.py file (and isn't in a subtree marked as a namespace package); take the directory just before that, i.e., the first directory in the package.

        For example, given:

        my_project\n\u251c\u2500\u2500 pyproject.toml\n\u2514\u2500\u2500 src\n    \u2514\u2500\u2500 foo\n        \u251c\u2500\u2500 __init__.py\n        \u2514\u2500\u2500 bar\n            \u251c\u2500\u2500 __init__.py\n            \u2514\u2500\u2500 baz.py\n

        Then when analyzing baz.py, the project root would be the top-level directory (./my_project), and the package root would be ./my_project/src/foo.

        "},{"location":"contributing/#project-root","title":"Project root","text":"

        The project root does not have a significant impact beyond that all relative paths within the loaded configuration file are resolved relative to the project root.

        For example, to indicate that bar above is a namespace package (it isn't, but let's run with it), the pyproject.toml would list namespace-packages = [\"./src/bar\"], which would resolve to my_project/src/bar.

        The same logic applies when providing a configuration file via --config. In that case, the current working directory is used as the project root, and so all paths in that configuration file are resolved relative to the current working directory. (As a general rule, we want to avoid relying on the current working directory as much as possible, to ensure that Ruff exhibits the same behavior regardless of where and how you invoke it \u2014 but that's hard to avoid in this case.)

        Additionally, if a pyproject.toml file extends another configuration file, Ruff will still use the directory containing that pyproject.toml file as the project root. For example, if ./my_project/pyproject.toml contains:

        [tool.ruff]\nextend = \"/path/to/pyproject.toml\"\n

        Then Ruff will use ./my_project as the project root, even though the configuration file extends /path/to/pyproject.toml. As such, if the configuration file at /path/to/pyproject.toml contains any relative paths, they will be resolved relative to ./my_project.

        If a project uses nested configuration files, then Ruff would detect multiple project roots, one for each configuration file.

        "},{"location":"contributing/#package-root","title":"Package root","text":"

        The package root is used to determine a file's \"module path\". Consider, again, baz.py. In that case, ./my_project/src/foo was identified as the package root, so the module path for baz.py would resolve to foo.bar.baz \u2014 as computed by taking the relative path from the package root (inclusive of the root itself). The module path can be thought of as \"the path you would use to import the module\" (e.g., import foo.bar.baz).

        The package root and module path are used to, e.g., convert relative to absolute imports, and for import categorization, as described below.

        "},{"location":"contributing/#import-categorization_1","title":"Import categorization","text":"

        When sorting and formatting import blocks, Ruff categorizes every import into one of five categories:

        1. \"Future\": the import is a __future__ import. That's easy: just look at the name of the imported module!
        2. \"Standard library\": the import comes from the Python standard library (e.g., import os). This is easy too: we include a list of all known standard library modules in Ruff itself, so it's a simple lookup.
        3. \"Local folder\": the import is a relative import (e.g., from .foo import bar). This is easy too: just check if the import includes a level (i.e., a dot-prefix).
        4. \"First party\": the import is part of the current project. (More on this below.)
        5. \"Third party\": everything else.

        The real challenge lies in determining whether an import is first-party \u2014 everything else is either trivial, or (as in the case of third-party) merely defined as \"not first-party\".

        There are three ways in which an import can be categorized as \"first-party\":

        1. Explicit settings: the import is marked as such via the known-first-party setting. (This should generally be seen as an escape hatch.)
        2. Same-package: the imported module is in the same package as the current file. This gets back to the importance of the \"package root\" and the file's \"module path\". Imagine that we're analyzing baz.py above. If baz.py contains any imports that appear to come from the foo package (e.g., from foo import bar or import foo.bar), they'll be classified as first-party automatically. This check is as simple as comparing the first segment of the current file's module path to the first segment of the import.
        3. Source roots: Ruff supports a src setting, which sets the directories to scan when identifying first-party imports. The algorithm is straightforward: given an import, like import foo, iterate over the directories enumerated in the src setting and, for each directory, check for the existence of a subdirectory foo or a file foo.py.

        By default, src is set to the project root, along with \"src\" subdirectory in the project root. This ensures that Ruff supports both flat and \"src\" layouts out of the box.

        "},{"location":"faq/","title":"FAQ","text":""},{"location":"faq/#is-the-ruff-linter-compatible-with-black","title":"Is the Ruff linter compatible with Black?","text":"

        Yes. The Ruff linter is compatible with Black out-of-the-box, as long as the line-length setting is consistent between the two.

        Ruff is designed to be used alongside a formatter (like Ruff's own formatter, or Black) and, as such, will defer implementing stylistic rules that are obviated by automated formatting.

        Note that Ruff's linter and Black treat line-length enforcement a little differently. Black, like Ruff's formatter, makes a best-effort attempt to adhere to the line-length, but avoids automatic line-wrapping in some cases (e.g., within comments). Ruff, on the other hand, will flag line-too-long (E501) for any line that exceeds the line-length setting. As such, if line-too-long (E501) is enabled, Ruff can still trigger line-length violations even when Black or ruff format is enabled.

        "},{"location":"faq/#how-does-ruffs-formatter-compare-to-black","title":"How does Ruff's formatter compare to Black?","text":"

        The Ruff formatter is designed to be a drop-in replacement for Black.

        Specifically, the formatter is intended to emit near-identical output when run over Black-formatted code. When run over extensive Black-formatted projects like Django and Zulip, > 99.9% of lines are formatted identically. When migrating an existing project from Black to Ruff, you should expect to see a few differences on the margins, but the vast majority of your code should be unchanged.

        When run over non-Black-formatted code, the formatter makes some different decisions than Black, and so more deviations should be expected, especially around the treatment of end-of-line comments.

        See Style Guide for more.

        "},{"location":"faq/#how-does-ruffs-linter-compare-to-flake8","title":"How does Ruff's linter compare to Flake8?","text":"

        Ruff can be used as a drop-in replacement for Flake8 when used (1) without or with a small number of plugins, (2) alongside Black, and (3) on Python 3 code.

        Under those conditions, Ruff implements every rule in Flake8. In practice, that means Ruff implements all of the F rules (which originate from Pyflakes), along with a subset of the E and W rules (which originate from pycodestyle).

        Ruff also re-implements some of the most popular Flake8 plugins and related code quality tools natively, including:

        • autoflake
        • eradicate
        • flake8-2020
        • flake8-annotations
        • flake8-async
        • flake8-bandit (#1646)
        • flake8-blind-except
        • flake8-boolean-trap
        • flake8-bugbear
        • flake8-builtins
        • flake8-commas
        • flake8-comprehensions
        • flake8-copyright
        • flake8-datetimez
        • flake8-debugger
        • flake8-django
        • flake8-docstrings
        • flake8-eradicate
        • flake8-errmsg
        • flake8-executable
        • flake8-gettext
        • flake8-implicit-str-concat
        • flake8-import-conventions
        • flake8-logging
        • flake8-logging-format
        • flake8-no-pep420
        • flake8-pie
        • flake8-print
        • flake8-pyi
        • flake8-pytest-style
        • flake8-quotes
        • flake8-raise
        • flake8-return
        • flake8-self
        • flake8-simplify
        • flake8-slots
        • flake8-super
        • flake8-tidy-imports
        • flake8-todos
        • flake8-type-checking
        • flake8-use-pathlib
        • flynt (#2102)
        • isort
        • mccabe
        • pandas-vet
        • pep8-naming
        • perflint (#4789)
        • pydocstyle
        • pygrep-hooks
        • pyupgrade
        • tryceratops
        • yesqa

        Note that, in some cases, Ruff uses different rule codes and prefixes than would be found in the originating Flake8 plugins. For example, Ruff uses TID252 to represent the I252 rule from flake8-tidy-imports. This helps minimize conflicts across plugins and allows any individual plugin to be toggled on or off with a single (e.g.) --select TID, as opposed to --select I2 (to avoid conflicts with the isort rules, like I001).

        Beyond the rule set, Ruff's primary limitation vis-\u00e0-vis Flake8 is that it does not support custom lint rules. (Instead, popular Flake8 plugins are re-implemented in Rust as part of Ruff itself.) One minor difference is that Ruff doesn't include all the 'opinionated' rules from flake8-bugbear.

        "},{"location":"faq/#how-does-ruffs-linter-compare-to-pylint","title":"How does Ruff's linter compare to Pylint?","text":"

        At time of writing, Pylint implements ~409 total rules, while Ruff implements over 800, of which at least 209 overlap with the Pylint rule set (see: #970).

        Pylint implements many rules that Ruff does not, and vice versa. For example, Pylint does more type inference than Ruff (e.g., Pylint can validate the number of arguments in a function call). As such, Ruff is not a \"pure\" drop-in replacement for Pylint (and vice versa), as they enforce different sets of rules.

        Despite these differences, many users have successfully switched from Pylint to Ruff, especially those using Ruff alongside a type checker, which can cover some of the functionality that Pylint provides.

        Like Flake8, Pylint supports plugins (called \"checkers\"), while Ruff implements all rules natively and does not support custom or third-party rules. Unlike Pylint, Ruff is capable of automatically fixing its own lint violations.

        In some cases, Ruff's rules may yield slightly different results than their Pylint counterparts. For example, Ruff's too-many-branches does not count try blocks as their own branches, unlike Pylint's R0912. Ruff's PL rule group also includes a small number of rules from Pylint extensions (like magic-value-comparison), which need to be explicitly activated when using Pylint. By enabling Ruff's PL group, you may see violations for rules that weren't previously enabled through your Pylint configuration.

        Pylint parity is being tracked in #970.

        "},{"location":"faq/#how-does-ruff-compare-to-mypy-or-pyright-or-pyre","title":"How does Ruff compare to Mypy, or Pyright, or Pyre?","text":"

        Ruff is a linter, not a type checker. It can detect some of the same problems that a type checker can, but a type checker will catch certain errors that Ruff would miss. The opposite is also true: Ruff will catch certain errors that a type checker would typically ignore.

        For example, unlike a type checker, Ruff will notify you if an import is unused, by looking for references to that import in the source code; on the other hand, a type checker could flag that you passed an integer argument to a function that expects a string, which Ruff would miss. The tools are complementary.

        It's recommended that you use Ruff in conjunction with a type checker, like Mypy, Pyright, or Pyre, with Ruff providing faster feedback on lint violations and the type checker providing more detailed feedback on type errors.

        "},{"location":"faq/#which-tools-does-ruff-replace","title":"Which tools does Ruff replace?","text":"

        Today, Ruff can be used to replace Flake8 when used with any of the following plugins:

        • flake8-2020
        • flake8-annotations
        • flake8-async
        • flake8-bandit (#1646)
        • flake8-blind-except
        • flake8-boolean-trap
        • flake8-bugbear
        • flake8-builtins
        • flake8-commas
        • flake8-comprehensions
        • flake8-copyright
        • flake8-datetimez
        • flake8-debugger
        • flake8-django
        • flake8-docstrings
        • flake8-eradicate
        • flake8-errmsg
        • flake8-executable
        • flake8-gettext
        • flake8-implicit-str-concat
        • flake8-import-conventions
        • flake8-logging
        • flake8-logging-format
        • flake8-no-pep420
        • flake8-pie
        • flake8-print
        • flake8-pytest-style
        • flake8-quotes
        • flake8-raise
        • flake8-return
        • flake8-self
        • flake8-simplify
        • flake8-slots
        • flake8-super
        • flake8-tidy-imports
        • flake8-todos
        • flake8-type-checking
        • flake8-use-pathlib
        • flynt (#2102)
        • mccabe
        • pandas-vet
        • pep8-naming
        • perflint (#4789)
        • pydocstyle
        • tryceratops

        Ruff can also replace Black, isort, yesqa, eradicate, and most of the rules implemented in pyupgrade.

        If you're looking to use Ruff, but rely on an unsupported Flake8 plugin, feel free to file an issue.

        "},{"location":"faq/#do-i-have-to-use-ruffs-linter-and-formatter-together","title":"Do I have to use Ruff's linter and formatter together?","text":"

        Nope! Ruff's linter and formatter can be used independently of one another -- you can use Ruff as a formatter, but not a linter, or vice versa.

        "},{"location":"faq/#what-versions-of-python-does-ruff-support","title":"What versions of Python does Ruff support?","text":"

        Ruff can lint code for any Python version from 3.7 onwards, including Python 3.13.

        Ruff does not support Python 2. Ruff may run on pre-Python 3.7 code, although such versions are not officially supported (e.g., Ruff does not respect type comments).

        Ruff is installable under any Python version from 3.7 onwards.

        "},{"location":"faq/#do-i-need-to-install-rust-to-use-ruff","title":"Do I need to install Rust to use Ruff?","text":"

        Nope! Ruff is available as ruff on PyPI. We recommend installing Ruff with uv, though it's also installable with pip, pipx, and a variety of other package managers:

        $ # Install Ruff globally.\n$ uv tool install ruff@latest\n\n$ # Or add Ruff to your project.\n$ uv add --dev ruff\n\n$ # With pip.\n$ pip install ruff\n\n$ # With pipx.\n$ pipx install ruff\n

        Starting with version 0.5.0, Ruff can also be installed with our standalone installers:

        $ # On macOS and Linux.\n$ curl -LsSf https://astral.sh/ruff/install.sh | sh\n\n$ # On Windows.\n$ powershell -c \"irm https://astral.sh/ruff/install.ps1 | iex\"\n\n$ # For a specific version.\n$ curl -LsSf https://astral.sh/ruff/0.5.0/install.sh | sh\n$ powershell -c \"irm https://astral.sh/ruff/0.5.0/install.ps1 | iex\"\n

        Ruff ships with wheels for all major platforms, which enables uv, pip, and other tools to install Ruff without relying on a Rust toolchain at all.

        "},{"location":"faq/#can-i-write-my-own-linter-plugins-for-ruff","title":"Can I write my own linter plugins for Ruff?","text":"

        Ruff does not yet support third-party plugins, though a plugin system is within-scope for the project. See #283 for more.

        "},{"location":"faq/#how-does-ruffs-import-sorting-compare-to-isort","title":"How does Ruff's import sorting compare to isort?","text":"

        Ruff's import sorting is intended to be near-equivalent to isort's when using isort's profile = \"black\".

        There are a few known differences in how Ruff and isort treat aliased imports, and in how Ruff and isort treat inline comments in some cases (see: #1381, #2104).

        For example, Ruff tends to group non-aliased imports from the same module:

        from numpy import cos, int8, int16, int32, int64, tan, uint8, uint16, uint32, uint64\nfrom numpy import sin as np_sin\n

        Whereas isort splits them into separate import statements at each aliased boundary:

        from numpy import cos, int8, int16, int32, int64\nfrom numpy import sin as np_sin\nfrom numpy import tan, uint8, uint16, uint32, uint64\n

        Ruff also correctly classifies some modules as standard-library that aren't recognized by isort, like _string and idlelib.

        Like isort, Ruff's import sorting is compatible with Black.

        "},{"location":"faq/#how-does-ruff-determine-which-of-my-imports-are-first-party-third-party-etc","title":"How does Ruff determine which of my imports are first-party, third-party, etc.?","text":"

        Ruff accepts a src option that in your pyproject.toml, ruff.toml, or .ruff.toml file, specifies the directories that Ruff should consider when determining whether an import is first-party.

        For example, if you have a project with the following structure:

        my_project\n\u251c\u2500\u2500 pyproject.toml\n\u2514\u2500\u2500 src\n    \u2514\u2500\u2500 foo\n        \u251c\u2500\u2500 __init__.py\n        \u2514\u2500\u2500 bar\n            \u251c\u2500\u2500 __init__.py\n            \u2514\u2500\u2500 baz.py\n

        When Ruff sees an import like import foo, it will then iterate over the src directories, looking for a corresponding Python module (in reality, a directory named foo or a file named foo.py). For module paths with multiple components like import foo.bar, the default behavior is to search only for a directory named foo or a file named foo.py. However, if preview is enabled, Ruff will require that the full relative path foo/bar exists as a directory, or that foo/bar.py or foo/bar.pyi exist as files. Finally, imports of the form from foo import bar, Ruff will only use foo when determining whether a module is first-party or third-party.

        If there is a directory whose name matches a third-party package, but does not contain Python code, it could happen that the above algorithm incorrectly infers an import to be first-party. To prevent this, you can modify the known-third-party setting. For example, if you import the package wandb but also have a subdirectory of your src with the same name, you can add the following:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nknown-third-party = [\"wandb\"]\n
        [lint.isort]\nknown-third-party = [\"wandb\"]\n

        If the src field is omitted, Ruff will default to using the \"project root\", along with a \"src\" subdirectory, as the first-party sources, to support both flat and nested project layouts. The \"project root\" is typically the directory containing your pyproject.toml, ruff.toml, or .ruff.toml file, unless a configuration file is provided on the command-line via the --config option, in which case, the current working directory is used as the project root.

        In this case, Ruff would check the \"src\" directory by default, but we can configure it as an explicit, exclusive first-party source like so:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Ruff supports a top-level `src` option in lieu of isort's `src_paths` setting.\n# All paths are relative to the project root, which is the directory containing the pyproject.toml.\nsrc = [\"src\"]\n
        # Ruff supports a top-level `src` option in lieu of isort's `src_paths` setting.\n# All paths are relative to the project root, which is the directory containing the pyproject.toml.\nsrc = [\"src\"]\n

        If your pyproject.toml, ruff.toml, or .ruff.toml extends another configuration file, Ruff will still use the directory containing your pyproject.toml, ruff.toml, or .ruff.toml file as the project root (as opposed to the directory of the file pointed to via the extends option).

        For example, if you add a configuration file to the tests directory in the above example, you'll want to explicitly set the src option in the extended configuration file:

        pyproject.tomlruff.toml
        [tool.ruff]\nextend = \"../pyproject.toml\"\nsrc = [\"../src\"]\n
        extend = \"../pyproject.toml\"\nsrc = [\"../src\"]\n

        Beyond this src-based detection, Ruff will also attempt to determine the current Python package for a given Python file, and mark imports from within the same package as first-party. For example, above, baz.py would be identified as part of the Python package beginning at ./my_project/src/foo, and so any imports in baz.py that begin with foo (like import foo.bar) would be considered first-party based on this same-package heuristic.

        For a detailed explanation of src resolution, see the contributing guide.

        Ruff can also be configured to treat certain modules as (e.g.) always first-party, regardless of their location on the filesystem. For example, you can set known-first-party like so:

        pyproject.tomlruff.toml
        [tool.ruff]\nsrc = [\"src\", \"tests\"]\n\n[tool.ruff.lint]\nselect = [\n    # Pyflakes\n    \"F\",\n    # Pycodestyle\n    \"E\",\n    \"W\",\n    # isort\n    \"I001\"\n]\n\n[tool.ruff.lint.isort]\nknown-first-party = [\"my_module1\", \"my_module2\"]\n
        src = [\"src\", \"tests\"]\n\n[lint]\nselect = [\n    # Pyflakes\n    \"F\",\n    # Pycodestyle\n    \"E\",\n    \"W\",\n    # isort\n    \"I001\"\n]\n\n[lint.isort]\nknown-first-party = [\"my_module1\", \"my_module2\"]\n

        Ruff does not yet support all of isort's configuration options, though it does support many of them. You can find the supported settings in the API reference.

        "},{"location":"faq/#does-ruff-support-jupyter-notebooks","title":"Does Ruff support Jupyter Notebooks?","text":"

        Ruff has built-in support for linting and formatting Jupyter Notebooks. Refer to the Jupyter Notebook section for more details.

        Ruff also integrates with nbQA, a tool for running linters and code formatters over Jupyter Notebooks.

        After installing ruff and nbqa, you can run Ruff over a notebook like so:

        $ nbqa ruff Untitled.ipynb\nUntitled.ipynb:cell_1:2:5: F841 Local variable `x` is assigned to but never used\nUntitled.ipynb:cell_2:1:1: E402 Module level import not at top of file\nUntitled.ipynb:cell_2:1:8: F401 `os` imported but unused\nFound 3 errors.\n1 potentially fixable with the --fix option.\n
        "},{"location":"faq/#does-ruff-support-numpy-or-google-style-docstrings","title":"Does Ruff support NumPy- or Google-style docstrings?","text":"

        Yes! To enforce a docstring convention, add a convention setting following to your configuration file:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydocstyle]\nconvention = \"google\"  # Accepts: \"google\", \"numpy\", or \"pep257\".\n
        [lint.pydocstyle]\nconvention = \"google\"  # Accepts: \"google\", \"numpy\", or \"pep257\".\n

        For example, if you're coming from flake8-docstrings, and your originating configuration uses --docstring-convention=numpy, you'd instead set convention = \"numpy\" in your pyproject.toml, as above.

        Alongside convention, you'll want to explicitly enable the D rule code prefix, since the D rules are not enabled by default:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nselect = [\"D\"]\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n
        [lint]\nselect = [\"D\"]\n\n[lint.pydocstyle]\nconvention = \"google\"\n

        Enabling a convention will disable any rules that are not included in the specified convention. As such, the intended workflow is to enable a convention and then selectively enable or disable any additional rules on top of it:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nselect = [\n    \"D\",\n    # Augment the convention by requiring an imperative mood for all docstrings.\n    \"D401\",\n]\n\nignore = [\n    # Relax the convention by _not_ requiring documentation for every function parameter.\n    \"D417\",\n]\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n
        [lint]\nselect = [\n    \"D\",\n    # Augment the convention by requiring an imperative mood for all docstrings.\n    \"D401\",\n]\n\nignore = [\n    # Relax the convention by _not_ requiring documentation for every function parameter.\n    \"D417\",\n]\n\n[lint.pydocstyle]\nconvention = \"google\"\n

        The PEP 257 convention includes all D errors apart from: D203, D212, D213, D214, D215, D404, D405, D406, D407, D408, D409, D410, D411, D413, D415, D416, and D417.

        The NumPy convention includes all D errors apart from: D107, D203, D212, D213, D402, D413, D415, D416, and D417.

        The Google convention includes all D errors apart from: D203, D204, D213, D215, D400, D401, D404, D406, D407, D408, D409, and D413.

        By default, no convention is set, and so the enabled rules are determined by the select setting alone.

        "},{"location":"faq/#what-is-preview","title":"What is \"preview\"?","text":"

        Preview enables a collection of newer rules and fixes that are considered experimental or unstable. See the preview documentation for more details; or, to see which rules are currently in preview, visit the rules reference.

        "},{"location":"faq/#how-can-i-tell-what-settings-ruff-is-using-to-check-my-code","title":"How can I tell what settings Ruff is using to check my code?","text":"

        Run ruff check /path/to/code.py --show-settings to view the resolved settings for a given file.

        "},{"location":"faq/#i-want-to-use-ruff-but-i-dont-want-to-use-pyprojecttoml-what-are-my-options","title":"I want to use Ruff, but I don't want to use pyproject.toml. What are my options?","text":"

        In lieu of a pyproject.toml file, you can use a ruff.toml file for configuration. The two files are functionally equivalent and have an identical schema, with the exception that a ruff.toml file can omit the [tool.ruff] section header. For example:

        pyproject.toml
        [tool.ruff]\nline-length = 88\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n
        ruff.toml
        line-length = 88\n\n[lint.pydocstyle]\nconvention = \"google\"\n

        Ruff doesn't currently support INI files, like setup.cfg or tox.ini.

        "},{"location":"faq/#how-can-i-change-ruffs-default-configuration","title":"How can I change Ruff's default configuration?","text":"

        When no configuration file is found, Ruff will look for a user-specific ruff.toml file as a last resort. This behavior is similar to Flake8's ~/.config/flake8.

        On macOS and Linux, Ruff expects that file to be located at ~/.config/ruff/ruff.toml, and respects the XDG_CONFIG_HOME specification.

        On Windows, Ruff expects that file to be located at ~\\AppData\\Roaming\\ruff\\ruff.toml.

        Note

        Prior to v0.5.0, Ruff would read user-specific configuration from ~/Library/Application Support/ruff/ruff.toml on macOS. While Ruff will still respect such configuration files, the use of ~/Library/Application Support is considered deprecated.

        For more, see the etcetera crate.

        "},{"location":"faq/#ruff-tried-to-fix-something-but-it-broke-my-code-whats-going-on","title":"Ruff tried to fix something \u2014 but it broke my code. What's going on?","text":"

        Ruff labels fixes as \"safe\" and \"unsafe\". By default, Ruff will fix all violations for which safe fixes are available, while unsafe fixes can be enabled via the unsafe-fixes setting, or passing the --unsafe-fixes flag to ruff check. For more, see the fix documentation.

        Even still, given the dynamic nature of Python, it's difficult to have complete certainty when making changes to code, even for seemingly trivial fixes. If a \"safe\" fix breaks your code, please file an Issue.

        "},{"location":"faq/#how-can-i-disableforce-ruffs-color-output","title":"How can I disable/force Ruff's color output?","text":"

        Ruff's color output is powered by the colored crate, which attempts to automatically detect whether the output stream supports color. However, you can force colors off by setting the NO_COLOR environment variable to any value (e.g., NO_COLOR=1), or force colors on by setting FORCE_COLOR to any non-empty value (e.g., FORCE_COLOR=1).

        colored also supports the CLICOLOR and CLICOLOR_FORCE environment variables (see the spec).

        "},{"location":"faq/#source-code-actions-in-notebooks","title":"Ruff behaves unexpectedly when using source.* code actions in Notebooks. What's going on?","text":"

        Ruff does not support source.organizeImports and source.fixAll code actions in Jupyter Notebooks (notebook.codeActionsOnSave in VS Code). It's recommended to use the notebook prefixed code actions for the same such as notebook.source.organizeImports and notebook.source.fixAll respectively.

        Ruff requires to have a full view of the notebook to provide accurate diagnostics and fixes. For example, if you have a cell that imports a module and another cell that uses that module, Ruff needs to see both cells to mark the import as used. If Ruff were to only see one cell at a time, it would incorrectly mark the import as unused.

        When using the source.* code actions for a Notebook, Ruff will be asked to fix any issues for each cell in parallel, which can lead to unexpected behavior. For example, if a user has configured to run source.organizeImports code action on save for a Notebook, Ruff will attempt to fix the imports for the entire notebook corresponding to each cell. This leads to the client making the same changes to the notebook multiple times, which can lead to unexpected behavior (astral-sh/ruff-vscode#680, astral-sh/ruff-vscode#640, astral-sh/ruff-vscode#391).

        "},{"location":"formatter/","title":"The Ruff Formatter","text":"

        The Ruff formatter is an extremely fast Python code formatter designed as a drop-in replacement for Black, available as part of the ruff CLI via ruff format.

        "},{"location":"formatter/#ruff-format","title":"ruff format","text":"

        ruff format is the primary entrypoint to the formatter. It accepts a list of files or directories, and formats all discovered Python files:

        ruff format                   # Format all files in the current directory.\nruff format path/to/code/     # Format all files in `path/to/code` (and any subdirectories).\nruff format path/to/file.py   # Format a single file.\n

        Similar to Black, running ruff format /path/to/file.py will format the given file or directory in-place, while ruff format --check /path/to/file.py will avoid writing any formatted files back, and instead exit with a non-zero status code upon detecting any unformatted files.

        For the full list of supported options, run ruff format --help.

        "},{"location":"formatter/#philosophy","title":"Philosophy","text":"

        The initial goal of the Ruff formatter is not to innovate on code style, but rather, to innovate on performance, and provide a unified toolchain across Ruff's linter, formatter, and any and all future tools.

        As such, the formatter is designed as a drop-in replacement for Black, but with an excessive focus on performance and direct integration with Ruff. Given Black's popularity within the Python ecosystem, targeting Black compatibility ensures that formatter adoption is minimally disruptive for the vast majority of projects.

        Specifically, the formatter is intended to emit near-identical output when run over existing Black-formatted code. When run over extensive Black-formatted projects like Django and Zulip, > 99.9% of lines are formatted identically. (See: Style Guide.)

        Given this focus on Black compatibility, the formatter thus adheres to Black's (stable) code style, which aims for \"consistency, generality, readability and reducing git diffs\". To give you a sense for the enforced code style, here's an example:

        # Input\ndef _make_ssl_transport(\n    rawsock, protocol, sslcontext, waiter=None,\n    *, server_side=False, server_hostname=None,\n    extra=None, server=None,\n    ssl_handshake_timeout=None,\n    call_connection_made=True):\n    '''Make an SSL transport.'''\n    if waiter is None:\n      waiter = Future(loop=loop)\n\n    if extra is None:\n      extra = {}\n\n    ...\n\n# Ruff\ndef _make_ssl_transport(\n    rawsock,\n    protocol,\n    sslcontext,\n    waiter=None,\n    *,\n    server_side=False,\n    server_hostname=None,\n    extra=None,\n    server=None,\n    ssl_handshake_timeout=None,\n    call_connection_made=True,\n):\n    \"\"\"Make an SSL transport.\"\"\"\n    if waiter is None:\n        waiter = Future(loop=loop)\n\n    if extra is None:\n        extra = {}\n\n    ...\n

        Like Black, the Ruff formatter does not support extensive code style configuration; however, unlike Black, it does support configuring the desired quote style, indent style, line endings, and more. (See: Configuration.)

        While the formatter is designed to be a drop-in replacement for Black, it is not intended to be used interchangeably with Black on an ongoing basis, as the formatter does differ from Black in a few conscious ways (see: Known deviations). In general, deviations are limited to cases in which Ruff's behavior was deemed more consistent, or significantly simpler to support (with negligible end-user impact) given the differences in the underlying implementations between Black and Ruff.

        Going forward, the Ruff Formatter will support Black's preview style under Ruff's own preview mode.

        "},{"location":"formatter/#configuration","title":"Configuration","text":"

        The Ruff Formatter exposes a small set of configuration options, some of which are also supported by Black (like line width), some of which are unique to Ruff (like quote, indentation style and formatting code examples in docstrings).

        For example, to configure the formatter to use single quotes, format code examples in docstrings, a line width of 100, and tab indentation, add the following to your configuration file:

        pyproject.tomlruff.toml
        [tool.ruff]\nline-length = 100\n\n[tool.ruff.format]\nquote-style = \"single\"\nindent-style = \"tab\"\ndocstring-code-format = true\n
        line-length = 100\n\n[format]\nquote-style = \"single\"\nindent-style = \"tab\"\ndocstring-code-format = true\n

        For the full list of supported settings, see Settings. For more on configuring Ruff via pyproject.toml, see Configuring Ruff.

        Given the focus on Black compatibility (and unlike formatters like YAPF), Ruff does not currently expose any other configuration options.

        "},{"location":"formatter/#docstring-formatting","title":"Docstring formatting","text":"

        The Ruff formatter provides an opt-in feature for automatically formatting Python code examples in docstrings. The Ruff formatter currently recognizes code examples in the following formats:

        • The Python doctest format.
        • CommonMark fenced code blocks with the following info strings: python, py, python3, or py3. Fenced code blocks without an info string are assumed to be Python code examples and also formatted.
        • reStructuredText literal blocks. While literal blocks may contain things other than Python, this is meant to reflect a long-standing convention in the Python ecosystem where literal blocks often contain Python code.
        • reStructuredText [code-block and sourcecode directives]. As with Markdown, the language names recognized for Python are python, py, python3, or py3.

        If a code example is recognized and treated as Python, the Ruff formatter will automatically skip it if the code does not parse as valid Python or if the reformatted code would produce an invalid Python program.

        Users may also configure the line length limit used for reformatting Python code examples in docstrings. The default is a special value, dynamic, which instructs the formatter to respect the line length limit setting for the surrounding Python code. The dynamic setting ensures that even when code examples are found inside indented docstrings, the line length limit configured for the surrounding Python code will not be exceeded. Users may also configure a fixed line length limit for code examples in docstrings.

        For example, this configuration shows how to enable docstring code formatting with a fixed line length limit:

        pyproject.tomlruff.toml
        [tool.ruff.format]\ndocstring-code-format = true\ndocstring-code-line-length = 20\n
        [format]\ndocstring-code-format = true\ndocstring-code-line-length = 20\n

        With the above configuration, this code:

        def f(x):\n    '''\n    Something about `f`. And an example:\n\n    .. code-block:: python\n\n        foo, bar, quux = this_is_a_long_line(lion, hippo, lemur, bear)\n    '''\n    pass\n

        ... will be reformatted (assuming the rest of the options are set to their defaults) as:

        def f(x):\n    \"\"\"\n    Something about `f`. And an example:\n\n    .. code-block:: python\n\n        (\n            foo,\n            bar,\n            quux,\n        ) = this_is_a_long_line(\n            lion,\n            hippo,\n            lemur,\n            bear,\n        )\n    \"\"\"\n    pass\n
        "},{"location":"formatter/#format-suppression","title":"Format suppression","text":"

        Like Black, Ruff supports # fmt: on, # fmt: off, and # fmt: skip pragma comments, which can be used to temporarily disable formatting for a given code block.

        # fmt: on and # fmt: off comments are enforced at the statement level:

        # fmt: off\nnot_formatted=3\nalso_not_formatted=4\n# fmt: on\n

        As such, adding # fmt: on and # fmt: off comments within expressions will have no effect. In the following example, both list entries will be formatted, despite the # fmt: off:

        [\n    # fmt: off\n    '1',\n    # fmt: on\n    '2',\n]\n

        Instead, apply the # fmt: off comment to the entire statement:

        # fmt: off\n[\n    '1',\n    '2',\n]\n# fmt: on\n

        Like Black, Ruff will also recognize YAPF's # yapf: disable and # yapf: enable pragma comments, which are treated equivalently to # fmt: off and # fmt: on, respectively.

        # fmt: skip comments suppress formatting for a preceding statement, case header, decorator, function definition, or class definition:

        if True:\n    pass\nelif False: # fmt: skip\n    pass\n\n@Test\n@Test2 # fmt: skip\ndef test(): ...\n\na = [1, 2, 3, 4, 5] # fmt: skip\n\ndef test(a, b, c, d, e, f) -> int: # fmt: skip\n    pass\n

        As such, adding an # fmt: skip comment at the end of an expression will have no effect. In the following example, the list entry '1' will be formatted, despite the # fmt: skip:

        a = call(\n    [\n        '1',  # fmt: skip\n        '2',\n    ],\n    b\n)\n

        Instead, apply the # fmt: skip comment to the entire statement:

        a = call(\n  [\n    '1',\n    '2',\n  ],\n  b\n)  # fmt: skip\n
        "},{"location":"formatter/#conflicting-lint-rules","title":"Conflicting lint rules","text":"

        Ruff's formatter is designed to be used alongside the linter. However, the linter includes some rules that, when enabled, can cause conflicts with the formatter, leading to unexpected behavior. When configured appropriately, the goal of Ruff's formatter-linter compatibility is such that running the formatter should never introduce new lint errors.

        When using Ruff as a formatter, we recommend avoiding the following lint rules:

        • tab-indentation (W191)
        • indentation-with-invalid-multiple (E111)
        • indentation-with-invalid-multiple-comment (E114)
        • over-indented (E117)
        • docstring-tab-indentation (D206)
        • triple-single-quotes (D300)
        • bad-quotes-inline-string (Q000)
        • bad-quotes-multiline-string (Q001)
        • bad-quotes-docstring (Q002)
        • avoidable-escaped-quote (Q003)
        • missing-trailing-comma (COM812)
        • prohibited-trailing-comma (COM819)
        • multi-line-implicit-string-concatenation (ISC002) if used without ISC001 and flake8-implicit-str-concat.allow-multiline = false

        While the line-too-long (E501) rule can be used alongside the formatter, the formatter only makes a best-effort attempt to wrap lines at the configured line-length. As such, formatted code may exceed the line length, leading to line-too-long (E501) errors.

        None of the above are included in Ruff's default configuration. However, if you've enabled any of these rules or their parent categories (like Q), we recommend disabling them via the linter's lint.ignore setting.

        Similarly, we recommend avoiding the following isort settings, which are incompatible with the formatter's treatment of import statements when set to non-default values:

        • force-single-line
        • force-wrap-aliases
        • lines-after-imports
        • lines-between-types
        • split-on-trailing-comma

        If you've configured any of these settings to take on non-default values, we recommend removing them from your Ruff configuration.

        When an incompatible lint rule or setting is enabled, ruff format will emit a warning. If your ruff format is free of warnings, you're good to go!

        "},{"location":"formatter/#exit-codes","title":"Exit codes","text":"

        ruff format exits with the following status codes:

        • 0 if Ruff terminates successfully, regardless of whether any files were formatted.
        • 2 if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an internal error.

        Meanwhile, ruff format --check exits with the following status codes:

        • 0 if Ruff terminates successfully, and no files would be formatted if --check were not specified.
        • 1 if Ruff terminates successfully, and one or more files would be formatted if --check were not specified.
        • 2 if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an internal error.
        "},{"location":"formatter/#style-guide","title":"Style Guide","text":"

        The formatter is designed to be a drop-in replacement for Black. This section documents the areas where the Ruff formatter goes beyond Black in terms of code style.

        "},{"location":"formatter/#intentional-deviations","title":"Intentional deviations","text":"

        While the Ruff formatter aims to be a drop-in replacement for Black, it does differ from Black in a few known ways. Some of these differences emerge from conscious attempts to improve upon Black's code style, while others fall out of differences in the underlying implementations.

        For a complete enumeration of these intentional deviations, see Known deviations.

        Unintentional deviations from Black are tracked in the issue tracker. If you've identified a new deviation, please file an issue.

        "},{"location":"formatter/#preview-style","title":"Preview style","text":"

        Similar to Black, Ruff implements formatting changes under the preview flag, promoting them to stable through minor releases, in accordance with our versioning policy.

        "},{"location":"formatter/#f-string-formatting","title":"F-string formatting","text":"

        Stabilized in Ruff 0.9.0

        Unlike Black, Ruff formats the expression parts of f-strings which are the parts inside the curly braces {...}. This is a known deviation from Black.

        Ruff employs several heuristics to determine how an f-string should be formatted which are detailed below.

        "},{"location":"formatter/#quotes","title":"Quotes","text":"

        Ruff will use the configured quote style for the f-string expression unless doing so would result in invalid syntax for the target Python version or requires more backslash escapes than the original expression. Specifically, Ruff will preserve the original quote style for the following cases:

        When the target Python version is < 3.12 and a self-documenting f-string contains a string literal with the configured quote style:

        # format.quote-style = \"double\"\n\nf'{10 + len(\"hello\")=}'\n# This f-string cannot be formatted as follows when targeting Python < 3.12\nf\"{10 + len(\"hello\")=}\"\n

        When the target Python version is < 3.12 and an f-string contains any triple-quoted string, byte or f-string literal that contains the configured quote style:

        # format.quote-style = \"double\"\n\nf'{\"\"\"nested \" \"\"\"}'\n# This f-string cannot be formatted as follows when targeting Python < 3.12\nf\"{'''nested \" '''}\"\n

        For all target Python versions, when a self-documenting f-string contains an expression between the curly braces ({...}) with a format specifier containing the configured quote style:

        # format.quote-style = \"double\"\n\nf'{1=:\"foo}'\n# This f-string cannot be formatted as follows for all target Python versions\nf\"{1=:\"foo}\"\n

        For nested f-strings, Ruff alternates quote styles, starting with the configured quote style for the outermost f-string. For example, consider the following f-string:

        # format.quote-style = \"double\"\n\nf\"outer f-string {f\"nested f-string {f\"another nested f-string\"} end\"} end\"\n

        Ruff formats it as:

        f\"outer f-string {f'nested f-string {f\"another nested f-string\"} end'} end\"\n
        "},{"location":"formatter/#line-breaks","title":"Line breaks","text":"

        Starting with Python 3.12 (PEP 701), the expression parts of an f-string can span multiple lines. Ruff needs to decide when to introduce a line break in an f-string expression. This depends on the semantic content of the expression parts of an f-string - for example, introducing a line break in the middle of a natural-language sentence is undesirable. Since Ruff doesn't have enough information to make that decision, it adopts a heuristic similar to Prettier: it will only split the expression parts of an f-string across multiple lines if there was already a line break within any of the expression parts.

        For example, the following code:

        f\"this f-string has a multiline expression {\n  ['red', 'green', 'blue', 'yellow',]} and does not fit within the line length\"\n

        ... is formatted as:

        # The list expression is split across multiple lines because of the trailing comma\nf\"this f-string has a multiline expression {\n    [\n        'red',\n        'green',\n        'blue',\n        'yellow',\n    ]\n} and does not fit within the line length\"\n

        But, the following will not be split across multiple lines even though it exceeds the line length:

        f\"this f-string has a multiline expression {['red', 'green', 'blue', 'yellow']} and does not fit within the line length\"\n

        If you want Ruff to split an f-string across multiple lines, ensure there's a linebreak somewhere within the {...} parts of an f-string.

        "},{"location":"formatter/#sorting-imports","title":"Sorting imports","text":"

        Currently, the Ruff formatter does not sort imports. In order to both sort imports and format, call the Ruff linter and then the formatter:

        ruff check --select I --fix\nruff format\n

        A unified command for both linting and formatting is planned.

        "},{"location":"installation/","title":"Installing Ruff","text":"

        Ruff is available as ruff on PyPI.

        Ruff can be invoked directly with uvx:

        uvx ruff check   # Lint all files in the current directory.\nuvx ruff format  # Format all files in the current directory.\n

        Or installed with uv (recommended), pip, or pipx:

        $ # Install Ruff globally.\n$ uv tool install ruff@latest\n\n$ # Or add Ruff to your project.\n$ uv add --dev ruff\n\n$ # With pip.\n$ pip install ruff\n\n$ # With pipx.\n$ pipx install ruff\n

        Once installed, you can run Ruff from the command line:

        $ ruff check   # Lint all files in the current directory.\n$ ruff format  # Format all files in the current directory.\n

        Starting with version 0.5.0, Ruff can also be installed with our standalone installers:

        $ # On macOS and Linux.\n$ curl -LsSf https://astral.sh/ruff/install.sh | sh\n\n$ # On Windows.\n$ powershell -c \"irm https://astral.sh/ruff/install.ps1 | iex\"\n\n$ # For a specific version.\n$ curl -LsSf https://astral.sh/ruff/0.5.0/install.sh | sh\n$ powershell -c \"irm https://astral.sh/ruff/0.5.0/install.ps1 | iex\"\n

        For macOS Homebrew and Linuxbrew users, Ruff is also available as ruff on Homebrew:

        $ brew install ruff\n

        For Conda users, Ruff is also available as ruff on conda-forge:

        $ conda install -c conda-forge ruff\n

        For pkgx users, Ruff is also available as ruff on the pkgx registry:

        $ pkgx install ruff\n

        For Arch Linux users, Ruff is also available as ruff on the official repositories:

        $ pacman -S ruff\n

        For Alpine users, Ruff is also available as ruff on the testing repositories:

        $ apk add ruff\n

        For openSUSE Tumbleweed users, Ruff is also available in the distribution repository:

        $ sudo zypper install python3-ruff\n

        On Docker, it is published as ghcr.io/astral-sh/ruff, tagged for each release and latest for the latest release.

        $ docker run -v .:/io --rm ghcr.io/astral-sh/ruff check\n$ docker run -v .:/io --rm ghcr.io/astral-sh/ruff:0.3.0 check\n\n$ # Or, for Podman on SELinux.\n$ docker run -v .:/io:Z --rm ghcr.io/astral-sh/ruff check\n

        "},{"location":"integrations/","title":"Integrations","text":""},{"location":"integrations/#github-actions","title":"GitHub Actions","text":"

        GitHub Actions has everything you need to run Ruff out-of-the-box:

        name: CI\non: push\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: \"3.11\"\n      - name: Install dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install ruff\n      # Update output format to enable automatic inline annotations.\n      - name: Run Ruff\n        run: ruff check --output-format=github .\n

        Ruff can also be used as a GitHub Action via ruff-action.

        By default, ruff-action runs as a pass-fail test to ensure that a given repository doesn't contain any lint rule violations as per its configuration. However, under-the-hood, ruff-action installs and runs ruff directly, so it can be used to execute any supported ruff command (e.g., ruff check --fix).

        ruff-action supports all GitHub-hosted runners, and can be used with any published Ruff version (i.e., any version available on PyPI).

        To use ruff-action, create a file (e.g., .github/workflows/ruff.yml) inside your repository with:

        name: Ruff\non: [ push, pull_request ]\njobs:\n  ruff:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: astral-sh/ruff-action@v3\n

        Alternatively, you can include ruff-action as a step in any other workflow file:

              - uses: astral-sh/ruff-action@v3\n

        ruff-action accepts optional configuration parameters via with:, including:

        • version: The Ruff version to install (default: latest).
        • args: The command-line arguments to pass to Ruff (default: \"check\").
        • src: The source paths to pass to Ruff (default: [\".\", \"src\"]).

        For example, to run ruff check --select B ./src using Ruff version 0.8.0:

        - uses: astral-sh/ruff-action@v3\n  with:\n    version: 0.8.0\n    args: check --select B\n    src: \"./src\"\n
        "},{"location":"integrations/#gitlab-cicd","title":"GitLab CI/CD","text":"

        You can add the following configuration to .gitlab-ci.yml to run a ruff format in parallel with a ruff check compatible with GitLab's codequality report.

        .base_ruff:\n  stage: build\n  interruptible: true\n  image:\n    name: ghcr.io/astral-sh/ruff:0.11.10-alpine\n  before_script:\n    - cd $CI_PROJECT_DIR\n    - ruff --version\n\nRuff Check:\n  extends: .base_ruff\n  script:\n    - ruff check --output-format=gitlab > code-quality-report.json\n  artifacts:\n    reports:\n      codequality: $CI_PROJECT_DIR/code-quality-report.json\n\nRuff Format:\n  extends: .base_ruff\n  script:\n    - ruff format --diff\n
        "},{"location":"integrations/#pre-commit","title":"pre-commit","text":"

        Ruff can be used as a pre-commit hook via ruff-pre-commit:

        - repo: https://github.com/astral-sh/ruff-pre-commit\n  # Ruff version.\n  rev: v0.11.10\n  hooks:\n    # Run the linter.\n    - id: ruff\n    # Run the formatter.\n    - id: ruff-format\n

        To enable lint fixes, add the --fix argument to the lint hook:

        - repo: https://github.com/astral-sh/ruff-pre-commit\n  # Ruff version.\n  rev: v0.11.10\n  hooks:\n    # Run the linter.\n    - id: ruff\n      args: [ --fix ]\n    # Run the formatter.\n    - id: ruff-format\n

        To avoid running on Jupyter Notebooks, remove jupyter from the list of allowed filetypes:

        - repo: https://github.com/astral-sh/ruff-pre-commit\n  # Ruff version.\n  rev: v0.11.10\n  hooks:\n    # Run the linter.\n    - id: ruff\n      types_or: [ python, pyi ]\n      args: [ --fix ]\n    # Run the formatter.\n    - id: ruff-format\n      types_or: [ python, pyi ]\n

        When running with --fix, Ruff's lint hook should be placed before Ruff's formatter hook, and before Black, isort, and other formatting tools, as Ruff's fix behavior can output code changes that require reformatting.

        When running without --fix, Ruff's formatter hook can be placed before or after Ruff's lint hook.

        (As long as your Ruff configuration avoids any linter-formatter incompatibilities, ruff format should never introduce new lint errors, so it's safe to run Ruff's format hook after ruff check --fix.)

        "},{"location":"integrations/#mdformat","title":"mdformat","text":"

        mdformat is capable of formatting code blocks within Markdown. The mdformat-ruff plugin enables mdformat to format Python code blocks with Ruff.

        "},{"location":"integrations/#docker","title":"Docker","text":"

        Ruff provides a distroless Docker image including the ruff binary. The following tags are published:

        • ruff:latest
        • ruff:{major}.{minor}.{patch}, e.g., ruff:0.6.6
        • ruff:{major}.{minor}, e.g., ruff:0.6 (the latest patch version)

        In addition, ruff publishes the following images:

        • Based on alpine:3.20:
        • ruff:alpine
        • ruff:alpine3.20
        • Based on debian:bookworm-slim:
        • ruff:debian-slim
        • ruff:bookworm-slim
        • Based on buildpack-deps:bookworm:
        • ruff:debian
        • ruff:bookworm

        As with the distroless image, each image is published with ruff version tags as ruff:{major}.{minor}.{patch}-{base} and ruff:{major}.{minor}-{base}, e.g., ruff:0.6.6-alpine.

        "},{"location":"linter/","title":"The Ruff Linter","text":"

        The Ruff Linter is an extremely fast Python linter designed as a drop-in replacement for Flake8 (plus dozens of plugins), isort, pydocstyle, pyupgrade, autoflake, and more.

        "},{"location":"linter/#ruff-check","title":"ruff check","text":"

        ruff check is the primary entrypoint to the Ruff linter. It accepts a list of files or directories, and lints all discovered Python files, optionally fixing any fixable errors. When linting a directory, Ruff searches for Python files recursively in that directory and all its subdirectories:

        $ ruff check                  # Lint files in the current directory.\n$ ruff check --fix            # Lint files in the current directory and fix any fixable errors.\n$ ruff check --watch          # Lint files in the current directory and re-lint on change.\n$ ruff check path/to/code/    # Lint files in `path/to/code`.\n

        For the full list of supported options, run ruff check --help.

        "},{"location":"linter/#rule-selection","title":"Rule selection","text":"

        The set of enabled rules is controlled via the lint.select, lint.extend-select, and lint.ignore settings.

        Ruff's linter mirrors Flake8's rule code system, in which each rule code consists of a one-to-three letter prefix, followed by three digits (e.g., F401). The prefix indicates that \"source\" of the rule (e.g., F for Pyflakes, E for pycodestyle, ANN for flake8-annotations).

        Rule selectors like lint.select and lint.ignore accept either a full rule code (e.g., F401) or any valid prefix (e.g., F). For example, given the following configuration file:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nselect = [\"E\", \"F\"]\nignore = [\"F401\"]\n
        [lint]\nselect = [\"E\", \"F\"]\nignore = [\"F401\"]\n

        Ruff would enable all rules with the E (pycodestyle) or F (Pyflakes) prefix, with the exception of F401. For more on configuring Ruff via pyproject.toml, see Configuring Ruff.

        As a special-case, Ruff also supports the ALL code, which enables all rules. Note that some pydocstyle rules conflict (e.g., D203 and D211) as they represent alternative docstring formats. Ruff will automatically disable any conflicting rules when ALL is enabled.

        If you're wondering how to configure Ruff, here are some recommended guidelines:

        • Prefer lint.select over lint.extend-select to make your rule set explicit.
        • Use ALL with discretion. Enabling ALL will implicitly enable new rules whenever you upgrade.
        • Start with a small set of rules (select = [\"E\", \"F\"]) and add a category at-a-time. For example, you might consider expanding to select = [\"E\", \"F\", \"B\"] to enable the popular flake8-bugbear extension.

        For example, a configuration that enables some of the most popular rules (without being too pedantic) might look like the following:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nselect = [\n    # pycodestyle\n    \"E\",\n    # Pyflakes\n    \"F\",\n    # pyupgrade\n    \"UP\",\n    # flake8-bugbear\n    \"B\",\n    # flake8-simplify\n    \"SIM\",\n    # isort\n    \"I\",\n]\n
        [lint]\nselect = [\n    # pycodestyle\n    \"E\",\n    # Pyflakes\n    \"F\",\n    # pyupgrade\n    \"UP\",\n    # flake8-bugbear\n    \"B\",\n    # flake8-simplify\n    \"SIM\",\n    # isort\n    \"I\",\n]\n

        To resolve the enabled rule set, Ruff may need to reconcile lint.select and lint.ignore from a variety of sources, including the current pyproject.toml, any inherited pyproject.toml files, and the CLI (e.g., --select).

        In those scenarios, Ruff uses the \"highest-priority\" select as the basis for the rule set, and then applies extend-select and ignore adjustments. CLI options are given higher priority than pyproject.toml options, and the current pyproject.toml file is given higher priority than any inherited pyproject.toml files.

        For example, given the following configuration file:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nselect = [\"E\", \"F\"]\nignore = [\"F401\"]\n
        [lint]\nselect = [\"E\", \"F\"]\nignore = [\"F401\"]\n

        Running ruff check --select F401 would result in Ruff enforcing F401, and no other rules.

        Running ruff check --extend-select B would result in Ruff enforcing the E, F, and B rules, with the exception of F401.

        "},{"location":"linter/#fixes","title":"Fixes","text":"

        Ruff supports automatic fixes for a variety of lint errors. For example, Ruff can remove unused imports, reformat docstrings, rewrite type annotations to use newer Python syntax, and more.

        To enable fixes, pass the --fix flag to ruff check:

        $ ruff check --fix\n

        By default, Ruff will fix all violations for which safe fixes are available; to determine whether a rule supports fixing, see Rules.

        "},{"location":"linter/#fix-safety","title":"Fix safety","text":"

        Ruff labels fixes as \"safe\" and \"unsafe\". The meaning and intent of your code will be retained when applying safe fixes, but the meaning could change when applying unsafe fixes.

        Specifically, an unsafe fix could lead to a change in runtime behavior, the removal of comments, or both, while safe fixes are intended to preserve runtime behavior and will only remove comments when deleting entire statements or expressions (e.g., removing unused imports).

        For example, unnecessary-iterable-allocation-for-first-element (RUF015) is a rule which checks for potentially unperformant use of list(...)[0]. The fix replaces this pattern with next(iter(...)) which can result in a drastic speedup:

        $ python -m timeit \"head = list(range(99999999))[0]\"\n1 loop, best of 5: 1.69 sec per loop\n
        $ python -m timeit \"head = next(iter(range(99999999)))\"\n5000000 loops, best of 5: 70.8 nsec per loop\n

        However, when the collection is empty, this raised exception changes from an IndexError to StopIteration:

        $ python -c 'list(range(0))[0]'\nTraceback (most recent call last):\n  File \"<string>\", line 1, in <module>\nIndexError: list index out of range\n
        $ python -c 'next(iter(range(0)))[0]'\nTraceback (most recent call last):\n  File \"<string>\", line 1, in <module>\nStopIteration\n

        Since the change in exception type could break error handling upstream, this fix is categorized as unsafe.

        Ruff only enables safe fixes by default. Unsafe fixes can be enabled by settings unsafe-fixes in your configuration file or passing the --unsafe-fixes flag to ruff check:

        # Show unsafe fixes\nruff check --unsafe-fixes\n\n# Apply unsafe fixes\nruff check --fix --unsafe-fixes\n

        By default, Ruff will display a hint when unsafe fixes are available but not enabled. The suggestion can be silenced by setting the unsafe-fixes setting to false or using the --no-unsafe-fixes flag.

        The safety of fixes can be adjusted per rule using the lint.extend-safe-fixes and lint.extend-unsafe-fixes settings.

        For example, the following configuration would promote unsafe fixes for F601 to safe fixes and demote safe fixes for UP034 to unsafe fixes:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nextend-safe-fixes = [\"F601\"]\nextend-unsafe-fixes = [\"UP034\"]\n
        [lint]\nextend-safe-fixes = [\"F601\"]\nextend-unsafe-fixes = [\"UP034\"]\n

        You may use prefixes to select rules as well, e.g., F can be used to promote fixes for all rules in Pyflakes to safe.

        Note

        All fixes will always be displayed by Ruff when using the json output format. The safety of each fix is available under the applicability field.

        "},{"location":"linter/#disabling-fixes","title":"Disabling fixes","text":"

        To limit the set of rules that Ruff should fix, use the lint.fixable or lint.extend-fixable, and lint.unfixable settings.

        For example, the following configuration would enable fixes for all rules except unused-imports (F401):

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nfixable = [\"ALL\"]\nunfixable = [\"F401\"]\n
        [lint]\nfixable = [\"ALL\"]\nunfixable = [\"F401\"]\n

        Conversely, the following configuration would only enable fixes for F401:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nfixable = [\"F401\"]\n
        [lint]\nfixable = [\"F401\"]\n
        "},{"location":"linter/#error-suppression","title":"Error suppression","text":"

        Ruff supports several mechanisms for suppressing lint errors, be they false positives or permissible violations.

        To omit a lint rule entirely, add it to the \"ignore\" list via the lint.ignore setting, either on the command-line or in your pyproject.toml or ruff.toml file.

        To suppress a violation inline, Ruff uses a noqa system similar to Flake8. To ignore an individual violation, add # noqa: {code} to the end of the line, like so:

        # Ignore F841.\nx = 1  # noqa: F841\n\n# Ignore E741 and F841.\ni = 1  # noqa: E741, F841\n\n# Ignore _all_ violations.\nx = 1  # noqa\n

        For multi-line strings (like docstrings), the noqa directive should come at the end of the string (after the closing triple quote), and will apply to the entire string, like so:

        \"\"\"Lorem ipsum dolor sit amet.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.\n\"\"\"  # noqa: E501\n

        For import sorting, the noqa should come at the end of the first line in the import block, and will apply to all imports in the block, like so:

        import os  # noqa: I001\nimport abc\n

        To ignore all violations across an entire file, add the line # ruff: noqa anywhere in the file, preferably towards the top, like so:

        # ruff: noqa\n

        To ignore a specific rule across an entire file, add the line # ruff: noqa: {code} anywhere in the file, preferably towards the top, like so:

        # ruff: noqa: F841\n

        Or see the lint.per-file-ignores setting, which enables the same functionality from within your pyproject.toml or ruff.toml file.

        Global noqa comments must be on their own line to disambiguate from comments which ignore violations on a single line.

        Note that Ruff will also respect Flake8's # flake8: noqa directive, and will treat it as equivalent to # ruff: noqa.

        "},{"location":"linter/#full-suppression-comment-specification","title":"Full suppression comment specification","text":"

        The full specification is as follows:

        • An inline blanket noqa comment is given by a case-insensitive match for #noqa with optional whitespace after the # symbol, followed by either: the end of the comment, the beginning of a new comment (#), or whitespace followed by any character other than :.
        • An inline rule suppression is given by first finding a case-insensitive match for #noqa with optional whitespace after the # symbol, optional whitespace after noqa, and followed by the symbol :. After this we are expected to have a list of rule codes which is given by sequences of uppercase ASCII characters followed by ASCII digits, separated by whitespace or commas. The list ends at the last valid code. We will attempt to interpret rules with a missing delimiter (e.g. F401F841), though a warning will be emitted in this case.
        • A file-level exemption comment is given by a case-sensitive match for #ruff: or #flake8:, with optional whitespace after # and before :, followed by optional whitespace and a case-insensitive match for noqa. After this, the specification is as in the inline case.
        "},{"location":"linter/#detecting-unused-suppression-comments","title":"Detecting unused suppression comments","text":"

        Ruff implements a special rule, unused-noqa, under the RUF100 code, to enforce that your noqa directives are \"valid\", in that the violations they say they ignore are actually being triggered on that line (and thus suppressed). To flag unused noqa directives, run: ruff check /path/to/file.py --extend-select RUF100.

        Ruff can also remove any unused noqa directives via its fix functionality. To remove any unused noqa directives, run: ruff check /path/to/file.py --extend-select RUF100 --fix.

        "},{"location":"linter/#inserting-necessary-suppression-comments","title":"Inserting necessary suppression comments","text":"

        Ruff can automatically add noqa directives to all lines that contain violations, which is useful when migrating a new codebase to Ruff. To automatically add noqa directives to all relevant lines (with the appropriate rule codes), run: ruff check /path/to/file.py --add-noqa.

        "},{"location":"linter/#action-comments","title":"Action comments","text":"

        Ruff respects isort's action comments (# isort: skip_file, # isort: on, # isort: off, # isort: skip, and # isort: split), which enable selectively enabling and disabling import sorting for blocks of code and other inline configuration.

        Ruff will also respect variants of these action comments with a # ruff: prefix (e.g., # ruff: isort: skip_file, # ruff: isort: on, and so on). These variants more clearly convey that the action comment is intended for Ruff, but are functionally equivalent to the isort variants.

        Unlike isort, Ruff does not respect action comments within docstrings.

        See the isort documentation for more.

        "},{"location":"linter/#exit-codes","title":"Exit codes","text":"

        By default, ruff check exits with the following status codes:

        • 0 if no violations were found, or if all present violations were fixed automatically.
        • 1 if violations were found.
        • 2 if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an internal error.

        This convention mirrors that of tools like ESLint, Prettier, and RuboCop.

        ruff check supports two command-line flags that alter its exit code behavior:

        • --exit-zero will cause Ruff to exit with a status code of 0 even if violations were found. Note that Ruff will still exit with a status code of 2 if it terminates abnormally.
        • --exit-non-zero-on-fix will cause Ruff to exit with a status code of 1 if violations were found, even if all such violations were fixed automatically. Note that the use of --exit-non-zero-on-fix can result in a non-zero exit code even if no violations remain after fixing.
        "},{"location":"preview/","title":"Preview","text":"

        Ruff includes an opt-in preview mode to provide an opportunity for community feedback and increase confidence that changes are a net-benefit before enabling them for everyone.

        Preview mode enables a collection of unstable features such as new lint rules and fixes, formatter style changes, interface updates, and more. Warnings about deprecated features may turn into errors when using preview mode.

        Enabling preview mode does not on its own enable all preview rules. See the rules section for details on selecting preview rules.

        "},{"location":"preview/#enabling-preview-mode","title":"Enabling preview mode","text":"

        Preview mode can be enabled with the --preview flag on the CLI or by setting preview = true in your Ruff configuration file.

        Preview mode can be configured separately for linting and formatting. To enable preview lint rules without preview style formatting:

        pyproject.tomlruff.tomlCLI
        [tool.ruff.lint]\npreview = true\n
        [lint]\npreview = true\n
        ruff check --preview\n

        To enable preview style formatting without enabling any preview lint rules:

        pyproject.tomlruff.tomlCLI
        [tool.ruff.format]\npreview = true\n
        [format]\npreview = true\n
        ruff format --preview\n
        "},{"location":"preview/#using-rules-that-are-in-preview","title":"Using rules that are in preview","text":"

        If a rule is marked as preview, it can only be selected if preview mode is enabled. For example, consider a hypothetical rule, HYP001. If HYP001 were in preview, it would not be enabled by adding it to the selected rule set.

        pyproject.tomlruff.tomlCLI
        [tool.ruff.lint]\nextend-select = [\"HYP001\"]\n
        [lint]\nextend-select = [\"HYP001\"]\n
        ruff check --extend-select HYP001\n

        It also would not be enabled by selecting the HYP category, like so:

        pyproject.tomlruff.tomlCLI
        [tool.ruff.lint]\nextend-select = [\"HYP\"]\n
        [lint]\nextend-select = [\"HYP\"]\n
        ruff check --extend-select HYP\n

        Similarly, it would not be enabled via the ALL selector:

        pyproject.tomlruff.tomlCLI
        [tool.ruff.lint]\nselect = [\"ALL\"]\n
        [lint]\nselect = [\"ALL\"]\n
        ruff check --select ALL\n

        However, it would be enabled in any of the above cases if you enabled preview mode:

        pyproject.tomlruff.tomlCLI
        [tool.ruff.lint]\nextend-select = [\"HYP\"]\npreview = true\n
        [lint]\nextend-select = [\"HYP\"]\npreview = true\n
        ruff check --extend-select HYP --preview\n

        To see which rules are currently in preview, visit the rules reference.

        "},{"location":"preview/#selecting-single-preview-rules","title":"Selecting single preview rules","text":"

        When preview mode is enabled, selecting rule categories or prefixes will include all preview rules that match. If you'd prefer to opt in to each preview rule individually, you can toggle the explicit-preview-rules setting in your configuration file:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\npreview = true\nexplicit-preview-rules = true\n
        [lint]\npreview = true\nexplicit-preview-rules = true\n

        In our previous example, --select with ALL HYP, HYP0, or HYP00 would not enable HYP001. Each preview rule will need to be selected with its exact code: for example, --select ALL,HYP001.

        If preview mode is not enabled, this setting has no effect.

        "},{"location":"preview/#deprecated-rules","title":"Deprecated rules","text":"

        When preview mode is enabled, deprecated rules will be disabled. If a deprecated rule is selected explicitly, an error will be raised. Deprecated rules will not be included if selected via a rule category or prefix.

        "},{"location":"rules/","title":"Rules","text":"

        Ruff supports over 800 lint rules, many of which are inspired by popular tools like Flake8, isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in Rust as a first-party feature.

        By default, Ruff enables Flake8's F rules, along with a subset of the E rules, omitting any stylistic rules that overlap with the use of a formatter, like ruff format or Black.

        If you're just getting started with Ruff, the default rule set is a great place to start: it catches a wide variety of common errors (like unused imports) with zero configuration.

        "},{"location":"rules/#legend","title":"Legend","text":"

        \u00a0\u00a0\u00a0\u00a0\u2714\ufe0f\u00a0\u00a0\u00a0\u00a0 The rule is stable.\u00a0\u00a0\u00a0\u00a0\ud83e\uddea\u00a0\u00a0\u00a0\u00a0 The rule is unstable and is in \"preview\".\u00a0\u00a0\u00a0\u00a0\u26a0\ufe0f\u00a0\u00a0\u00a0\u00a0 The rule has been deprecated and will be removed in a future release.\u00a0\u00a0\u00a0\u00a0\u274c\u00a0\u00a0\u00a0\u00a0 The rule has been removed only the documentation is available.\u00a0\u00a0\u00a0\u00a0\ud83d\udee0\ufe0f\u00a0\u00a0\u00a0\u00a0 The rule is automatically fixable by the --fix command-line option.

        "},{"location":"rules/#airflow-air","title":"Airflow (AIR)","text":"

        For more, see Airflow on PyPI.

        Code Name Message AIR001 airflow-variable-name-task-id-mismatch Task variable name should match the task_id: \"{task_id}\" \u2714\ufe0f \ud83d\udee0\ufe0f AIR002 airflow-dag-no-schedule-argument DAG should have an explicit schedule argument \ud83e\uddea \ud83d\udee0\ufe0f AIR301 airflow3-removal {deprecated} is removed in Airflow 3.0 \ud83e\uddea \ud83d\udee0\ufe0f AIR302 airflow3-moved-to-provider {deprecated} is removed in Airflow 3.0 \ud83e\uddea \ud83d\udee0\ufe0f AIR311 airflow3-suggested-update {deprecated} is removed in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version. \ud83e\uddea \ud83d\udee0\ufe0f AIR312 airflow3-suggested-to-move-to-provider {deprecated} is removed in Airflow 3.0 \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#eradicate-era","title":"eradicate (ERA)","text":"

        For more, see eradicate on PyPI.

        Code Name Message ERA001 commented-out-code Found commented-out code \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#fastapi-fast","title":"FastAPI (FAST)","text":"

        For more, see FastAPI on PyPI.

        Code Name Message FAST001 fast-api-redundant-response-model FastAPI route with redundant response_model argument \u2714\ufe0f \ud83d\udee0\ufe0f FAST002 fast-api-non-annotated-dependency FastAPI dependency without Annotated \u2714\ufe0f \ud83d\udee0\ufe0f FAST003 fast-api-unused-path-parameter Parameter {arg_name} appears in route path, but not in {function_name} signature \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-2020-ytt","title":"flake8-2020 (YTT)","text":"

        For more, see flake8-2020 on PyPI.

        Code Name Message YTT101 sys-version-slice3 sys.version[:3] referenced (python3.10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f YTT102 sys-version2 sys.version[2] referenced (python3.10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f YTT103 sys-version-cmp-str3 sys.version compared to string (python3.10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f YTT201 sys-version-info0-eq3 sys.version_info[0] == 3 referenced (python4), use >= \u2714\ufe0f \ud83d\udee0\ufe0f YTT202 six-py3 six.PY3 referenced (python4), use not six.PY2 \u2714\ufe0f \ud83d\udee0\ufe0f YTT203 sys-version-info1-cmp-int sys.version_info[1] compared to integer (python4), compare sys.version_info to tuple \u2714\ufe0f \ud83d\udee0\ufe0f YTT204 sys-version-info-minor-cmp-int sys.version_info.minor compared to integer (python4), compare sys.version_info to tuple \u2714\ufe0f \ud83d\udee0\ufe0f YTT301 sys-version0 sys.version[0] referenced (python10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f YTT302 sys-version-cmp-str10 sys.version compared to string (python10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f YTT303 sys-version-slice1 sys.version[:1] referenced (python10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-annotations-ann","title":"flake8-annotations (ANN)","text":"

        For more, see flake8-annotations on PyPI.

        For related settings, see flake8-annotations.

        Code Name Message ANN001 missing-type-function-argument Missing type annotation for function argument {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN002 missing-type-args Missing type annotation for *{name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN003 missing-type-kwargs Missing type annotation for **{name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN101 missing-type-self Missing type annotation for {name} in method \u274c \ud83d\udee0\ufe0f ANN102 missing-type-cls Missing type annotation for {name} in classmethod \u274c \ud83d\udee0\ufe0f ANN201 missing-return-type-undocumented-public-function Missing return type annotation for public function {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN202 missing-return-type-private-function Missing return type annotation for private function {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN204 missing-return-type-special-method Missing return type annotation for special method {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN205 missing-return-type-static-method Missing return type annotation for staticmethod {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN206 missing-return-type-class-method Missing return type annotation for classmethod {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN401 any-type Dynamically typed expressions (typing.Any) are disallowed in {name} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-async-async","title":"flake8-async (ASYNC)","text":"

        For more, see flake8-async on PyPI.

        Code Name Message ASYNC100 cancel-scope-no-checkpoint A with {method_name}(...): context does not contain any await statements. This makes it pointless, as the timeout can only be triggered by a checkpoint. \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC105 trio-sync-call Call to {method_name} is not immediately awaited \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC109 async-function-with-timeout Async function definition with a timeout parameter \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC110 async-busy-wait Use {module}.Event instead of awaiting {module}.sleep in a while loop \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC115 async-zero-sleep Use {module}.lowlevel.checkpoint() instead of {module}.sleep(0) \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC116 long-sleep-not-forever {module}.sleep() with >24 hour interval should usually be {module}.sleep_forever() \ud83e\uddea \ud83d\udee0\ufe0f ASYNC210 blocking-http-call-in-async-function Async functions should not call blocking HTTP methods \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC220 create-subprocess-in-async-function Async functions should not create subprocesses with blocking methods \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC221 run-process-in-async-function Async functions should not run processes with blocking methods \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC222 wait-for-process-in-async-function Async functions should not wait on processes with blocking methods \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC230 blocking-open-call-in-async-function Async functions should not open files with blocking methods like open \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC251 blocking-sleep-in-async-function Async functions should not call time.sleep \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-bandit-s","title":"flake8-bandit (S)","text":"

        For more, see flake8-bandit on PyPI.

        For related settings, see flake8-bandit.

        Code Name Message S101 assert Use of assert detected \u2714\ufe0f \ud83d\udee0\ufe0f S102 exec-builtin Use of exec detected \u2714\ufe0f \ud83d\udee0\ufe0f S103 bad-file-permissions os.chmod setting a permissive mask {mask:#o} on file or directory \u2714\ufe0f \ud83d\udee0\ufe0f S104 hardcoded-bind-all-interfaces Possible binding to all interfaces \u2714\ufe0f \ud83d\udee0\ufe0f S105 hardcoded-password-string Possible hardcoded password assigned to: \"{}\" \u2714\ufe0f \ud83d\udee0\ufe0f S106 hardcoded-password-func-arg Possible hardcoded password assigned to argument: \"{}\" \u2714\ufe0f \ud83d\udee0\ufe0f S107 hardcoded-password-default Possible hardcoded password assigned to function default: \"{}\" \u2714\ufe0f \ud83d\udee0\ufe0f S108 hardcoded-temp-file Probable insecure usage of temporary file or directory: \"{}\" \u2714\ufe0f \ud83d\udee0\ufe0f S110 try-except-pass try-except-pass detected, consider logging the exception \u2714\ufe0f \ud83d\udee0\ufe0f S112 try-except-continue try-except-continue detected, consider logging the exception \u2714\ufe0f \ud83d\udee0\ufe0f S113 request-without-timeout Probable use of {module} call without timeout \u2714\ufe0f \ud83d\udee0\ufe0f S201 flask-debug-true Use of debug=True in Flask app detected \u2714\ufe0f \ud83d\udee0\ufe0f S202 tarfile-unsafe-members Uses of tarfile.extractall() \u2714\ufe0f \ud83d\udee0\ufe0f S301 suspicious-pickle-usage pickle and modules that wrap it can be unsafe when used to deserialize untrusted data, possible security issue \u2714\ufe0f \ud83d\udee0\ufe0f S302 suspicious-marshal-usage Deserialization with the marshal module is possibly dangerous \u2714\ufe0f \ud83d\udee0\ufe0f S303 suspicious-insecure-hash-usage Use of insecure MD2, MD4, MD5, or SHA1 hash function \u2714\ufe0f \ud83d\udee0\ufe0f S304 suspicious-insecure-cipher-usage Use of insecure cipher, replace with a known secure cipher such as AES \u2714\ufe0f \ud83d\udee0\ufe0f S305 suspicious-insecure-cipher-mode-usage Use of insecure block cipher mode, replace with a known secure mode such as CBC or CTR \u2714\ufe0f \ud83d\udee0\ufe0f S306 suspicious-mktemp-usage Use of insecure and deprecated function (mktemp) \u2714\ufe0f \ud83d\udee0\ufe0f S307 suspicious-eval-usage Use of possibly insecure function; consider using ast.literal_eval \u2714\ufe0f \ud83d\udee0\ufe0f S308 suspicious-mark-safe-usage Use of mark_safe may expose cross-site scripting vulnerabilities \u2714\ufe0f \ud83d\udee0\ufe0f S310 suspicious-url-open-usage Audit URL open for permitted schemes. Allowing use of file: or custom schemes is often unexpected. \u2714\ufe0f \ud83d\udee0\ufe0f S311 suspicious-non-cryptographic-random-usage Standard pseudo-random generators are not suitable for cryptographic purposes \u2714\ufe0f \ud83d\udee0\ufe0f S312 suspicious-telnet-usage Telnet is considered insecure. Use SSH or some other encrypted protocol. \u2714\ufe0f \ud83d\udee0\ufe0f S313 suspicious-xmlc-element-tree-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S314 suspicious-xml-element-tree-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S315 suspicious-xml-expat-reader-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S316 suspicious-xml-expat-builder-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S317 suspicious-xml-sax-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S318 suspicious-xml-mini-dom-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S319 suspicious-xml-pull-dom-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S320 suspicious-xmle-tree-usage Using lxml to parse untrusted data is known to be vulnerable to XML attacks \u26a0\ufe0f \ud83d\udee0\ufe0f S321 suspicious-ftp-lib-usage FTP-related functions are being called. FTP is considered insecure. Use SSH/SFTP/SCP or some other encrypted protocol. \u2714\ufe0f \ud83d\udee0\ufe0f S323 suspicious-unverified-context-usage Python allows using an insecure context via the _create_unverified_context that reverts to the previous behavior that does not validate certificates or perform hostname checks. \u2714\ufe0f \ud83d\udee0\ufe0f S324 hashlib-insecure-hash-function Probable use of insecure hash functions in {library}: {string} \u2714\ufe0f \ud83d\udee0\ufe0f S401 suspicious-telnetlib-import telnetlib and related modules are considered insecure. Use SSH or another encrypted protocol. \ud83e\uddea \ud83d\udee0\ufe0f S402 suspicious-ftplib-import ftplib and related modules are considered insecure. Use SSH, SFTP, SCP, or another encrypted protocol. \ud83e\uddea \ud83d\udee0\ufe0f S403 suspicious-pickle-import pickle, cPickle, dill, and shelve modules are possibly insecure \ud83e\uddea \ud83d\udee0\ufe0f S404 suspicious-subprocess-import subprocess module is possibly insecure \ud83e\uddea \ud83d\udee0\ufe0f S405 suspicious-xml-etree-import xml.etree methods are vulnerable to XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S406 suspicious-xml-sax-import xml.sax methods are vulnerable to XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S407 suspicious-xml-expat-import xml.dom.expatbuilder is vulnerable to XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S408 suspicious-xml-minidom-import xml.dom.minidom is vulnerable to XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S409 suspicious-xml-pulldom-import xml.dom.pulldom is vulnerable to XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S410 suspicious-lxml-import lxml is vulnerable to XML attacks \u274c \ud83d\udee0\ufe0f S411 suspicious-xmlrpc-import XMLRPC is vulnerable to remote XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S412 suspicious-httpoxy-import httpoxy is a set of vulnerabilities that affect application code running inCGI, or CGI-like environments. The use of CGI for web applications should be avoided \ud83e\uddea \ud83d\udee0\ufe0f S413 suspicious-pycrypto-import pycrypto library is known to have publicly disclosed buffer overflow vulnerability \ud83e\uddea \ud83d\udee0\ufe0f S415 suspicious-pyghmi-import An IPMI-related module is being imported. Prefer an encrypted protocol over IPMI. \ud83e\uddea \ud83d\udee0\ufe0f S501 request-with-no-cert-validation Probable use of {string} call with verify=False disabling SSL certificate checks \u2714\ufe0f \ud83d\udee0\ufe0f S502 ssl-insecure-version Call made with insecure SSL protocol: {protocol} \u2714\ufe0f \ud83d\udee0\ufe0f S503 ssl-with-bad-defaults Argument default set to insecure SSL protocol: {protocol} \u2714\ufe0f \ud83d\udee0\ufe0f S504 ssl-with-no-version ssl.wrap_socket called without an `ssl_version`` \u2714\ufe0f \ud83d\udee0\ufe0f S505 weak-cryptographic-key {cryptographic_key} key sizes below {minimum_key_size} bits are considered breakable \u2714\ufe0f \ud83d\udee0\ufe0f S506 unsafe-yaml-load Probable use of unsafe loader {name} with yaml.load. Allows instantiation of arbitrary objects. Consider yaml.safe_load. \u2714\ufe0f \ud83d\udee0\ufe0f S507 ssh-no-host-key-verification Paramiko call with policy set to automatically trust the unknown host key \u2714\ufe0f \ud83d\udee0\ufe0f S508 snmp-insecure-version The use of SNMPv1 and SNMPv2 is insecure. Use SNMPv3 if able. \u2714\ufe0f \ud83d\udee0\ufe0f S509 snmp-weak-cryptography You should not use SNMPv3 without encryption. noAuthNoPriv & authNoPriv is insecure. \u2714\ufe0f \ud83d\udee0\ufe0f S601 paramiko-call Possible shell injection via Paramiko call; check inputs are properly sanitized \u2714\ufe0f \ud83d\udee0\ufe0f S602 subprocess-popen-with-shell-equals-true subprocess call with shell=True seems safe, but may be changed in the future; consider rewriting without shell \u2714\ufe0f \ud83d\udee0\ufe0f S603 subprocess-without-shell-equals-true subprocess call: check for execution of untrusted input \u2714\ufe0f \ud83d\udee0\ufe0f S604 call-with-shell-equals-true Function call with shell=True parameter identified, security issue \u2714\ufe0f \ud83d\udee0\ufe0f S605 start-process-with-a-shell Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without shell \u2714\ufe0f \ud83d\udee0\ufe0f S606 start-process-with-no-shell Starting a process without a shell \u2714\ufe0f \ud83d\udee0\ufe0f S607 start-process-with-partial-path Starting a process with a partial executable path \u2714\ufe0f \ud83d\udee0\ufe0f S608 hardcoded-sql-expression Possible SQL injection vector through string-based query construction \u2714\ufe0f \ud83d\udee0\ufe0f S609 unix-command-wildcard-injection Possible wildcard injection in call due to * usage \u2714\ufe0f \ud83d\udee0\ufe0f S610 django-extra Use of Django extra can lead to SQL injection vulnerabilities \u2714\ufe0f \ud83d\udee0\ufe0f S611 django-raw-sql Use of RawSQL can lead to SQL injection vulnerabilities \u2714\ufe0f \ud83d\udee0\ufe0f S612 logging-config-insecure-listen Use of insecure logging.config.listen detected \u2714\ufe0f \ud83d\udee0\ufe0f S701 jinja2-autoescape-false Using jinja2 templates with autoescape=False is dangerous and can lead to XSS. Ensure autoescape=True or use the select_autoescape function. \u2714\ufe0f \ud83d\udee0\ufe0f S702 mako-templates Mako templates allow HTML and JavaScript rendering by default and are inherently open to XSS attacks \u2714\ufe0f \ud83d\udee0\ufe0f S704 unsafe-markup-use Unsafe use of {name} detected \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-blind-except-ble","title":"flake8-blind-except (BLE)","text":"

        For more, see flake8-blind-except on PyPI.

        Code Name Message BLE001 blind-except Do not catch blind exception: {name} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-boolean-trap-fbt","title":"flake8-boolean-trap (FBT)","text":"

        For more, see flake8-boolean-trap on PyPI.

        For related settings, see flake8-boolean-trap.

        Code Name Message FBT001 boolean-type-hint-positional-argument Boolean-typed positional argument in function definition \u2714\ufe0f \ud83d\udee0\ufe0f FBT002 boolean-default-value-positional-argument Boolean default positional argument in function definition \u2714\ufe0f \ud83d\udee0\ufe0f FBT003 boolean-positional-value-in-call Boolean positional value in function call \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-bugbear-b","title":"flake8-bugbear (B)","text":"

        For more, see flake8-bugbear on PyPI.

        For related settings, see flake8-bugbear.

        Code Name Message B002 unary-prefix-increment-decrement Python does not support the unary prefix increment operator (++) \u2714\ufe0f \ud83d\udee0\ufe0f B003 assignment-to-os-environ Assigning to os.environ doesn't clear the environment \u2714\ufe0f \ud83d\udee0\ufe0f B004 unreliable-callable-check Using hasattr(x, \"__call__\") to test if x is callable is unreliable. Use callable(x) for consistent results. \u2714\ufe0f \ud83d\udee0\ufe0f B005 strip-with-multi-characters Using .strip() with multi-character strings is misleading \u2714\ufe0f \ud83d\udee0\ufe0f B006 mutable-argument-default Do not use mutable data structures for argument defaults \u2714\ufe0f \ud83d\udee0\ufe0f B007 unused-loop-control-variable Loop control variable {name} not used within loop body \u2714\ufe0f \ud83d\udee0\ufe0f B008 function-call-in-default-argument Do not perform function call {name} in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable \u2714\ufe0f \ud83d\udee0\ufe0f B009 get-attr-with-constant Do not call getattr with a constant attribute value. It is not any safer than normal property access. \u2714\ufe0f \ud83d\udee0\ufe0f B010 set-attr-with-constant Do not call setattr with a constant attribute value. It is not any safer than normal property access. \u2714\ufe0f \ud83d\udee0\ufe0f B011 assert-false Do not assert False (python -O removes these calls), raise AssertionError() \u2714\ufe0f \ud83d\udee0\ufe0f B012 jump-statement-in-finally {name} inside finally blocks cause exceptions to be silenced \u2714\ufe0f \ud83d\udee0\ufe0f B013 redundant-tuple-in-exception-handler A length-one tuple literal is redundant in exception handlers \u2714\ufe0f \ud83d\udee0\ufe0f B014 duplicate-handler-exception Exception handler with duplicate exception: {name} \u2714\ufe0f \ud83d\udee0\ufe0f B015 useless-comparison Pointless comparison. Did you mean to assign a value? Otherwise, prepend assert or remove it. \u2714\ufe0f \ud83d\udee0\ufe0f B016 raise-literal Cannot raise a literal. Did you intend to return it or raise an Exception? \u2714\ufe0f \ud83d\udee0\ufe0f B017 assert-raises-exception Do not assert blind exception: {exception} \u2714\ufe0f \ud83d\udee0\ufe0f B018 useless-expression Found useless expression. Either assign it to a variable or remove it. \u2714\ufe0f \ud83d\udee0\ufe0f B019 cached-instance-method Use of functools.lru_cache or functools.cache on methods can lead to memory leaks \u2714\ufe0f \ud83d\udee0\ufe0f B020 loop-variable-overrides-iterator Loop control variable {name} overrides iterable it iterates \u2714\ufe0f \ud83d\udee0\ufe0f B021 f-string-docstring f-string used as docstring. Python will interpret this as a joined string, rather than a docstring. \u2714\ufe0f \ud83d\udee0\ufe0f B022 useless-contextlib-suppress No arguments passed to contextlib.suppress. No exceptions will be suppressed and therefore this context manager is redundant \u2714\ufe0f \ud83d\udee0\ufe0f B023 function-uses-loop-variable Function definition does not bind loop variable {name} \u2714\ufe0f \ud83d\udee0\ufe0f B024 abstract-base-class-without-abstract-method {name} is an abstract base class, but it has no abstract methods or properties \u2714\ufe0f \ud83d\udee0\ufe0f B025 duplicate-try-block-exception try-except* block with duplicate exception {name} \u2714\ufe0f \ud83d\udee0\ufe0f B026 star-arg-unpacking-after-keyword-arg Star-arg unpacking after a keyword argument is strongly discouraged \u2714\ufe0f \ud83d\udee0\ufe0f B027 empty-method-without-abstract-decorator {name} is an empty method in an abstract base class, but has no abstract decorator \u2714\ufe0f \ud83d\udee0\ufe0f B028 no-explicit-stacklevel No explicit stacklevel keyword argument found \u2714\ufe0f \ud83d\udee0\ufe0f B029 except-with-empty-tuple Using except* (): with an empty tuple does not catch anything; add exceptions to handle \u2714\ufe0f \ud83d\udee0\ufe0f B030 except-with-non-exception-classes except* handlers should only be exception classes or tuples of exception classes \u2714\ufe0f \ud83d\udee0\ufe0f B031 reuse-of-groupby-generator Using the generator returned from itertools.groupby() more than once will do nothing on the second usage \u2714\ufe0f \ud83d\udee0\ufe0f B032 unintentional-type-annotation Possible unintentional type annotation (using :). Did you mean to assign (using =)? \u2714\ufe0f \ud83d\udee0\ufe0f B033 duplicate-value Sets should not contain duplicate item {value} \u2714\ufe0f \ud83d\udee0\ufe0f B034 re-sub-positional-args {method} should pass {param_name} and flags as keyword arguments to avoid confusion due to unintuitive argument positions \u2714\ufe0f \ud83d\udee0\ufe0f B035 static-key-dict-comprehension Dictionary comprehension uses static key: {key} \u2714\ufe0f \ud83d\udee0\ufe0f B039 mutable-contextvar-default Do not use mutable data structures for ContextVar defaults \u2714\ufe0f \ud83d\udee0\ufe0f B901 return-in-generator Using yield and return {value} in a generator function can lead to confusing behavior \ud83e\uddea \ud83d\udee0\ufe0f B903 class-as-data-structure Class could be dataclass or namedtuple \ud83e\uddea \ud83d\udee0\ufe0f B904 raise-without-from-inside-except Within an except* clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling \u2714\ufe0f \ud83d\udee0\ufe0f B905 zip-without-explicit-strict zip() without an explicit strict= parameter \u2714\ufe0f \ud83d\udee0\ufe0f B909 loop-iterator-mutation Mutation to loop iterable {name} during iteration \ud83e\uddea \ud83d\udee0\ufe0f B911 batched-without-explicit-strict itertools.batched() without an explicit strict parameter \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-builtins-a","title":"flake8-builtins (A)","text":"

        For more, see flake8-builtins on PyPI.

        For related settings, see flake8-builtins.

        Code Name Message A001 builtin-variable-shadowing Variable {name} is shadowing a Python builtin \u2714\ufe0f \ud83d\udee0\ufe0f A002 builtin-argument-shadowing Function argument {name} is shadowing a Python builtin \u2714\ufe0f \ud83d\udee0\ufe0f A003 builtin-attribute-shadowing Python builtin is shadowed by class attribute {name} from {row} \u2714\ufe0f \ud83d\udee0\ufe0f A004 builtin-import-shadowing Import {name} is shadowing a Python builtin \u2714\ufe0f \ud83d\udee0\ufe0f A005 stdlib-module-shadowing Module {name} shadows a Python standard-library module \u2714\ufe0f \ud83d\udee0\ufe0f A006 builtin-lambda-argument-shadowing Lambda argument {name} is shadowing a Python builtin \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-commas-com","title":"flake8-commas (COM)","text":"

        For more, see flake8-commas on PyPI.

        Code Name Message COM812 missing-trailing-comma Trailing comma missing \u2714\ufe0f \ud83d\udee0\ufe0f COM818 trailing-comma-on-bare-tuple Trailing comma on bare tuple prohibited \u2714\ufe0f \ud83d\udee0\ufe0f COM819 prohibited-trailing-comma Trailing comma prohibited \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-comprehensions-c4","title":"flake8-comprehensions (C4)","text":"

        For more, see flake8-comprehensions on PyPI.

        For related settings, see flake8-comprehensions.

        Code Name Message C400 unnecessary-generator-list Unnecessary generator (rewrite using list()) \u2714\ufe0f \ud83d\udee0\ufe0f C401 unnecessary-generator-set Unnecessary generator (rewrite using set()) \u2714\ufe0f \ud83d\udee0\ufe0f C402 unnecessary-generator-dict Unnecessary generator (rewrite as a dict comprehension) \u2714\ufe0f \ud83d\udee0\ufe0f C403 unnecessary-list-comprehension-set Unnecessary list comprehension (rewrite as a set comprehension) \u2714\ufe0f \ud83d\udee0\ufe0f C404 unnecessary-list-comprehension-dict Unnecessary list comprehension (rewrite as a dict comprehension) \u2714\ufe0f \ud83d\udee0\ufe0f C405 unnecessary-literal-set Unnecessary {kind} literal (rewrite as a set literal) \u2714\ufe0f \ud83d\udee0\ufe0f C406 unnecessary-literal-dict Unnecessary {obj_type} literal (rewrite as a dict literal) \u2714\ufe0f \ud83d\udee0\ufe0f C408 unnecessary-collection-call Unnecessary {kind}() call (rewrite as a literal) \u2714\ufe0f \ud83d\udee0\ufe0f C409 unnecessary-literal-within-tuple-call Unnecessary list literal passed to tuple() (rewrite as a tuple literal) \u2714\ufe0f \ud83d\udee0\ufe0f C410 unnecessary-literal-within-list-call Unnecessary list literal passed to list() (remove the outer call to list()) \u2714\ufe0f \ud83d\udee0\ufe0f C411 unnecessary-list-call Unnecessary list() call (remove the outer call to list()) \u2714\ufe0f \ud83d\udee0\ufe0f C413 unnecessary-call-around-sorted Unnecessary {func}() call around sorted() \u2714\ufe0f \ud83d\udee0\ufe0f C414 unnecessary-double-cast-or-process Unnecessary {inner}() call within {outer}() \u2714\ufe0f \ud83d\udee0\ufe0f C415 unnecessary-subscript-reversal Unnecessary subscript reversal of iterable within {func}() \u2714\ufe0f \ud83d\udee0\ufe0f C416 unnecessary-comprehension Unnecessary {kind} comprehension (rewrite using {kind}()) \u2714\ufe0f \ud83d\udee0\ufe0f C417 unnecessary-map Unnecessary map() usage (rewrite using a {object_type}) \u2714\ufe0f \ud83d\udee0\ufe0f C418 unnecessary-literal-within-dict-call Unnecessary dict {kind} passed to dict() (remove the outer call to dict()) \u2714\ufe0f \ud83d\udee0\ufe0f C419 unnecessary-comprehension-in-call Unnecessary list comprehension \u2714\ufe0f \ud83d\udee0\ufe0f C420 unnecessary-dict-comprehension-for-iterable Unnecessary dict comprehension for iterable; use dict.fromkeys instead \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-copyright-cpy","title":"flake8-copyright (CPY)","text":"

        For more, see flake8-copyright on PyPI.

        For related settings, see flake8-copyright.

        Code Name Message CPY001 missing-copyright-notice Missing copyright notice at top of file \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-datetimez-dtz","title":"flake8-datetimez (DTZ)","text":"

        For more, see flake8-datetimez on PyPI.

        Code Name Message DTZ001 call-datetime-without-tzinfo datetime.datetime() called without a tzinfo argument \u2714\ufe0f \ud83d\udee0\ufe0f DTZ002 call-datetime-today datetime.datetime.today() used \u2714\ufe0f \ud83d\udee0\ufe0f DTZ003 call-datetime-utcnow datetime.datetime.utcnow() used \u2714\ufe0f \ud83d\udee0\ufe0f DTZ004 call-datetime-utcfromtimestamp datetime.datetime.utcfromtimestamp() used \u2714\ufe0f \ud83d\udee0\ufe0f DTZ005 call-datetime-now-without-tzinfo datetime.datetime.now() called without a tz argument \u2714\ufe0f \ud83d\udee0\ufe0f DTZ006 call-datetime-fromtimestamp datetime.datetime.fromtimestamp() called without a tz argument \u2714\ufe0f \ud83d\udee0\ufe0f DTZ007 call-datetime-strptime-without-zone Naive datetime constructed using datetime.datetime.strptime() without %z \u2714\ufe0f \ud83d\udee0\ufe0f DTZ011 call-date-today datetime.date.today() used \u2714\ufe0f \ud83d\udee0\ufe0f DTZ012 call-date-fromtimestamp datetime.date.fromtimestamp() used \u2714\ufe0f \ud83d\udee0\ufe0f DTZ901 datetime-min-max Use of datetime.datetime.{min_max} without timezone information \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-debugger-t10","title":"flake8-debugger (T10)","text":"

        For more, see flake8-debugger on PyPI.

        Code Name Message T100 debugger Trace found: {name} used \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-django-dj","title":"flake8-django (DJ)","text":"

        For more, see flake8-django on PyPI.

        Code Name Message DJ001 django-nullable-model-string-field Avoid using null=True on string-based fields such as {field_name} \u2714\ufe0f \ud83d\udee0\ufe0f DJ003 django-locals-in-render-function Avoid passing locals() as context to a render function \u2714\ufe0f \ud83d\udee0\ufe0f DJ006 django-exclude-with-model-form Do not use exclude with ModelForm, use fields instead \u2714\ufe0f \ud83d\udee0\ufe0f DJ007 django-all-with-model-form Do not use __all__ with ModelForm, use fields instead \u2714\ufe0f \ud83d\udee0\ufe0f DJ008 django-model-without-dunder-str Model does not define __str__ method \u2714\ufe0f \ud83d\udee0\ufe0f DJ012 django-unordered-body-content-in-model Order of model's inner classes, methods, and fields does not follow the Django Style Guide: {element_type} should come before {prev_element_type} \u2714\ufe0f \ud83d\udee0\ufe0f DJ013 django-non-leading-receiver-decorator @receiver decorator must be on top of all the other decorators \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-errmsg-em","title":"flake8-errmsg (EM)","text":"

        For more, see flake8-errmsg on PyPI.

        For related settings, see flake8-errmsg.

        Code Name Message EM101 raw-string-in-exception Exception must not use a string literal, assign to variable first \u2714\ufe0f \ud83d\udee0\ufe0f EM102 f-string-in-exception Exception must not use an f-string literal, assign to variable first \u2714\ufe0f \ud83d\udee0\ufe0f EM103 dot-format-in-exception Exception must not use a .format() string directly, assign to variable first \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-executable-exe","title":"flake8-executable (EXE)","text":"

        For more, see flake8-executable on PyPI.

        Code Name Message EXE001 shebang-not-executable Shebang is present but file is not executable \u2714\ufe0f \ud83d\udee0\ufe0f EXE002 shebang-missing-executable-file The file is executable but no shebang is present \u2714\ufe0f \ud83d\udee0\ufe0f EXE003 shebang-missing-python Shebang should contain python, pytest, or uv run \u2714\ufe0f \ud83d\udee0\ufe0f EXE004 shebang-leading-whitespace Avoid whitespace before shebang \u2714\ufe0f \ud83d\udee0\ufe0f EXE005 shebang-not-first-line Shebang should be at the beginning of the file \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-fixme-fix","title":"flake8-fixme (FIX)","text":"

        For more, see flake8-fixme on GitHub.

        Code Name Message FIX001 line-contains-fixme Line contains FIXME, consider resolving the issue \u2714\ufe0f \ud83d\udee0\ufe0f FIX002 line-contains-todo Line contains TODO, consider resolving the issue \u2714\ufe0f \ud83d\udee0\ufe0f FIX003 line-contains-xxx Line contains XXX, consider resolving the issue \u2714\ufe0f \ud83d\udee0\ufe0f FIX004 line-contains-hack Line contains HACK, consider resolving the issue \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-future-annotations-fa","title":"flake8-future-annotations (FA)","text":"

        For more, see flake8-future-annotations on PyPI.

        Code Name Message FA100 future-rewritable-type-annotation Add from __future__ import annotations to simplify {name} \u2714\ufe0f \ud83d\udee0\ufe0f FA102 future-required-type-annotation Missing from __future__ import annotations, but uses {reason} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-gettext-int","title":"flake8-gettext (INT)","text":"

        For more, see flake8-gettext on PyPI.

        For related settings, see flake8-gettext.

        Code Name Message INT001 f-string-in-get-text-func-call f-string is resolved before function call; consider _(\"string %s\") % arg \u2714\ufe0f \ud83d\udee0\ufe0f INT002 format-in-get-text-func-call format method argument is resolved before function call; consider _(\"string %s\") % arg \u2714\ufe0f \ud83d\udee0\ufe0f INT003 printf-in-get-text-func-call printf-style format is resolved before function call; consider _(\"string %s\") % arg \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-implicit-str-concat-isc","title":"flake8-implicit-str-concat (ISC)","text":"

        For more, see flake8-implicit-str-concat on PyPI.

        For related settings, see flake8-implicit-str-concat.

        Code Name Message ISC001 single-line-implicit-string-concatenation Implicitly concatenated string literals on one line \u2714\ufe0f \ud83d\udee0\ufe0f ISC002 multi-line-implicit-string-concatenation Implicitly concatenated string literals over multiple lines \u2714\ufe0f \ud83d\udee0\ufe0f ISC003 explicit-string-concatenation Explicitly concatenated string should be implicitly concatenated \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-import-conventions-icn","title":"flake8-import-conventions (ICN)","text":"

        For more, see flake8-import-conventions on GitHub.

        For related settings, see flake8-import-conventions.

        Code Name Message ICN001 unconventional-import-alias {name} should be imported as {asname} \u2714\ufe0f \ud83d\udee0\ufe0f ICN002 banned-import-alias {name} should not be imported as {asname} \u2714\ufe0f \ud83d\udee0\ufe0f ICN003 banned-import-from Members of {name} should not be imported explicitly \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-logging-log","title":"flake8-logging (LOG)","text":"

        For more, see flake8-logging on PyPI.

        Code Name Message LOG001 direct-logger-instantiation Use logging.getLogger() to instantiate loggers \u2714\ufe0f \ud83d\udee0\ufe0f LOG002 invalid-get-logger-argument Use __name__ with logging.getLogger() \u2714\ufe0f \ud83d\udee0\ufe0f LOG004 log-exception-outside-except-handler .exception() call outside exception handlers \ud83e\uddea \ud83d\udee0\ufe0f LOG007 exception-without-exc-info Use of logging.exception with falsy exc_info \u2714\ufe0f \ud83d\udee0\ufe0f LOG009 undocumented-warn Use of undocumented logging.WARN constant \u2714\ufe0f \ud83d\udee0\ufe0f LOG014 exc-info-outside-except-handler exc_info= outside exception handlers \ud83e\uddea \ud83d\udee0\ufe0f LOG015 root-logger-call {}() call on root logger \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-logging-format-g","title":"flake8-logging-format (G)","text":"

        For more, see flake8-logging-format on PyPI.

        Code Name Message G001 logging-string-format Logging statement uses str.format \u2714\ufe0f \ud83d\udee0\ufe0f G002 logging-percent-format Logging statement uses % \u2714\ufe0f \ud83d\udee0\ufe0f G003 logging-string-concat Logging statement uses + \u2714\ufe0f \ud83d\udee0\ufe0f G004 logging-f-string Logging statement uses f-string \u2714\ufe0f \ud83d\udee0\ufe0f G010 logging-warn Logging statement uses warn instead of warning \u2714\ufe0f \ud83d\udee0\ufe0f G101 logging-extra-attr-clash Logging statement uses an extra field that clashes with a LogRecord field: {key} \u2714\ufe0f \ud83d\udee0\ufe0f G201 logging-exc-info Logging .exception(...) should be used instead of .error(..., exc_info=True) \u2714\ufe0f \ud83d\udee0\ufe0f G202 logging-redundant-exc-info Logging statement has redundant exc_info \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-no-pep420-inp","title":"flake8-no-pep420 (INP)","text":"

        For more, see flake8-no-pep420 on PyPI.

        Code Name Message INP001 implicit-namespace-package File {filename} is part of an implicit namespace package. Add an __init__.py. \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-pie-pie","title":"flake8-pie (PIE)","text":"

        For more, see flake8-pie on PyPI.

        Code Name Message PIE790 unnecessary-placeholder Unnecessary pass statement \u2714\ufe0f \ud83d\udee0\ufe0f PIE794 duplicate-class-field-definition Class field {name} is defined multiple times \u2714\ufe0f \ud83d\udee0\ufe0f PIE796 non-unique-enums Enum contains duplicate value: {value} \u2714\ufe0f \ud83d\udee0\ufe0f PIE800 unnecessary-spread Unnecessary spread ** \u2714\ufe0f \ud83d\udee0\ufe0f PIE804 unnecessary-dict-kwargs Unnecessary dict kwargs \u2714\ufe0f \ud83d\udee0\ufe0f PIE807 reimplemented-container-builtin Prefer {container} over useless lambda \u2714\ufe0f \ud83d\udee0\ufe0f PIE808 unnecessary-range-start Unnecessary start argument in range \u2714\ufe0f \ud83d\udee0\ufe0f PIE810 multiple-starts-ends-with Call {attr} once with a tuple \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-print-t20","title":"flake8-print (T20)","text":"

        For more, see flake8-print on PyPI.

        Code Name Message T201 print print found \u2714\ufe0f \ud83d\udee0\ufe0f T203 p-print pprint found \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-pyi-pyi","title":"flake8-pyi (PYI)","text":"

        For more, see flake8-pyi on PyPI.

        Code Name Message PYI001 unprefixed-type-param Name of private {kind} must start with _ \u2714\ufe0f \ud83d\udee0\ufe0f PYI002 complex-if-statement-in-stub if test must be a simple comparison against sys.platform or sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f PYI003 unrecognized-version-info-check Unrecognized sys.version_info check \u2714\ufe0f \ud83d\udee0\ufe0f PYI004 patch-version-comparison Version comparison must use only major and minor version \u2714\ufe0f \ud83d\udee0\ufe0f PYI005 wrong-tuple-length-version-comparison Version comparison must be against a length-{expected_length} tuple \u2714\ufe0f \ud83d\udee0\ufe0f PYI006 bad-version-info-comparison Use < or >= for sys.version_info comparisons \u2714\ufe0f \ud83d\udee0\ufe0f PYI007 unrecognized-platform-check Unrecognized sys.platform check \u2714\ufe0f \ud83d\udee0\ufe0f PYI008 unrecognized-platform-name Unrecognized platform {platform} \u2714\ufe0f \ud83d\udee0\ufe0f PYI009 pass-statement-stub-body Empty body should contain ..., not pass \u2714\ufe0f \ud83d\udee0\ufe0f PYI010 non-empty-stub-body Function body must contain only ... \u2714\ufe0f \ud83d\udee0\ufe0f PYI011 typed-argument-default-in-stub Only simple default values allowed for typed arguments \u2714\ufe0f \ud83d\udee0\ufe0f PYI012 pass-in-class-body Class body must not contain pass \u2714\ufe0f \ud83d\udee0\ufe0f PYI013 ellipsis-in-non-empty-class-body Non-empty class body must not contain ... \u2714\ufe0f \ud83d\udee0\ufe0f PYI014 argument-default-in-stub Only simple default values allowed for arguments \u2714\ufe0f \ud83d\udee0\ufe0f PYI015 assignment-default-in-stub Only simple default values allowed for assignments \u2714\ufe0f \ud83d\udee0\ufe0f PYI016 duplicate-union-member Duplicate union member {} \u2714\ufe0f \ud83d\udee0\ufe0f PYI017 complex-assignment-in-stub Stubs should not contain assignments to attributes or multiple targets \u2714\ufe0f \ud83d\udee0\ufe0f PYI018 unused-private-type-var Private {type_var_like_kind} {type_var_like_name} is never used \u2714\ufe0f \ud83d\udee0\ufe0f PYI019 custom-type-var-for-self Use Self instead of custom TypeVar {} \u2714\ufe0f \ud83d\udee0\ufe0f PYI020 quoted-annotation-in-stub Quoted annotations should not be included in stubs \u2714\ufe0f \ud83d\udee0\ufe0f PYI021 docstring-in-stub Docstrings should not be included in stubs \u2714\ufe0f \ud83d\udee0\ufe0f PYI024 collections-named-tuple Use typing.NamedTuple instead of collections.namedtuple \u2714\ufe0f \ud83d\udee0\ufe0f PYI025 unaliased-collections-abc-set-import Use from collections.abc import Set as AbstractSet to avoid confusion with the set builtin \u2714\ufe0f \ud83d\udee0\ufe0f PYI026 type-alias-without-annotation Use {module}.TypeAlias for type alias, e.g., {name}: TypeAlias = {value} \u2714\ufe0f \ud83d\udee0\ufe0f PYI029 str-or-repr-defined-in-stub Defining {name} in a stub is almost always redundant \u2714\ufe0f \ud83d\udee0\ufe0f PYI030 unnecessary-literal-union Multiple literal members in a union. Use a single literal, e.g. Literal[{}] \u2714\ufe0f \ud83d\udee0\ufe0f PYI032 any-eq-ne-annotation Prefer object to Any for the second parameter to {method_name} \u2714\ufe0f \ud83d\udee0\ufe0f PYI033 type-comment-in-stub Don't use type comments in stub file \u2714\ufe0f \ud83d\udee0\ufe0f PYI034 non-self-return-type __new__ methods usually return self at runtime \u2714\ufe0f \ud83d\udee0\ufe0f PYI035 unassigned-special-variable-in-stub {name} in a stub file must have a value, as it has the same semantics as {name} at runtime \u2714\ufe0f \ud83d\udee0\ufe0f PYI036 bad-exit-annotation Star-args in {method_name} should be annotated with object \u2714\ufe0f \ud83d\udee0\ufe0f PYI041 redundant-numeric-union Use {supertype} instead of {subtype} | {supertype} \u2714\ufe0f \ud83d\udee0\ufe0f PYI042 snake-case-type-alias Type alias {name} should be CamelCase \u2714\ufe0f \ud83d\udee0\ufe0f PYI043 t-suffixed-type-alias Private type alias {name} should not be suffixed with T (the T suffix implies that an object is a TypeVar) \u2714\ufe0f \ud83d\udee0\ufe0f PYI044 future-annotations-in-stub from __future__ import annotations has no effect in stub files, since type checkers automatically treat stubs as having those semantics \u2714\ufe0f \ud83d\udee0\ufe0f PYI045 iter-method-return-iterable __aiter__ methods should return an AsyncIterator, not an AsyncIterable \u2714\ufe0f \ud83d\udee0\ufe0f PYI046 unused-private-protocol Private protocol {name} is never used \u2714\ufe0f \ud83d\udee0\ufe0f PYI047 unused-private-type-alias Private TypeAlias {name} is never used \u2714\ufe0f \ud83d\udee0\ufe0f PYI048 stub-body-multiple-statements Function body must contain exactly one statement \u2714\ufe0f \ud83d\udee0\ufe0f PYI049 unused-private-typed-dict Private TypedDict {name} is never used \u2714\ufe0f \ud83d\udee0\ufe0f PYI050 no-return-argument-annotation-in-stub Prefer {module}.Never over NoReturn for argument annotations \u2714\ufe0f \ud83d\udee0\ufe0f PYI051 redundant-literal-union Literal[{literal}] is redundant in a union with {builtin_type} \u2714\ufe0f \ud83d\udee0\ufe0f PYI052 unannotated-assignment-in-stub Need type annotation for {name} \u2714\ufe0f \ud83d\udee0\ufe0f PYI053 string-or-bytes-too-long String and bytes literals longer than 50 characters are not permitted \u2714\ufe0f \ud83d\udee0\ufe0f PYI054 numeric-literal-too-long Numeric literals with a string representation longer than ten characters are not permitted \u2714\ufe0f \ud83d\udee0\ufe0f PYI055 unnecessary-type-union Multiple type members in a union. Combine them into one, e.g., type[{union_str}]. \u2714\ufe0f \ud83d\udee0\ufe0f PYI056 unsupported-method-call-on-all Calling .{name}() on __all__ may not be supported by all type checkers (use += instead) \u2714\ufe0f \ud83d\udee0\ufe0f PYI057 byte-string-usage Do not use {origin}.ByteString, which has unclear semantics and is deprecated \u2714\ufe0f \ud83d\udee0\ufe0f PYI058 generator-return-from-iter-method Use {return_type} as the return value for simple {method} methods \u2714\ufe0f \ud83d\udee0\ufe0f PYI059 generic-not-last-base-class Generic[] should always be the last base class \ud83e\uddea \ud83d\udee0\ufe0f PYI061 redundant-none-literal Use None rather than Literal[None] \ud83e\uddea \ud83d\udee0\ufe0f PYI062 duplicate-literal-member Duplicate literal member {} \u2714\ufe0f \ud83d\udee0\ufe0f PYI063 pep484-style-positional-only-parameter Use PEP 570 syntax for positional-only parameters \u2714\ufe0f \ud83d\udee0\ufe0f PYI064 redundant-final-literal Final[Literal[{literal}]] can be replaced with a bare Final \u2714\ufe0f \ud83d\udee0\ufe0f PYI066 bad-version-info-order Put branches for newer Python versions first when branching on sys.version_info comparisons \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-pytest-style-pt","title":"flake8-pytest-style (PT)","text":"

        For more, see flake8-pytest-style on PyPI.

        For related settings, see flake8-pytest-style.

        Code Name Message PT001 pytest-fixture-incorrect-parentheses-style Use @pytest.fixture{expected} over @pytest.fixture{actual} \u2714\ufe0f \ud83d\udee0\ufe0f PT002 pytest-fixture-positional-args Configuration for fixture {function} specified via positional args, use kwargs \u2714\ufe0f \ud83d\udee0\ufe0f PT003 pytest-extraneous-scope-function scope='function' is implied in @pytest.fixture() \u2714\ufe0f \ud83d\udee0\ufe0f PT004 pytest-missing-fixture-name-underscore Fixture {function} does not return anything, add leading underscore \u274c \ud83d\udee0\ufe0f PT005 pytest-incorrect-fixture-name-underscore Fixture {function} returns a value, remove leading underscore \u274c \ud83d\udee0\ufe0f PT006 pytest-parametrize-names-wrong-type Wrong type passed to first argument of pytest.mark.parametrize; expected {expected_string} \u2714\ufe0f \ud83d\udee0\ufe0f PT007 pytest-parametrize-values-wrong-type Wrong values type in pytest.mark.parametrize expected {values} of {row} \u2714\ufe0f \ud83d\udee0\ufe0f PT008 pytest-patch-with-lambda Use return_value= instead of patching with lambda \u2714\ufe0f \ud83d\udee0\ufe0f PT009 pytest-unittest-assertion Use a regular assert instead of unittest-style {assertion} \u2714\ufe0f \ud83d\udee0\ufe0f PT010 pytest-raises-without-exception Set the expected exception in pytest.raises() \u2714\ufe0f \ud83d\udee0\ufe0f PT011 pytest-raises-too-broad pytest.raises({exception}) is too broad, set the match parameter or use a more specific exception \u2714\ufe0f \ud83d\udee0\ufe0f PT012 pytest-raises-with-multiple-statements pytest.raises() block should contain a single simple statement \u2714\ufe0f \ud83d\udee0\ufe0f PT013 pytest-incorrect-pytest-import Incorrect import of pytest; use import pytest instead \u2714\ufe0f \ud83d\udee0\ufe0f PT014 pytest-duplicate-parametrize-test-cases Duplicate of test case at index {index} in pytest.mark.parametrize \u2714\ufe0f \ud83d\udee0\ufe0f PT015 pytest-assert-always-false Assertion always fails, replace with pytest.fail() \u2714\ufe0f \ud83d\udee0\ufe0f PT016 pytest-fail-without-message No message passed to pytest.fail() \u2714\ufe0f \ud83d\udee0\ufe0f PT017 pytest-assert-in-except Found assertion on exception {name} in except block, use pytest.raises() instead \u2714\ufe0f \ud83d\udee0\ufe0f PT018 pytest-composite-assertion Assertion should be broken down into multiple parts \u2714\ufe0f \ud83d\udee0\ufe0f PT019 pytest-fixture-param-without-value Fixture {name} without value is injected as parameter, use @pytest.mark.usefixtures instead \u2714\ufe0f \ud83d\udee0\ufe0f PT020 pytest-deprecated-yield-fixture @pytest.yield_fixture is deprecated, use @pytest.fixture \u2714\ufe0f \ud83d\udee0\ufe0f PT021 pytest-fixture-finalizer-callback Use yield instead of request.addfinalizer \u2714\ufe0f \ud83d\udee0\ufe0f PT022 pytest-useless-yield-fixture No teardown in fixture {name}, use return instead of yield \u2714\ufe0f \ud83d\udee0\ufe0f PT023 pytest-incorrect-mark-parentheses-style Use @pytest.mark.{mark_name}{expected_parens} over @pytest.mark.{mark_name}{actual_parens} \u2714\ufe0f \ud83d\udee0\ufe0f PT024 pytest-unnecessary-asyncio-mark-on-fixture pytest.mark.asyncio is unnecessary for fixtures \u2714\ufe0f \ud83d\udee0\ufe0f PT025 pytest-erroneous-use-fixtures-on-fixture pytest.mark.usefixtures has no effect on fixtures \u2714\ufe0f \ud83d\udee0\ufe0f PT026 pytest-use-fixtures-without-parameters Useless pytest.mark.usefixtures without parameters \u2714\ufe0f \ud83d\udee0\ufe0f PT027 pytest-unittest-raises-assertion Use pytest.raises instead of unittest-style {assertion} \u2714\ufe0f \ud83d\udee0\ufe0f PT028 pytest-parameter-with-default-argument Test function parameter {} has default argument \ud83e\uddea \ud83d\udee0\ufe0f PT029 pytest-warns-without-warning Set the expected warning in pytest.warns() \ud83e\uddea \ud83d\udee0\ufe0f PT030 pytest-warns-too-broad pytest.warns({warning}) is too broad, set the match parameter or use a more specific warning \ud83e\uddea \ud83d\udee0\ufe0f PT031 pytest-warns-with-multiple-statements pytest.warns() block should contain a single simple statement \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-quotes-q","title":"flake8-quotes (Q)","text":"

        For more, see flake8-quotes on PyPI.

        For related settings, see flake8-quotes.

        Code Name Message Q000 bad-quotes-inline-string Single quotes found but double quotes preferred \u2714\ufe0f \ud83d\udee0\ufe0f Q001 bad-quotes-multiline-string Single quote multiline found but double quotes preferred \u2714\ufe0f \ud83d\udee0\ufe0f Q002 bad-quotes-docstring Single quote docstring found but double quotes preferred \u2714\ufe0f \ud83d\udee0\ufe0f Q003 avoidable-escaped-quote Change outer quotes to avoid escaping inner quotes \u2714\ufe0f \ud83d\udee0\ufe0f Q004 unnecessary-escaped-quote Unnecessary escape on inner quote character \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-raise-rse","title":"flake8-raise (RSE)","text":"

        For more, see flake8-raise on PyPI.

        Code Name Message RSE102 unnecessary-paren-on-raise-exception Unnecessary parentheses on raised exception \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-return-ret","title":"flake8-return (RET)","text":"

        For more, see flake8-return on PyPI.

        Code Name Message RET501 unnecessary-return-none Do not explicitly return None in function if it is the only possible return value \u2714\ufe0f \ud83d\udee0\ufe0f RET502 implicit-return-value Do not implicitly return None in function able to return non-None value \u2714\ufe0f \ud83d\udee0\ufe0f RET503 implicit-return Missing explicit return at the end of function able to return non-None value \u2714\ufe0f \ud83d\udee0\ufe0f RET504 unnecessary-assign Unnecessary assignment to {name} before return statement \u2714\ufe0f \ud83d\udee0\ufe0f RET505 superfluous-else-return Unnecessary {branch} after return statement \u2714\ufe0f \ud83d\udee0\ufe0f RET506 superfluous-else-raise Unnecessary {branch} after raise statement \u2714\ufe0f \ud83d\udee0\ufe0f RET507 superfluous-else-continue Unnecessary {branch} after continue statement \u2714\ufe0f \ud83d\udee0\ufe0f RET508 superfluous-else-break Unnecessary {branch} after break statement \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-self-slf","title":"flake8-self (SLF)","text":"

        For more, see flake8-self on PyPI.

        For related settings, see flake8-self.

        Code Name Message SLF001 private-member-access Private member accessed: {access} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-simplify-sim","title":"flake8-simplify (SIM)","text":"

        For more, see flake8-simplify on PyPI.

        Code Name Message SIM101 duplicate-isinstance-call Multiple isinstance calls for {name}, merge into a single call \u2714\ufe0f \ud83d\udee0\ufe0f SIM102 collapsible-if Use a single if statement instead of nested if statements \u2714\ufe0f \ud83d\udee0\ufe0f SIM103 needless-bool Return the condition {condition} directly \u2714\ufe0f \ud83d\udee0\ufe0f SIM105 suppressible-exception Use contextlib.suppress({exception}) instead of try-except-pass \u2714\ufe0f \ud83d\udee0\ufe0f SIM107 return-in-try-except-finally Don't use return in try-except and finally \u2714\ufe0f \ud83d\udee0\ufe0f SIM108 if-else-block-instead-of-if-exp Use ternary operator {contents} instead of if-else-block \u2714\ufe0f \ud83d\udee0\ufe0f SIM109 compare-with-tuple Use {replacement} instead of multiple equality comparisons \u2714\ufe0f \ud83d\udee0\ufe0f SIM110 reimplemented-builtin Use {replacement} instead of for loop \u2714\ufe0f \ud83d\udee0\ufe0f SIM112 uncapitalized-environment-variables Use capitalized environment variable {expected} instead of {actual} \u2714\ufe0f \ud83d\udee0\ufe0f SIM113 enumerate-for-loop Use enumerate() for index variable {index} in for loop \u2714\ufe0f \ud83d\udee0\ufe0f SIM114 if-with-same-arms Combine if branches using logical or operator \u2714\ufe0f \ud83d\udee0\ufe0f SIM115 open-file-with-context-handler Use a context manager for opening files \u2714\ufe0f \ud83d\udee0\ufe0f SIM116 if-else-block-instead-of-dict-lookup Use a dictionary instead of consecutive if statements \u2714\ufe0f \ud83d\udee0\ufe0f SIM117 multiple-with-statements Use a single with statement with multiple contexts instead of nested with statements \u2714\ufe0f \ud83d\udee0\ufe0f SIM118 in-dict-keys Use key {operator} dict instead of key {operator} dict.keys() \u2714\ufe0f \ud83d\udee0\ufe0f SIM201 negate-equal-op Use {left} != {right} instead of not {left} == {right} \u2714\ufe0f \ud83d\udee0\ufe0f SIM202 negate-not-equal-op Use {left} == {right} instead of not {left} != {right} \u2714\ufe0f \ud83d\udee0\ufe0f SIM208 double-negation Use {expr} instead of not (not {expr}) \u2714\ufe0f \ud83d\udee0\ufe0f SIM210 if-expr-with-true-false Remove unnecessary True if ... else False \u2714\ufe0f \ud83d\udee0\ufe0f SIM211 if-expr-with-false-true Use not ... instead of False if ... else True \u2714\ufe0f \ud83d\udee0\ufe0f SIM212 if-expr-with-twisted-arms Use {expr_else} if {expr_else} else {expr_body} instead of {expr_body} if not {expr_else} else {expr_else} \u2714\ufe0f \ud83d\udee0\ufe0f SIM220 expr-and-not-expr Use False instead of {name} and not {name} \u2714\ufe0f \ud83d\udee0\ufe0f SIM221 expr-or-not-expr Use True instead of {name} or not {name} \u2714\ufe0f \ud83d\udee0\ufe0f SIM222 expr-or-true Use {expr} instead of {replaced} \u2714\ufe0f \ud83d\udee0\ufe0f SIM223 expr-and-false Use {expr} instead of {replaced} \u2714\ufe0f \ud83d\udee0\ufe0f SIM300 yoda-conditions Yoda condition detected \u2714\ufe0f \ud83d\udee0\ufe0f SIM401 if-else-block-instead-of-dict-get Use {contents} instead of an if block \u2714\ufe0f \ud83d\udee0\ufe0f SIM905 split-static-string Consider using a list literal instead of str.split \u2714\ufe0f \ud83d\udee0\ufe0f SIM910 dict-get-with-none-default Use {expected} instead of {actual} \u2714\ufe0f \ud83d\udee0\ufe0f SIM911 zip-dict-keys-and-values Use {expected} instead of {actual} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-slots-slot","title":"flake8-slots (SLOT)","text":"

        For more, see flake8-slots on PyPI.

        Code Name Message SLOT000 no-slots-in-str-subclass Subclasses of str should define __slots__ \u2714\ufe0f \ud83d\udee0\ufe0f SLOT001 no-slots-in-tuple-subclass Subclasses of tuple should define __slots__ \u2714\ufe0f \ud83d\udee0\ufe0f SLOT002 no-slots-in-namedtuple-subclass Subclasses of {namedtuple_kind} should define __slots__ \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-tidy-imports-tid","title":"flake8-tidy-imports (TID)","text":"

        For more, see flake8-tidy-imports on PyPI.

        For related settings, see flake8-tidy-imports.

        Code Name Message TID251 banned-api {name} is banned: {message} \u2714\ufe0f \ud83d\udee0\ufe0f TID252 relative-imports Prefer absolute imports over relative imports from parent modules \u2714\ufe0f \ud83d\udee0\ufe0f TID253 banned-module-level-imports {name} is banned at the module level \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-todos-td","title":"flake8-todos (TD)","text":"

        For more, see flake8-todos on GitHub.

        Code Name Message TD001 invalid-todo-tag Invalid TODO tag: {tag} \u2714\ufe0f \ud83d\udee0\ufe0f TD002 missing-todo-author Missing author in TODO; try: # TODO(<author_name>): ... or # TODO @<author_name>: ... \u2714\ufe0f \ud83d\udee0\ufe0f TD003 missing-todo-link Missing issue link for this TODO \u2714\ufe0f \ud83d\udee0\ufe0f TD004 missing-todo-colon Missing colon in TODO \u2714\ufe0f \ud83d\udee0\ufe0f TD005 missing-todo-description Missing issue description after TODO \u2714\ufe0f \ud83d\udee0\ufe0f TD006 invalid-todo-capitalization Invalid TODO capitalization: {tag} should be TODO \u2714\ufe0f \ud83d\udee0\ufe0f TD007 missing-space-after-todo-colon Missing space after colon in TODO \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-type-checking-tc","title":"flake8-type-checking (TC)","text":"

        For more, see flake8-type-checking on PyPI.

        For related settings, see flake8-type-checking.

        Code Name Message TC001 typing-only-first-party-import Move application import {} into a type-checking block \u2714\ufe0f \ud83d\udee0\ufe0f TC002 typing-only-third-party-import Move third-party import {} into a type-checking block \u2714\ufe0f \ud83d\udee0\ufe0f TC003 typing-only-standard-library-import Move standard library import {} into a type-checking block \u2714\ufe0f \ud83d\udee0\ufe0f TC004 runtime-import-in-type-checking-block Move import {qualified_name} out of type-checking block. Import is used for more than type hinting. \u2714\ufe0f \ud83d\udee0\ufe0f TC005 empty-type-checking-block Found empty type-checking block \u2714\ufe0f \ud83d\udee0\ufe0f TC006 runtime-cast-value Add quotes to type expression in typing.cast() \u2714\ufe0f \ud83d\udee0\ufe0f TC007 unquoted-type-alias Add quotes to type alias \u2714\ufe0f \ud83d\udee0\ufe0f TC008 quoted-type-alias Remove quotes from type alias \ud83e\uddea \ud83d\udee0\ufe0f TC010 runtime-string-union Invalid string member in X | Y-style union type \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-unused-arguments-arg","title":"flake8-unused-arguments (ARG)","text":"

        For more, see flake8-unused-arguments on PyPI.

        For related settings, see flake8-unused-arguments.

        Code Name Message ARG001 unused-function-argument Unused function argument: {name} \u2714\ufe0f \ud83d\udee0\ufe0f ARG002 unused-method-argument Unused method argument: {name} \u2714\ufe0f \ud83d\udee0\ufe0f ARG003 unused-class-method-argument Unused class method argument: {name} \u2714\ufe0f \ud83d\udee0\ufe0f ARG004 unused-static-method-argument Unused static method argument: {name} \u2714\ufe0f \ud83d\udee0\ufe0f ARG005 unused-lambda-argument Unused lambda argument: {name} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-use-pathlib-pth","title":"flake8-use-pathlib (PTH)","text":"

        For more, see flake8-use-pathlib on PyPI.

        Code Name Message PTH100 os-path-abspath os.path.abspath() should be replaced by Path.resolve() \u2714\ufe0f \ud83d\udee0\ufe0f PTH101 os-chmod os.chmod() should be replaced by Path.chmod() \u2714\ufe0f \ud83d\udee0\ufe0f PTH102 os-mkdir os.mkdir() should be replaced by Path.mkdir() \u2714\ufe0f \ud83d\udee0\ufe0f PTH103 os-makedirs os.makedirs() should be replaced by Path.mkdir(parents=True) \u2714\ufe0f \ud83d\udee0\ufe0f PTH104 os-rename os.rename() should be replaced by Path.rename() \u2714\ufe0f \ud83d\udee0\ufe0f PTH105 os-replace os.replace() should be replaced by Path.replace() \u2714\ufe0f \ud83d\udee0\ufe0f PTH106 os-rmdir os.rmdir() should be replaced by Path.rmdir() \u2714\ufe0f \ud83d\udee0\ufe0f PTH107 os-remove os.remove() should be replaced by Path.unlink() \u2714\ufe0f \ud83d\udee0\ufe0f PTH108 os-unlink os.unlink() should be replaced by Path.unlink() \u2714\ufe0f \ud83d\udee0\ufe0f PTH109 os-getcwd os.getcwd() should be replaced by Path.cwd() \u2714\ufe0f \ud83d\udee0\ufe0f PTH110 os-path-exists os.path.exists() should be replaced by Path.exists() \u2714\ufe0f \ud83d\udee0\ufe0f PTH111 os-path-expanduser os.path.expanduser() should be replaced by Path.expanduser() \u2714\ufe0f \ud83d\udee0\ufe0f PTH112 os-path-isdir os.path.isdir() should be replaced by Path.is_dir() \u2714\ufe0f \ud83d\udee0\ufe0f PTH113 os-path-isfile os.path.isfile() should be replaced by Path.is_file() \u2714\ufe0f \ud83d\udee0\ufe0f PTH114 os-path-islink os.path.islink() should be replaced by Path.is_symlink() \u2714\ufe0f \ud83d\udee0\ufe0f PTH115 os-readlink os.readlink() should be replaced by Path.readlink() \u2714\ufe0f \ud83d\udee0\ufe0f PTH116 os-stat os.stat() should be replaced by Path.stat(), Path.owner(), or Path.group() \u2714\ufe0f \ud83d\udee0\ufe0f PTH117 os-path-isabs os.path.isabs() should be replaced by Path.is_absolute() \u2714\ufe0f \ud83d\udee0\ufe0f PTH118 os-path-join os.{module}.join() should be replaced by Path with / operator \u2714\ufe0f \ud83d\udee0\ufe0f PTH119 os-path-basename os.path.basename() should be replaced by Path.name \u2714\ufe0f \ud83d\udee0\ufe0f PTH120 os-path-dirname os.path.dirname() should be replaced by Path.parent \u2714\ufe0f \ud83d\udee0\ufe0f PTH121 os-path-samefile os.path.samefile() should be replaced by Path.samefile() \u2714\ufe0f \ud83d\udee0\ufe0f PTH122 os-path-splitext os.path.splitext() should be replaced by Path.suffix, Path.stem, and Path.parent \u2714\ufe0f \ud83d\udee0\ufe0f PTH123 builtin-open open() should be replaced by Path.open() \u2714\ufe0f \ud83d\udee0\ufe0f PTH124 py-path py.path is in maintenance mode, use pathlib instead \u2714\ufe0f \ud83d\udee0\ufe0f PTH201 path-constructor-current-directory Do not pass the current directory explicitly to Path \u2714\ufe0f \ud83d\udee0\ufe0f PTH202 os-path-getsize os.path.getsize should be replaced by Path.stat().st_size \u2714\ufe0f \ud83d\udee0\ufe0f PTH203 os-path-getatime os.path.getatime should be replaced by Path.stat().st_atime \u2714\ufe0f \ud83d\udee0\ufe0f PTH204 os-path-getmtime os.path.getmtime should be replaced by Path.stat().st_mtime \u2714\ufe0f \ud83d\udee0\ufe0f PTH205 os-path-getctime os.path.getctime should be replaced by Path.stat().st_ctime \u2714\ufe0f \ud83d\udee0\ufe0f PTH206 os-sep-split Replace .split(os.sep) with Path.parts \u2714\ufe0f \ud83d\udee0\ufe0f PTH207 glob Replace {function} with Path.glob or Path.rglob \u2714\ufe0f \ud83d\udee0\ufe0f PTH208 os-listdir Use pathlib.Path.iterdir() instead. \u2714\ufe0f \ud83d\udee0\ufe0f PTH210 invalid-pathlib-with-suffix Invalid suffix passed to .with_suffix() \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flynt-fly","title":"flynt (FLY)","text":"

        For more, see flynt on PyPI.

        Code Name Message FLY002 static-join-to-f-string Consider {expression} instead of string join \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#isort-i","title":"isort (I)","text":"

        For more, see isort on PyPI.

        For related settings, see isort.

        Code Name Message I001 unsorted-imports Import block is un-sorted or un-formatted \u2714\ufe0f \ud83d\udee0\ufe0f I002 missing-required-import Missing required import: {name} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#mccabe-c90","title":"mccabe (C90)","text":"

        For more, see mccabe on PyPI.

        For related settings, see mccabe.

        Code Name Message C901 complex-structure {name} is too complex ({complexity} > {max_complexity}) \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#numpy-specific-rules-npy","title":"NumPy-specific rules (NPY)","text":"Code Name Message NPY001 numpy-deprecated-type-alias Type alias np.{type_name} is deprecated, replace with builtin type \u2714\ufe0f \ud83d\udee0\ufe0f NPY002 numpy-legacy-random Replace legacy np.random.{method_name} call with np.random.Generator \u2714\ufe0f \ud83d\udee0\ufe0f NPY003 numpy-deprecated-function np.{existing} is deprecated; use np.{replacement} instead \u2714\ufe0f \ud83d\udee0\ufe0f NPY201 numpy2-deprecation np.{existing} will be removed in NumPy 2.0. {migration_guide} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pandas-vet-pd","title":"pandas-vet (PD)","text":"

        For more, see pandas-vet on PyPI.

        Code Name Message PD002 pandas-use-of-inplace-argument inplace=True should be avoided; it has inconsistent behavior \u2714\ufe0f \ud83d\udee0\ufe0f PD003 pandas-use-of-dot-is-null .isna is preferred to .isnull; functionality is equivalent \u2714\ufe0f \ud83d\udee0\ufe0f PD004 pandas-use-of-dot-not-null .notna is preferred to .notnull; functionality is equivalent \u2714\ufe0f \ud83d\udee0\ufe0f PD007 pandas-use-of-dot-ix .ix is deprecated; use more explicit .loc or .iloc \u2714\ufe0f \ud83d\udee0\ufe0f PD008 pandas-use-of-dot-at Use .loc instead of .at. If speed is important, use NumPy. \u2714\ufe0f \ud83d\udee0\ufe0f PD009 pandas-use-of-dot-iat Use .iloc instead of .iat. If speed is important, use NumPy. \u2714\ufe0f \ud83d\udee0\ufe0f PD010 pandas-use-of-dot-pivot-or-unstack .pivot_table is preferred to .pivot or .unstack; provides same functionality \u2714\ufe0f \ud83d\udee0\ufe0f PD011 pandas-use-of-dot-values Use .to_numpy() instead of .values \u2714\ufe0f \ud83d\udee0\ufe0f PD012 pandas-use-of-dot-read-table Use .read_csv instead of .read_table to read CSV files \u2714\ufe0f \ud83d\udee0\ufe0f PD013 pandas-use-of-dot-stack .melt is preferred to .stack; provides same functionality \u2714\ufe0f \ud83d\udee0\ufe0f PD015 pandas-use-of-pd-merge Use .merge method instead of pd.merge function. They have equivalent functionality. \u2714\ufe0f \ud83d\udee0\ufe0f PD101 pandas-nunique-constant-series-check Using series.nunique() for checking that a series is constant is inefficient \u2714\ufe0f \ud83d\udee0\ufe0f PD901 pandas-df-variable-name Avoid using the generic variable name df for DataFrames \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pep8-naming-n","title":"pep8-naming (N)","text":"

        For more, see pep8-naming on PyPI.

        For related settings, see pep8-naming.

        Code Name Message N801 invalid-class-name Class name {name} should use CapWords convention \u2714\ufe0f \ud83d\udee0\ufe0f N802 invalid-function-name Function name {name} should be lowercase \u2714\ufe0f \ud83d\udee0\ufe0f N803 invalid-argument-name Argument name {name} should be lowercase \u2714\ufe0f \ud83d\udee0\ufe0f N804 invalid-first-argument-name-for-class-method First argument of a class method should be named cls \u2714\ufe0f \ud83d\udee0\ufe0f N805 invalid-first-argument-name-for-method First argument of a method should be named self \u2714\ufe0f \ud83d\udee0\ufe0f N806 non-lowercase-variable-in-function Variable {name} in function should be lowercase \u2714\ufe0f \ud83d\udee0\ufe0f N807 dunder-function-name Function name should not start and end with __ \u2714\ufe0f \ud83d\udee0\ufe0f N811 constant-imported-as-non-constant Constant {name} imported as non-constant {asname} \u2714\ufe0f \ud83d\udee0\ufe0f N812 lowercase-imported-as-non-lowercase Lowercase {name} imported as non-lowercase {asname} \u2714\ufe0f \ud83d\udee0\ufe0f N813 camelcase-imported-as-lowercase Camelcase {name} imported as lowercase {asname} \u2714\ufe0f \ud83d\udee0\ufe0f N814 camelcase-imported-as-constant Camelcase {name} imported as constant {asname} \u2714\ufe0f \ud83d\udee0\ufe0f N815 mixed-case-variable-in-class-scope Variable {name} in class scope should not be mixedCase \u2714\ufe0f \ud83d\udee0\ufe0f N816 mixed-case-variable-in-global-scope Variable {name} in global scope should not be mixedCase \u2714\ufe0f \ud83d\udee0\ufe0f N817 camelcase-imported-as-acronym CamelCase {name} imported as acronym {asname} \u2714\ufe0f \ud83d\udee0\ufe0f N818 error-suffix-on-exception-name Exception name {name} should be named with an Error suffix \u2714\ufe0f \ud83d\udee0\ufe0f N999 invalid-module-name Invalid module name: '{name}' \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#perflint-perf","title":"Perflint (PERF)","text":"

        For more, see Perflint on PyPI.

        Code Name Message PERF101 unnecessary-list-cast Do not cast an iterable to list before iterating over it \u2714\ufe0f \ud83d\udee0\ufe0f PERF102 incorrect-dict-iterator When using only the {subset} of a dict use the {subset}() method \u2714\ufe0f \ud83d\udee0\ufe0f PERF203 try-except-in-loop try-except within a loop incurs performance overhead \u2714\ufe0f \ud83d\udee0\ufe0f PERF401 manual-list-comprehension Use {message_str} to create a transformed list \u2714\ufe0f \ud83d\udee0\ufe0f PERF402 manual-list-copy Use list or list.copy to create a copy of a list \u2714\ufe0f \ud83d\udee0\ufe0f PERF403 manual-dict-comprehension Use a dictionary comprehension instead of {modifier} for-loop \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pycodestyle-e-w","title":"pycodestyle (E, W)","text":"

        For more, see pycodestyle on PyPI.

        For related settings, see pycodestyle.

        "},{"location":"rules/#error-e","title":"Error (E)","text":"Code Name Message E101 mixed-spaces-and-tabs Indentation contains mixed spaces and tabs \u2714\ufe0f \ud83d\udee0\ufe0f E111 indentation-with-invalid-multiple Indentation is not a multiple of {indent_width} \ud83e\uddea \ud83d\udee0\ufe0f E112 no-indented-block Expected an indented block \ud83e\uddea \ud83d\udee0\ufe0f E113 unexpected-indentation Unexpected indentation \ud83e\uddea \ud83d\udee0\ufe0f E114 indentation-with-invalid-multiple-comment Indentation is not a multiple of {indent_width} (comment) \ud83e\uddea \ud83d\udee0\ufe0f E115 no-indented-block-comment Expected an indented block (comment) \ud83e\uddea \ud83d\udee0\ufe0f E116 unexpected-indentation-comment Unexpected indentation (comment) \ud83e\uddea \ud83d\udee0\ufe0f E117 over-indented Over-indented (comment) \ud83e\uddea \ud83d\udee0\ufe0f E201 whitespace-after-open-bracket Whitespace after '{symbol}' \ud83e\uddea \ud83d\udee0\ufe0f E202 whitespace-before-close-bracket Whitespace before '{symbol}' \ud83e\uddea \ud83d\udee0\ufe0f E203 whitespace-before-punctuation Whitespace before '{symbol}' \ud83e\uddea \ud83d\udee0\ufe0f E204 whitespace-after-decorator Whitespace after decorator \ud83e\uddea \ud83d\udee0\ufe0f E211 whitespace-before-parameters Whitespace before '{bracket}' \ud83e\uddea \ud83d\udee0\ufe0f E221 multiple-spaces-before-operator Multiple spaces before operator \ud83e\uddea \ud83d\udee0\ufe0f E222 multiple-spaces-after-operator Multiple spaces after operator \ud83e\uddea \ud83d\udee0\ufe0f E223 tab-before-operator Tab before operator \ud83e\uddea \ud83d\udee0\ufe0f E224 tab-after-operator Tab after operator \ud83e\uddea \ud83d\udee0\ufe0f E225 missing-whitespace-around-operator Missing whitespace around operator \ud83e\uddea \ud83d\udee0\ufe0f E226 missing-whitespace-around-arithmetic-operator Missing whitespace around arithmetic operator \ud83e\uddea \ud83d\udee0\ufe0f E227 missing-whitespace-around-bitwise-or-shift-operator Missing whitespace around bitwise or shift operator \ud83e\uddea \ud83d\udee0\ufe0f E228 missing-whitespace-around-modulo-operator Missing whitespace around modulo operator \ud83e\uddea \ud83d\udee0\ufe0f E231 missing-whitespace Missing whitespace after {} \ud83e\uddea \ud83d\udee0\ufe0f E241 multiple-spaces-after-comma Multiple spaces after comma \ud83e\uddea \ud83d\udee0\ufe0f E242 tab-after-comma Tab after comma \ud83e\uddea \ud83d\udee0\ufe0f E251 unexpected-spaces-around-keyword-parameter-equals Unexpected spaces around keyword / parameter equals \ud83e\uddea \ud83d\udee0\ufe0f E252 missing-whitespace-around-parameter-equals Missing whitespace around parameter equals \ud83e\uddea \ud83d\udee0\ufe0f E261 too-few-spaces-before-inline-comment Insert at least two spaces before an inline comment \ud83e\uddea \ud83d\udee0\ufe0f E262 no-space-after-inline-comment Inline comment should start with # \ud83e\uddea \ud83d\udee0\ufe0f E265 no-space-after-block-comment Block comment should start with # \ud83e\uddea \ud83d\udee0\ufe0f E266 multiple-leading-hashes-for-block-comment Too many leading # before block comment \ud83e\uddea \ud83d\udee0\ufe0f E271 multiple-spaces-after-keyword Multiple spaces after keyword \ud83e\uddea \ud83d\udee0\ufe0f E272 multiple-spaces-before-keyword Multiple spaces before keyword \ud83e\uddea \ud83d\udee0\ufe0f E273 tab-after-keyword Tab after keyword \ud83e\uddea \ud83d\udee0\ufe0f E274 tab-before-keyword Tab before keyword \ud83e\uddea \ud83d\udee0\ufe0f E275 missing-whitespace-after-keyword Missing whitespace after keyword \ud83e\uddea \ud83d\udee0\ufe0f E301 blank-line-between-methods Expected {BLANK_LINES_NESTED_LEVEL:?} blank line, found 0 \ud83e\uddea \ud83d\udee0\ufe0f E302 blank-lines-top-level Expected {expected_blank_lines:?} blank lines, found {actual_blank_lines} \ud83e\uddea \ud83d\udee0\ufe0f E303 too-many-blank-lines Too many blank lines ({actual_blank_lines}) \ud83e\uddea \ud83d\udee0\ufe0f E304 blank-line-after-decorator Blank lines found after function decorator ({lines}) \ud83e\uddea \ud83d\udee0\ufe0f E305 blank-lines-after-function-or-class Expected 2 blank lines after class or function definition, found ({blank_lines}) \ud83e\uddea \ud83d\udee0\ufe0f E306 blank-lines-before-nested-definition Expected 1 blank line before a nested definition, found 0 \ud83e\uddea \ud83d\udee0\ufe0f E401 multiple-imports-on-one-line Multiple imports on one line \u2714\ufe0f \ud83d\udee0\ufe0f E402 module-import-not-at-top-of-file Module level import not at top of cell \u2714\ufe0f \ud83d\udee0\ufe0f E501 line-too-long Line too long ({width} > {limit}) \u2714\ufe0f \ud83d\udee0\ufe0f E502 redundant-backslash Redundant backslash \ud83e\uddea \ud83d\udee0\ufe0f E701 multiple-statements-on-one-line-colon Multiple statements on one line (colon) \u2714\ufe0f \ud83d\udee0\ufe0f E702 multiple-statements-on-one-line-semicolon Multiple statements on one line (semicolon) \u2714\ufe0f \ud83d\udee0\ufe0f E703 useless-semicolon Statement ends with an unnecessary semicolon \u2714\ufe0f \ud83d\udee0\ufe0f E711 none-comparison Comparison to None should be cond is None \u2714\ufe0f \ud83d\udee0\ufe0f E712 true-false-comparison Avoid equality comparisons to True; use if {cond}: for truth checks \u2714\ufe0f \ud83d\udee0\ufe0f E713 not-in-test Test for membership should be not in \u2714\ufe0f \ud83d\udee0\ufe0f E714 not-is-test Test for object identity should be is not \u2714\ufe0f \ud83d\udee0\ufe0f E721 type-comparison Use is and is not for type comparisons, or isinstance() for isinstance checks \u2714\ufe0f \ud83d\udee0\ufe0f E722 bare-except Do not use bare except \u2714\ufe0f \ud83d\udee0\ufe0f E731 lambda-assignment Do not assign a lambda expression, use a def \u2714\ufe0f \ud83d\udee0\ufe0f E741 ambiguous-variable-name Ambiguous variable name: {name} \u2714\ufe0f \ud83d\udee0\ufe0f E742 ambiguous-class-name Ambiguous class name: {name} \u2714\ufe0f \ud83d\udee0\ufe0f E743 ambiguous-function-name Ambiguous function name: {name} \u2714\ufe0f \ud83d\udee0\ufe0f E902 io-error {message} \u2714\ufe0f \ud83d\udee0\ufe0f E999 syntax-error SyntaxError \u274c \ud83d\udee0\ufe0f"},{"location":"rules/#warning-w","title":"Warning (W)","text":"Code Name Message W191 tab-indentation Indentation contains tabs \u2714\ufe0f \ud83d\udee0\ufe0f W291 trailing-whitespace Trailing whitespace \u2714\ufe0f \ud83d\udee0\ufe0f W292 missing-newline-at-end-of-file No newline at end of file \u2714\ufe0f \ud83d\udee0\ufe0f W293 blank-line-with-whitespace Blank line contains whitespace \u2714\ufe0f \ud83d\udee0\ufe0f W391 too-many-newlines-at-end-of-file Too many newlines at end of {domain} \ud83e\uddea \ud83d\udee0\ufe0f W505 doc-line-too-long Doc line too long ({width} > {limit}) \u2714\ufe0f \ud83d\udee0\ufe0f W605 invalid-escape-sequence Invalid escape sequence: \\{ch} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pydoclint-doc","title":"pydoclint (DOC)","text":"

        For more, see pydoclint on PyPI.

        For related settings, see pydoclint.

        Code Name Message DOC201 docstring-missing-returns return is not documented in docstring \ud83e\uddea \ud83d\udee0\ufe0f DOC202 docstring-extraneous-returns Docstring should not have a returns section because the function doesn't return anything \ud83e\uddea \ud83d\udee0\ufe0f DOC402 docstring-missing-yields yield is not documented in docstring \ud83e\uddea \ud83d\udee0\ufe0f DOC403 docstring-extraneous-yields Docstring has a \"Yields\" section but the function doesn't yield anything \ud83e\uddea \ud83d\udee0\ufe0f DOC501 docstring-missing-exception Raised exception {id} missing from docstring \ud83e\uddea \ud83d\udee0\ufe0f DOC502 docstring-extraneous-exception Raised exception is not explicitly raised: {id} \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#pydocstyle-d","title":"pydocstyle (D)","text":"

        For more, see pydocstyle on PyPI.

        For related settings, see pydocstyle.

        Code Name Message D100 undocumented-public-module Missing docstring in public module \u2714\ufe0f \ud83d\udee0\ufe0f D101 undocumented-public-class Missing docstring in public class \u2714\ufe0f \ud83d\udee0\ufe0f D102 undocumented-public-method Missing docstring in public method \u2714\ufe0f \ud83d\udee0\ufe0f D103 undocumented-public-function Missing docstring in public function \u2714\ufe0f \ud83d\udee0\ufe0f D104 undocumented-public-package Missing docstring in public package \u2714\ufe0f \ud83d\udee0\ufe0f D105 undocumented-magic-method Missing docstring in magic method \u2714\ufe0f \ud83d\udee0\ufe0f D106 undocumented-public-nested-class Missing docstring in public nested class \u2714\ufe0f \ud83d\udee0\ufe0f D107 undocumented-public-init Missing docstring in __init__ \u2714\ufe0f \ud83d\udee0\ufe0f D200 unnecessary-multiline-docstring One-line docstring should fit on one line \u2714\ufe0f \ud83d\udee0\ufe0f D201 blank-line-before-function No blank lines allowed before function docstring (found {num_lines}) \u2714\ufe0f \ud83d\udee0\ufe0f D202 blank-line-after-function No blank lines allowed after function docstring (found {num_lines}) \u2714\ufe0f \ud83d\udee0\ufe0f D203 incorrect-blank-line-before-class 1 blank line required before class docstring \u2714\ufe0f \ud83d\udee0\ufe0f D204 incorrect-blank-line-after-class 1 blank line required after class docstring \u2714\ufe0f \ud83d\udee0\ufe0f D205 missing-blank-line-after-summary 1 blank line required between summary line and description \u2714\ufe0f \ud83d\udee0\ufe0f D206 docstring-tab-indentation Docstring should be indented with spaces, not tabs \u2714\ufe0f \ud83d\udee0\ufe0f D207 under-indentation Docstring is under-indented \u2714\ufe0f \ud83d\udee0\ufe0f D208 over-indentation Docstring is over-indented \u2714\ufe0f \ud83d\udee0\ufe0f D209 new-line-after-last-paragraph Multi-line docstring closing quotes should be on a separate line \u2714\ufe0f \ud83d\udee0\ufe0f D210 surrounding-whitespace No whitespaces allowed surrounding docstring text \u2714\ufe0f \ud83d\udee0\ufe0f D211 blank-line-before-class No blank lines allowed before class docstring \u2714\ufe0f \ud83d\udee0\ufe0f D212 multi-line-summary-first-line Multi-line docstring summary should start at the first line \u2714\ufe0f \ud83d\udee0\ufe0f D213 multi-line-summary-second-line Multi-line docstring summary should start at the second line \u2714\ufe0f \ud83d\udee0\ufe0f D214 overindented-section Section is over-indented (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D215 overindented-section-underline Section underline is over-indented (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D300 triple-single-quotes Use triple double quotes \"\"\" \u2714\ufe0f \ud83d\udee0\ufe0f D301 escape-sequence-in-docstring Use r\"\"\" if any backslashes in a docstring \u2714\ufe0f \ud83d\udee0\ufe0f D400 missing-trailing-period First line should end with a period \u2714\ufe0f \ud83d\udee0\ufe0f D401 non-imperative-mood First line of docstring should be in imperative mood: \"{first_line}\" \u2714\ufe0f \ud83d\udee0\ufe0f D402 signature-in-docstring First line should not be the function's signature \u2714\ufe0f \ud83d\udee0\ufe0f D403 first-word-uncapitalized First word of the docstring should be capitalized: {} -> {} \u2714\ufe0f \ud83d\udee0\ufe0f D404 docstring-starts-with-this First word of the docstring should not be \"This\" \u2714\ufe0f \ud83d\udee0\ufe0f D405 non-capitalized-section-name Section name should be properly capitalized (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D406 missing-new-line-after-section-name Section name should end with a newline (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D407 missing-dashed-underline-after-section Missing dashed underline after section (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D408 missing-section-underline-after-name Section underline should be in the line following the section's name (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D409 mismatched-section-underline-length Section underline should match the length of its name (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D410 no-blank-line-after-section Missing blank line after section (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D411 no-blank-line-before-section Missing blank line before section (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D412 blank-lines-between-header-and-content No blank lines allowed between a section header and its content (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D413 missing-blank-line-after-last-section Missing blank line after last section (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D414 empty-docstring-section Section has no content (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D415 missing-terminal-punctuation First line should end with a period, question mark, or exclamation point \u2714\ufe0f \ud83d\udee0\ufe0f D416 missing-section-name-colon Section name should end with a colon (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D417 undocumented-param Missing argument description in the docstring for {definition}: {name} \u2714\ufe0f \ud83d\udee0\ufe0f D418 overload-with-docstring Function decorated with @overload shouldn't contain a docstring \u2714\ufe0f \ud83d\udee0\ufe0f D419 empty-docstring Docstring is empty \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pyflakes-f","title":"Pyflakes (F)","text":"

        For more, see Pyflakes on PyPI.

        Code Name Message F401 unused-import {name} imported but unused; consider using importlib.util.find_spec to test for availability \u2714\ufe0f \ud83d\udee0\ufe0f F402 import-shadowed-by-loop-var Import {name} from {row} shadowed by loop variable \u2714\ufe0f \ud83d\udee0\ufe0f F403 undefined-local-with-import-star from {name} import * used; unable to detect undefined names \u2714\ufe0f \ud83d\udee0\ufe0f F404 late-future-import from __future__ imports must occur at the beginning of the file \u2714\ufe0f \ud83d\udee0\ufe0f F405 undefined-local-with-import-star-usage {name} may be undefined, or defined from star imports \u2714\ufe0f \ud83d\udee0\ufe0f F406 undefined-local-with-nested-import-star-usage from {name} import * only allowed at module level \u2714\ufe0f \ud83d\udee0\ufe0f F407 future-feature-not-defined Future feature {name} is not defined \u2714\ufe0f \ud83d\udee0\ufe0f F501 percent-format-invalid-format %-format string has invalid format string: {message} \u2714\ufe0f \ud83d\udee0\ufe0f F502 percent-format-expected-mapping %-format string expected mapping but got sequence \u2714\ufe0f \ud83d\udee0\ufe0f F503 percent-format-expected-sequence %-format string expected sequence but got mapping \u2714\ufe0f \ud83d\udee0\ufe0f F504 percent-format-extra-named-arguments %-format string has unused named argument(s): {message} \u2714\ufe0f \ud83d\udee0\ufe0f F505 percent-format-missing-argument %-format string is missing argument(s) for placeholder(s): {message} \u2714\ufe0f \ud83d\udee0\ufe0f F506 percent-format-mixed-positional-and-named %-format string has mixed positional and named placeholders \u2714\ufe0f \ud83d\udee0\ufe0f F507 percent-format-positional-count-mismatch %-format string has {wanted} placeholder(s) but {got} substitution(s) \u2714\ufe0f \ud83d\udee0\ufe0f F508 percent-format-star-requires-sequence %-format string * specifier requires sequence \u2714\ufe0f \ud83d\udee0\ufe0f F509 percent-format-unsupported-format-character %-format string has unsupported format character {char} \u2714\ufe0f \ud83d\udee0\ufe0f F521 string-dot-format-invalid-format .format call has invalid format string: {message} \u2714\ufe0f \ud83d\udee0\ufe0f F522 string-dot-format-extra-named-arguments .format call has unused named argument(s): {message} \u2714\ufe0f \ud83d\udee0\ufe0f F523 string-dot-format-extra-positional-arguments .format call has unused arguments at position(s): {message} \u2714\ufe0f \ud83d\udee0\ufe0f F524 string-dot-format-missing-arguments .format call is missing argument(s) for placeholder(s): {message} \u2714\ufe0f \ud83d\udee0\ufe0f F525 string-dot-format-mixing-automatic .format string mixes automatic and manual numbering \u2714\ufe0f \ud83d\udee0\ufe0f F541 f-string-missing-placeholders f-string without any placeholders \u2714\ufe0f \ud83d\udee0\ufe0f F601 multi-value-repeated-key-literal Dictionary key literal {name} repeated \u2714\ufe0f \ud83d\udee0\ufe0f F602 multi-value-repeated-key-variable Dictionary key {name} repeated \u2714\ufe0f \ud83d\udee0\ufe0f F621 expressions-in-star-assignment Too many expressions in star-unpacking assignment \u2714\ufe0f \ud83d\udee0\ufe0f F622 multiple-starred-expressions Two starred expressions in assignment \u2714\ufe0f \ud83d\udee0\ufe0f F631 assert-tuple Assert test is a non-empty tuple, which is always True \u2714\ufe0f \ud83d\udee0\ufe0f F632 is-literal Use == to compare constant literals \u2714\ufe0f \ud83d\udee0\ufe0f F633 invalid-print-syntax Use of >> is invalid with print function \u2714\ufe0f \ud83d\udee0\ufe0f F634 if-tuple If test is a tuple, which is always True \u2714\ufe0f \ud83d\udee0\ufe0f F701 break-outside-loop break outside loop \u2714\ufe0f \ud83d\udee0\ufe0f F702 continue-outside-loop continue not properly in loop \u2714\ufe0f \ud83d\udee0\ufe0f F704 yield-outside-function {keyword} statement outside of a function \u2714\ufe0f \ud83d\udee0\ufe0f F706 return-outside-function return statement outside of a function/method \u2714\ufe0f \ud83d\udee0\ufe0f F707 default-except-not-last An except block as not the last exception handler \u2714\ufe0f \ud83d\udee0\ufe0f F722 forward-annotation-syntax-error Syntax error in forward annotation: {parse_error} \u2714\ufe0f \ud83d\udee0\ufe0f F811 redefined-while-unused Redefinition of unused {name} from {row} \u2714\ufe0f \ud83d\udee0\ufe0f F821 undefined-name Undefined name {name}. {tip} \u2714\ufe0f \ud83d\udee0\ufe0f F822 undefined-export Undefined name {name} in __all__ \u2714\ufe0f \ud83d\udee0\ufe0f F823 undefined-local Local variable {name} referenced before assignment \u2714\ufe0f \ud83d\udee0\ufe0f F841 unused-variable Local variable {name} is assigned to but never used \u2714\ufe0f \ud83d\udee0\ufe0f F842 unused-annotation Local variable {name} is annotated but never used \u2714\ufe0f \ud83d\udee0\ufe0f F901 raise-not-implemented raise NotImplemented should be raise NotImplementedError \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pygrep-hooks-pgh","title":"pygrep-hooks (PGH)","text":"

        For more, see pygrep-hooks on GitHub.

        Code Name Message PGH001 eval No builtin eval() allowed \u274c \ud83d\udee0\ufe0f PGH002 deprecated-log-warn warn is deprecated in favor of warning \u274c \ud83d\udee0\ufe0f PGH003 blanket-type-ignore Use specific rule codes when ignoring type issues \u2714\ufe0f \ud83d\udee0\ufe0f PGH004 blanket-noqa Use specific rule codes when using noqa \u2714\ufe0f \ud83d\udee0\ufe0f PGH005 invalid-mock-access Mock method should be called: {name} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pylint-pl","title":"Pylint (PL)","text":"

        For more, see Pylint on PyPI.

        "},{"location":"rules/#convention-plc","title":"Convention (PLC)","text":"Code Name Message PLC0105 type-name-incorrect-variance {kind} name \"{param_name}\" does not reflect its {variance}; consider renaming it to \"{replacement_name}\" \u2714\ufe0f \ud83d\udee0\ufe0f PLC0131 type-bivariance {kind} cannot be both covariant and contravariant \u2714\ufe0f \ud83d\udee0\ufe0f PLC0132 type-param-name-mismatch {kind} name {param_name} does not match assigned variable name {var_name} \u2714\ufe0f \ud83d\udee0\ufe0f PLC0205 single-string-slots Class __slots__ should be a non-string iterable \u2714\ufe0f \ud83d\udee0\ufe0f PLC0206 dict-index-missing-items Extracting value from dictionary without calling .items() \u2714\ufe0f \ud83d\udee0\ufe0f PLC0208 iteration-over-set Use a sequence type instead of a set when iterating over values \u2714\ufe0f \ud83d\udee0\ufe0f PLC0414 useless-import-alias Import alias does not rename original package \u2714\ufe0f \ud83d\udee0\ufe0f PLC0415 import-outside-top-level import should be at the top-level of a file \ud83e\uddea \ud83d\udee0\ufe0f PLC1802 len-test len({expression}) used as condition without comparison \u2714\ufe0f \ud83d\udee0\ufe0f PLC1901 compare-to-empty-string {existing} can be simplified to {replacement} as an empty string is falsey \ud83e\uddea \ud83d\udee0\ufe0f PLC2401 non-ascii-name {kind} name {name} contains a non-ASCII character \u2714\ufe0f \ud83d\udee0\ufe0f PLC2403 non-ascii-import-name Module alias {name} contains a non-ASCII character \u2714\ufe0f \ud83d\udee0\ufe0f PLC2701 import-private-name Private name import {name} from external module {module} \ud83e\uddea \ud83d\udee0\ufe0f PLC2801 unnecessary-dunder-call Unnecessary dunder call to {method}. {replacement}. \ud83e\uddea \ud83d\udee0\ufe0f PLC3002 unnecessary-direct-lambda-call Lambda expression called directly. Execute the expression inline instead. \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#error-ple","title":"Error (PLE)","text":"Code Name Message PLE0100 yield-in-init __init__ method is a generator \u2714\ufe0f \ud83d\udee0\ufe0f PLE0101 return-in-init Explicit return in __init__ \u2714\ufe0f \ud83d\udee0\ufe0f PLE0115 nonlocal-and-global Name {name} is both nonlocal and global \u2714\ufe0f \ud83d\udee0\ufe0f PLE0116 continue-in-finally continue not supported inside finally clause \u2714\ufe0f \ud83d\udee0\ufe0f PLE0117 nonlocal-without-binding Nonlocal name {name} found without binding \u2714\ufe0f \ud83d\udee0\ufe0f PLE0118 load-before-global-declaration Name {name} is used prior to global declaration on {row} \u2714\ufe0f \ud83d\udee0\ufe0f PLE0237 non-slot-assignment Attribute {name} is not defined in class's __slots__ \u2714\ufe0f \ud83d\udee0\ufe0f PLE0241 duplicate-bases Duplicate base {base} for class {class} \u2714\ufe0f \ud83d\udee0\ufe0f PLE0302 unexpected-special-method-signature The special method {} expects {}, {} {} given \u2714\ufe0f \ud83d\udee0\ufe0f PLE0303 invalid-length-return-type __len__ does not return a non-negative integer \u2714\ufe0f \ud83d\udee0\ufe0f PLE0304 invalid-bool-return-type __bool__ does not return bool \ud83e\uddea \ud83d\udee0\ufe0f PLE0305 invalid-index-return-type __index__ does not return an integer \u2714\ufe0f \ud83d\udee0\ufe0f PLE0307 invalid-str-return-type __str__ does not return str \u2714\ufe0f \ud83d\udee0\ufe0f PLE0308 invalid-bytes-return-type __bytes__ does not return bytes \u2714\ufe0f \ud83d\udee0\ufe0f PLE0309 invalid-hash-return-type __hash__ does not return an integer \u2714\ufe0f \ud83d\udee0\ufe0f PLE0604 invalid-all-object Invalid object in __all__, must contain only strings \u2714\ufe0f \ud83d\udee0\ufe0f PLE0605 invalid-all-format Invalid format for __all__, must be tuple or list \u2714\ufe0f \ud83d\udee0\ufe0f PLE0643 potential-index-error Expression is likely to raise IndexError \u2714\ufe0f \ud83d\udee0\ufe0f PLE0704 misplaced-bare-raise Bare raise statement is not inside an exception handler \u2714\ufe0f \ud83d\udee0\ufe0f PLE1132 repeated-keyword-argument Repeated keyword argument: {duplicate_keyword} \u2714\ufe0f \ud83d\udee0\ufe0f PLE1141 dict-iter-missing-items Unpacking a dictionary in iteration without calling .items() \ud83e\uddea \ud83d\udee0\ufe0f PLE1142 await-outside-async await should be used within an async function \u2714\ufe0f \ud83d\udee0\ufe0f PLE1205 logging-too-many-args Too many arguments for logging format string \u2714\ufe0f \ud83d\udee0\ufe0f PLE1206 logging-too-few-args Not enough arguments for logging format string \u2714\ufe0f \ud83d\udee0\ufe0f PLE1300 bad-string-format-character Unsupported format character '{format_char}' \u2714\ufe0f \ud83d\udee0\ufe0f PLE1307 bad-string-format-type Format type does not match argument type \u2714\ufe0f \ud83d\udee0\ufe0f PLE1310 bad-str-strip-call String {strip} call contains duplicate characters (did you mean {removal}?) \u2714\ufe0f \ud83d\udee0\ufe0f PLE1507 invalid-envvar-value Invalid type for initial os.getenv argument; expected str \u2714\ufe0f \ud83d\udee0\ufe0f PLE1519 singledispatch-method @singledispatch decorator should not be used on methods \u2714\ufe0f \ud83d\udee0\ufe0f PLE1520 singledispatchmethod-function @singledispatchmethod decorator should not be used on non-method functions \u2714\ufe0f \ud83d\udee0\ufe0f PLE1700 yield-from-in-async-function yield from statement in async function; use async for instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE2502 bidirectional-unicode Contains control characters that can permit obfuscated code \u2714\ufe0f \ud83d\udee0\ufe0f PLE2510 invalid-character-backspace Invalid unescaped character backspace, use \"\\b\" instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE2512 invalid-character-sub Invalid unescaped character SUB, use \"\\x1A\" instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE2513 invalid-character-esc Invalid unescaped character ESC, use \"\\x1B\" instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE2514 invalid-character-nul Invalid unescaped character NUL, use \"\\0\" instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE2515 invalid-character-zero-width-space Invalid unescaped character zero-width-space, use \"\\u200B\" instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE4703 modified-iterating-set Iterated set {name} is modified within the for loop \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#refactor-plr","title":"Refactor (PLR)","text":"Code Name Message PLR0124 comparison-with-itself Name compared with itself, consider replacing {actual} \u2714\ufe0f \ud83d\udee0\ufe0f PLR0133 comparison-of-constant Two constants compared in a comparison, consider replacing {left_constant} {op} {right_constant} \u2714\ufe0f \ud83d\udee0\ufe0f PLR0202 no-classmethod-decorator Class method defined without decorator \ud83e\uddea \ud83d\udee0\ufe0f PLR0203 no-staticmethod-decorator Static method defined without decorator \ud83e\uddea \ud83d\udee0\ufe0f PLR0206 property-with-parameters Cannot have defined parameters for properties \u2714\ufe0f \ud83d\udee0\ufe0f PLR0402 manual-from-import Use from {module} import {name} in lieu of alias \u2714\ufe0f \ud83d\udee0\ufe0f PLR0904 too-many-public-methods Too many public methods ({methods} > {max_methods}) \ud83e\uddea \ud83d\udee0\ufe0f PLR0911 too-many-return-statements Too many return statements ({returns} > {max_returns}) \u2714\ufe0f \ud83d\udee0\ufe0f PLR0912 too-many-branches Too many branches ({branches} > {max_branches}) \u2714\ufe0f \ud83d\udee0\ufe0f PLR0913 too-many-arguments Too many arguments in function definition ({c_args} > {max_args}) \u2714\ufe0f \ud83d\udee0\ufe0f PLR0914 too-many-locals Too many local variables ({current_amount}/{max_amount}) \ud83e\uddea \ud83d\udee0\ufe0f PLR0915 too-many-statements Too many statements ({statements} > {max_statements}) \u2714\ufe0f \ud83d\udee0\ufe0f PLR0916 too-many-boolean-expressions Too many Boolean expressions ({expressions} > {max_expressions}) \ud83e\uddea \ud83d\udee0\ufe0f PLR0917 too-many-positional-arguments Too many positional arguments ({c_pos}/{max_pos}) \ud83e\uddea \ud83d\udee0\ufe0f PLR1701 repeated-isinstance-calls Merge isinstance calls: {expression} \u274c \ud83d\udee0\ufe0f PLR1702 too-many-nested-blocks Too many nested blocks ({nested_blocks} > {max_nested_blocks}) \ud83e\uddea \ud83d\udee0\ufe0f PLR1704 redefined-argument-from-local Redefining argument with the local name {name} \u2714\ufe0f \ud83d\udee0\ufe0f PLR1706 and-or-ternary Consider using if-else expression \u274c \ud83d\udee0\ufe0f PLR1711 useless-return Useless return statement at end of function \u2714\ufe0f \ud83d\udee0\ufe0f PLR1714 repeated-equality-comparison Consider merging multiple comparisons: {expression}. Use a set if the elements are hashable. \u2714\ufe0f \ud83d\udee0\ufe0f PLR1716 boolean-chained-comparison Contains chained boolean comparison that can be simplified \u2714\ufe0f \ud83d\udee0\ufe0f PLR1722 sys-exit-alias Use sys.exit() instead of {name} \u2714\ufe0f \ud83d\udee0\ufe0f PLR1730 if-stmt-min-max Replace if statement with {replacement} \u2714\ufe0f \ud83d\udee0\ufe0f PLR1733 unnecessary-dict-index-lookup Unnecessary lookup of dictionary value by key \ud83e\uddea \ud83d\udee0\ufe0f PLR1736 unnecessary-list-index-lookup List index lookup in enumerate() loop \u2714\ufe0f \ud83d\udee0\ufe0f PLR2004 magic-value-comparison Magic value used in comparison, consider replacing {value} with a constant variable \u2714\ufe0f \ud83d\udee0\ufe0f PLR2044 empty-comment Line with empty comment \u2714\ufe0f \ud83d\udee0\ufe0f PLR5501 collapsible-else-if Use elif instead of else then if, to reduce indentation \u2714\ufe0f \ud83d\udee0\ufe0f PLR6104 non-augmented-assignment Use {operator} to perform an augmented assignment directly \ud83e\uddea \ud83d\udee0\ufe0f PLR6201 literal-membership Use a set literal when testing for membership \ud83e\uddea \ud83d\udee0\ufe0f PLR6301 no-self-use Method {method_name} could be a function, class method, or static method \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#warning-plw","title":"Warning (PLW)","text":"Code Name Message PLW0108 unnecessary-lambda Lambda may be unnecessary; consider inlining inner function \ud83e\uddea \ud83d\udee0\ufe0f PLW0120 useless-else-on-loop else clause on loop without a break statement; remove the else and dedent its contents \u2714\ufe0f \ud83d\udee0\ufe0f PLW0127 self-assigning-variable Self-assignment of variable {name} \u2714\ufe0f \ud83d\udee0\ufe0f PLW0128 redeclared-assigned-name Redeclared variable {name} in assignment \u2714\ufe0f \ud83d\udee0\ufe0f PLW0129 assert-on-string-literal Asserting on an empty string literal will never pass \u2714\ufe0f \ud83d\udee0\ufe0f PLW0131 named-expr-without-context Named expression used without context \u2714\ufe0f \ud83d\udee0\ufe0f PLW0133 useless-exception-statement Missing raise statement on exception \u2714\ufe0f \ud83d\udee0\ufe0f PLW0177 nan-comparison Comparing against a NaN value; use math.isnan instead \ud83e\uddea \ud83d\udee0\ufe0f PLW0211 bad-staticmethod-argument First argument of a static method should not be named {argument_name} \u2714\ufe0f \ud83d\udee0\ufe0f PLW0244 redefined-slots-in-subclass Slot {slot_name} redefined from base class {base} \ud83e\uddea \ud83d\udee0\ufe0f PLW0245 super-without-brackets super call is missing parentheses \u2714\ufe0f \ud83d\udee0\ufe0f PLW0406 import-self Module {name} imports itself \u2714\ufe0f \ud83d\udee0\ufe0f PLW0602 global-variable-not-assigned Using global for {name} but no assignment is done \u2714\ufe0f \ud83d\udee0\ufe0f PLW0603 global-statement Using the global statement to update {name} is discouraged \u2714\ufe0f \ud83d\udee0\ufe0f PLW0604 global-at-module-level global at module level is redundant \u2714\ufe0f \ud83d\udee0\ufe0f PLW0642 self-or-cls-assignment Reassigned {} variable in {method_type} method \u2714\ufe0f \ud83d\udee0\ufe0f PLW0711 binary-op-exception Exception to catch is the result of a binary and operation \u2714\ufe0f \ud83d\udee0\ufe0f PLW1501 bad-open-mode {mode} is not a valid mode for open \u2714\ufe0f \ud83d\udee0\ufe0f PLW1507 shallow-copy-environ Shallow copy of os.environ via copy.copy(os.environ) \u2714\ufe0f \ud83d\udee0\ufe0f PLW1508 invalid-envvar-default Invalid type for environment variable default; expected str or None \u2714\ufe0f \ud83d\udee0\ufe0f PLW1509 subprocess-popen-preexec-fn preexec_fn argument is unsafe when using threads \u2714\ufe0f \ud83d\udee0\ufe0f PLW1510 subprocess-run-without-check subprocess.run without explicit check argument \u2714\ufe0f \ud83d\udee0\ufe0f PLW1514 unspecified-encoding {function_name} in text mode without explicit encoding argument \ud83e\uddea \ud83d\udee0\ufe0f PLW1641 eq-without-hash Object does not implement __hash__ method \ud83e\uddea \ud83d\udee0\ufe0f PLW2101 useless-with-lock Threading lock directly created in with statement has no effect \u2714\ufe0f \ud83d\udee0\ufe0f PLW2901 redefined-loop-name Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target \u2714\ufe0f \ud83d\udee0\ufe0f PLW3201 bad-dunder-method-name Dunder method {name} has no special meaning in Python 3 \ud83e\uddea \ud83d\udee0\ufe0f PLW3301 nested-min-max Nested {func} calls can be flattened \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pyupgrade-up","title":"pyupgrade (UP)","text":"

        For more, see pyupgrade on PyPI.

        For related settings, see pyupgrade.

        Code Name Message UP001 useless-metaclass-type __metaclass__ = type is implied \u2714\ufe0f \ud83d\udee0\ufe0f UP003 type-of-primitive Use {} instead of type(...) \u2714\ufe0f \ud83d\udee0\ufe0f UP004 useless-object-inheritance Class {name} inherits from object \u2714\ufe0f \ud83d\udee0\ufe0f UP005 deprecated-unittest-alias {alias} is deprecated, use {target} \u2714\ufe0f \ud83d\udee0\ufe0f UP006 non-pep585-annotation Use {to} instead of {from} for type annotation \u2714\ufe0f \ud83d\udee0\ufe0f UP007 non-pep604-annotation-union Use X | Y for type annotations \u2714\ufe0f \ud83d\udee0\ufe0f UP008 super-call-with-parameters Use super() instead of super(__class__, self) \u2714\ufe0f \ud83d\udee0\ufe0f UP009 utf8-encoding-declaration UTF-8 encoding declaration is unnecessary \u2714\ufe0f \ud83d\udee0\ufe0f UP010 unnecessary-future-import Unnecessary __future__ import {import} for target Python version \u2714\ufe0f \ud83d\udee0\ufe0f UP011 lru-cache-without-parameters Unnecessary parentheses to functools.lru_cache \u2714\ufe0f \ud83d\udee0\ufe0f UP012 unnecessary-encode-utf8 Unnecessary call to encode as UTF-8 \u2714\ufe0f \ud83d\udee0\ufe0f UP013 convert-typed-dict-functional-to-class Convert {name} from TypedDict functional to class syntax \u2714\ufe0f \ud83d\udee0\ufe0f UP014 convert-named-tuple-functional-to-class Convert {name} from NamedTuple functional to class syntax \u2714\ufe0f \ud83d\udee0\ufe0f UP015 redundant-open-modes Unnecessary mode argument \u2714\ufe0f \ud83d\udee0\ufe0f UP017 datetime-timezone-utc Use datetime.UTC alias \u2714\ufe0f \ud83d\udee0\ufe0f UP018 native-literals Unnecessary {literal_type} call (rewrite as a literal) \u2714\ufe0f \ud83d\udee0\ufe0f UP019 typing-text-str-alias typing.Text is deprecated, use str \u2714\ufe0f \ud83d\udee0\ufe0f UP020 open-alias Use builtin open \u2714\ufe0f \ud83d\udee0\ufe0f UP021 replace-universal-newlines universal_newlines is deprecated, use text \u2714\ufe0f \ud83d\udee0\ufe0f UP022 replace-stdout-stderr Prefer capture_output over sending stdout and stderr to PIPE \u2714\ufe0f \ud83d\udee0\ufe0f UP023 deprecated-c-element-tree cElementTree is deprecated, use ElementTree \u2714\ufe0f \ud83d\udee0\ufe0f UP024 os-error-alias Replace aliased errors with OSError \u2714\ufe0f \ud83d\udee0\ufe0f UP025 unicode-kind-prefix Remove unicode literals from strings \u2714\ufe0f \ud83d\udee0\ufe0f UP026 deprecated-mock-import mock is deprecated, use unittest.mock \u2714\ufe0f \ud83d\udee0\ufe0f UP027 unpacked-list-comprehension Replace unpacked list comprehension with a generator expression \u274c \ud83d\udee0\ufe0f UP028 yield-in-for-loop Replace yield over for loop with yield from \u2714\ufe0f \ud83d\udee0\ufe0f UP029 unnecessary-builtin-import Unnecessary builtin import: {import} \u2714\ufe0f \ud83d\udee0\ufe0f UP030 format-literals Use implicit references for positional format fields \u2714\ufe0f \ud83d\udee0\ufe0f UP031 printf-string-formatting Use format specifiers instead of percent format \u2714\ufe0f \ud83d\udee0\ufe0f UP032 f-string Use f-string instead of format call \u2714\ufe0f \ud83d\udee0\ufe0f UP033 lru-cache-with-maxsize-none Use @functools.cache instead of @functools.lru_cache(maxsize=None) \u2714\ufe0f \ud83d\udee0\ufe0f UP034 extraneous-parentheses Avoid extraneous parentheses \u2714\ufe0f \ud83d\udee0\ufe0f UP035 deprecated-import Import from {target} instead: {names} \u2714\ufe0f \ud83d\udee0\ufe0f UP036 outdated-version-block Version block is outdated for minimum Python version \u2714\ufe0f \ud83d\udee0\ufe0f UP037 quoted-annotation Remove quotes from type annotation \u2714\ufe0f \ud83d\udee0\ufe0f UP038 non-pep604-isinstance Use X | Y in {} call instead of (X, Y) \u26a0\ufe0f \ud83d\udee0\ufe0f UP039 unnecessary-class-parentheses Unnecessary parentheses after class definition \u2714\ufe0f \ud83d\udee0\ufe0f UP040 non-pep695-type-alias Type alias {name} uses {type_alias_method} instead of the type keyword \u2714\ufe0f \ud83d\udee0\ufe0f UP041 timeout-error-alias Replace aliased errors with TimeoutError \u2714\ufe0f \ud83d\udee0\ufe0f UP042 replace-str-enum Class {name} inherits from both str and enum.Enum \ud83e\uddea \ud83d\udee0\ufe0f UP043 unnecessary-default-type-args Unnecessary default type arguments \u2714\ufe0f \ud83d\udee0\ufe0f UP044 non-pep646-unpack Use * for unpacking \u2714\ufe0f \ud83d\udee0\ufe0f UP045 non-pep604-annotation-optional Use X | None for type annotations \ud83e\uddea \ud83d\udee0\ufe0f UP046 non-pep695-generic-class Generic class {name} uses Generic subclass instead of type parameters \ud83e\uddea \ud83d\udee0\ufe0f UP047 non-pep695-generic-function Generic function {name} should use type parameters \ud83e\uddea \ud83d\udee0\ufe0f UP049 private-type-parameter Generic {} uses private type parameters \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#refurb-furb","title":"refurb (FURB)","text":"

        For more, see refurb on PyPI.

        Code Name Message FURB101 read-whole-file open and read should be replaced by Path({filename}).{suggestion} \ud83e\uddea \ud83d\udee0\ufe0f FURB103 write-whole-file open and write should be replaced by Path({filename}).{suggestion} \ud83e\uddea \ud83d\udee0\ufe0f FURB105 print-empty-string Unnecessary empty string passed to print \u2714\ufe0f \ud83d\udee0\ufe0f FURB110 if-exp-instead-of-or-operator Replace ternary if expression with or operator \ud83e\uddea \ud83d\udee0\ufe0f FURB113 repeated-append Use {suggestion} instead of repeatedly calling {name}.append() \ud83e\uddea \ud83d\udee0\ufe0f FURB116 f-string-number-format Replace {function_name} call with {display} \ud83e\uddea \ud83d\udee0\ufe0f FURB118 reimplemented-operator Use operator.{operator} instead of defining a {target} \ud83e\uddea \ud83d\udee0\ufe0f FURB122 for-loop-writes Use of {}.write in a for loop \ud83e\uddea \ud83d\udee0\ufe0f FURB129 readlines-in-for Instead of calling readlines(), iterate over file object directly \u2714\ufe0f \ud83d\udee0\ufe0f FURB131 delete-full-slice Prefer clear over deleting a full slice \ud83e\uddea \ud83d\udee0\ufe0f FURB132 check-and-remove-from-set Use {suggestion} instead of check and remove \ud83e\uddea \ud83d\udee0\ufe0f FURB136 if-expr-min-max Replace if expression with {min_max} call \u2714\ufe0f \ud83d\udee0\ufe0f FURB140 reimplemented-starmap Use itertools.starmap instead of the generator \ud83e\uddea \ud83d\udee0\ufe0f FURB142 for-loop-set-mutations Use of set.{}() in a for loop \ud83e\uddea \ud83d\udee0\ufe0f FURB145 slice-copy Prefer copy method over slicing \ud83e\uddea \ud83d\udee0\ufe0f FURB148 unnecessary-enumerate enumerate value is unused, use for x in range(len(y)) instead \ud83e\uddea \ud83d\udee0\ufe0f FURB152 math-constant Replace {literal} with math.{constant} \ud83e\uddea \ud83d\udee0\ufe0f FURB154 repeated-global Use of repeated consecutive {} \ud83e\uddea \ud83d\udee0\ufe0f FURB156 hardcoded-string-charset Use of hardcoded string charset \ud83e\uddea \ud83d\udee0\ufe0f FURB157 verbose-decimal-constructor Verbose expression in Decimal constructor \ud83e\uddea \ud83d\udee0\ufe0f FURB161 bit-count Use of bin({existing}).count('1') \u2714\ufe0f \ud83d\udee0\ufe0f FURB162 fromisoformat-replace-z Unnecessary timezone replacement with zero offset \ud83e\uddea \ud83d\udee0\ufe0f FURB163 redundant-log-base Prefer math.{log_function}({arg}) over math.log with a redundant base \u2714\ufe0f \ud83d\udee0\ufe0f FURB164 unnecessary-from-float Verbose method {method_name} in {constructor} construction \ud83e\uddea \ud83d\udee0\ufe0f FURB166 int-on-sliced-str Use of int with explicit base={base} after removing prefix \ud83e\uddea \ud83d\udee0\ufe0f FURB167 regex-flag-alias Use of regular expression alias re.{} \u2714\ufe0f \ud83d\udee0\ufe0f FURB168 isinstance-type-none Prefer is operator over isinstance to check if an object is None \u2714\ufe0f \ud83d\udee0\ufe0f FURB169 type-none-comparison When checking against None, use {} instead of comparison with type(None) \u2714\ufe0f \ud83d\udee0\ufe0f FURB171 single-item-membership-test Membership test against single-item container \ud83e\uddea \ud83d\udee0\ufe0f FURB177 implicit-cwd Prefer Path.cwd() over Path().resolve() for current-directory lookups \u2714\ufe0f \ud83d\udee0\ufe0f FURB180 meta-class-abc-meta Use of metaclass=abc.ABCMeta to define abstract base class \ud83e\uddea \ud83d\udee0\ufe0f FURB181 hashlib-digest-hex Use of hashlib's .digest().hex() \u2714\ufe0f \ud83d\udee0\ufe0f FURB187 list-reverse-copy Use of assignment of reversed on list {name} \u2714\ufe0f \ud83d\udee0\ufe0f FURB188 slice-to-remove-prefix-or-suffix Prefer str.removeprefix() over conditionally replacing with slice. \u2714\ufe0f \ud83d\udee0\ufe0f FURB189 subclass-builtin Subclassing {subclass} can be error prone, use collections.{replacement} instead \ud83e\uddea \ud83d\udee0\ufe0f FURB192 sorted-min-max Prefer min over sorted() to compute the minimum value in a sequence \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#ruff-specific-rules-ruf","title":"Ruff-specific rules (RUF)","text":"Code Name Message RUF001 ambiguous-unicode-character-string String contains ambiguous {}. Did you mean {}? \u2714\ufe0f \ud83d\udee0\ufe0f RUF002 ambiguous-unicode-character-docstring Docstring contains ambiguous {}. Did you mean {}? \u2714\ufe0f \ud83d\udee0\ufe0f RUF003 ambiguous-unicode-character-comment Comment contains ambiguous {}. Did you mean {}? \u2714\ufe0f \ud83d\udee0\ufe0f RUF005 collection-literal-concatenation Consider {expression} instead of concatenation \u2714\ufe0f \ud83d\udee0\ufe0f RUF006 asyncio-dangling-task Store a reference to the return value of {expr}.{method} \u2714\ufe0f \ud83d\udee0\ufe0f RUF007 zip-instead-of-pairwise Prefer itertools.pairwise() over zip() when iterating over successive pairs \u2714\ufe0f \ud83d\udee0\ufe0f RUF008 mutable-dataclass-default Do not use mutable default values for dataclass attributes \u2714\ufe0f \ud83d\udee0\ufe0f RUF009 function-call-in-dataclass-default-argument Do not perform function call {name} in dataclass defaults \u2714\ufe0f \ud83d\udee0\ufe0f RUF010 explicit-f-string-type-conversion Use explicit conversion flag \u2714\ufe0f \ud83d\udee0\ufe0f RUF011 ruff-static-key-dict-comprehension Dictionary comprehension uses static key \u274c \ud83d\udee0\ufe0f RUF012 mutable-class-default Mutable class attributes should be annotated with typing.ClassVar \u2714\ufe0f \ud83d\udee0\ufe0f RUF013 implicit-optional PEP 484 prohibits implicit Optional \u2714\ufe0f \ud83d\udee0\ufe0f RUF015 unnecessary-iterable-allocation-for-first-element Prefer next({iterable}) over single element slice \u2714\ufe0f \ud83d\udee0\ufe0f RUF016 invalid-index-type Slice in indexed access to type {value_type} uses type {index_type} instead of an integer \u2714\ufe0f \ud83d\udee0\ufe0f RUF017 quadratic-list-summation Avoid quadratic list summation \u2714\ufe0f \ud83d\udee0\ufe0f RUF018 assignment-in-assert Avoid assignment expressions in assert statements \u2714\ufe0f \ud83d\udee0\ufe0f RUF019 unnecessary-key-check Unnecessary key check before dictionary access \u2714\ufe0f \ud83d\udee0\ufe0f RUF020 never-union {never_like} | T is equivalent to T \u2714\ufe0f \ud83d\udee0\ufe0f RUF021 parenthesize-chained-operators Parenthesize a and b expressions when chaining and and or together, to make the precedence clear \u2714\ufe0f \ud83d\udee0\ufe0f RUF022 unsorted-dunder-all __all__ is not sorted \u2714\ufe0f \ud83d\udee0\ufe0f RUF023 unsorted-dunder-slots {}.__slots__ is not sorted \u2714\ufe0f \ud83d\udee0\ufe0f RUF024 mutable-fromkeys-value Do not pass mutable objects as values to dict.fromkeys \u2714\ufe0f \ud83d\udee0\ufe0f RUF026 default-factory-kwarg default_factory is a positional-only argument to defaultdict \u2714\ufe0f \ud83d\udee0\ufe0f RUF027 missing-f-string-syntax Possible f-string without an f prefix \ud83e\uddea \ud83d\udee0\ufe0f RUF028 invalid-formatter-suppression-comment This suppression comment is invalid because {} \ud83e\uddea \ud83d\udee0\ufe0f RUF029 unused-async Function {name} is declared async, but doesn't await or use async features. \ud83e\uddea \ud83d\udee0\ufe0f RUF030 assert-with-print-message print() call in assert statement is likely unintentional \u2714\ufe0f \ud83d\udee0\ufe0f RUF031 incorrectly-parenthesized-tuple-in-subscript Use parentheses for tuples in subscripts \ud83e\uddea \ud83d\udee0\ufe0f RUF032 decimal-from-float-literal Decimal() called with float literal argument \u2714\ufe0f \ud83d\udee0\ufe0f RUF033 post-init-default __post_init__ method with argument defaults \u2714\ufe0f \ud83d\udee0\ufe0f RUF034 useless-if-else Useless if-else condition \u2714\ufe0f \ud83d\udee0\ufe0f RUF035 ruff-unsafe-markup-use Unsafe use of {name} detected \u274c \ud83d\udee0\ufe0f RUF036 none-not-at-end-of-union None not at the end of the type annotation. \ud83e\uddea \ud83d\udee0\ufe0f RUF037 unnecessary-empty-iterable-within-deque-call Unnecessary empty iterable within a deque call \ud83e\uddea \ud83d\udee0\ufe0f RUF038 redundant-bool-literal Literal[True, False, ...] can be replaced with Literal[...] | bool \ud83e\uddea \ud83d\udee0\ufe0f RUF039 unraw-re-pattern First argument to {call} is not raw string \ud83e\uddea \ud83d\udee0\ufe0f RUF040 invalid-assert-message-literal-argument Non-string literal used as assert message \u2714\ufe0f \ud83d\udee0\ufe0f RUF041 unnecessary-nested-literal Unnecessary nested Literal \u2714\ufe0f \ud83d\udee0\ufe0f RUF043 pytest-raises-ambiguous-pattern Pattern passed to match= contains metacharacters but is neither escaped nor raw \ud83e\uddea \ud83d\udee0\ufe0f RUF045 implicit-class-var-in-dataclass Assignment without annotation found in dataclass body \ud83e\uddea \ud83d\udee0\ufe0f RUF046 unnecessary-cast-to-int Value being cast to int is already an integer \u2714\ufe0f \ud83d\udee0\ufe0f RUF047 needless-else Empty else clause \ud83e\uddea \ud83d\udee0\ufe0f RUF048 map-int-version-parsing __version__ may contain non-integral-like elements \u2714\ufe0f \ud83d\udee0\ufe0f RUF049 dataclass-enum An enum class should not be decorated with @dataclass \ud83e\uddea \ud83d\udee0\ufe0f RUF051 if-key-in-dict-del Use pop instead of key in dict followed by del dict[key] \u2714\ufe0f \ud83d\udee0\ufe0f RUF052 used-dummy-variable Local dummy variable {} is accessed \ud83e\uddea \ud83d\udee0\ufe0f RUF053 class-with-mixed-type-vars Class with type parameter list inherits from Generic \ud83e\uddea \ud83d\udee0\ufe0f RUF054 indented-form-feed Indented form feed \ud83e\uddea \ud83d\udee0\ufe0f RUF055 unnecessary-regular-expression Plain string pattern passed to re function \ud83e\uddea \ud83d\udee0\ufe0f RUF056 falsy-dict-get-fallback Avoid providing a falsy fallback to dict.get() in boolean test positions. The default fallback None is already falsy. \ud83e\uddea \ud83d\udee0\ufe0f RUF057 unnecessary-round Value being rounded is already an integer \ud83e\uddea \ud83d\udee0\ufe0f RUF058 starmap-zip itertools.starmap called on zip iterable \ud83e\uddea \ud83d\udee0\ufe0f RUF059 unused-unpacked-variable Unpacked variable {name} is never used \ud83e\uddea \ud83d\udee0\ufe0f RUF060 in-empty-collection Unnecessary membership test on empty collection \ud83e\uddea \ud83d\udee0\ufe0f RUF100 unused-noqa Unused noqa directive \u2714\ufe0f \ud83d\udee0\ufe0f RUF101 redirected-noqa {original} is a redirect to {target} \u2714\ufe0f \ud83d\udee0\ufe0f RUF102 invalid-rule-code Invalid rule code in # noqa: {} \ud83e\uddea \ud83d\udee0\ufe0f RUF200 invalid-pyproject-toml Failed to parse pyproject.toml: {message} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#tryceratops-try","title":"tryceratops (TRY)","text":"

        For more, see tryceratops on PyPI.

        Code Name Message TRY002 raise-vanilla-class Create your own exception \u2714\ufe0f \ud83d\udee0\ufe0f TRY003 raise-vanilla-args Avoid specifying long messages outside the exception class \u2714\ufe0f \ud83d\udee0\ufe0f TRY004 type-check-without-type-error Prefer TypeError exception for invalid type \u2714\ufe0f \ud83d\udee0\ufe0f TRY200 reraise-no-cause Use raise from to specify exception cause \u274c \ud83d\udee0\ufe0f TRY201 verbose-raise Use raise without specifying exception name \u2714\ufe0f \ud83d\udee0\ufe0f TRY203 useless-try-except Remove exception handler; error is immediately re-raised \u2714\ufe0f \ud83d\udee0\ufe0f TRY300 try-consider-else Consider moving this statement to an else block \u2714\ufe0f \ud83d\udee0\ufe0f TRY301 raise-within-try Abstract raise to an inner function \u2714\ufe0f \ud83d\udee0\ufe0f TRY400 error-instead-of-exception Use logging.exception instead of logging.error \u2714\ufe0f \ud83d\udee0\ufe0f TRY401 verbose-log-message Redundant exception object included in logging.exception call \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"settings/","title":"Settings","text":""},{"location":"settings/#top-level","title":"Top-level","text":""},{"location":"settings/#builtins","title":"builtins","text":"

        A list of builtins to treat as defined references, in addition to the system builtins.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nbuiltins = [\"_\"]\n
        builtins = [\"_\"]\n
        "},{"location":"settings/#cache-dir","title":"cache-dir","text":"

        A path to the cache directory.

        By default, Ruff stores cache results in a .ruff_cache directory in the current project root.

        However, Ruff will also respect the RUFF_CACHE_DIR environment variable, which takes precedence over that default.

        This setting will override even the RUFF_CACHE_DIR environment variable, if set.

        Default value: \".ruff_cache\"

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\ncache-dir = \"~/.cache/ruff\"\n
        cache-dir = \"~/.cache/ruff\"\n
        "},{"location":"settings/#exclude","title":"exclude","text":"

        A list of file patterns to exclude from formatting and linting.

        Exclusions are based on globs, and can be either:

        • Single-path patterns, like .mypy_cache (to exclude any directory named .mypy_cache in the tree), foo.py (to exclude any file named foo.py), or foo_*.py (to exclude any file matching foo_*.py ).
        • Relative patterns, like directory/foo.py (to exclude that specific file) or directory/*.py (to exclude any Python files in directory). Note that these paths are relative to the project root (e.g., the directory containing your pyproject.toml).

        For more information on the glob syntax, refer to the globset documentation.

        Note that you'll typically want to use extend-exclude to modify the excluded paths.

        Default value: [\".bzr\", \".direnv\", \".eggs\", \".git\", \".git-rewrite\", \".hg\", \".mypy_cache\", \".nox\", \".pants.d\", \".pytype\", \".ruff_cache\", \".svn\", \".tox\", \".venv\", \"__pypackages__\", \"_build\", \"buck-out\", \"dist\", \"node_modules\", \"venv\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nexclude = [\".venv\"]\n
        exclude = [\".venv\"]\n
        "},{"location":"settings/#extend","title":"extend","text":"

        A path to a local pyproject.toml file to merge into this configuration. User home directory and environment variables will be expanded.

        To resolve the current pyproject.toml file, Ruff will first resolve this base configuration file, then merge in any properties defined in the current configuration file.

        Default value: null

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Extend the `pyproject.toml` file in the parent directory.\nextend = \"../pyproject.toml\"\n# But use a different line length.\nline-length = 100\n
        # Extend the `pyproject.toml` file in the parent directory.\nextend = \"../pyproject.toml\"\n# But use a different line length.\nline-length = 100\n
        "},{"location":"settings/#extend-exclude","title":"extend-exclude","text":"

        A list of file patterns to omit from formatting and linting, in addition to those specified by exclude.

        Exclusions are based on globs, and can be either:

        • Single-path patterns, like .mypy_cache (to exclude any directory named .mypy_cache in the tree), foo.py (to exclude any file named foo.py), or foo_*.py (to exclude any file matching foo_*.py ).
        • Relative patterns, like directory/foo.py (to exclude that specific file) or directory/*.py (to exclude any Python files in directory). Note that these paths are relative to the project root (e.g., the directory containing your pyproject.toml).

        For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# In addition to the standard set of exclusions, omit all tests, plus a specific file.\nextend-exclude = [\"tests\", \"src/bad.py\"]\n
        # In addition to the standard set of exclusions, omit all tests, plus a specific file.\nextend-exclude = [\"tests\", \"src/bad.py\"]\n
        "},{"location":"settings/#extend-include","title":"extend-include","text":"

        A list of file patterns to include when linting, in addition to those specified by include.

        Inclusion are based on globs, and should be single-path patterns, like *.pyw, to include any file with the .pyw extension.

        For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# In addition to the standard set of inclusions, include `.pyw` files.\nextend-include = [\"*.pyw\"]\n
        # In addition to the standard set of inclusions, include `.pyw` files.\nextend-include = [\"*.pyw\"]\n
        "},{"location":"settings/#fix","title":"fix","text":"

        Enable fix behavior by-default when running ruff (overridden by the --fix and --no-fix command-line flags). Only includes automatic fixes unless --unsafe-fixes is provided.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nfix = true\n
        fix = true\n
        "},{"location":"settings/#fix-only","title":"fix-only","text":"

        Like fix, but disables reporting on leftover violation. Implies fix.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nfix-only = true\n
        fix-only = true\n
        "},{"location":"settings/#force-exclude","title":"force-exclude","text":"

        Whether to enforce exclude and extend-exclude patterns, even for paths that are passed to Ruff explicitly. Typically, Ruff will lint any paths passed in directly, even if they would typically be excluded. Setting force-exclude = true will cause Ruff to respect these exclusions unequivocally.

        This is useful for pre-commit, which explicitly passes all changed files to the ruff-pre-commit plugin, regardless of whether they're marked as excluded by Ruff's own settings.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nforce-exclude = true\n
        force-exclude = true\n
        "},{"location":"settings/#include","title":"include","text":"

        A list of file patterns to include when linting.

        Inclusion are based on globs, and should be single-path patterns, like *.pyw, to include any file with the .pyw extension. pyproject.toml is included here not for configuration but because we lint whether e.g. the [project] matches the schema.

        Notebook files (.ipynb extension) are included by default on Ruff 0.6.0+.

        For more information on the glob syntax, refer to the globset documentation.

        Default value: [\"*.py\", \"*.pyi\", \"*.ipynb\", \"**/pyproject.toml\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\ninclude = [\"*.py\"]\n
        include = [\"*.py\"]\n
        "},{"location":"settings/#indent-width","title":"indent-width","text":"

        The number of spaces per indentation level (tab).

        Used by the formatter and when enforcing long-line violations (like E501) to determine the visual width of a tab.

        This option changes the number of spaces the formatter inserts when using soft-tabs (indent-style = space).

        PEP 8 recommends using 4 spaces per indentation level.

        Default value: 4

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nindent-width = 2\n
        indent-width = 2\n
        "},{"location":"settings/#line-length","title":"line-length","text":"

        The line length to use when enforcing long-lines violations (like E501) and at which isort and the formatter prefers to wrap lines.

        The length is determined by the number of characters per line, except for lines containing East Asian characters or emojis. For these lines, the unicode width of each character is added up to determine the length.

        The value must be greater than 0 and less than or equal to 320.

        Note: While the formatter will attempt to format lines such that they remain within the line-length, it isn't a hard upper bound, and formatted lines may exceed the line-length.

        See pycodestyle.max-line-length to configure different lengths for E501 and the formatter.

        Default value: 88

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Allow lines to be as long as 120.\nline-length = 120\n
        # Allow lines to be as long as 120.\nline-length = 120\n
        "},{"location":"settings/#namespace-packages","title":"namespace-packages","text":"

        Mark the specified directories as namespace packages. For the purpose of module resolution, Ruff will treat those directories and all their subdirectories as if they contained an __init__.py file.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nnamespace-packages = [\"airflow/providers\"]\n
        namespace-packages = [\"airflow/providers\"]\n
        "},{"location":"settings/#output-format","title":"output-format","text":"

        The style in which violation messages should be formatted: \"full\" (default) (shows source), \"concise\", \"grouped\" (group messages by file), \"json\" (machine-readable), \"junit\" (machine-readable XML), \"github\" (GitHub Actions annotations), \"gitlab\" (GitLab CI code quality report), \"pylint\" (Pylint text format) or \"azure\" (Azure Pipeline logging commands).

        Default value: \"full\"

        Type: \"full\" | \"concise\" | \"grouped\" | \"json\" | \"junit\" | \"github\" | \"gitlab\" | \"pylint\" | \"azure\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Group violations by containing file.\noutput-format = \"grouped\"\n
        # Group violations by containing file.\noutput-format = \"grouped\"\n
        "},{"location":"settings/#per-file-target-version","title":"per-file-target-version","text":"

        A list of mappings from glob-style file pattern to Python version to use when checking the corresponding file(s).

        This may be useful for overriding the global Python version settings in target-version or requires-python for a subset of files. For example, if you have a project with a minimum supported Python version of 3.9 but a subdirectory of developer scripts that want to use a newer feature like the match statement from Python 3.10, you can use per-file-target-version to specify \"developer_scripts/*.py\" = \"py310\".

        This setting is used by the linter to enforce any enabled version-specific lint rules, as well as by the formatter for any version-specific formatting options, such as parenthesizing context managers on Python 3.10+.

        Default value: {}

        Type: dict[str, PythonVersion]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.per-file-target-version]\n# Override the project-wide Python version for a developer scripts directory:\n\"scripts/**.py\" = \"py312\"\n
        [per-file-target-version]\n# Override the project-wide Python version for a developer scripts directory:\n\"scripts/**.py\" = \"py312\"\n
        "},{"location":"settings/#preview","title":"preview","text":"

        Whether to enable preview mode. When preview mode is enabled, Ruff will use unstable rules, fixes, and formatting.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Enable preview features.\npreview = true\n
        # Enable preview features.\npreview = true\n
        "},{"location":"settings/#required-version","title":"required-version","text":"

        Enforce a requirement on the version of Ruff, to enforce at runtime. If the version of Ruff does not meet the requirement, Ruff will exit with an error.

        Useful for unifying results across many environments, e.g., with a pyproject.toml file.

        Accepts a PEP 440 specifier, like ==0.3.1 or >=0.3.1.

        Default value: null

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nrequired-version = \">=0.0.193\"\n
        required-version = \">=0.0.193\"\n
        "},{"location":"settings/#respect-gitignore","title":"respect-gitignore","text":"

        Whether to automatically exclude files that are ignored by .ignore, .gitignore, .git/info/exclude, and global gitignore files. Enabled by default.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nrespect-gitignore = false\n
        respect-gitignore = false\n
        "},{"location":"settings/#show-fixes","title":"show-fixes","text":"

        Whether to show an enumeration of all fixed lint violations (overridden by the --show-fixes command-line flag).

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Enumerate all fixed violations.\nshow-fixes = true\n
        # Enumerate all fixed violations.\nshow-fixes = true\n
        "},{"location":"settings/#src","title":"src","text":"

        The directories to consider when resolving first- vs. third-party imports.

        When omitted, the src directory will typically default to including both:

        1. The directory containing the nearest pyproject.toml, ruff.toml, or .ruff.toml file (the \"project root\").
        2. The \"src\" subdirectory of the project root.

        These defaults ensure that Ruff supports both flat layouts and src layouts out-of-the-box. (If a configuration file is explicitly provided (e.g., via the --config command-line flag), the current working directory will be considered the project root.)

        As an example, consider an alternative project structure, like:

        my_project\n\u251c\u2500\u2500 pyproject.toml\n\u2514\u2500\u2500 lib\n    \u2514\u2500\u2500 my_package\n        \u251c\u2500\u2500 __init__.py\n        \u251c\u2500\u2500 foo.py\n        \u2514\u2500\u2500 bar.py\n

        In this case, the ./lib directory should be included in the src option (e.g., src = [\"lib\"]), such that when resolving imports, my_package.foo is considered first-party.

        This field supports globs. For example, if you have a series of Python packages in a python_modules directory, src = [\"python_modules/*\"] would expand to incorporate all packages in that directory. User home directory and environment variables will also be expanded.

        Default value: [\".\", \"src\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Allow imports relative to the \"src\" and \"test\" directories.\nsrc = [\"src\", \"test\"]\n
        # Allow imports relative to the \"src\" and \"test\" directories.\nsrc = [\"src\", \"test\"]\n
        "},{"location":"settings/#target-version","title":"target-version","text":"

        The minimum Python version to target, e.g., when considering automatic code upgrades, like rewriting type annotations. Ruff will not propose changes using features that are not available in the given version.

        For example, to represent supporting Python >=3.10 or ==3.10 specify target-version = \"py310\".

        If you're already using a pyproject.toml file, we recommend project.requires-python instead, as it's based on Python packaging standards, and will be respected by other tools. For example, Ruff treats the following as identical to target-version = \"py38\":

        [project]\nrequires-python = \">=3.8\"\n

        If both are specified, target-version takes precedence over requires-python. See Inferring the Python version for a complete description of how the target-version is determined when left unspecified.

        Note that a stub file can sometimes make use of a typing feature before it is available at runtime, as long as the stub does not make use of new syntax. For example, a type checker will understand int | str in a stub as being a Union type annotation, even if the type checker is run using Python 3.9, despite the fact that the | operator can only be used to create union types at runtime on Python 3.10+. As such, Ruff will often recommend newer features in a stub file than it would for an equivalent runtime file with the same target version.

        Default value: \"py39\"

        Type: \"py37\" | \"py38\" | \"py39\" | \"py310\" | \"py311\" | \"py312\" | \"py313\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Always generate Python 3.7-compatible code.\ntarget-version = \"py37\"\n
        # Always generate Python 3.7-compatible code.\ntarget-version = \"py37\"\n
        "},{"location":"settings/#unsafe-fixes","title":"unsafe-fixes","text":"

        Enable application of unsafe fixes. If excluded, a hint will be displayed when unsafe fixes are available. If set to false, the hint will be hidden.

        Default value: null

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nunsafe-fixes = true\n
        unsafe-fixes = true\n
        "},{"location":"settings/#analyze","title":"analyze","text":"

        Configures Ruff's analyze command.

        "},{"location":"settings/#analyze_detect-string-imports","title":"detect-string-imports","text":"

        Whether to detect imports from string literals. When enabled, Ruff will search for string literals that \"look like\" import paths, and include them in the import map, if they resolve to valid Python modules.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.analyze]\ndetect-string-imports = true\n
        [analyze]\ndetect-string-imports = true\n
        "},{"location":"settings/#analyze_direction","title":"direction","text":"

        Whether to generate a map from file to files that it depends on (dependencies) or files that depend on it (dependents).

        Default value: \"dependencies\"

        Type: \"dependents\" | \"dependencies\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.analyze]\ndirection = \"dependencies\"\n
        [analyze]\ndirection = \"dependencies\"\n
        "},{"location":"settings/#analyze_exclude","title":"exclude","text":"

        A list of file patterns to exclude from analysis in addition to the files excluded globally (see exclude, and extend-exclude).

        Exclusions are based on globs, and can be either:

        • Single-path patterns, like .mypy_cache (to exclude any directory named .mypy_cache in the tree), foo.py (to exclude any file named foo.py), or foo_*.py (to exclude any file matching foo_*.py ).
        • Relative patterns, like directory/foo.py (to exclude that specific file) or directory/*.py (to exclude any Python files in directory). Note that these paths are relative to the project root (e.g., the directory containing your pyproject.toml).

        For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.analyze]\nexclude = [\"generated\"]\n
        [analyze]\nexclude = [\"generated\"]\n
        "},{"location":"settings/#analyze_include-dependencies","title":"include-dependencies","text":"

        A map from file path to the list of Python or non-Python file paths or globs that should be considered dependencies of that file, regardless of whether relevant imports are detected.

        Default value: {}

        Type: dict[str, list[str]]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.analyze.include-dependencies]\n\"foo/bar.py\" = [\"foo/baz/*.py\"]\n\"foo/baz/reader.py\" = [\"configs/bar.json\"]\n
        [analyze.include-dependencies]\n\"foo/bar.py\" = [\"foo/baz/*.py\"]\n\"foo/baz/reader.py\" = [\"configs/bar.json\"]\n
        "},{"location":"settings/#analyze_preview","title":"preview","text":"

        Whether to enable preview mode. When preview mode is enabled, Ruff will expose unstable commands.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.analyze]\n# Enable preview features.\npreview = true\n
        [analyze]\n# Enable preview features.\npreview = true\n
        "},{"location":"settings/#format","title":"format","text":"

        Configures the way Ruff formats your code.

        "},{"location":"settings/#format_docstring-code-format","title":"docstring-code-format","text":"

        Whether to format code snippets in docstrings.

        When this is enabled, Python code examples within docstrings are automatically reformatted.

        For example, when this is enabled, the following code:

        def f(x):\n    \"\"\"\n    Something about `f`. And an example in doctest format:\n\n    >>> f(  x  )\n\n    Markdown is also supported:\n\n    ```py\n    f(  x  )\n    ```\n\n    As are reStructuredText literal blocks::\n\n        f(  x  )\n\n\n    And reStructuredText code blocks:\n\n    .. code-block:: python\n\n        f(  x  )\n    \"\"\"\n    pass\n

        ... will be reformatted (assuming the rest of the options are set to their defaults) as:

        def f(x):\n    \"\"\"\n    Something about `f`. And an example in doctest format:\n\n    >>> f(x)\n\n    Markdown is also supported:\n\n    ```py\n    f(x)\n    ```\n\n    As are reStructuredText literal blocks::\n\n        f(x)\n\n\n    And reStructuredText code blocks:\n\n    .. code-block:: python\n\n        f(x)\n    \"\"\"\n    pass\n

        If a code snippet in a docstring contains invalid Python code or if the formatter would otherwise write invalid Python code, then the code example is ignored by the formatter and kept as-is.

        Currently, doctest, Markdown, reStructuredText literal blocks, and reStructuredText code blocks are all supported and automatically recognized. In the case of unlabeled fenced code blocks in Markdown and reStructuredText literal blocks, the contents are assumed to be Python and reformatted. As with any other format, if the contents aren't valid Python, then the block is left untouched automatically.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Enable reformatting of code snippets in docstrings.\ndocstring-code-format = true\n
        [format]\n# Enable reformatting of code snippets in docstrings.\ndocstring-code-format = true\n
        "},{"location":"settings/#format_docstring-code-line-length","title":"docstring-code-line-length","text":"

        Set the line length used when formatting code snippets in docstrings.

        This only has an effect when the docstring-code-format setting is enabled.

        The default value for this setting is \"dynamic\", which has the effect of ensuring that any reformatted code examples in docstrings adhere to the global line length configuration that is used for the surrounding Python code. The point of this setting is that it takes the indentation of the docstring into account when reformatting code examples.

        Alternatively, this can be set to a fixed integer, which will result in the same line length limit being applied to all reformatted code examples in docstrings. When set to a fixed integer, the indent of the docstring is not taken into account. That is, this may result in lines in the reformatted code example that exceed the globally configured line length limit.

        For example, when this is set to 20 and docstring-code-format is enabled, then this code:

        def f(x):\n    '''\n    Something about `f`. And an example:\n\n    .. code-block:: python\n\n        foo, bar, quux = this_is_a_long_line(lion, hippo, lemur, bear)\n    '''\n    pass\n

        ... will be reformatted (assuming the rest of the options are set to their defaults) as:

        def f(x):\n    \"\"\"\n    Something about `f`. And an example:\n\n    .. code-block:: python\n\n        (\n            foo,\n            bar,\n            quux,\n        ) = this_is_a_long_line(\n            lion,\n            hippo,\n            lemur,\n            bear,\n        )\n    \"\"\"\n    pass\n

        Default value: \"dynamic\"

        Type: int | \"dynamic\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Format all docstring code snippets with a line length of 60.\ndocstring-code-line-length = 60\n
        [format]\n# Format all docstring code snippets with a line length of 60.\ndocstring-code-line-length = 60\n
        "},{"location":"settings/#format_exclude","title":"exclude","text":"

        A list of file patterns to exclude from formatting in addition to the files excluded globally (see exclude, and extend-exclude).

        Exclusions are based on globs, and can be either:

        • Single-path patterns, like .mypy_cache (to exclude any directory named .mypy_cache in the tree), foo.py (to exclude any file named foo.py), or foo_*.py (to exclude any file matching foo_*.py ).
        • Relative patterns, like directory/foo.py (to exclude that specific file) or directory/*.py (to exclude any Python files in directory). Note that these paths are relative to the project root (e.g., the directory containing your pyproject.toml).

        For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\nexclude = [\"generated\"]\n
        [format]\nexclude = [\"generated\"]\n
        "},{"location":"settings/#format_indent-style","title":"indent-style","text":"

        Whether to use spaces or tabs for indentation.

        indent-style = \"space\" (default):

        def f():\n    print(\"Hello\") #  Spaces indent the `print` statement.\n

        indent-style = \"tab\":

        def f():\n    print(\"Hello\") #  A tab `\\t` indents the `print` statement.\n

        PEP 8 recommends using spaces for indentation. We care about accessibility; if you do not need tabs for accessibility, we do not recommend you use them.

        See indent-width to configure the number of spaces per indentation and the tab width.

        Default value: \"space\"

        Type: \"space\" | \"tab\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Use tabs instead of 4 space indentation.\nindent-style = \"tab\"\n
        [format]\n# Use tabs instead of 4 space indentation.\nindent-style = \"tab\"\n
        "},{"location":"settings/#format_line-ending","title":"line-ending","text":"

        The character Ruff uses at the end of a line.

        • auto: The newline style is detected automatically on a file per file basis. Files with mixed line endings will be converted to the first detected line ending. Defaults to \\n for files that contain no line endings.
        • lf: Line endings will be converted to \\n. The default line ending on Unix.
        • cr-lf: Line endings will be converted to \\r\\n. The default line ending on Windows.
        • native: Line endings will be converted to \\n on Unix and \\r\\n on Windows.

        Default value: \"auto\"

        Type: \"auto\" | \"lf\" | \"cr-lf\" | \"native\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Use `\\n` line endings for all files\nline-ending = \"lf\"\n
        [format]\n# Use `\\n` line endings for all files\nline-ending = \"lf\"\n
        "},{"location":"settings/#format_preview","title":"preview","text":"

        Whether to enable the unstable preview style formatting.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Enable preview style formatting.\npreview = true\n
        [format]\n# Enable preview style formatting.\npreview = true\n
        "},{"location":"settings/#format_quote-style","title":"quote-style","text":"

        Configures the preferred quote character for strings. The recommended options are

        • double (default): Use double quotes \"
        • single: Use single quotes '

        In compliance with PEP 8 and PEP 257, Ruff prefers double quotes for triple quoted strings and docstrings even when using quote-style = \"single\".

        Ruff deviates from using the configured quotes if doing so prevents the need for escaping quote characters inside the string:

        a = \"a string without any quotes\"\nb = \"It's monday morning\"\n

        Ruff will change the quotes of the string assigned to a to single quotes when using quote-style = \"single\". However, Ruff uses double quotes for the string assigned to b because using single quotes would require escaping the ', which leads to the less readable code: 'It\\'s monday morning'.

        In addition, Ruff supports the quote style preserve for projects that already use a mixture of single and double quotes and can't migrate to the double or single style. The quote style preserve leaves the quotes of all strings unchanged.

        Default value: \"double\"

        Type: \"double\" | \"single\" | \"preserve\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Prefer single quotes over double quotes.\nquote-style = \"single\"\n
        [format]\n# Prefer single quotes over double quotes.\nquote-style = \"single\"\n
        "},{"location":"settings/#format_skip-magic-trailing-comma","title":"skip-magic-trailing-comma","text":"

        Ruff uses existing trailing commas as an indication that short lines should be left separate. If this option is set to true, the magic trailing comma is ignored.

        For example, Ruff leaves the arguments separate even though collapsing the arguments to a single line doesn't exceed the line length if skip-magic-trailing-comma = false:

        # The arguments remain on separate lines because of the trailing comma after `b`\ndef test(\n    a,\n    b,\n): pass\n

        Setting skip-magic-trailing-comma = true changes the formatting to:

        # The arguments remain on separate lines because of the trailing comma after `b`\ndef test(a, b):\n    pass\n

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\nskip-magic-trailing-comma = true\n
        [format]\nskip-magic-trailing-comma = true\n
        "},{"location":"settings/#lint","title":"lint","text":"

        Configures how Ruff checks your code.

        Options specified in the lint section take precedence over the deprecated top-level settings.

        "},{"location":"settings/#lint_allowed-confusables","title":"allowed-confusables","text":"

        A list of allowed \"confusable\" Unicode characters to ignore when enforcing RUF001, RUF002, and RUF003.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Allow minus-sign (U+2212), greek-small-letter-rho (U+03C1), and the asterisk-operator (U+2217),\n# which could be confused for \"-\", \"p\", and \"*\", respectively.\nallowed-confusables = [\"\u2212\", \"\u03c1\", \"\u2217\"]\n
        [lint]\n# Allow minus-sign (U+2212), greek-small-letter-rho (U+03C1), and the asterisk-operator (U+2217),\n# which could be confused for \"-\", \"p\", and \"*\", respectively.\nallowed-confusables = [\"\u2212\", \"\u03c1\", \"\u2217\"]\n
        "},{"location":"settings/#lint_dummy-variable-rgx","title":"dummy-variable-rgx","text":"

        A regular expression used to identify \"dummy\" variables, or those which should be ignored when enforcing (e.g.) unused-variable rules. The default expression matches _, __, and _var, but not _var_.

        Default value: \"^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$\"

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Only ignore variables named \"_\".\ndummy-variable-rgx = \"^_$\"\n
        [lint]\n# Only ignore variables named \"_\".\ndummy-variable-rgx = \"^_$\"\n
        "},{"location":"settings/#lint_exclude","title":"exclude","text":"

        A list of file patterns to exclude from linting in addition to the files excluded globally (see exclude, and extend-exclude).

        Exclusions are based on globs, and can be either:

        • Single-path patterns, like .mypy_cache (to exclude any directory named .mypy_cache in the tree), foo.py (to exclude any file named foo.py), or foo_*.py (to exclude any file matching foo_*.py ).
        • Relative patterns, like directory/foo.py (to exclude that specific file) or directory/*.py (to exclude any Python files in directory). Note that these paths are relative to the project root (e.g., the directory containing your pyproject.toml).

        For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nexclude = [\"generated\"]\n
        [lint]\nexclude = [\"generated\"]\n
        "},{"location":"settings/#lint_explicit-preview-rules","title":"explicit-preview-rules","text":"

        Whether to require exact codes to select preview rules. When enabled, preview rules will not be selected by prefixes \u2014 the full code of each preview rule will be required to enable the rule.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Require explicit selection of preview rules.\nexplicit-preview-rules = true\n
        [lint]\n# Require explicit selection of preview rules.\nexplicit-preview-rules = true\n
        "},{"location":"settings/#lint_extend-fixable","title":"extend-fixable","text":"

        A list of rule codes or prefixes to consider fixable, in addition to those specified by fixable.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Enable fix for flake8-bugbear (`B`), on top of any rules specified by `fixable`.\nextend-fixable = [\"B\"]\n
        [lint]\n# Enable fix for flake8-bugbear (`B`), on top of any rules specified by `fixable`.\nextend-fixable = [\"B\"]\n
        "},{"location":"settings/#lint_extend-ignore","title":"extend-ignore","text":"

        Deprecated

        This option has been deprecated. The extend-ignore option is now interchangeable with ignore. Please update your configuration to use the ignore option instead.

        A list of rule codes or prefixes to ignore, in addition to those specified by ignore.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Skip unused variable rules (`F841`).\nextend-ignore = [\"F841\"]\n
        [lint]\n# Skip unused variable rules (`F841`).\nextend-ignore = [\"F841\"]\n
        "},{"location":"settings/#lint_extend-per-file-ignores","title":"extend-per-file-ignores","text":"

        A list of mappings from file pattern to rule codes or prefixes to exclude, in addition to any rules excluded by per-file-ignores.

        Default value: {}

        Type: dict[str, list[RuleSelector]]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.extend-per-file-ignores]\n# Also ignore `E402` in all `__init__.py` files.\n\"__init__.py\" = [\"E402\"]\n
        [lint.extend-per-file-ignores]\n# Also ignore `E402` in all `__init__.py` files.\n\"__init__.py\" = [\"E402\"]\n
        "},{"location":"settings/#lint_extend-safe-fixes","title":"extend-safe-fixes","text":"

        A list of rule codes or prefixes for which unsafe fixes should be considered safe.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Allow applying all unsafe fixes in the `E` rules and `F401` without the `--unsafe-fixes` flag\nextend-safe-fixes = [\"E\", \"F401\"]\n
        [lint]\n# Allow applying all unsafe fixes in the `E` rules and `F401` without the `--unsafe-fixes` flag\nextend-safe-fixes = [\"E\", \"F401\"]\n
        "},{"location":"settings/#lint_extend-select","title":"extend-select","text":"

        A list of rule codes or prefixes to enable, in addition to those specified by select.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# On top of the default `select` (`E4`, E7`, `E9`, and `F`), enable flake8-bugbear (`B`) and flake8-quotes (`Q`).\nextend-select = [\"B\", \"Q\"]\n
        [lint]\n# On top of the default `select` (`E4`, E7`, `E9`, and `F`), enable flake8-bugbear (`B`) and flake8-quotes (`Q`).\nextend-select = [\"B\", \"Q\"]\n
        "},{"location":"settings/#lint_extend-unsafe-fixes","title":"extend-unsafe-fixes","text":"

        A list of rule codes or prefixes for which safe fixes should be considered unsafe.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Require the `--unsafe-fixes` flag when fixing the `E` rules and `F401`\nextend-unsafe-fixes = [\"E\", \"F401\"]\n
        [lint]\n# Require the `--unsafe-fixes` flag when fixing the `E` rules and `F401`\nextend-unsafe-fixes = [\"E\", \"F401\"]\n
        "},{"location":"settings/#lint_external","title":"external","text":"

        A list of rule codes or prefixes that are unsupported by Ruff, but should be preserved when (e.g.) validating # noqa directives. Useful for retaining # noqa directives that cover plugins not yet implemented by Ruff.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Avoiding flagging (and removing) any codes starting with `V` from any\n# `# noqa` directives, despite Ruff's lack of support for `vulture`.\nexternal = [\"V\"]\n
        [lint]\n# Avoiding flagging (and removing) any codes starting with `V` from any\n# `# noqa` directives, despite Ruff's lack of support for `vulture`.\nexternal = [\"V\"]\n
        "},{"location":"settings/#lint_fixable","title":"fixable","text":"

        A list of rule codes or prefixes to consider fixable. By default, all rules are considered fixable.

        Default value: [\"ALL\"]

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Only allow fix behavior for `E` and `F` rules.\nfixable = [\"E\", \"F\"]\n
        [lint]\n# Only allow fix behavior for `E` and `F` rules.\nfixable = [\"E\", \"F\"]\n
        "},{"location":"settings/#lint_ignore","title":"ignore","text":"

        A list of rule codes or prefixes to ignore. Prefixes can specify exact rules (like F841), entire categories (like F), or anything in between.

        When breaking ties between enabled and disabled rules (via select and ignore, respectively), more specific prefixes override less specific prefixes. ignore takes precedence over select if the same prefix appears in both.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Skip unused variable rules (`F841`).\nignore = [\"F841\"]\n
        [lint]\n# Skip unused variable rules (`F841`).\nignore = [\"F841\"]\n
        "},{"location":"settings/#lint_ignore-init-module-imports","title":"ignore-init-module-imports","text":"

        Deprecated

        This option has been deprecated in 0.4.4. ignore-init-module-imports will be removed in a future version because F401 now recommends appropriate fixes for unused imports in __init__.py (currently in preview mode). See documentation for more information and please update your configuration.

        Avoid automatically removing unused imports in __init__.py files. Such imports will still be flagged, but with a dedicated message suggesting that the import is either added to the module's __all__ symbol, or re-exported with a redundant alias (e.g., import os as os).

        This option is enabled by default, but you can opt-in to removal of imports via an unsafe fix.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nignore-init-module-imports = false\n
        [lint]\nignore-init-module-imports = false\n
        "},{"location":"settings/#lint_logger-objects","title":"logger-objects","text":"

        A list of objects that should be treated equivalently to a logging.Logger object.

        This is useful for ensuring proper diagnostics (e.g., to identify logging deprecations and other best-practices) for projects that re-export a logging.Logger object from a common module.

        For example, if you have a module logging_setup.py with the following contents:

        import logging\n\nlogger = logging.getLogger(__name__)\n

        Adding \"logging_setup.logger\" to logger-objects will ensure that logging_setup.logger is treated as a logging.Logger object when imported from other modules (e.g., from logging_setup import logger).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nlogger-objects = [\"logging_setup.logger\"]\n
        [lint]\nlogger-objects = [\"logging_setup.logger\"]\n
        "},{"location":"settings/#lint_per-file-ignores","title":"per-file-ignores","text":"

        A list of mappings from file pattern to rule codes or prefixes to exclude, when considering any matching files. An initial '!' negates the file pattern.

        Default value: {}

        Type: dict[str, list[RuleSelector]]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.per-file-ignores]\n# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.\n\"__init__.py\" = [\"E402\"]\n\"path/to/file.py\" = [\"E402\"]\n# Ignore `D` rules everywhere except for the `src/` directory.\n\"!src/**.py\" = [\"D\"]\n
        [lint.per-file-ignores]\n# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.\n\"__init__.py\" = [\"E402\"]\n\"path/to/file.py\" = [\"E402\"]\n# Ignore `D` rules everywhere except for the `src/` directory.\n\"!src/**.py\" = [\"D\"]\n
        "},{"location":"settings/#lint_preview","title":"preview","text":"

        Whether to enable preview mode. When preview mode is enabled, Ruff will use unstable rules and fixes.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Enable preview features.\npreview = true\n
        [lint]\n# Enable preview features.\npreview = true\n
        "},{"location":"settings/#lint_select","title":"select","text":"

        A list of rule codes or prefixes to enable. Prefixes can specify exact rules (like F841), entire categories (like F), or anything in between.

        When breaking ties between enabled and disabled rules (via select and ignore, respectively), more specific prefixes override less specific prefixes. ignore takes precedence over select if the same prefix appears in both.

        Default value: [\"E4\", \"E7\", \"E9\", \"F\"]

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# On top of the defaults (`E4`, E7`, `E9`, and `F`), enable flake8-bugbear (`B`) and flake8-quotes (`Q`).\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"B\", \"Q\"]\n
        [lint]\n# On top of the defaults (`E4`, E7`, `E9`, and `F`), enable flake8-bugbear (`B`) and flake8-quotes (`Q`).\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"B\", \"Q\"]\n
        "},{"location":"settings/#lint_task-tags","title":"task-tags","text":"

        A list of task tags to recognize (e.g., \"TODO\", \"FIXME\", \"XXX\").

        Comments starting with these tags will be ignored by commented-out code detection (ERA), and skipped by line-length rules (E501) if ignore-overlong-task-comments is set to true.

        Default value: [\"TODO\", \"FIXME\", \"XXX\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\ntask-tags = [\"HACK\"]\n
        [lint]\ntask-tags = [\"HACK\"]\n
        "},{"location":"settings/#lint_typing-extensions","title":"typing-extensions","text":"

        Whether to allow imports from the third-party typing_extensions module for Python versions before a symbol was added to the first-party typing module.

        Many rules try to import symbols from the typing module but fall back to typing_extensions for earlier versions of Python. This option can be used to disable this fallback behavior in cases where typing_extensions is not installed.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Disable `typing_extensions` imports\ntyping-extensions = false\n
        [lint]\n# Disable `typing_extensions` imports\ntyping-extensions = false\n
        "},{"location":"settings/#lint_typing-modules","title":"typing-modules","text":"

        A list of modules whose exports should be treated equivalently to members of the typing module.

        This is useful for ensuring proper type annotation inference for projects that re-export typing and typing_extensions members from a compatibility module. If omitted, any members imported from modules apart from typing and typing_extensions will be treated as ordinary Python objects.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\ntyping-modules = [\"airflow.typing_compat\"]\n
        [lint]\ntyping-modules = [\"airflow.typing_compat\"]\n
        "},{"location":"settings/#lint_unfixable","title":"unfixable","text":"

        A list of rule codes or prefixes to consider non-fixable.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Disable fix for unused imports (`F401`).\nunfixable = [\"F401\"]\n
        [lint]\n# Disable fix for unused imports (`F401`).\nunfixable = [\"F401\"]\n
        "},{"location":"settings/#lintflake8-annotations","title":"lint.flake8-annotations","text":"

        Options for the flake8-annotations plugin.

        "},{"location":"settings/#lint_flake8-annotations_allow-star-arg-any","title":"allow-star-arg-any","text":"

        Whether to suppress ANN401 for dynamically typed *args and **kwargs arguments.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-annotations]\nallow-star-arg-any = true\n
        [lint.flake8-annotations]\nallow-star-arg-any = true\n
        "},{"location":"settings/#lint_flake8-annotations_ignore-fully-untyped","title":"ignore-fully-untyped","text":"

        Whether to suppress ANN* rules for any declaration that hasn't been typed at all. This makes it easier to gradually add types to a codebase.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-annotations]\nignore-fully-untyped = true\n
        [lint.flake8-annotations]\nignore-fully-untyped = true\n
        "},{"location":"settings/#lint_flake8-annotations_mypy-init-return","title":"mypy-init-return","text":"

        Whether to allow the omission of a return type hint for __init__ if at least one argument is annotated.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-annotations]\nmypy-init-return = true\n
        [lint.flake8-annotations]\nmypy-init-return = true\n
        "},{"location":"settings/#lint_flake8-annotations_suppress-dummy-args","title":"suppress-dummy-args","text":"

        Whether to suppress ANN000-level violations for arguments matching the \"dummy\" variable regex (like _).

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-annotations]\nsuppress-dummy-args = true\n
        [lint.flake8-annotations]\nsuppress-dummy-args = true\n
        "},{"location":"settings/#lint_flake8-annotations_suppress-none-returning","title":"suppress-none-returning","text":"

        Whether to suppress ANN200-level violations for functions that meet either of the following criteria:

        • Contain no return statement.
        • Explicit return statement(s) all return None (explicitly or implicitly).

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-annotations]\nsuppress-none-returning = true\n
        [lint.flake8-annotations]\nsuppress-none-returning = true\n
        "},{"location":"settings/#lintflake8-bandit","title":"lint.flake8-bandit","text":"

        Options for the flake8-bandit plugin.

        "},{"location":"settings/#lint_flake8-bandit_allowed-markup-calls","title":"allowed-markup-calls","text":"

        A list of callable names, whose result may be safely passed into markupsafe.Markup.

        Expects to receive a list of fully-qualified names (e.g., bleach.clean, rather than clean).

        This setting helps you avoid false positives in code like:

        from bleach import clean\nfrom markupsafe import Markup\n\ncleaned_markup = Markup(clean(some_user_input))\n

        Where the use of bleach.clean usually ensures that there's no XSS vulnerability.

        Although it is not recommended, you may also use this setting to whitelist other kinds of calls, e.g. calls to i18n translation functions, where how safe that is will depend on the implementation and how well the translations are audited.

        Another common use-case is to wrap the output of functions that generate markup like xml.etree.ElementTree.tostring or template rendering engines where sanitization of potential user input is either already baked in or has to happen before rendering.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bandit]\nallowed-markup-calls = [\"bleach.clean\", \"my_package.sanitize\"]\n
        [lint.flake8-bandit]\nallowed-markup-calls = [\"bleach.clean\", \"my_package.sanitize\"]\n
        "},{"location":"settings/#lint_flake8-bandit_check-typed-exception","title":"check-typed-exception","text":"

        Whether to disallow try-except-pass (S110) for specific exception types. By default, try-except-pass is only disallowed for Exception and BaseException.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bandit]\ncheck-typed-exception = true\n
        [lint.flake8-bandit]\ncheck-typed-exception = true\n
        "},{"location":"settings/#lint_flake8-bandit_extend-markup-names","title":"extend-markup-names","text":"

        A list of additional callable names that behave like markupsafe.Markup.

        Expects to receive a list of fully-qualified names (e.g., webhelpers.html.literal, rather than literal).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bandit]\nextend-markup-names = [\"webhelpers.html.literal\", \"my_package.Markup\"]\n
        [lint.flake8-bandit]\nextend-markup-names = [\"webhelpers.html.literal\", \"my_package.Markup\"]\n
        "},{"location":"settings/#lint_flake8-bandit_hardcoded-tmp-directory","title":"hardcoded-tmp-directory","text":"

        A list of directories to consider temporary (see S108).

        Default value: [\"/tmp\", \"/var/tmp\", \"/dev/shm\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bandit]\nhardcoded-tmp-directory = [\"/foo/bar\"]\n
        [lint.flake8-bandit]\nhardcoded-tmp-directory = [\"/foo/bar\"]\n
        "},{"location":"settings/#lint_flake8-bandit_hardcoded-tmp-directory-extend","title":"hardcoded-tmp-directory-extend","text":"

        A list of directories to consider temporary, in addition to those specified by hardcoded-tmp-directory (see S108).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bandit]\nhardcoded-tmp-directory-extend = [\"/foo/bar\"]\n
        [lint.flake8-bandit]\nhardcoded-tmp-directory-extend = [\"/foo/bar\"]\n
        "},{"location":"settings/#lintflake8-boolean-trap","title":"lint.flake8-boolean-trap","text":"

        Options for the flake8-boolean-trap plugin

        "},{"location":"settings/#lint_flake8-boolean-trap_extend-allowed-calls","title":"extend-allowed-calls","text":"

        Additional callable functions with which to allow boolean traps.

        Expects to receive a list of fully-qualified names (e.g., pydantic.Field, rather than Field).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-boolean-trap]\nextend-allowed-calls = [\"pydantic.Field\", \"django.db.models.Value\"]\n
        [lint.flake8-boolean-trap]\nextend-allowed-calls = [\"pydantic.Field\", \"django.db.models.Value\"]\n
        "},{"location":"settings/#lintflake8-bugbear","title":"lint.flake8-bugbear","text":"

        Options for the flake8-bugbear plugin.

        "},{"location":"settings/#lint_flake8-bugbear_extend-immutable-calls","title":"extend-immutable-calls","text":"

        Additional callable functions to consider \"immutable\" when evaluating, e.g., the function-call-in-default-argument rule (B008) or function-call-in-dataclass-defaults rule (RUF009).

        Expects to receive a list of fully-qualified names (e.g., fastapi.Query, rather than Query).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bugbear]\n# Allow default arguments like, e.g., `data: List[str] = fastapi.Query(None)`.\nextend-immutable-calls = [\"fastapi.Depends\", \"fastapi.Query\"]\n
        [lint.flake8-bugbear]\n# Allow default arguments like, e.g., `data: List[str] = fastapi.Query(None)`.\nextend-immutable-calls = [\"fastapi.Depends\", \"fastapi.Query\"]\n
        "},{"location":"settings/#lintflake8-builtins","title":"lint.flake8-builtins","text":"

        Options for the flake8-builtins plugin.

        "},{"location":"settings/#lint_flake8-builtins_allowed-modules","title":"allowed-modules","text":"

        List of builtin module names to allow.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nallowed-modules = [\"secrets\"]\n
        [lint.flake8-builtins]\nallowed-modules = [\"secrets\"]\n
        "},{"location":"settings/#lint_flake8-builtins_builtins-allowed-modules","title":"builtins-allowed-modules","text":"

        Deprecated

        This option has been deprecated in 0.10.0. builtins-allowed-modules has been renamed to allowed-modules. Use that instead.

        DEPRECATED: This option has been renamed to allowed-modules. Use allowed-modules instead.

        List of builtin module names to allow.

        This option is ignored if both allowed-modules and builtins-allowed-modules are set.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nbuiltins-allowed-modules = [\"secrets\"]\n
        [lint.flake8-builtins]\nbuiltins-allowed-modules = [\"secrets\"]\n
        "},{"location":"settings/#lint_flake8-builtins_builtins-ignorelist","title":"builtins-ignorelist","text":"

        Deprecated

        This option has been deprecated in 0.10.0. builtins-ignorelist has been renamed to ignorelist. Use that instead.

        DEPRECATED: This option has been renamed to ignorelist. Use ignorelist instead.

        Ignore list of builtins.

        This option is ignored if both ignorelist and builtins-ignorelist are set.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nbuiltins-ignorelist = [\"id\"]\n
        [lint.flake8-builtins]\nbuiltins-ignorelist = [\"id\"]\n
        "},{"location":"settings/#lint_flake8-builtins_builtins-strict-checking","title":"builtins-strict-checking","text":"

        Deprecated

        This option has been deprecated in 0.10.0. builtins-strict-checking has been renamed to strict-checking. Use that instead.

        DEPRECATED: This option has been renamed to strict-checking. Use strict-checking instead.

        Compare module names instead of full module paths.

        This option is ignored if both strict-checking and builtins-strict-checking are set.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nbuiltins-strict-checking = true\n
        [lint.flake8-builtins]\nbuiltins-strict-checking = true\n
        "},{"location":"settings/#lint_flake8-builtins_ignorelist","title":"ignorelist","text":"

        Ignore list of builtins.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nignorelist = [\"id\"]\n
        [lint.flake8-builtins]\nignorelist = [\"id\"]\n
        "},{"location":"settings/#lint_flake8-builtins_strict-checking","title":"strict-checking","text":"

        Compare module names instead of full module paths.

        Used by A005 - stdlib-module-shadowing.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nstrict-checking = true\n
        [lint.flake8-builtins]\nstrict-checking = true\n
        "},{"location":"settings/#lintflake8-comprehensions","title":"lint.flake8-comprehensions","text":"

        Options for the flake8-comprehensions plugin.

        "},{"location":"settings/#lint_flake8-comprehensions_allow-dict-calls-with-keyword-arguments","title":"allow-dict-calls-with-keyword-arguments","text":"

        Allow dict calls that make use of keyword arguments (e.g., dict(a=1, b=2)).

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-comprehensions]\nallow-dict-calls-with-keyword-arguments = true\n
        [lint.flake8-comprehensions]\nallow-dict-calls-with-keyword-arguments = true\n
        "},{"location":"settings/#lintflake8-copyright","title":"lint.flake8-copyright","text":"

        Options for the flake8-copyright plugin.

        "},{"location":"settings/#lint_flake8-copyright_author","title":"author","text":"

        Author to enforce within the copyright notice. If provided, the author must be present immediately following the copyright notice.

        Default value: null

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-copyright]\nauthor = \"Ruff\"\n
        [lint.flake8-copyright]\nauthor = \"Ruff\"\n
        "},{"location":"settings/#lint_flake8-copyright_min-file-size","title":"min-file-size","text":"

        A minimum file size (in bytes) required for a copyright notice to be enforced. By default, all files are validated.

        Default value: 0

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-copyright]\n# Avoid enforcing a header on files smaller than 1024 bytes.\nmin-file-size = 1024\n
        [lint.flake8-copyright]\n# Avoid enforcing a header on files smaller than 1024 bytes.\nmin-file-size = 1024\n
        "},{"location":"settings/#lint_flake8-copyright_notice-rgx","title":"notice-rgx","text":"

        The regular expression used to match the copyright notice, compiled with the regex crate. Defaults to (?i)Copyright\\s+((?:\\(C\\)|\u00a9)\\s+)?\\d{4}((-|,\\s)\\d{4})*, which matches the following:

        • Copyright 2023
        • Copyright (C) 2023
        • Copyright 2021-2023
        • Copyright (C) 2021-2023
        • Copyright (C) 2021, 2023

        Default value: \"(?i)Copyright\\s+((?:\\(C\\)|\u00a9)\\s+)?\\d{4}((-|,\\s)\\d{4})*\"

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-copyright]\nnotice-rgx = \"(?i)Copyright \\\\(C\\\\) \\\\d{4}\"\n
        [lint.flake8-copyright]\nnotice-rgx = \"(?i)Copyright \\\\(C\\\\) \\\\d{4}\"\n
        "},{"location":"settings/#lintflake8-errmsg","title":"lint.flake8-errmsg","text":"

        Options for the flake8-errmsg plugin.

        "},{"location":"settings/#lint_flake8-errmsg_max-string-length","title":"max-string-length","text":"

        Maximum string length for string literals in exception messages.

        Default value: 0

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-errmsg]\nmax-string-length = 20\n
        [lint.flake8-errmsg]\nmax-string-length = 20\n
        "},{"location":"settings/#lintflake8-gettext","title":"lint.flake8-gettext","text":"

        Options for the flake8-gettext plugin.

        "},{"location":"settings/#lint_flake8-gettext_extend-function-names","title":"extend-function-names","text":"

        Additional function names to consider as internationalization calls, in addition to those included in function-names.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-gettext]\nextend-function-names = [\"ugettetxt\"]\n
        [lint.flake8-gettext]\nextend-function-names = [\"ugettetxt\"]\n
        "},{"location":"settings/#lint_flake8-gettext_function-names","title":"function-names","text":"

        The function names to consider as internationalization calls.

        Default value: [\"_\", \"gettext\", \"ngettext\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-gettext]\nfunction-names = [\"_\", \"gettext\", \"ngettext\", \"ugettetxt\"]\n
        [lint.flake8-gettext]\nfunction-names = [\"_\", \"gettext\", \"ngettext\", \"ugettetxt\"]\n
        "},{"location":"settings/#lintflake8-implicit-str-concat","title":"lint.flake8-implicit-str-concat","text":"

        Options for the flake8-implicit-str-concat plugin

        "},{"location":"settings/#lint_flake8-implicit-str-concat_allow-multiline","title":"allow-multiline","text":"

        Whether to allow implicit string concatenations for multiline strings. By default, implicit concatenations of multiline strings are allowed (but continuation lines, delimited with a backslash, are prohibited).

        Setting allow-multiline = false will automatically disable the explicit-string-concatenation (ISC003) rule. Otherwise, both implicit and explicit multiline string concatenations would be seen as violations, making it impossible to write a linter-compliant multiline string.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-implicit-str-concat]\nallow-multiline = false\n
        [lint.flake8-implicit-str-concat]\nallow-multiline = false\n
        "},{"location":"settings/#lintflake8-import-conventions","title":"lint.flake8-import-conventions","text":"

        Options for the flake8-import-conventions plugin

        "},{"location":"settings/#lint_flake8-import-conventions_aliases","title":"aliases","text":"

        The conventional aliases for imports. These aliases can be extended by the extend-aliases option.

        Default value: {\"altair\": \"alt\", \"matplotlib\": \"mpl\", \"matplotlib.pyplot\": \"plt\", \"numpy\": \"np\", \"numpy.typing\": \"npt\", \"pandas\": \"pd\", \"seaborn\": \"sns\", \"tensorflow\": \"tf\", \"tkinter\": \"tk\", \"holoviews\": \"hv\", \"panel\": \"pn\", \"plotly.express\": \"px\", \"polars\": \"pl\", \"pyarrow\": \"pa\", \"xml.etree.ElementTree\": \"ET\"}

        Type: dict[str, str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-import-conventions.aliases]\n# Declare the default aliases.\naltair = \"alt\"\n\"matplotlib.pyplot\" = \"plt\"\nnumpy = \"np\"\npandas = \"pd\"\nseaborn = \"sns\"\nscipy = \"sp\"\n
        [lint.flake8-import-conventions.aliases]\n# Declare the default aliases.\naltair = \"alt\"\n\"matplotlib.pyplot\" = \"plt\"\nnumpy = \"np\"\npandas = \"pd\"\nseaborn = \"sns\"\nscipy = \"sp\"\n
        "},{"location":"settings/#lint_flake8-import-conventions_banned-aliases","title":"banned-aliases","text":"

        A mapping from module to its banned import aliases.

        Default value: {}

        Type: dict[str, list[str]]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-import-conventions.banned-aliases]\n# Declare the banned aliases.\n\"tensorflow.keras.backend\" = [\"K\"]\n
        [lint.flake8-import-conventions.banned-aliases]\n# Declare the banned aliases.\n\"tensorflow.keras.backend\" = [\"K\"]\n
        "},{"location":"settings/#lint_flake8-import-conventions_banned-from","title":"banned-from","text":"

        A list of modules that should not be imported from using the from ... import ... syntax.

        For example, given banned-from = [\"pandas\"], from pandas import DataFrame would be disallowed, while import pandas would be allowed.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-import-conventions]\n# Declare the banned `from` imports.\nbanned-from = [\"typing\"]\n
        [lint.flake8-import-conventions]\n# Declare the banned `from` imports.\nbanned-from = [\"typing\"]\n
        "},{"location":"settings/#lint_flake8-import-conventions_extend-aliases","title":"extend-aliases","text":"

        A mapping from module to conventional import alias. These aliases will be added to the aliases mapping.

        Default value: {}

        Type: dict[str, str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-import-conventions.extend-aliases]\n# Declare a custom alias for the `dask` module.\n\"dask.dataframe\" = \"dd\"\n
        [lint.flake8-import-conventions.extend-aliases]\n# Declare a custom alias for the `dask` module.\n\"dask.dataframe\" = \"dd\"\n
        "},{"location":"settings/#lintflake8-pytest-style","title":"lint.flake8-pytest-style","text":"

        Options for the flake8-pytest-style plugin

        "},{"location":"settings/#lint_flake8-pytest-style_fixture-parentheses","title":"fixture-parentheses","text":"

        Boolean flag specifying whether @pytest.fixture() without parameters should have parentheses. If the option is set to false (the default), @pytest.fixture is valid and @pytest.fixture() is invalid. If set to true, @pytest.fixture() is valid and @pytest.fixture is invalid.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nfixture-parentheses = true\n
        [lint.flake8-pytest-style]\nfixture-parentheses = true\n
        "},{"location":"settings/#lint_flake8-pytest-style_mark-parentheses","title":"mark-parentheses","text":"

        Boolean flag specifying whether @pytest.mark.foo() without parameters should have parentheses. If the option is set to false (the default), @pytest.mark.foo is valid and @pytest.mark.foo() is invalid. If set to true, @pytest.mark.foo() is valid and @pytest.mark.foo is invalid.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nmark-parentheses = true\n
        [lint.flake8-pytest-style]\nmark-parentheses = true\n
        "},{"location":"settings/#lint_flake8-pytest-style_parametrize-names-type","title":"parametrize-names-type","text":"

        Expected type for multiple argument names in @pytest.mark.parametrize. The following values are supported:

        • csv \u2014 a comma-separated list, e.g. @pytest.mark.parametrize(\"name1,name2\", ...)
        • tuple (default) \u2014 e.g. @pytest.mark.parametrize((\"name1\", \"name2\"), ...)
        • list \u2014 e.g. @pytest.mark.parametrize([\"name1\", \"name2\"], ...)

        Default value: tuple

        Type: \"csv\" | \"tuple\" | \"list\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nparametrize-names-type = \"list\"\n
        [lint.flake8-pytest-style]\nparametrize-names-type = \"list\"\n
        "},{"location":"settings/#lint_flake8-pytest-style_parametrize-values-row-type","title":"parametrize-values-row-type","text":"

        Expected type for each row of values in @pytest.mark.parametrize in case of multiple parameters. The following values are supported:

        • tuple (default) \u2014 e.g. @pytest.mark.parametrize((\"name1\", \"name2\"), [(1, 2), (3, 4)])
        • list \u2014 e.g. @pytest.mark.parametrize((\"name1\", \"name2\"), [[1, 2], [3, 4]])

        Default value: tuple

        Type: \"tuple\" | \"list\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nparametrize-values-row-type = \"list\"\n
        [lint.flake8-pytest-style]\nparametrize-values-row-type = \"list\"\n
        "},{"location":"settings/#lint_flake8-pytest-style_parametrize-values-type","title":"parametrize-values-type","text":"

        Expected type for the list of values rows in @pytest.mark.parametrize. The following values are supported:

        • tuple \u2014 e.g. @pytest.mark.parametrize(\"name\", (1, 2, 3))
        • list (default) \u2014 e.g. @pytest.mark.parametrize(\"name\", [1, 2, 3])

        Default value: list

        Type: \"tuple\" | \"list\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nparametrize-values-type = \"tuple\"\n
        [lint.flake8-pytest-style]\nparametrize-values-type = \"tuple\"\n
        "},{"location":"settings/#lint_flake8-pytest-style_raises-extend-require-match-for","title":"raises-extend-require-match-for","text":"

        List of additional exception names that require a match= parameter in a pytest.raises() call. This extends the default list of exceptions that require a match= parameter. This option is useful if you want to extend the default list of exceptions that require a match= parameter without having to specify the entire list. Note that this option does not remove any exceptions from the default list.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nraises-extend-require-match-for = [\"requests.RequestException\"]\n
        [lint.flake8-pytest-style]\nraises-extend-require-match-for = [\"requests.RequestException\"]\n
        "},{"location":"settings/#lint_flake8-pytest-style_raises-require-match-for","title":"raises-require-match-for","text":"

        List of exception names that require a match= parameter in a pytest.raises() call.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: [\"BaseException\", \"Exception\", \"ValueError\", \"OSError\", \"IOError\", \"EnvironmentError\", \"socket.error\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nraises-require-match-for = [\"requests.RequestException\"]\n
        [lint.flake8-pytest-style]\nraises-require-match-for = [\"requests.RequestException\"]\n
        "},{"location":"settings/#lint_flake8-pytest-style_warns-extend-require-match-for","title":"warns-extend-require-match-for","text":"

        List of additional warning names that require a match= parameter in a pytest.warns() call. This extends the default list of warnings that require a match= parameter.

        This option is useful if you want to extend the default list of warnings that require a match= parameter without having to specify the entire list.

        Note that this option does not remove any warnings from the default list.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nwarns-extend-require-match-for = [\"requests.RequestsWarning\"]\n
        [lint.flake8-pytest-style]\nwarns-extend-require-match-for = [\"requests.RequestsWarning\"]\n
        "},{"location":"settings/#lint_flake8-pytest-style_warns-require-match-for","title":"warns-require-match-for","text":"

        List of warning names that require a match= parameter in a pytest.warns() call.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: [\"Warning\", \"UserWarning\", \"DeprecationWarning\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nwarns-require-match-for = [\"requests.RequestsWarning\"]\n
        [lint.flake8-pytest-style]\nwarns-require-match-for = [\"requests.RequestsWarning\"]\n
        "},{"location":"settings/#lintflake8-quotes","title":"lint.flake8-quotes","text":"

        Options for the flake8-quotes plugin.

        "},{"location":"settings/#lint_flake8-quotes_avoid-escape","title":"avoid-escape","text":"

        Whether to avoid using single quotes if a string contains single quotes, or vice-versa with double quotes, as per PEP 8. This minimizes the need to escape quotation marks within strings.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-quotes]\n# Don't bother trying to avoid escapes.\navoid-escape = false\n
        [lint.flake8-quotes]\n# Don't bother trying to avoid escapes.\navoid-escape = false\n
        "},{"location":"settings/#lint_flake8-quotes_docstring-quotes","title":"docstring-quotes","text":"

        Quote style to prefer for docstrings (either \"single\" or \"double\").

        When using the formatter, only \"double\" is compatible, as the formatter enforces double quotes for docstrings strings.

        Default value: \"double\"

        Type: \"single\" | \"double\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-quotes]\ndocstring-quotes = \"single\"\n
        [lint.flake8-quotes]\ndocstring-quotes = \"single\"\n
        "},{"location":"settings/#lint_flake8-quotes_inline-quotes","title":"inline-quotes","text":"

        Quote style to prefer for inline strings (either \"single\" or \"double\").

        When using the formatter, ensure that format.quote-style is set to the same preferred quote style.

        Default value: \"double\"

        Type: \"single\" | \"double\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-quotes]\ninline-quotes = \"single\"\n
        [lint.flake8-quotes]\ninline-quotes = \"single\"\n
        "},{"location":"settings/#lint_flake8-quotes_multiline-quotes","title":"multiline-quotes","text":"

        Quote style to prefer for multiline strings (either \"single\" or \"double\").

        When using the formatter, only \"double\" is compatible, as the formatter enforces double quotes for multiline strings.

        Default value: \"double\"

        Type: \"single\" | \"double\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-quotes]\nmultiline-quotes = \"single\"\n
        [lint.flake8-quotes]\nmultiline-quotes = \"single\"\n
        "},{"location":"settings/#lintflake8-self","title":"lint.flake8-self","text":"

        Options for the flake8_self plugin.

        "},{"location":"settings/#lint_flake8-self_extend-ignore-names","title":"extend-ignore-names","text":"

        Additional names to ignore when considering flake8-self violations, in addition to those included in ignore-names.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-self]\nextend-ignore-names = [\"_base_manager\", \"_default_manager\",  \"_meta\"]\n
        [lint.flake8-self]\nextend-ignore-names = [\"_base_manager\", \"_default_manager\",  \"_meta\"]\n
        "},{"location":"settings/#lint_flake8-self_ignore-names","title":"ignore-names","text":"

        A list of names to ignore when considering flake8-self violations.

        Default value: [\"_make\", \"_asdict\", \"_replace\", \"_fields\", \"_field_defaults\", \"_name_\", \"_value_\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-self]\nignore-names = [\"_new\"]\n
        [lint.flake8-self]\nignore-names = [\"_new\"]\n
        "},{"location":"settings/#lintflake8-tidy-imports","title":"lint.flake8-tidy-imports","text":"

        Options for the flake8-tidy-imports plugin

        "},{"location":"settings/#lint_flake8-tidy-imports_ban-relative-imports","title":"ban-relative-imports","text":"

        Whether to ban all relative imports (\"all\"), or only those imports that extend into the parent module or beyond (\"parents\").

        Default value: \"parents\"

        Type: \"parents\" | \"all\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-tidy-imports]\n# Disallow all relative imports.\nban-relative-imports = \"all\"\n
        [lint.flake8-tidy-imports]\n# Disallow all relative imports.\nban-relative-imports = \"all\"\n
        "},{"location":"settings/#lint_flake8-tidy-imports_banned-api","title":"banned-api","text":"

        Specific modules or module members that may not be imported or accessed. Note that this rule is only meant to flag accidental uses, and can be circumvented via eval or importlib.

        Default value: {}

        Type: dict[str, { \"msg\": str }]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-tidy-imports.banned-api]\n\"cgi\".msg = \"The cgi module is deprecated, see https://peps.python.org/pep-0594/#cgi.\"\n\"typing.TypedDict\".msg = \"Use typing_extensions.TypedDict instead.\"\n
        [lint.flake8-tidy-imports.banned-api]\n\"cgi\".msg = \"The cgi module is deprecated, see https://peps.python.org/pep-0594/#cgi.\"\n\"typing.TypedDict\".msg = \"Use typing_extensions.TypedDict instead.\"\n
        "},{"location":"settings/#lint_flake8-tidy-imports_banned-module-level-imports","title":"banned-module-level-imports","text":"

        List of specific modules that may not be imported at module level, and should instead be imported lazily (e.g., within a function definition, or an if TYPE_CHECKING: block, or some other nested context).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-tidy-imports]\n# Ban certain modules from being imported at module level, instead requiring\n# that they're imported lazily (e.g., within a function definition).\nbanned-module-level-imports = [\"torch\", \"tensorflow\"]\n
        [lint.flake8-tidy-imports]\n# Ban certain modules from being imported at module level, instead requiring\n# that they're imported lazily (e.g., within a function definition).\nbanned-module-level-imports = [\"torch\", \"tensorflow\"]\n
        "},{"location":"settings/#lintflake8-type-checking","title":"lint.flake8-type-checking","text":"

        Options for the flake8-type-checking plugin

        "},{"location":"settings/#lint_flake8-type-checking_exempt-modules","title":"exempt-modules","text":"

        Exempt certain modules from needing to be moved into type-checking blocks.

        Default value: [\"typing\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-type-checking]\nexempt-modules = [\"typing\", \"typing_extensions\"]\n
        [lint.flake8-type-checking]\nexempt-modules = [\"typing\", \"typing_extensions\"]\n
        "},{"location":"settings/#lint_flake8-type-checking_quote-annotations","title":"quote-annotations","text":"

        Whether to add quotes around type annotations, if doing so would allow the corresponding import to be moved into a type-checking block.

        For example, in the following, Python requires that Sequence be available at runtime, despite the fact that it's only used in a type annotation:

        from collections.abc import Sequence\n\n\ndef func(value: Sequence[int]) -> None:\n    ...\n

        In other words, moving from collections.abc import Sequence into an if TYPE_CHECKING: block above would cause a runtime error, as the type would no longer be available at runtime.

        By default, Ruff will respect such runtime semantics and avoid moving the import to prevent such runtime errors.

        Setting quote-annotations to true will instruct Ruff to add quotes around the annotation (e.g., \"Sequence[int]\"), which in turn enables Ruff to move the import into an if TYPE_CHECKING: block, like so:

        from typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from collections.abc import Sequence\n\n\ndef func(value: \"Sequence[int]\") -> None:\n    ...\n

        Note that this setting has no effect when from __future__ import annotations is present, as __future__ annotations are always treated equivalently to quoted annotations.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-type-checking]\n# Add quotes around type annotations, if doing so would allow\n# an import to be moved into a type-checking block.\nquote-annotations = true\n
        [lint.flake8-type-checking]\n# Add quotes around type annotations, if doing so would allow\n# an import to be moved into a type-checking block.\nquote-annotations = true\n
        "},{"location":"settings/#lint_flake8-type-checking_runtime-evaluated-base-classes","title":"runtime-evaluated-base-classes","text":"

        Exempt classes that list any of the enumerated classes as a base class from needing to be moved into type-checking blocks.

        Common examples include Pydantic's pydantic.BaseModel and SQLAlchemy's sqlalchemy.orm.DeclarativeBase, but can also support user-defined classes that inherit from those base classes. For example, if you define a common DeclarativeBase subclass that's used throughout your project (e.g., class Base(DeclarativeBase) ... in base.py), you can add it to this list (runtime-evaluated-base-classes = [\"base.Base\"]) to exempt models from being moved into type-checking blocks.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-type-checking]\nruntime-evaluated-base-classes = [\"pydantic.BaseModel\", \"sqlalchemy.orm.DeclarativeBase\"]\n
        [lint.flake8-type-checking]\nruntime-evaluated-base-classes = [\"pydantic.BaseModel\", \"sqlalchemy.orm.DeclarativeBase\"]\n
        "},{"location":"settings/#lint_flake8-type-checking_runtime-evaluated-decorators","title":"runtime-evaluated-decorators","text":"

        Exempt classes and functions decorated with any of the enumerated decorators from being moved into type-checking blocks.

        Common examples include Pydantic's @pydantic.validate_call decorator (for functions) and attrs' @attrs.define decorator (for classes).

        This also supports framework decorators like FastAPI's fastapi.FastAPI.get which will work across assignments in the same module.

        For example:

        import fastapi\n\napp = FastAPI(\"app\")\n\n@app.get(\"/home\")\ndef home() -> str: ...\n

        Here app.get will correctly be identified as fastapi.FastAPI.get.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-type-checking]\nruntime-evaluated-decorators = [\"pydantic.validate_call\", \"attrs.define\"]\n
        [lint.flake8-type-checking]\nruntime-evaluated-decorators = [\"pydantic.validate_call\", \"attrs.define\"]\n
        "},{"location":"settings/#lint_flake8-type-checking_strict","title":"strict","text":"

        Enforce TC001, TC002, and TC003 rules even when valid runtime imports are present for the same module.

        See flake8-type-checking's strict option.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-type-checking]\nstrict = true\n
        [lint.flake8-type-checking]\nstrict = true\n
        "},{"location":"settings/#lintflake8-unused-arguments","title":"lint.flake8-unused-arguments","text":"

        Options for the flake8-unused-arguments plugin

        "},{"location":"settings/#lint_flake8-unused-arguments_ignore-variadic-names","title":"ignore-variadic-names","text":"

        Whether to allow unused variadic arguments, like *args and **kwargs.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-unused-arguments]\nignore-variadic-names = true\n
        [lint.flake8-unused-arguments]\nignore-variadic-names = true\n
        "},{"location":"settings/#lintisort","title":"lint.isort","text":"

        Options for the isort plugin.

        "},{"location":"settings/#lint_isort_case-sensitive","title":"case-sensitive","text":"

        Sort imports taking into account case sensitivity.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\ncase-sensitive = true\n
        [lint.isort]\ncase-sensitive = true\n
        "},{"location":"settings/#lint_isort_classes","title":"classes","text":"

        An override list of tokens to always recognize as a Class for order-by-type regardless of casing.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nclasses = [\"SVC\"]\n
        [lint.isort]\nclasses = [\"SVC\"]\n
        "},{"location":"settings/#lint_isort_combine-as-imports","title":"combine-as-imports","text":"

        Combines as imports on the same line. See isort's combine-as-imports option.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\ncombine-as-imports = true\n
        [lint.isort]\ncombine-as-imports = true\n
        "},{"location":"settings/#lint_isort_constants","title":"constants","text":"

        An override list of tokens to always recognize as a CONSTANT for order-by-type regardless of casing.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nconstants = [\"constant\"]\n
        [lint.isort]\nconstants = [\"constant\"]\n
        "},{"location":"settings/#lint_isort_default-section","title":"default-section","text":"

        Define a default section for any imports that don't fit into the specified section-order.

        Default value: \"third-party\"

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\ndefault-section = \"first-party\"\n
        [lint.isort]\ndefault-section = \"first-party\"\n
        "},{"location":"settings/#lint_isort_detect-same-package","title":"detect-same-package","text":"

        Whether to automatically mark imports from within the same package as first-party. For example, when detect-same-package = true, then when analyzing files within the foo package, any imports from within the foo package will be considered first-party.

        This heuristic is often unnecessary when src is configured to detect all first-party sources; however, if src is not configured, this heuristic can be useful to detect first-party imports from within (but not across) first-party packages.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\ndetect-same-package = false\n
        [lint.isort]\ndetect-same-package = false\n
        "},{"location":"settings/#lint_isort_extra-standard-library","title":"extra-standard-library","text":"

        A list of modules to consider standard-library, in addition to those known to Ruff in advance.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nextra-standard-library = [\"path\"]\n
        [lint.isort]\nextra-standard-library = [\"path\"]\n
        "},{"location":"settings/#lint_isort_force-single-line","title":"force-single-line","text":"

        Forces all from imports to appear on their own line.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nforce-single-line = true\n
        [lint.isort]\nforce-single-line = true\n
        "},{"location":"settings/#lint_isort_force-sort-within-sections","title":"force-sort-within-sections","text":"

        Don't sort straight-style imports (like import sys) before from-style imports (like from itertools import groupby). Instead, sort the imports by module, independent of import style.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nforce-sort-within-sections = true\n
        [lint.isort]\nforce-sort-within-sections = true\n
        "},{"location":"settings/#lint_isort_force-to-top","title":"force-to-top","text":"

        Force specific imports to the top of their appropriate section.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nforce-to-top = [\"src\"]\n
        [lint.isort]\nforce-to-top = [\"src\"]\n
        "},{"location":"settings/#lint_isort_force-wrap-aliases","title":"force-wrap-aliases","text":"

        Force import from statements with multiple members and at least one alias (e.g., import A as B) to wrap such that every line contains exactly one member. For example, this formatting would be retained, rather than condensing to a single line:

        from .utils import (\n    test_directory as test_directory,\n    test_id as test_id\n)\n

        Note that this setting is only effective when combined with combine-as-imports = true. When combine-as-imports isn't enabled, every aliased import from will be given its own line, in which case, wrapping is not necessary.

        When using the formatter, ensure that format.skip-magic-trailing-comma is set to false (default) when enabling force-wrap-aliases to avoid that the formatter collapses members if they all fit on a single line.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nforce-wrap-aliases = true\ncombine-as-imports = true\n
        [lint.isort]\nforce-wrap-aliases = true\ncombine-as-imports = true\n
        "},{"location":"settings/#lint_isort_forced-separate","title":"forced-separate","text":"

        A list of modules to separate into auxiliary block(s) of imports, in the order specified.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nforced-separate = [\"tests\"]\n
        [lint.isort]\nforced-separate = [\"tests\"]\n
        "},{"location":"settings/#lint_isort_from-first","title":"from-first","text":"

        Whether to place import from imports before straight imports when sorting.

        For example, by default, imports will be sorted such that straight imports appear before import from imports, as in:

        import os\nimport sys\nfrom typing import List\n

        Setting from-first = true will instead sort such that import from imports appear before straight imports, as in:

        from typing import List\nimport os\nimport sys\n

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nfrom-first = true\n
        [lint.isort]\nfrom-first = true\n
        "},{"location":"settings/#lint_isort_known-first-party","title":"known-first-party","text":"

        A list of modules to consider first-party, regardless of whether they can be identified as such via introspection of the local filesystem.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nknown-first-party = [\"src\"]\n
        [lint.isort]\nknown-first-party = [\"src\"]\n
        "},{"location":"settings/#lint_isort_known-local-folder","title":"known-local-folder","text":"

        A list of modules to consider being a local folder. Generally, this is reserved for relative imports (from . import module).

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nknown-local-folder = [\"src\"]\n
        [lint.isort]\nknown-local-folder = [\"src\"]\n
        "},{"location":"settings/#lint_isort_known-third-party","title":"known-third-party","text":"

        A list of modules to consider third-party, regardless of whether they can be identified as such via introspection of the local filesystem.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nknown-third-party = [\"src\"]\n
        [lint.isort]\nknown-third-party = [\"src\"]\n
        "},{"location":"settings/#lint_isort_length-sort","title":"length-sort","text":"

        Sort imports by their string length, such that shorter imports appear before longer imports. For example, by default, imports will be sorted alphabetically, as in:

        import collections\nimport os\n

        Setting length-sort = true will instead sort such that shorter imports appear before longer imports, as in:

        import os\nimport collections\n

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nlength-sort = true\n
        [lint.isort]\nlength-sort = true\n
        "},{"location":"settings/#lint_isort_length-sort-straight","title":"length-sort-straight","text":"

        Sort straight imports by their string length. Similar to length-sort, but applies only to straight imports and doesn't affect from imports.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nlength-sort-straight = true\n
        [lint.isort]\nlength-sort-straight = true\n
        "},{"location":"settings/#lint_isort_lines-after-imports","title":"lines-after-imports","text":"

        The number of blank lines to place after imports. Use -1 for automatic determination.

        Ruff uses at most one blank line after imports in typing stub files (files with .pyi extension) in accordance to the typing style recommendations (source).

        When using the formatter, only the values -1, 1, and 2 are compatible because it enforces at least one empty and at most two empty lines after imports.

        Default value: -1

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\n# Use a single line after each import block.\nlines-after-imports = 1\n
        [lint.isort]\n# Use a single line after each import block.\nlines-after-imports = 1\n
        "},{"location":"settings/#lint_isort_lines-between-types","title":"lines-between-types","text":"

        The number of lines to place between \"direct\" and import from imports.

        When using the formatter, only the values 0 and 1 are compatible because it preserves up to one empty line after imports in nested blocks.

        Default value: 0

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\n# Use a single line between direct and from import.\nlines-between-types = 1\n
        [lint.isort]\n# Use a single line between direct and from import.\nlines-between-types = 1\n
        "},{"location":"settings/#lint_isort_no-lines-before","title":"no-lines-before","text":"

        A list of sections that should not be delineated from the previous section via empty lines.

        Default value: []

        Type: list[\"future\" | \"standard-library\" | \"third-party\" | \"first-party\" | \"local-folder\" | str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nno-lines-before = [\"future\", \"standard-library\"]\n
        [lint.isort]\nno-lines-before = [\"future\", \"standard-library\"]\n
        "},{"location":"settings/#lint_isort_no-sections","title":"no-sections","text":"

        Put all imports into the same section bucket.

        For example, rather than separating standard library and third-party imports, as in:

        import os\nimport sys\n\nimport numpy\nimport pandas\n

        Setting no-sections = true will instead group all imports into a single section:

        import numpy\nimport os\nimport pandas\nimport sys\n

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nno-sections = true\n
        [lint.isort]\nno-sections = true\n
        "},{"location":"settings/#lint_isort_order-by-type","title":"order-by-type","text":"

        Order imports by type, which is determined by case, in addition to alphabetically.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\norder-by-type = true\n
        [lint.isort]\norder-by-type = true\n
        "},{"location":"settings/#lint_isort_relative-imports-order","title":"relative-imports-order","text":"

        Whether to place \"closer\" imports (fewer . characters, most local) before \"further\" imports (more . characters, least local), or vice versa.

        The default (\"furthest-to-closest\") is equivalent to isort's reverse-relative default (reverse-relative = false); setting this to \"closest-to-furthest\" is equivalent to isort's reverse-relative = true.

        Default value: \"furthest-to-closest\"

        Type: \"furthest-to-closest\" | \"closest-to-furthest\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nrelative-imports-order = \"closest-to-furthest\"\n
        [lint.isort]\nrelative-imports-order = \"closest-to-furthest\"\n
        "},{"location":"settings/#lint_isort_required-imports","title":"required-imports","text":"

        Add the specified import line to all files.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nrequired-imports = [\"from __future__ import annotations\"]\n
        [lint.isort]\nrequired-imports = [\"from __future__ import annotations\"]\n
        "},{"location":"settings/#lint_isort_section-order","title":"section-order","text":"

        Override in which order the sections should be output. Can be used to move custom sections.

        Default value: [\"future\", \"standard-library\", \"third-party\", \"first-party\", \"local-folder\"]

        Type: list[\"future\" | \"standard-library\" | \"third-party\" | \"first-party\" | \"local-folder\" | str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nsection-order = [\"future\", \"standard-library\", \"first-party\", \"local-folder\", \"third-party\"]\n
        [lint.isort]\nsection-order = [\"future\", \"standard-library\", \"first-party\", \"local-folder\", \"third-party\"]\n
        "},{"location":"settings/#lint_isort_sections","title":"sections","text":"

        A list of mappings from section names to modules.

        By default, imports are categorized according to their type (e.g., future, third-party, and so on). This setting allows you to group modules into custom sections, to augment or override the built-in sections.

        For example, to group all testing utilities, you could create a testing section:

        testing = [\"pytest\", \"hypothesis\"]\n

        The values in the list are treated as glob patterns. For example, to match all packages in the LangChain ecosystem (langchain-core, langchain-openai, etc.):

        langchain = [\"langchain-*\"]\n

        Custom sections should typically be inserted into the section-order list to ensure that they're displayed as a standalone group and in the intended order, as in:

        section-order = [\n  \"future\",\n  \"standard-library\",\n  \"third-party\",\n  \"first-party\",\n  \"local-folder\",\n  \"testing\"\n]\n

        If a custom section is omitted from section-order, imports in that section will be assigned to the default-section (which defaults to third-party).

        Default value: {}

        Type: dict[str, list[str]]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort.sections]\n# Group all Django imports into a separate section.\n\"django\" = [\"django\"]\n
        [lint.isort.sections]\n# Group all Django imports into a separate section.\n\"django\" = [\"django\"]\n
        "},{"location":"settings/#lint_isort_single-line-exclusions","title":"single-line-exclusions","text":"

        One or more modules to exclude from the single line rule.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nsingle-line-exclusions = [\"os\", \"json\"]\n
        [lint.isort]\nsingle-line-exclusions = [\"os\", \"json\"]\n
        "},{"location":"settings/#lint_isort_split-on-trailing-comma","title":"split-on-trailing-comma","text":"

        If a comma is placed after the last member in a multi-line import, then the imports will never be folded into one line.

        See isort's split-on-trailing-comma option.

        When using the formatter, ensure that format.skip-magic-trailing-comma is set to false (default) when enabling split-on-trailing-comma to avoid that the formatter removes the trailing commas.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nsplit-on-trailing-comma = false\n
        [lint.isort]\nsplit-on-trailing-comma = false\n
        "},{"location":"settings/#lint_isort_variables","title":"variables","text":"

        An override list of tokens to always recognize as a var for order-by-type regardless of casing.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nvariables = [\"VAR\"]\n
        [lint.isort]\nvariables = [\"VAR\"]\n
        "},{"location":"settings/#lintmccabe","title":"lint.mccabe","text":"

        Options for the mccabe plugin.

        "},{"location":"settings/#lint_mccabe_max-complexity","title":"max-complexity","text":"

        The maximum McCabe complexity to allow before triggering C901 errors.

        Default value: 10

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.mccabe]\n# Flag errors (`C901`) whenever the complexity level exceeds 5.\nmax-complexity = 5\n
        [lint.mccabe]\n# Flag errors (`C901`) whenever the complexity level exceeds 5.\nmax-complexity = 5\n
        "},{"location":"settings/#lintpep8-naming","title":"lint.pep8-naming","text":"

        Options for the pep8-naming plugin.

        "},{"location":"settings/#lint_pep8-naming_classmethod-decorators","title":"classmethod-decorators","text":"

        A list of decorators that, when applied to a method, indicate that the method should be treated as a class method (in addition to the builtin @classmethod).

        For example, Ruff will expect that any method decorated by a decorator in this list takes a cls argument as its first argument.

        Expects to receive a list of fully-qualified names (e.g., pydantic.validator, rather than validator) or alternatively a plain name which is then matched against the last segment in case the decorator itself consists of a dotted name.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pep8-naming]\nclassmethod-decorators = [\n    # Allow Pydantic's `@validator` decorator to trigger class method treatment.\n    \"pydantic.validator\",\n    # Allow SQLAlchemy's dynamic decorators, like `@field.expression`, to trigger class method treatment.\n    \"declared_attr\",\n    \"expression\",\n    \"comparator\",\n]\n
        [lint.pep8-naming]\nclassmethod-decorators = [\n    # Allow Pydantic's `@validator` decorator to trigger class method treatment.\n    \"pydantic.validator\",\n    # Allow SQLAlchemy's dynamic decorators, like `@field.expression`, to trigger class method treatment.\n    \"declared_attr\",\n    \"expression\",\n    \"comparator\",\n]\n
        "},{"location":"settings/#lint_pep8-naming_extend-ignore-names","title":"extend-ignore-names","text":"

        Additional names (or patterns) to ignore when considering pep8-naming violations, in addition to those included in ignore-names.

        Supports glob patterns. For example, to ignore all names starting with test_ or ending with _test, you could use ignore-names = [\"test_*\", \"*_test\"]. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pep8-naming]\nextend-ignore-names = [\"callMethod\"]\n
        [lint.pep8-naming]\nextend-ignore-names = [\"callMethod\"]\n
        "},{"location":"settings/#lint_pep8-naming_ignore-names","title":"ignore-names","text":"

        A list of names (or patterns) to ignore when considering pep8-naming violations.

        Supports glob patterns. For example, to ignore all names starting with test_ or ending with _test, you could use ignore-names = [\"test_*\", \"*_test\"]. For more information on the glob syntax, refer to the globset documentation.

        Default value: [\"setUp\", \"tearDown\", \"setUpClass\", \"tearDownClass\", \"setUpModule\", \"tearDownModule\", \"asyncSetUp\", \"asyncTearDown\", \"setUpTestData\", \"failureException\", \"longMessage\", \"maxDiff\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pep8-naming]\nignore-names = [\"callMethod\"]\n
        [lint.pep8-naming]\nignore-names = [\"callMethod\"]\n
        "},{"location":"settings/#lint_pep8-naming_staticmethod-decorators","title":"staticmethod-decorators","text":"

        A list of decorators that, when applied to a method, indicate that the method should be treated as a static method (in addition to the builtin @staticmethod).

        For example, Ruff will expect that any method decorated by a decorator in this list has no self or cls argument.

        Expects to receive a list of fully-qualified names (e.g., belay.Device.teardown, rather than teardown) or alternatively a plain name which is then matched against the last segment in case the decorator itself consists of a dotted name.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pep8-naming]\n# Allow Belay's `@Device.teardown` decorator to trigger static method treatment.\nstaticmethod-decorators = [\"belay.Device.teardown\"]\n
        [lint.pep8-naming]\n# Allow Belay's `@Device.teardown` decorator to trigger static method treatment.\nstaticmethod-decorators = [\"belay.Device.teardown\"]\n
        "},{"location":"settings/#lintpycodestyle","title":"lint.pycodestyle","text":"

        Options for the pycodestyle plugin.

        "},{"location":"settings/#lint_pycodestyle_ignore-overlong-task-comments","title":"ignore-overlong-task-comments","text":"

        Whether line-length violations (E501) should be triggered for comments starting with task-tags (by default: \"TODO\", \"FIXME\", and \"XXX\").

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pycodestyle]\nignore-overlong-task-comments = true\n
        [lint.pycodestyle]\nignore-overlong-task-comments = true\n
        "},{"location":"settings/#lint_pycodestyle_max-doc-length","title":"max-doc-length","text":"

        The maximum line length to allow for doc-line-too-long violations within documentation (W505), including standalone comments. By default, this is set to null which disables reporting violations.

        The length is determined by the number of characters per line, except for lines containing Asian characters or emojis. For these lines, the unicode width of each character is added up to determine the length.

        See the doc-line-too-long rule for more information.

        Default value: null

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pycodestyle]\nmax-doc-length = 88\n
        [lint.pycodestyle]\nmax-doc-length = 88\n
        "},{"location":"settings/#lint_pycodestyle_max-line-length","title":"max-line-length","text":"

        The maximum line length to allow for line-too-long violations. By default, this is set to the value of the line-length option.

        Use this option when you want to detect extra-long lines that the formatter can't automatically split by setting pycodestyle.line-length to a value larger than line-length.

        # The formatter wraps lines at a length of 88.\nline-length = 88\n\n[pycodestyle]\n# E501 reports lines that exceed the length of 100.\nmax-line-length = 100\n

        The length is determined by the number of characters per line, except for lines containing East Asian characters or emojis. For these lines, the unicode width of each character is added up to determine the length.

        See the line-too-long rule for more information.

        Default value: null

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pycodestyle]\nmax-line-length = 100\n
        [lint.pycodestyle]\nmax-line-length = 100\n
        "},{"location":"settings/#lintpydoclint","title":"lint.pydoclint","text":"

        Options for the pydoclint plugin.

        "},{"location":"settings/#lint_pydoclint_ignore-one-line-docstrings","title":"ignore-one-line-docstrings","text":"

        Skip docstrings which fit on a single line.

        Note: The corresponding setting in pydoclint is named skip-checking-short-docstrings.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydoclint]\n# Skip docstrings which fit on a single line.\nignore-one-line-docstrings = true\n
        [lint.pydoclint]\n# Skip docstrings which fit on a single line.\nignore-one-line-docstrings = true\n
        "},{"location":"settings/#lintpydocstyle","title":"lint.pydocstyle","text":"

        Options for the pydocstyle plugin.

        "},{"location":"settings/#lint_pydocstyle_convention","title":"convention","text":"

        Whether to use Google-style, NumPy-style conventions, or the PEP 257 defaults when analyzing docstring sections.

        Enabling a convention will disable all rules that are not included in the specified convention. As such, the intended workflow is to enable a convention and then selectively enable or disable any additional rules on top of it.

        For example, to use Google-style conventions but avoid requiring documentation for every function parameter:

        [tool.ruff.lint]\n# Enable all `pydocstyle` rules, limiting to those that adhere to the\n# Google convention via `convention = \"google\"`, below.\nselect = [\"D\"]\n\n# On top of the Google convention, disable `D417`, which requires\n# documentation for every function parameter.\nignore = [\"D417\"]\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n

        To enable an additional rule that's excluded from the convention, select the desired rule via its fully qualified rule code (e.g., D400 instead of D4 or D40):

        [tool.ruff.lint]\n# Enable D400 on top of the Google convention.\nextend-select = [\"D400\"]\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n

        Default value: null

        Type: \"google\" | \"numpy\" | \"pep257\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydocstyle]\n# Use Google-style docstrings.\nconvention = \"google\"\n
        [lint.pydocstyle]\n# Use Google-style docstrings.\nconvention = \"google\"\n
        "},{"location":"settings/#lint_pydocstyle_ignore-decorators","title":"ignore-decorators","text":"

        Ignore docstrings for functions or methods decorated with the specified fully-qualified decorators.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydocstyle]\nignore-decorators = [\"typing.overload\"]\n
        [lint.pydocstyle]\nignore-decorators = [\"typing.overload\"]\n
        "},{"location":"settings/#lint_pydocstyle_ignore-var-parameters","title":"ignore-var-parameters","text":"

        If set to true, ignore missing documentation for *args and **kwargs parameters.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydocstyle]\nignore-var-parameters = true\n
        [lint.pydocstyle]\nignore-var-parameters = true\n
        "},{"location":"settings/#lint_pydocstyle_property-decorators","title":"property-decorators","text":"

        A list of decorators that, when applied to a method, indicate that the method should be treated as a property (in addition to the builtin @property and standard-library @functools.cached_property).

        For example, Ruff will expect that any method decorated by a decorator in this list can use a non-imperative summary line.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydocstyle]\nproperty-decorators = [\"gi.repository.GObject.Property\"]\n
        [lint.pydocstyle]\nproperty-decorators = [\"gi.repository.GObject.Property\"]\n
        "},{"location":"settings/#lintpyflakes","title":"lint.pyflakes","text":"

        Options for the pyflakes plugin.

        "},{"location":"settings/#lint_pyflakes_allowed-unused-imports","title":"allowed-unused-imports","text":"

        A list of modules to ignore when considering unused imports.

        Used to prevent violations for specific modules that are known to have side effects on import (e.g., hvplot.pandas).

        Modules in this list are expected to be fully-qualified names (e.g., hvplot.pandas). Any submodule of a given module will also be ignored (e.g., given hvplot, hvplot.pandas will also be ignored).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pyflakes]\nallowed-unused-imports = [\"hvplot.pandas\"]\n
        [lint.pyflakes]\nallowed-unused-imports = [\"hvplot.pandas\"]\n
        "},{"location":"settings/#lint_pyflakes_extend-generics","title":"extend-generics","text":"

        Additional functions or classes to consider generic, such that any subscripts should be treated as type annotation (e.g., ForeignKey in django.db.models.ForeignKey[\"User\"].

        Expects to receive a list of fully-qualified names (e.g., django.db.models.ForeignKey, rather than ForeignKey).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pyflakes]\nextend-generics = [\"django.db.models.ForeignKey\"]\n
        [lint.pyflakes]\nextend-generics = [\"django.db.models.ForeignKey\"]\n
        "},{"location":"settings/#lintpylint","title":"lint.pylint","text":"

        Options for the pylint plugin.

        "},{"location":"settings/#lint_pylint_allow-dunder-method-names","title":"allow-dunder-method-names","text":"

        Dunder methods name to allow, in addition to the default set from the Python standard library (see PLW3201).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nallow-dunder-method-names = [\"__tablename__\", \"__table_args__\"]\n
        [lint.pylint]\nallow-dunder-method-names = [\"__tablename__\", \"__table_args__\"]\n
        "},{"location":"settings/#lint_pylint_allow-magic-value-types","title":"allow-magic-value-types","text":"

        Constant types to ignore when used as \"magic values\" (see PLR2004).

        Default value: [\"str\", \"bytes\"]

        Type: list[\"str\" | \"bytes\" | \"complex\" | \"float\" | \"int\"]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nallow-magic-value-types = [\"int\"]\n
        [lint.pylint]\nallow-magic-value-types = [\"int\"]\n
        "},{"location":"settings/#lint_pylint_max-args","title":"max-args","text":"

        Maximum number of arguments allowed for a function or method definition (see PLR0913).

        Default value: 5

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-args = 10\n
        [lint.pylint]\nmax-args = 10\n
        "},{"location":"settings/#lint_pylint_max-bool-expr","title":"max-bool-expr","text":"

        Maximum number of Boolean expressions allowed within a single if statement (see PLR0916).

        Default value: 5

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-bool-expr = 10\n
        [lint.pylint]\nmax-bool-expr = 10\n
        "},{"location":"settings/#lint_pylint_max-branches","title":"max-branches","text":"

        Maximum number of branches allowed for a function or method body (see PLR0912).

        Default value: 12

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-branches = 15\n
        [lint.pylint]\nmax-branches = 15\n
        "},{"location":"settings/#lint_pylint_max-locals","title":"max-locals","text":"

        Maximum number of local variables allowed for a function or method body (see PLR0914).

        Default value: 15

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-locals = 20\n
        [lint.pylint]\nmax-locals = 20\n
        "},{"location":"settings/#lint_pylint_max-nested-blocks","title":"max-nested-blocks","text":"

        Maximum number of nested blocks allowed within a function or method body (see PLR1702).

        Default value: 5

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-nested-blocks = 10\n
        [lint.pylint]\nmax-nested-blocks = 10\n
        "},{"location":"settings/#lint_pylint_max-positional-args","title":"max-positional-args","text":"

        Maximum number of positional arguments allowed for a function or method definition (see PLR0917).

        If not specified, defaults to the value of max-args.

        Default value: 5

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-positional-args = 3\n
        [lint.pylint]\nmax-positional-args = 3\n
        "},{"location":"settings/#lint_pylint_max-public-methods","title":"max-public-methods","text":"

        Maximum number of public methods allowed for a class (see PLR0904).

        Default value: 20

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-public-methods = 30\n
        [lint.pylint]\nmax-public-methods = 30\n
        "},{"location":"settings/#lint_pylint_max-returns","title":"max-returns","text":"

        Maximum number of return statements allowed for a function or method body (see PLR0911)

        Default value: 6

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-returns = 10\n
        [lint.pylint]\nmax-returns = 10\n
        "},{"location":"settings/#lint_pylint_max-statements","title":"max-statements","text":"

        Maximum number of statements allowed for a function or method body (see PLR0915).

        Default value: 50

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-statements = 75\n
        [lint.pylint]\nmax-statements = 75\n
        "},{"location":"settings/#lintpyupgrade","title":"lint.pyupgrade","text":"

        Options for the pyupgrade plugin.

        "},{"location":"settings/#lint_pyupgrade_keep-runtime-typing","title":"keep-runtime-typing","text":"

        Whether to avoid PEP 585 (List[int] -> list[int]) and PEP 604 (Union[str, int] -> str | int) rewrites even if a file imports from __future__ import annotations.

        This setting is only applicable when the target Python version is below 3.9 and 3.10 respectively, and is most commonly used when working with libraries like Pydantic and FastAPI, which rely on the ability to parse type annotations at runtime. The use of from __future__ import annotations causes Python to treat the type annotations as strings, which typically allows for the use of language features that appear in later Python versions but are not yet supported by the current version (e.g., str | int). However, libraries that rely on runtime type annotations will break if the annotations are incompatible with the current Python version.

        For example, while the following is valid Python 3.8 code due to the presence of from __future__ import annotations, the use of str | int prior to Python 3.10 will cause Pydantic to raise a TypeError at runtime:

        from __future__ import annotations\n\nimport pydantic\n\nclass Foo(pydantic.BaseModel):\n    bar: str | int\n

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pyupgrade]\n# Preserve types, even if a file imports `from __future__ import annotations`.\nkeep-runtime-typing = true\n
        [lint.pyupgrade]\n# Preserve types, even if a file imports `from __future__ import annotations`.\nkeep-runtime-typing = true\n
        "},{"location":"settings/#lintruff","title":"lint.ruff","text":"

        Options for the ruff plugin

        "},{"location":"settings/#lint_ruff_allowed-markup-calls","title":"allowed-markup-calls","text":"

        Deprecated

        This option has been deprecated in 0.10.0. The allowed-markup-names option has been moved to the flake8-bandit section of the configuration.

        A list of callable names, whose result may be safely passed into markupsafe.Markup.

        Expects to receive a list of fully-qualified names (e.g., bleach.clean, rather than clean).

        This setting helps you avoid false positives in code like:

        from bleach import clean\nfrom markupsafe import Markup\n\ncleaned_markup = Markup(clean(some_user_input))\n

        Where the use of bleach.clean usually ensures that there's no XSS vulnerability.

        Although it is not recommended, you may also use this setting to whitelist other kinds of calls, e.g. calls to i18n translation functions, where how safe that is will depend on the implementation and how well the translations are audited.

        Another common use-case is to wrap the output of functions that generate markup like xml.etree.ElementTree.tostring or template rendering engines where sanitization of potential user input is either already baked in or has to happen before rendering.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.ruff]\nallowed-markup-calls = [\"bleach.clean\", \"my_package.sanitize\"]\n
        [lint.ruff]\nallowed-markup-calls = [\"bleach.clean\", \"my_package.sanitize\"]\n
        "},{"location":"settings/#lint_ruff_extend-markup-names","title":"extend-markup-names","text":"

        Deprecated

        This option has been deprecated in 0.10.0. The extend-markup-names option has been moved to the flake8-bandit section of the configuration.

        A list of additional callable names that behave like markupsafe.Markup.

        Expects to receive a list of fully-qualified names (e.g., webhelpers.html.literal, rather than literal).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.ruff]\nextend-markup-names = [\"webhelpers.html.literal\", \"my_package.Markup\"]\n
        [lint.ruff]\nextend-markup-names = [\"webhelpers.html.literal\", \"my_package.Markup\"]\n
        "},{"location":"settings/#lint_ruff_parenthesize-tuple-in-subscript","title":"parenthesize-tuple-in-subscript","text":"

        Whether to prefer accessing items keyed by tuples with parentheses around the tuple (see RUF031).

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.ruff]\n# Make it a violation to use a tuple in a subscript without parentheses.\nparenthesize-tuple-in-subscript = true\n
        [lint.ruff]\n# Make it a violation to use a tuple in a subscript without parentheses.\nparenthesize-tuple-in-subscript = true\n
        "},{"location":"tutorial/","title":"Tutorial","text":"

        This tutorial will walk you through the process of integrating Ruff's linter and formatter into your project. For a more detailed overview, see Configuring Ruff.

        "},{"location":"tutorial/#getting-started","title":"Getting Started","text":"

        To start, we'll initialize a project using uv:

        $ uv init --lib numbers\n

        This command creates a Python project with the following structure:

        numbers\n  \u251c\u2500\u2500 README.md\n  \u251c\u2500\u2500 pyproject.toml\n  \u2514\u2500\u2500 src\n      \u2514\u2500\u2500 numbers\n          \u251c\u2500\u2500 __init__.py\n          \u2514\u2500\u2500 py.typed\n

        We'll then clear out the auto-generated content in src/numbers/__init__.py and create src/numbers/calculate.py with the following code:

        from typing import Iterable\n\nimport os\n\n\ndef sum_even_numbers(numbers: Iterable[int]) -> int:\n    \"\"\"Given an iterable of integers, return the sum of all even numbers in the iterable.\"\"\"\n    return sum(\n        num for num in numbers\n        if num % 2 == 0\n    )\n

        Next, we'll add Ruff to our project:

        $ uv add --dev ruff\n

        We can then run the Ruff linter over our project via uv run ruff check:

        $ uv run ruff check\nsrc/numbers/calculate.py:3:8: F401 [*] `os` imported but unused\nFound 1 error.\n[*] 1 fixable with the `--fix` option.\n

        Note

        As an alternative to uv run, you can also run Ruff by activating the project's virtual environment (source .venv/bin/active on Linux and macOS, or .venv\\Scripts\\activate on Windows) and running ruff check directly.

        Ruff identified an unused import, which is a common error in Python code. Ruff considers this a \"fixable\" error, so we can resolve the issue automatically by running ruff check --fix:

        $ uv run ruff check --fix\nFound 1 error (1 fixed, 0 remaining).\n

        Running git diff shows the following:

        --- a/src/numbers/calculate.py\n+++ b/src/numbers/calculate.py\n@@ -1,7 +1,5 @@\n from typing import Iterable\n\n-import os\n-\n\ndef sum_even_numbers(numbers: Iterable[int]) -> int:\n    \"\"\"Given an iterable of integers, return the sum of all even numbers in the iterable.\"\"\"\n    return sum(\n        num for num in numbers\n        if num % 2 == 0\n    )\n

        Note Ruff runs in the current directory by default, but you can pass specific paths to check:

        $ uv run ruff check src/numbers/calculate.py\n

        Now that our project is passing ruff check, we can run the Ruff formatter via ruff format:

        $ uv run ruff format\n1 file reformatted\n

        Running git diff shows that the sum call was reformatted to fit within the default 88-character line length limit:

        --- a/src/numbers/calculate.py\n+++ b/src/numbers/calculate.py\n@@ -3,7 +3,4 @@ from typing import Iterable\n\n def sum_even_numbers(numbers: Iterable[int]) -> int:\n     \"\"\"Given an iterable of integers, return the sum of all even numbers in the iterable.\"\"\"\n-    return sum(\n-        num for num in numbers\n-        if num % 2 == 0\n-    )\n+    return sum(num for num in numbers if num % 2 == 0)\n

        Thus far, we've been using Ruff's default configuration. Let's take a look at how we can customize Ruff's behavior.

        "},{"location":"tutorial/#configuration","title":"Configuration","text":"

        To determine the appropriate settings for each Python file, Ruff looks for the first pyproject.toml, ruff.toml, or .ruff.toml file in the file's directory or any parent directory.

        To configure Ruff, we'll add the following to the configuration file in our project's root directory:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Set the maximum line length to 79.\nline-length = 79\n\n[tool.ruff.lint]\n# Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that\n# overlap with the use of a formatter, like Black, but we can override this behavior by\n# explicitly adding the rule.\nextend-select = [\"E501\"]\n
        # Set the maximum line length to 79.\nline-length = 79\n\n[lint]\n# Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that\n# overlap with the use of a formatter, like Black, but we can override this behavior by\n# explicitly adding the rule.\nextend-select = [\"E501\"]\n

        Running Ruff again, we see that it now enforces a maximum line width, with a limit of 79:

        $ uv run ruff check\nsrc/numbers/calculate.py:5:80: E501 Line too long (90 > 79)\nFound 1 error.\n

        For a full enumeration of the supported settings, see Settings. For our project specifically, we'll want to make note of the minimum supported Python version:

        pyproject.tomlruff.toml
        [project]\n# Support Python 3.10+.\nrequires-python = \">=3.10\"\n\n[tool.ruff]\n# Set the maximum line length to 79.\nline-length = 79\n\n[tool.ruff.lint]\n# Add the `line-too-long` rule to the enforced rule set.\nextend-select = [\"E501\"]\n
        # Support Python 3.10+.\ntarget-version = \"py310\"\n# Set the maximum line length to 79.\nline-length = 79\n\n[lint]\n# Add the `line-too-long` rule to the enforced rule set.\nextend-select = [\"E501\"]\n
        "},{"location":"tutorial/#rule-selection","title":"Rule Selection","text":"

        Ruff supports over 800 lint rules split across over 50 built-in plugins, but determining the right set of rules will depend on your project's needs: some rules may be too strict, some are framework-specific, and so on.

        By default, Ruff enables Flake8's F rules, along with a subset of the E rules, omitting any stylistic rules that overlap with the use of a formatter, like ruff format or Black.

        If you're introducing a linter for the first time, the default rule set is a great place to start: it's narrow and focused while catching a wide variety of common errors (like unused imports) with zero configuration.

        If you're migrating to Ruff from another linter, you can enable rules that are equivalent to those enforced in your previous configuration. For example, if we want to enforce the pyupgrade rules, we can set our configuration file to the following:

        pyproject.tomlruff.toml
        [project]\nrequires-python = \">=3.10\"\n\n[tool.ruff.lint]\nextend-select = [\n  \"UP\",  # pyupgrade\n]\n
        target-version = \"py310\"\n\n[lint]\nextend-select = [\n  \"UP\",  # pyupgrade\n]\n

        If we run Ruff again, we'll see that it now enforces the pyupgrade rules. In particular, Ruff flags the use of the deprecated typing.Iterable instead of collections.abc.Iterable:

        $ uv run ruff check\nsrc/numbers/calculate.py:1:1: UP035 [*] Import from `collections.abc` instead: `Iterable`\nFound 1 error.\n[*] 1 fixable with the `--fix` option.\n

        Over time, we may choose to enforce additional rules. For example, we may want to enforce that all functions have docstrings:

        pyproject.tomlruff.toml
        [project]\nrequires-python = \">=3.10\"\n\n[tool.ruff.lint]\nextend-select = [\n  \"UP\",  # pyupgrade\n  \"D\",   # pydocstyle\n]\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n
        target-version = \"py310\"\n\n[lint]\nextend-select = [\n  \"UP\",  # pyupgrade\n  \"D\",   # pydocstyle\n]\n\n[lint.pydocstyle]\nconvention = \"google\"\n

        If we run Ruff again, we'll see that it now enforces the pydocstyle rules:

        $ uv run ruff check\nsrc/numbers/__init__.py:1:1: D104 Missing docstring in public package\nsrc/numbers/calculate.py:1:1: UP035 [*] Import from `collections.abc` instead: `Iterable`\n  |\n1 | from typing import Iterable\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035\n  |\n  = help: Import from `collections.abc`\n\nsrc/numbers/calculate.py:1:1: D100 Missing docstring in public module\nFound 3 errors.\n[*] 1 fixable with the `--fix` option.\n
        "},{"location":"tutorial/#ignoring-errors","title":"Ignoring Errors","text":"

        Any lint rule can be ignored by adding a # noqa comment to the line in question. For example, let's ignore the UP035 rule for the Iterable import:

        from typing import Iterable  # noqa: UP035\n\n\ndef sum_even_numbers(numbers: Iterable[int]) -> int:\n    \"\"\"Given an iterable of integers, return the sum of all even numbers in the iterable.\"\"\"\n    return sum(num for num in numbers if num % 2 == 0)\n

        Running ruff check again, we'll see that it no longer flags the Iterable import:

        $ uv run ruff check\nsrc/numbers/__init__.py:1:1: D104 Missing docstring in public package\nsrc/numbers/calculate.py:1:1: D100 Missing docstring in public module\nFound 2 errors.\n

        If we want to ignore a rule for an entire file, we can add the line # ruff: noqa: {code} anywhere in the file, preferably towards the top, like so:

        # ruff: noqa: UP035\nfrom typing import Iterable\n\n\ndef sum_even_numbers(numbers: Iterable[int]) -> int:\n    \"\"\"Given an iterable of integers, return the sum of all even numbers in the iterable.\"\"\"\n    return sum(num for num in numbers if num % 2 == 0)\n

        For more in-depth instructions on ignoring errors, please see Error suppression.

        "},{"location":"tutorial/#adding-rules","title":"Adding Rules","text":"

        When enabling a new rule on an existing codebase, you may want to ignore all existing violations of that rule and instead focus on enforcing it going forward.

        Ruff enables this workflow via the --add-noqa flag, which will add a # noqa directive to each line based on its existing violations. We can combine --add-noqa with the --select command-line flag to add # noqa directives to all existing UP035 violations:

        $ uv run ruff check --select UP035 --add-noqa .\nAdded 1 noqa directive.\n

        Running git diff shows the following:

        diff --git a/numbers/src/numbers/calculate.py b/numbers/src/numbers/calculate.py\nindex 71fca60c8d..e92d839f1b 100644\n--- a/numbers/src/numbers/calculate.py\n+++ b/numbers/src/numbers/calculate.py\n@@ -1,4 +1,4 @@\n-from typing import Iterable\n+from typing import Iterable  # noqa: UP035\n
        "},{"location":"tutorial/#integrations","title":"Integrations","text":"

        This tutorial has focused on Ruff's command-line interface, but Ruff can also be used as a pre-commit hook via ruff-pre-commit:

        - repo: https://github.com/astral-sh/ruff-pre-commit\n  # Ruff version.\n  rev: v0.11.10\n  hooks:\n    # Run the linter.\n    - id: ruff\n    # Run the formatter.\n    - id: ruff-format\n

        Ruff can also be integrated into your editor of choice. Refer to the Editors section for more information.

        For other integrations, see the Integrations section.

        "},{"location":"versioning/","title":"Versioning","text":"

        Ruff uses a custom versioning scheme that uses the minor version number for breaking changes and the patch version number for bug fixes. Ruff does not yet have a stable API; once Ruff's API is stable, the major version number and semantic versioning will be used.

        "},{"location":"versioning/#version-changes","title":"Version changes","text":"

        Minor version increases will occur when:

        • A deprecated option or feature is removed
        • Configuration changes in a backwards incompatible way
          • This may occur in minor version changes until 1.0.0, however, it should generally be avoided.
        • Support for a new file type is promoted to stable
        • Support for an end-of-life Python version is dropped
        • Linter:
          • A rule is promoted to stable
          • The behavior of a stable rule is changed
            • The scope of a stable rule is significantly increased
            • The intent of the rule changes
            • Does not include bug fixes that follow the original intent of the rule
          • Stable rules are added to the default set
          • Stable rules are removed from the default set
          • A safe fix for a rule is promoted to stable
        • Formatter:
          • The stable style changed
        • Language server:
          • An existing capability is removed
          • A deprecated server setting is removed

        Patch version increases will occur when:

        • Bugs are fixed, including behavior changes that fix bugs
        • A new configuration option is added in a backwards compatible way (no formatting changes or new lint errors)
        • Support for a new Python version is added
        • Support for a new file type is added in preview
        • An option or feature is deprecated
        • Linter:
          • An unsafe fix for a rule is added
          • A safe fix for a rule is added in preview
          • The scope of a rule is increased in preview
          • A fix\u2019s applicability is demoted
          • A rule is added in preview
          • The behavior of a preview rule is changed
        • Formatter:
          • The stable style changed to prevent invalid syntax, changes to the program's semantics, or removal of comments
          • The preview style changed
        • Language server:
          • Support for a new capability is added
          • A new server setting is added
          • A server setting is deprecated
        "},{"location":"versioning/#minimum-supported-rust-version","title":"Minimum supported Rust version","text":"

        The minimum supported Rust version required to compile Ruff is listed in the rust-version key of the [workspace.package] section in Cargo.toml. It may change in any release (minor or patch). It will never be newer than N-2 Rust versions, where N is the latest stable version. For example, if the latest stable Rust version is 1.85, Ruff's minimum supported Rust version will be at most 1.83.

        This is only relevant to users who build Ruff from source. Installing Ruff from the Python package index usually installs a pre-built binary and does not require Rust compilation.

        "},{"location":"versioning/#preview-mode","title":"Preview mode","text":"

        A preview mode is available to enable new, unstable rules and features, e.g., support for a new file type.

        The preview mode is intended to help us collect community feedback and gain confidence that changes are a net-benefit.

        The preview mode is not intended to gate access to work that is incomplete or features that we are likely to remove. However, we reserve the right to make changes to any behavior gated by the mode including the removal of preview features or rules.

        "},{"location":"versioning/#rule-stabilization","title":"Rule stabilization","text":"

        When modifying or adding rules, we use the following guidelines:

        • New rules should always be added in preview mode
        • New rules will remain in preview mode for at least one minor release before being promoted to stable
          • If added in a patch release i.e. 0.6.1 then a rule will not be eligible for stability until 0.8.0
        • Stable rule behaviors are not changed significantly in patch versions
        • Promotion of rules to stable may be delayed in order to \u201cbatch\u201d them into a single minor release
        • Not all rules in preview need to be promoted in a given minor release
        "},{"location":"versioning/#fix-stabilization","title":"Fix stabilization","text":"

        Fixes have three applicability levels:

        • Display: Never applied, just displayed.
        • Unsafe: Can be applied with explicit opt-in.
        • Safe: Can be applied automatically.

        Fixes for rules may be introduced at a lower applicability, then promoted to a higher applicability. Reducing the applicability of a fix is not a breaking change. The applicability of a given fix may change when the preview mode is enabled.

        "},{"location":"versioning/#visual-studio-code-extension","title":"Visual Studio Code Extension","text":"

        Visual Studio Code doesn't support pre-release tags for extensions. Consequently, Ruff uses the following scheme to distinguish between stable and preview releases:

        Stable releases use even numbers in minor version component: 2024.30.0, 2024.32.0, 2024.34.0, \u2026 Preview releases use odd numbers in minor version component: 2024.31.0, 2024.33.0, 2024.35.0, \u2026

        "},{"location":"editors/","title":"Editor Integrations","text":"

        Ruff can be integrated with various editors and IDEs to provide a seamless development experience. This section provides instructions on how to set up Ruff with your editor and configure it to your liking.

        "},{"location":"editors/#language-server-protocol","title":"Language Server Protocol","text":"

        The editor integration is mainly powered by the Ruff Language Server which implements the Language Server Protocol. The server is written in Rust and is available as part of the ruff CLI via ruff server. It is a single, common backend built directly into Ruff, and a direct replacement for ruff-lsp, our previous language server. You can read more about ruff server in the v0.4.5 blog post.

        The server supports surfacing Ruff diagnostics, providing Code Actions to fix them, and formatting the code using Ruff's built-in formatter. Currently, the server is intended to be used alongside another Python Language Server in order to support features like navigation and autocompletion.

        The Ruff Language Server was available first in Ruff v0.4.5 in beta and stabilized in Ruff v0.5.3.

        Note

        This is the documentation for Ruff's built-in language server written in Rust (ruff server). If you are looking for the documentation for the ruff-lsp language server, please refer to the README of the ruff-lsp repository.

        "},{"location":"editors/features/","title":"Features","text":"

        This section provides a detailed overview of the features provided by the Ruff Language Server.

        "},{"location":"editors/features/#diagnostic-highlighting","title":"Diagnostic Highlighting","text":"

        Provide diagnostics for your Python code in real-time.

        "},{"location":"editors/features/#dynamic-configuration","title":"Dynamic Configuration","text":"

        The server dynamically refreshes the diagnostics when a configuration file is changed in the workspace, whether it's a pyproject.toml, ruff.toml, or .ruff.toml file.

        The server relies on the file watching capabilities of the editor to detect changes to these files. If an editor does not support file watching, the server will not be able to detect changes to the configuration file and thus will not refresh the diagnostics.

        "},{"location":"editors/features/#formatting","title":"Formatting","text":"

        Provide code formatting for your Python code. The server can format an entire document or a specific range of lines.

        The VS Code extension provides the Ruff: Format Document command to format an entire document. In VS Code, the range formatting can be triggered by selecting a range of lines, right-clicking, and selecting Format Selection from the context menu.

        "},{"location":"editors/features/#code-actions","title":"Code Actions","text":"

        Code actions are context-sensitive suggestions that can help you fix issues in your code. They are usually triggered by a shortcut or by clicking a light bulb icon in the editor. The Ruff Language Server provides the following code actions:

        • Apply a quick fix for a diagnostic that has a fix available (e.g., removing an unused import).
        • Ignore a diagnostic with a # noqa comment.
        • Apply all quick fixes available in the document.
        • Organize imports in the document.

        You can even run these actions on-save. For example, to fix all issues and organize imports on save in VS Code, add the following to your settings.json:

        {\n  \"[python]\": {\n    \"editor.codeActionsOnSave\": {\n      \"source.fixAll.ruff\": \"explicit\",\n      \"source.organizeImports.ruff\": \"explicit\"\n    }\n  }\n}\n
        "},{"location":"editors/features/#fix-safety","title":"Fix Safety","text":"

        Ruff's automatic fixes are labeled as \"safe\" and \"unsafe\". By default, the \"Fix all\" action will not apply unsafe fixes. However, unsafe fixes can be applied manually with the \"Quick fix\" action. Application of unsafe fixes when using \"Fix all\" can be enabled by setting unsafe-fixes = true in your Ruff configuration file.

        See the Ruff fix documentation for more details on how fix safety works.

        "},{"location":"editors/features/#hover","title":"Hover","text":"

        The server can provide the rule documentation when focusing over a NoQA code in the comment. Focusing is usually hovering with a mouse, but can also be triggered with a shortcut.

        "},{"location":"editors/features/#jupyter-notebook","title":"Jupyter Notebook","text":"

        Similar to Ruff's CLI, the Ruff Language Server fully supports Jupyter Notebook files with all the capabilities available to Python files.

        Note

        Unlike ruff-lsp and similar to the Ruff's CLI, the native language server requires user to explicitly include the Jupyter Notebook files in the set of files to lint and format. Refer to the Jupyter Notebook discovery section on how to do this.

        "},{"location":"editors/migration/","title":"Migrating from ruff-lsp","text":"

        ruff-lsp is the Language Server Protocol implementation for Ruff to power the editor integrations. It is written in Python and is a separate package from Ruff itself. The native server, however, is the Language Server Protocol implementation which is written in Rust and is available under the ruff server command. This guide is intended to help users migrate from ruff-lsp to the native server.

        Note

        The native server was first introduced in Ruff version 0.3.5. It was marked as beta in version 0.4.5 and officially stabilized in version 0.5.3. It is recommended to use the latest version of Ruff to ensure the best experience.

        The migration process involves any or all of the following:

        1. Migrate deprecated settings to the new settings
        2. Remove settings that are no longer supported
        3. Update the ruff version

        Read on to learn more about the unsupported or new settings, or jump to the examples that enumerate some of the common settings and how to migrate them.

        "},{"location":"editors/migration/#unsupported-settings","title":"Unsupported Settings","text":"

        The following ruff-lsp settings are not supported by the native server:

        • lint.run: This setting is no longer relevant for the native language server, which runs on every keystroke by default.
        • lint.args, format.args: These settings have been replaced by more granular settings in the native server like lint.select, format.preview, etc. along with the ability to override any configuration using the configuration setting.

        The following settings are not accepted by the language server but are still used by the VS Code extension. Refer to their respective documentation for more information on how each is used by the extension:

        • path
        • interpreter
        "},{"location":"editors/migration/#removed-settings","title":"Removed Settings","text":"

        Additionally, the following settings are not supported by the native server and should be removed:

        • ignoreStandardLibrary
        • showNotifications
        "},{"location":"editors/migration/#new-settings","title":"New Settings","text":"

        The native server introduces several new settings that ruff-lsp does not have:

        • configuration
        • configurationPreference
        • exclude
        • format.preview
        • lineLength
        • lint.select
        • lint.extendSelect
        • lint.ignore
        • lint.preview
        "},{"location":"editors/migration/#examples","title":"Examples","text":"

        All of the examples mentioned below are only valid for the VS Code extension. For other editors, please refer to their respective documentation sections in the settings page.

        "},{"location":"editors/migration/#configuration-file","title":"Configuration file","text":"

        If you've been providing a configuration file as shown below:

        {\n    \"ruff.lint.args\": \"--config ~/.config/custom_ruff_config.toml\",\n    \"ruff.format.args\": \"--config ~/.config/custom_ruff_config.toml\"\n}\n

        You can migrate to the new server by using the configuration setting like below which will apply the configuration to both the linter and the formatter:

        {\n    \"ruff.configuration\": \"~/.config/custom_ruff_config.toml\"\n}\n
        "},{"location":"editors/migration/#lintargs","title":"lint.args","text":"

        If you're providing the linter flags by using ruff.lint.args like so:

        {\n    \"ruff.lint.args\": \"--select=E,F --unfixable=F401 --unsafe-fixes\"\n}\n

        You can migrate to the new server by using the lint.select and configuration setting like so:

        {\n    \"ruff.lint.select\": [\"E\", \"F\"],\n    \"ruff.configuration\": {\n        \"unsafe-fixes\": true,\n        \"lint\": {\n            \"unfixable\": [\"F401\"]\n        }\n    }\n}\n

        The following options can be set directly in the editor settings:

        • lint.select
        • lint.extendSelect
        • lint.ignore
        • lint.preview

        The remaining options can be set using the configuration setting.

        "},{"location":"editors/migration/#formatargs","title":"format.args","text":"

        If you're also providing formatter flags by using ruff.format.args like so:

        {\n    \"ruff.format.args\": \"--line-length 80 --config='format.quote-style=double'\"\n}\n

        You can migrate to the new server by using the lineLength and configuration setting like so:

        {\n    \"ruff.lineLength\": 80,\n    \"ruff.configuration\": {\n        \"format\": {\n            \"quote-style\": \"double\"\n        }\n    }\n}\n

        The following options can be set directly in the editor settings:

        • lineLength
        • format.preview

        The remaining options can be set using the configuration setting.

        "},{"location":"editors/settings/","title":"Settings","text":"

        The Ruff Language Server provides a set of configuration options to customize its behavior along with the ability to use an existing pyproject.toml or ruff.toml file to configure the linter and formatter. This is done by providing these settings while initializing the server. VS Code provides a UI to configure these settings, while other editors may require manual configuration. The setup section provides instructions on where to place these settings as per the editor.

        "},{"location":"editors/settings/#top-level","title":"Top-level","text":""},{"location":"editors/settings/#configuration","title":"configuration","text":"

        The configuration setting allows you to configure editor-specific Ruff behavior. This can be done in one of the following ways:

        1. Configuration file path: Specify the path to a ruff.toml or pyproject.toml file that contains the configuration. User home directory and environment variables will be expanded.
        2. Inline JSON configuration: Directly provide the configuration as a JSON object.

        Added in Ruff 0.9.8

        The Inline JSON configuration option was introduced in Ruff 0.9.8.

        The default behavior, if configuration is unset, is to load the settings from the project's configuration (a ruff.toml or pyproject.toml in the project's directory), consistent with when running Ruff on the command-line.

        The configurationPreference setting controls the precedence if both an editor-provided configuration (configuration) and a project level configuration file are present.

        "},{"location":"editors/settings/#configuration_resolution_order","title":"Resolution order","text":"

        In an editor, Ruff supports three sources of configuration, prioritized as follows (from highest to lowest):

        1. Specific settings: Individual settings like lineLength or lint.select defined in the editor
        2. ruff.configuration: Settings provided via the configuration field (either a path to a configuration file or an inline configuration object)
        3. Configuration file: Settings defined in a ruff.toml or pyproject.toml file in the project's directory (if present)

        For example, if the line length is specified in all three sources, Ruff will use the value from the lineLength setting.

        Default value: null

        Type: string

        Example usage:

        Using configuration file path:

        VS CodeNeovimZed
        {\n    \"ruff.configuration\": \"~/path/to/ruff.toml\"\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    configuration = \"~/path/to/ruff.toml\"\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"configuration\": \"~/path/to/ruff.toml\"\n        }\n      }\n    }\n  }\n}\n

        Using inline configuration:

        VS CodeNeovimZed
        {\n    \"ruff.configuration\": {\n        \"lint\": {\n            \"unfixable\": [\"F401\"],\n            \"extend-select\": [\"TID251\"],\n            \"flake8-tidy-imports\": {\n                \"banned-api\": {\n                    \"typing.TypedDict\": {\n                        \"msg\": \"Use `typing_extensions.TypedDict` instead\",\n                    }\n                }\n            }\n        },\n        \"format\": {\n            \"quote-style\": \"single\"\n        }\n    }\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    configuration = {\n      lint = {\n        unfixable = {\"F401\"},\n        [\"extend-select\"] = {\"TID251\"},\n        [\"flake8-tidy-imports\"] = {\n          [\"banned-api\"] = {\n            [\"typing.TypedDict\"] = {\n              msg = \"Use `typing_extensions.TypedDict` instead\"\n            }\n          }\n        }\n      },\n      format = {\n        [\"quote-style\"] = \"single\"\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"configuration\": {\n            \"lint\": {\n              \"unfixable\": [\"F401\"],\n              \"extend-select\": [\"TID251\"],\n              \"flake8-tidy-imports\": {\n                \"banned-api\": {\n                  \"typing.TypedDict\": {\n                    \"msg\": \"Use `typing_extensions.TypedDict` instead\"\n                  }\n                }\n              }\n            },\n            \"format\": {\n              \"quote-style\": \"single\"\n            }\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#configurationpreference","title":"configurationPreference","text":"

        The strategy to use when resolving settings across VS Code and the filesystem. By default, editor configuration is prioritized over ruff.toml and pyproject.toml files.

        • \"editorFirst\": Editor settings take priority over configuration files present in the workspace.
        • \"filesystemFirst\": Configuration files present in the workspace takes priority over editor settings.
        • \"editorOnly\": Ignore configuration files entirely i.e., only use editor settings.

        Default value: \"editorFirst\"

        Type: \"editorFirst\" | \"filesystemFirst\" | \"editorOnly\"

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.configurationPreference\": \"filesystemFirst\"\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      configurationPreference = \"filesystemFirst\"\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"configurationPreference\": \"filesystemFirst\"\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#exclude","title":"exclude","text":"

        A list of file patterns to exclude from linting and formatting. See the documentation for more details.

        Default value: null

        Type: string[]

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.exclude\": [\"**/tests/**\"]\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      exclude = [\"**/tests/**\"]\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"exclude\": [\"**/tests/**\"]\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#linelength","title":"lineLength","text":"

        The line length to use for the linter and formatter.

        Default value: null

        Type: int

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lineLength\": 100\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lineLength = 100\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lineLength\": 100\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#fixall","title":"fixAll","text":"

        Whether to register the server as capable of handling source.fixAll code actions.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.fixAll\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      fixAll = false\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"fixAll\": false\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#organizeimports","title":"organizeImports","text":"

        Whether to register the server as capable of handling source.organizeImports code actions.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.organizeImports\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      organizeImports = false\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"organizeImports\": false\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#showsyntaxerrors","title":"showSyntaxErrors","text":"

        New in Ruff v0.5.0

        Whether to show syntax error diagnostics.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.showSyntaxErrors\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      showSyntaxErrors = false\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"showSyntaxErrors\": false\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#loglevel","title":"logLevel","text":"

        The log level to use for the server.

        Default value: \"info\"

        Type: \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\"

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.logLevel\": \"debug\"\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      logLevel = \"debug\"\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"logLevel\": \"debug\"\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#logfile","title":"logFile","text":"

        Path to the log file to use for the server.

        If not set, logs will be written to stderr.

        Default value: null

        Type: string

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.logFile\": \"~/path/to/ruff.log\"\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      logFile = \"~/path/to/ruff.log\"\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"logFile\": \"~/path/to/ruff.log\"\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#codeaction","title":"codeAction","text":"

        Enable or disable code actions provided by the server.

        "},{"location":"editors/settings/#disablerulecommentenable","title":"disableRuleComment.enable","text":"

        Whether to display Quick Fix actions to disable rules via noqa suppression comments.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.codeAction.disableRuleComment.enable\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      codeAction = {\n        disableRuleComment = {\n          enable = false\n        }\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"codeAction\": {\n            \"disableRuleComment\": {\n              \"enable\": false\n            }\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#fixviolationenable","title":"fixViolation.enable","text":"

        Whether to display Quick Fix actions to autofix violations.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.codeAction.fixViolation.enable\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      codeAction = {\n        fixViolation = {\n          enable = false\n        }\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"codeAction\": {\n            \"fixViolation\": = {\n              \"enable\": false\n            }\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#lint","title":"lint","text":"

        Settings specific to the Ruff linter.

        "},{"location":"editors/settings/#lint_enable","title":"enable","text":"

        Whether to enable linting. Set to false to use Ruff exclusively as a formatter.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lint.enable\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lint = {\n        enable = false\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lint\": {\n            \"enable\": false\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#lint_preview","title":"preview","text":"

        Whether to enable Ruff's preview mode when linting.

        Default value: null

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lint.preview\": true\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lint = {\n        preview = true\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lint\": {\n            \"preview\": true\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#select","title":"select","text":"

        Rules to enable by default. See the documentation.

        Default value: null

        Type: string[]

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lint.select\": [\"E\", \"F\"]\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lint = {\n        select = {\"E\", \"F\"}\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lint\": {\n            \"select\": [\"E\", \"F\"]\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#extendselect","title":"extendSelect","text":"

        Rules to enable in addition to those in lint.select.

        Default value: null

        Type: string[]

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lint.extendSelect\": [\"W\"]\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lint = {\n        extendSelect = {\"W\"}\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lint\": {\n            \"extendSelect\": [\"W\"]\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#ignore","title":"ignore","text":"

        Rules to disable by default. See the documentation.

        Default value: null

        Type: string[]

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lint.ignore\": [\"E4\", \"E7\"]\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lint = {\n        ignore = {\"E4\", \"E7\"}\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lint\": {\n            \"ignore\": [\"E4\", \"E7\"]\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#format","title":"format","text":"

        Settings specific to the Ruff formatter.

        "},{"location":"editors/settings/#format_preview","title":"preview","text":"

        Whether to enable Ruff's preview mode when formatting.

        Default value: null

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.format.preview\": true\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      format = {\n        preview = true\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"format\": {\n            \"preview\": true\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#vs-code-specific","title":"VS Code specific","text":"

        Additionally, the Ruff extension provides the following settings specific to VS Code. These settings are not used by the language server and are only relevant to the extension.

        "},{"location":"editors/settings/#enable","title":"enable","text":"

        Whether to enable the Ruff extension. Modifying this setting requires restarting VS Code to take effect.

        Default value: true

        Type: bool

        Example usage:

        {\n    \"ruff.enable\": false\n}\n
        "},{"location":"editors/settings/#formatargs","title":"format.args","text":"

        Deprecated

        This setting is only used by ruff-lsp which is deprecated in favor of the native language server. Refer to the migration guide for more information.

        This setting is not used by the native language server.

        Additional arguments to pass to the Ruff formatter.

        Default value: []

        Type: string[]

        Example usage:

        {\n    \"ruff.format.args\": [\"--line-length\", \"100\"]\n}\n
        "},{"location":"editors/settings/#ignorestandardlibrary","title":"ignoreStandardLibrary","text":"

        Deprecated

        This setting is only used by ruff-lsp which is deprecated in favor of the native language server. Refer to the migration guide for more information.

        This setting is not used by the native language server.

        Whether to ignore files that are inferred to be part of the Python standard library.

        Default value: true

        Type: bool

        Example usage:

        {\n    \"ruff.ignoreStandardLibrary\": false\n}\n
        "},{"location":"editors/settings/#importstrategy","title":"importStrategy","text":"

        Strategy for loading the ruff executable.

        • fromEnvironment finds Ruff in the environment, falling back to the bundled version
        • useBundled uses the version bundled with the extension

        Default value: \"fromEnvironment\"

        Type: \"fromEnvironment\" | \"useBundled\"

        Example usage:

        {\n    \"ruff.importStrategy\": \"useBundled\"\n}\n
        "},{"location":"editors/settings/#interpreter","title":"interpreter","text":"

        A list of paths to Python interpreters. Even though this is a list, only the first interpreter is used.

        This setting depends on the ruff.nativeServer setting:

        • If using the native server, the interpreter is used to find the ruff executable when ruff.importStrategy is set to fromEnvironment.
        • Otherwise, the interpreter is used to run the ruff-lsp server.

        Default value: []

        Type: string[]

        Example usage:

        {\n    \"ruff.interpreter\": [\"/home/user/.local/bin/python\"]\n}\n
        "},{"location":"editors/settings/#lintargs","title":"lint.args","text":"

        Deprecated

        This setting is only used by ruff-lsp which is deprecated in favor of the native language server. Refer to the migration guide for more information.

        This setting is not used by the native language server.

        Additional arguments to pass to the Ruff linter.

        Default value: []

        Type: string[]

        Example usage:

        {\n    \"ruff.lint.args\": [\"--config\", \"/path/to/pyproject.toml\"]\n}\n
        "},{"location":"editors/settings/#lintrun","title":"lint.run","text":"

        Deprecated

        This setting is only used by ruff-lsp which is deprecated in favor of the native language server. Refer to the migration guide for more information.

        This setting is not used by the native language server.

        Run Ruff on every keystroke (onType) or on save (onSave).

        Default value: \"onType\"

        Type: \"onType\" | \"onSave\"

        Example usage:

        {\n    \"ruff.lint.run\": \"onSave\"\n}\n
        "},{"location":"editors/settings/#nativeserver","title":"nativeServer","text":"

        Whether to use the native language server, ruff-lsp or automatically decide between the two based on the Ruff version and extension settings.

        • \"on\": Use the native language server. A warning will be displayed if deprecated settings are detected.
        • \"off\": Use ruff-lsp. A warning will be displayed if settings specific to the native server are detected.
        • \"auto\": Automatically select between the native language server and ruff-lsp based on the following conditions:
          1. If the Ruff version is >= 0.5.3, use the native language server unless any deprecated settings are detected. In that case, show a warning and use ruff-lsp instead.
          2. If the Ruff version is < 0.5.3, use ruff-lsp. A warning will be displayed if settings specific to the native server are detected.
        • true: Same as on
        • false: Same as off

        Default value: \"auto\"

        Type: \"on\" | \"off\" | \"auto\" | true | false

        Example usage:

        {\n    \"ruff.nativeServer\": \"on\"\n}\n
        "},{"location":"editors/settings/#path","title":"path","text":"

        A list of path to ruff executables.

        The first executable in the list which is exists is used. This setting takes precedence over the ruff.importStrategy setting.

        Default value: []

        Type: string[]

        Example usage:

        {\n    \"ruff.path\": [\"/home/user/.local/bin/ruff\"]\n}\n
        "},{"location":"editors/settings/#shownotifications","title":"showNotifications","text":"

        Deprecated

        This setting is only used by ruff-lsp which is deprecated in favor of the native language server. Refer to the migration guide for more information.

        Setting to control when a notification is shown.

        Default value: \"off\"

        Type: \"off\" | \"onError\" | \"onWarning\" | \"always\"

        Example usage:

        {\n    \"ruff.showNotifications\": \"onWarning\"\n}\n
        "},{"location":"editors/settings/#traceserver","title":"trace.server","text":"

        The trace level for the language server. Refer to the LSP specification for more information.

        Default value: \"off\"

        Type: \"off\" | \"messages\" | \"verbose\"

        Example usage:

        {\n    \"ruff.trace.server\": \"messages\"\n}\n
        "},{"location":"editors/setup/","title":"Setup","text":"

        We have specific setup instructions depending on your editor of choice. If you don't see your editor on this list and would like a setup guide, please open an issue.

        If you're transferring your configuration from ruff-lsp, regardless of editor, there are several settings which have changed or are no longer available. See the migration guide for more.

        Note

        The setup instructions provided below are on a best-effort basis. If you encounter any issues while setting up the Ruff in an editor, please open an issue for assistance and help in improving this documentation.

        Tip

        Regardless of the editor, it is recommended to disable the older language server (ruff-lsp) to prevent any conflicts.

        "},{"location":"editors/setup/#vs-code","title":"VS Code","text":"

        Install the Ruff extension from the VS Code Marketplace. It is recommended to have the Ruff extension version 2024.32.0 or later to get the best experience with the Ruff Language Server.

        For more documentation on the Ruff extension, refer to the README of the extension repository.

        "},{"location":"editors/setup/#neovim","title":"Neovim","text":"

        The nvim-lspconfig plugin can be used to configure the Ruff Language Server in Neovim. To set it up, install nvim-lspconfig plugin, set it up as per the configuration documentation, and add the following to your init.lua:

        Neovim 0.10 (with nvim-lspconfig)Neovim 0.11+ (with vim.lsp.config)
        require('lspconfig').ruff.setup({\n  init_options = {\n    settings = {\n      -- Ruff language server settings go here\n    }\n  }\n})\n
        vim.lsp.config('ruff', {\n  init_options = {\n    settings = {\n      -- Ruff language server settings go here\n    }\n  }\n})\n\nvim.lsp.enable('ruff')\n

        Note

        If the installed version of nvim-lspconfig includes the changes from neovim/nvim-lspconfig@70d1c2c, you will need to use Ruff version 0.5.3 or later.

        If you're using Ruff alongside another language server (like Pyright), you may want to defer to that language server for certain capabilities, like textDocument/hover:

        vim.api.nvim_create_autocmd(\"LspAttach\", {\n  group = vim.api.nvim_create_augroup('lsp_attach_disable_ruff_hover', { clear = true }),\n  callback = function(args)\n    local client = vim.lsp.get_client_by_id(args.data.client_id)\n    if client == nil then\n      return\n    end\n    if client.name == 'ruff' then\n      -- Disable hover in favor of Pyright\n      client.server_capabilities.hoverProvider = false\n    end\n  end,\n  desc = 'LSP: Disable hover capability from Ruff',\n})\n

        If you'd like to use Ruff exclusively for linting, formatting, and organizing imports, you can disable those capabilities for Pyright:

        require('lspconfig').pyright.setup {\n  settings = {\n    pyright = {\n      -- Using Ruff's import organizer\n      disableOrganizeImports = true,\n    },\n    python = {\n      analysis = {\n        -- Ignore all files for analysis to exclusively use Ruff for linting\n        ignore = { '*' },\n      },\n    },\n  },\n}\n

        By default, the log level for Ruff is set to info. To change the log level, you can set the logLevel setting:

        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      logLevel = 'debug',\n    }\n  }\n}\n

        By default, Ruff will write logs to stderr which will be available in Neovim's LSP client log file (:lua vim.print(vim.lsp.get_log_path())). It's also possible to divert these logs to a separate file with the logFile setting.

        To view the trace logs between Neovim and Ruff, set the log level for Neovim's LSP client to debug:

        vim.lsp.set_log_level('debug')\n
        "},{"location":"editors/setup/#vim","title":"Vim","text":"

        The vim-lsp plugin can be used to configure the Ruff Language Server in Vim. To set it up, install vim-lsp plugin and register the server using the following in your .vimrc:

        if executable('ruff')\n    au User lsp_setup call lsp#register_server({\n        \\ 'name': 'ruff',\n        \\ 'cmd': {server_info->['ruff', 'server']},\n        \\ 'allowlist': ['python'],\n        \\ 'workspace_config': {},\n        \\ })\nendif\n

        See the vim-lsp documentation for more details on how to configure the language server.

        If you're using Ruff alongside another LSP (like Pyright), you may want to defer to that LSP for certain capabilities, like textDocument/hover by adding the following to the function s:on_lsp_buffer_enabled():

        function! s:on_lsp_buffer_enabled() abort\n    \" add your keybindings here (see https://github.com/prabirshrestha/vim-lsp?tab=readme-ov-file#registering-servers)\n\n    let l:capabilities = lsp#get_server_capabilities('ruff')\n    if !empty(l:capabilities)\n      let l:capabilities.hoverProvider = v:false\n    endif\nendfunction\n

        Ruff is also available as part of the coc-pyright extension for coc.nvim.

        With the ALE plugin for Vim or Neovim.
        \" Linters\nlet g:ale_linters = { \"python\": [\"ruff\"] }\n\" Fixers\nlet g:ale_fixers = { \"python\": [\"ruff\", \"ruff_format\"] }\n
        For the fixers, `ruff` will run `ruff check --fix` (to fix all auto-fixable problems) whereas `ruff_format` will run `ruff format`. Ruff can also be integrated via efm language server in just a few lines. Following is an example config for efm to use Ruff for linting and formatting Python files:
        tools:\n  python-ruff:\n    lint-command: \"ruff check --stdin-filename ${INPUT} --output-format concise --quiet -\"\n    lint-stdin: true\n    lint-formats:\n      - \"%f:%l:%c: %m\"\n    format-command: \"ruff format --stdin-filename ${INPUT} --quiet -\"\n    format-stdin: true\n
        With the conform.nvim plugin for Neovim.
        require(\"conform\").setup({\n    formatters_by_ft = {\n        python = {\n          -- To fix auto-fixable lint errors.\n          \"ruff_fix\",\n          -- To run the Ruff formatter.\n          \"ruff_format\",\n          -- To organize the imports.\n          \"ruff_organize_imports\",\n        },\n    },\n})\n
        With the nvim-lint plugin for Neovim.
        require(\"lint\").linters_by_ft = {\n  python = { \"ruff\" },\n}\n
        "},{"location":"editors/setup/#helix","title":"Helix","text":"

        Open the language configuration file for Helix and add the language server as follows:

        [language-server.ruff]\ncommand = \"ruff\"\nargs = [\"server\"]\n

        Then, you'll register the language server as the one to use with Python. If you don't already have a language server registered to use with Python, add this to languages.toml:

        [[language]]\nname = \"python\"\nlanguage-servers = [\"ruff\"]\n

        Otherwise, if you already have language-servers defined, you can simply add \"ruff\" to the list. For example, if you already have pylsp as a language server, you can modify the language entry as follows:

        [[language]]\nname = \"python\"\nlanguage-servers = [\"ruff\", \"pylsp\"]\n

        Note

        Support for multiple language servers for a language is only available in Helix version 23.10 and later.

        If you want to, as an example, turn on auto-formatting, add auto-format = true:

        [[language]]\nname = \"python\"\nlanguage-servers = [\"ruff\", \"pylsp\"]\nauto-format = true\n

        See the Helix documentation for more settings you can use here.

        You can pass settings into ruff server using [language-server.ruff.config.settings]. For example:

        [language-server.ruff.config.settings]\nlineLength = 80\n\n[language-server.ruff.config.settings.lint]\nselect = [\"E4\", \"E7\"]\npreview = false\n\n[language-server.ruff.config.settings.format]\npreview = true\n

        By default, the log level for Ruff is set to info. To change the log level, you can set the logLevel setting:

        [language-server.ruff]\ncommand = \"ruff\"\nargs = [\"server\"]\n\n[language-server.ruff.config.settings]\nlogLevel = \"debug\"\n

        You can also divert Ruff's logs to a separate file with the logFile setting.

        To view the trace logs between Helix and Ruff, pass in the -v (verbose) flag when starting Helix:

        hx -v path/to/file.py\n
        "},{"location":"editors/setup/#kate","title":"Kate","text":"
        1. Activate the LSP Client plugin.
        2. Setup LSP Client as desired.
        3. Finally, add this to Settings -> Configure Kate -> LSP Client -> User Server Settings:
        {\n  \"servers\": {\n    \"python\": {\n      \"command\": [\"ruff\", \"server\"],\n      \"url\": \"https://github.com/astral-sh/ruff\",\n      \"highlightingModeRegex\": \"^Python$\",\n      \"settings\": {}\n    }\n  }\n}\n

        See LSP Client documentation for more details on how to configure the server from there.

        Important

        Kate's LSP Client plugin does not support multiple servers for the same language. As a workaround, you can use the python-lsp-server along with the python-lsp-ruff plugin to use Ruff alongside another language server. Note that this setup won't use the server settings because the python-lsp-ruff plugin uses the ruff executable and not the language server.

        "},{"location":"editors/setup/#sublime-text","title":"Sublime Text","text":"

        To use Ruff with Sublime Text, install Sublime Text's LSP and LSP-ruff package.

        "},{"location":"editors/setup/#pycharm","title":"PyCharm","text":""},{"location":"editors/setup/#via-external-tool","title":"Via External Tool","text":"

        Ruff can be installed as an External Tool in PyCharm. Open the Preferences pane, then navigate to \"Tools\", then \"External Tools\". From there, add a new tool with the following configuration:

        Ruff should then appear as a runnable action:

        "},{"location":"editors/setup/#via-third-party-plugin","title":"Via third-party plugin","text":"

        Ruff is also available as the Ruff plugin on the IntelliJ Marketplace (maintained by @koxudaxi).

        "},{"location":"editors/setup/#emacs","title":"Emacs","text":"

        Ruff can be utilized as a language server via Eglot, which is in Emacs's core. To enable Ruff with automatic formatting on save, use the following configuration:

        (add-hook 'python-mode-hook 'eglot-ensure)\n(with-eval-after-load 'eglot\n  (add-to-list 'eglot-server-programs\n               '(python-mode . (\"ruff\" \"server\")))\n  (add-hook 'after-save-hook 'eglot-format))\n

        Ruff is available as flymake-ruff on MELPA:

        (require 'flymake-ruff)\n(add-hook 'python-mode-hook #'flymake-ruff-load)\n

        Ruff is also available as emacs-ruff-format:

        (require 'ruff-format)\n(add-hook 'python-mode-hook 'ruff-format-on-save-mode)\n

        Alternatively, it can be used via the Apheleia formatter library, by setting this configuration:

        ;; Replace default (black) to use ruff for sorting import and formatting.\n(setf (alist-get 'python-mode apheleia-mode-alist)\n      '(ruff-isort ruff))\n(setf (alist-get 'python-ts-mode apheleia-mode-alist)\n      '(ruff-isort ruff))\n
        "},{"location":"editors/setup/#textmate","title":"TextMate","text":"

        Ruff is also available via the textmate2-ruff-linter bundle for TextMate.

        "},{"location":"editors/setup/#zed","title":"Zed","text":"

        Ruff is available as an extension for the Zed editor. To install it:

        1. Open the command palette with Cmd+Shift+P
        2. Search for \"zed: extensions\"
        3. Search for \"ruff\" in the extensions list and click \"Install\"

        To configure Zed to use the Ruff language server for Python files, add the following to your settings.json file:

        {\n  \"languages\": {\n    \"Python\": {\n      \"language_servers\": [\"ruff\"]\n      // Or, if there are other language servers you want to use with Python\n      // \"language_servers\": [\"pyright\", \"ruff\"]\n    }\n  }\n}\n

        To configure the language server, you can provide the server settings under the lsp.ruff.initialization_options.settings key:

        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          // Ruff server settings goes here\n          \"lineLength\": 80,\n          \"lint\": {\n            \"extendSelect\": [\"I\"],\n          }\n        }\n      }\n    }\n  }\n}\n

        Note

        Support for multiple formatters for a given language is only available in Zed version 0.146.0 and later.

        You can configure Ruff to format Python code on-save by registering the Ruff formatter and enabling the format_on_save setting:

        Zed 0.146.0+
        {\n  \"languages\": {\n    \"Python\": {\n      \"language_servers\": [\"ruff\"],\n      \"format_on_save\": \"on\",\n      \"formatter\": [\n        {\n          \"language_server\": {\n            \"name\": \"ruff\"\n          }\n        }\n      ]\n    }\n  }\n}\n

        You can configure Ruff to fix lint violations and/or organize imports on-save by enabling the source.fixAll.ruff and source.organizeImports.ruff code actions respectively:

        Zed 0.146.0+
        {\n  \"languages\": {\n    \"Python\": {\n      \"language_servers\": [\"ruff\"],\n      \"format_on_save\": \"on\",\n      \"formatter\": [\n        {\n          \"code_actions\": {\n            // Fix all auto-fixable lint violations\n            \"source.fixAll.ruff\": true,\n            // Organize imports\n            \"source.organizeImports.ruff\": true\n          }\n        }\n      ]\n    }\n  }\n}\n

        Taken together, you can configure Ruff to format, fix, and organize imports on-save via the following settings.json:

        Note

        For this configuration, it is important to use the correct order of the code action and formatter language server settings. The code actions should be defined before the formatter to ensure that the formatter takes care of any remaining style issues after the code actions have been applied.

        Zed 0.146.0+
        {\n  \"languages\": {\n    \"Python\": {\n      \"language_servers\": [\"ruff\"],\n      \"format_on_save\": \"on\",\n      \"formatter\": [\n        {\n          \"code_actions\": {\n            \"source.organizeImports.ruff\": true,\n            \"source.fixAll.ruff\": true\n          }\n        },\n        {\n          \"language_server\": {\n            \"name\": \"ruff\"\n          }\n        }\n      ]\n    }\n  }\n}\n
        "},{"location":"formatter/black/","title":"Known Deviations from Black","text":"

        This document enumerates the known, intentional differences in code style between Black and Ruff's formatter.

        For a list of unintentional deviations, see issue tracker.

        "},{"location":"formatter/black/#trailing-end-of-line-comments","title":"Trailing end-of-line comments","text":"

        Black's priority is to fit an entire statement on a line, even if it contains end-of-line comments. In such cases, Black collapses the statement, and moves the comment to the end of the collapsed statement:

        # Input\nwhile (\n    cond1  # almost always true\n    and cond2  # almost never true\n):\n    print(\"Do something\")\n\n# Black\nwhile cond1 and cond2:  # almost always true  # almost never true\n    print(\"Do something\")\n

        Ruff, like Prettier, expands any statement that contains trailing end-of-line comments. For example, Ruff would avoid collapsing the while test in the snippet above. This ensures that the comments remain close to their original position and retain their original intent, at the cost of retaining additional vertical space.

        This deviation only impacts unformatted code, in that Ruff's output should not deviate for code that has already been formatted by Black.

        "},{"location":"formatter/black/#pragma-comments-are-ignored-when-computing-line-width","title":"Pragma comments are ignored when computing line width","text":"

        Pragma comments (# type, # noqa, # pyright, # pylint, etc.) are ignored when computing the width of a line. This prevents Ruff from moving pragma comments around, thereby modifying their meaning and behavior:

        See Ruff's pragma comment handling proposal for details.

        This is similar to Pyink but a deviation from Black. Black avoids splitting any lines that contain a # type comment (#997), but otherwise avoids special-casing pragma comments.

        As Ruff expands trailing end-of-line comments, Ruff will also avoid moving pragma comments in cases like the following, where moving the # noqa to the end of the line causes it to suppress errors on both first() and second():

        # Input\n[\n    first(),  # noqa\n    second()\n]\n\n# Black\n[first(), second()]  # noqa\n\n# Ruff\n[\n    first(),  # noqa\n    second(),\n]\n
        "},{"location":"formatter/black/#line-width-vs-line-length","title":"Line width vs. line length","text":"

        Ruff uses the Unicode width of a line to determine if a line fits. Black uses Unicode width for strings, and character width for all other tokens. Ruff also uses Unicode width for identifiers and comments.

        "},{"location":"formatter/black/#parenthesizing-long-nested-expressions","title":"Parenthesizing long nested-expressions","text":"

        Black 24 and newer parenthesizes long conditional expressions and type annotations in function parameters:

        # Black\n[\n    \"____________________________\",\n    \"foo\",\n    \"bar\",\n    (\n        \"baz\"\n        if some_really_looooooooong_variable\n        else \"some other looooooooooooooong value\"\n    ),\n]\n\n\ndef foo(\n    i: int,\n    x: (\n        Loooooooooooooooooooooooong\n        | Looooooooooooooooong\n        | Looooooooooooooooooooong\n        | Looooooong\n    ),\n    *,\n    s: str,\n) -> None:\n    pass\n\n# Ruff\n[\n    \"____________________________\",\n    \"foo\",\n    \"bar\",\n    \"baz\"\n    if some_really_looooooooong_variable\n    else \"some other looooooooooooooong value\",\n]\n\n\ndef foo(\n    i: int,\n    x: Loooooooooooooooooooooooong\n    | Looooooooooooooooong\n    | Looooooooooooooooooooong\n    | Looooooong,\n    *,\n    s: str,\n) -> None:\n    pass\n

        We agree that Ruff's formatting (that matches Black's 23) is hard to read and needs improvement. But we aren't convinced that parenthesizing long nested expressions is the best solution, especially when considering expression formatting holistically. That's why we want to defer the decision until we've explored alternative nested expression formatting styles. See psf/Black#4123 for an in-depth explanation of our concerns and an outline of possible alternatives.

        "},{"location":"formatter/black/#call-expressions-with-a-single-multiline-string-argument","title":"Call expressions with a single multiline string argument","text":"

        Unlike Black, Ruff preserves the indentation of a single multiline-string argument in a call expression:

        # Input\ncall(\n  \"\"\"\"\n  A multiline\n  string\n  \"\"\"\n)\n\ndedent(\"\"\"\"\n    A multiline\n    string\n\"\"\")\n\n# Black\ncall(\n  \"\"\"\"\n  A multiline\n  string\n  \"\"\"\n)\n\ndedent(\n  \"\"\"\"\n  A multiline\n  string\n\"\"\"\n)\n\n\n# Ruff\ncall(\n  \"\"\"\"\n  A multiline\n  string\n  \"\"\"\n)\n\ndedent(\"\"\"\"\n    A multiline\n    string\n\"\"\")\n

        Black intended to ship a similar style change as part of the 2024 style that always removes the indent. It turned out that this change was too disruptive to justify the cases where it improved formatting. Ruff introduced the new heuristic of preserving the indent. We believe it's a good compromise that improves formatting but minimizes disruption for users.

        "},{"location":"formatter/black/#blank-lines-at-the-start-of-a-block","title":"Blank lines at the start of a block","text":"

        Black 24 and newer allows blank lines at the start of a block, where Ruff always removes them:

        # Black\nif x:\n\n  a = 123\n\n# Ruff\nif x:\n  a = 123\n

        Currently, we are concerned that allowing blank lines at the start of a block leads to unintentional blank lines when refactoring or moving code. However, we will consider adopting Black's formatting at a later point with an improved heuristic. The style change is tracked in #9745.

        "},{"location":"formatter/black/#f-strings","title":"F-strings","text":"

        Ruff formats expression parts in f-strings whereas Black does not:

        # Input\nf'test{inner   + \"nested_string\"} including math {5 ** 3 + 10}'\n\n# Black\nf'test{inner   + \"nested_string\"} including math {5 ** 3 + 10}'\n\n# Ruff\nf\"test{inner + 'nested_string'} including math {5**3 + 10}\"\n

        For more details on the formatting style, refer to the f-string formatting section.

        "},{"location":"formatter/black/#implicit-concatenated-strings","title":"Implicit concatenated strings","text":"

        Ruff merges implicitly concatenated strings if the entire string fits on a single line:

        # Input\ndef test(max_history):\n    raise argparse.ArgumentTypeError(\n        f\"The value of `--max-history {max_history}` \" f\"is not a positive integer.\"\n    )\n\n# Black\ndef test(max_history):\n    raise argparse.ArgumentTypeError(\n        f\"The value of `--max-history {max_history}` \" f\"is not a positive integer.\"\n    )\n\n# Ruff\ndef test(max_history):\n    raise argparse.ArgumentTypeError(\n        f\"The value of `--max-history {max_history}` is not a positive integer.\"\n    )\n

        Black's unstable style applies the same formatting.

        There are few rare cases where Ruff can't merge the implicitly concatenated strings automatically. In those cases, Ruff preserves if the implicit concatenated strings are formatted over multiple lines:

        # Input\na = (\n    r\"aaaaaaa\"\n    \"bbbbbbbbbbbb\"\n)\n\n# Black\na = r\"aaaaaaa\" \"bbbbbbbbbbbb\"\n\n# Ruff\na = (\n    r\"aaaaaaa\"\n    \"bbbbbbbbbbbb\"\n)\n

        This ensures compatibility with ISC001 (#8272).

        "},{"location":"formatter/black/#assert-statements","title":"assert statements","text":"

        Unlike Black, Ruff prefers breaking the message over breaking the assertion, similar to how both Ruff and Black prefer breaking the assignment value over breaking the assignment target:

        # Input\nassert (\n    len(policy_types) >= priority + num_duplicates\n), f\"This tests needs at least {priority+num_duplicates} many types.\"\n\n\n# Black\nassert (\n    len(policy_types) >= priority + num_duplicates\n), f\"This tests needs at least {priority+num_duplicates} many types.\"\n\n# Ruff\nassert len(policy_types) >= priority + num_duplicates, (\n    f\"This tests needs at least {priority + num_duplicates} many types.\"\n)\n
        "},{"location":"formatter/black/#global-and-nonlocal-names-are-broken-across-multiple-lines-by-continuations","title":"global and nonlocal names are broken across multiple lines by continuations","text":"

        If a global or nonlocal statement includes multiple names, and exceeds the configured line width, Ruff will break them across multiple lines using continuations:

        # Input\nglobal analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model\n\n# Ruff\nglobal \\\n    analyze_featuremap_layer, \\\n    analyze_featuremapcompression_layer, \\\n    analyze_latencies_post, \\\n    analyze_motions_layer, \\\n    analyze_size_model\n
        "},{"location":"formatter/black/#trailing-own-line-comments-on-imports-are-not-moved-to-the-next-line","title":"Trailing own-line comments on imports are not moved to the next line","text":"

        Black enforces a single empty line between an import and a trailing own-line comment. Ruff leaves such comments in-place:

        # Input\nimport os\n# comment\n\nimport sys\n\n# Black\nimport os\n\n# comment\n\nimport sys\n\n# Ruff\nimport os\n# comment\n\nimport sys\n
        "},{"location":"formatter/black/#parentheses-around-awaited-collections-are-not-preserved","title":"Parentheses around awaited collections are not preserved","text":"

        Black preserves parentheses around awaited collections:

        await ([1, 2, 3])\n

        Ruff will instead remove them:

        await [1, 2, 3]\n

        This is more consistent to the formatting of other awaited expressions: Ruff and Black both remove parentheses around, e.g., await (1), only retaining them when syntactically required, as in, e.g., await (x := 1).

        "},{"location":"formatter/black/#implicit-string-concatenations-in-attribute-accesses","title":"Implicit string concatenations in attribute accesses","text":"

        Given the following unformatted code:

        print(\"aaaaaaaaaaaaaaaa\" \"aaaaaaaaaaaaaaaa\".format(bbbbbbbbbbbbbbbbbb + bbbbbbbbbbbbbbbbbb))\n

        Internally, Black's logic will first expand the outermost print call:

        print(\n    \"aaaaaaaaaaaaaaaa\" \"aaaaaaaaaaaaaaaa\".format(bbbbbbbbbbbbbbbbbb + bbbbbbbbbbbbbbbbbb)\n)\n

        Since the argument is still too long, Black will then split on the operator with the highest split precedence. In this case, Black splits on the implicit string concatenation, to produce the following Black-formatted code:

        print(\n    \"aaaaaaaaaaaaaaaa\"\n    \"aaaaaaaaaaaaaaaa\".format(bbbbbbbbbbbbbbbbbb + bbbbbbbbbbbbbbbbbb)\n)\n

        Ruff gives implicit concatenations a \"lower\" priority when breaking lines. As a result, Ruff would instead format the above as:

        print(\n    \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\".format(bbbbbbbbbbbbbbbbbb + bbbbbbbbbbbbbbbbbb)\n)\n

        In general, Black splits implicit string concatenations over multiple lines more often than Ruff, even if those concatenations can fit on a single line. Ruff instead avoids splitting such concatenations unless doing so is necessary to fit within the configured line width.

        "},{"location":"formatter/black/#own-line-comments-on-expressions-dont-cause-the-expression-to-expand","title":"Own-line comments on expressions don't cause the expression to expand","text":"

        Given an expression like:

        (\n    # A comment in the middle\n    some_example_var and some_example_var not in some_example_var\n)\n

        Black associates the comment with some_example_var, thus splitting it over two lines:

        (\n    # A comment in the middle\n    some_example_var\n    and some_example_var not in some_example_var\n)\n

        Ruff will instead associate the comment with the entire boolean expression, thus preserving the initial formatting:

        (\n    # A comment in the middle\n    some_example_var and some_example_var not in some_example_var\n)\n
        "},{"location":"formatter/black/#tuples-are-parenthesized-when-expanded","title":"Tuples are parenthesized when expanded","text":"

        Ruff tends towards parenthesizing tuples (with a few exceptions), while Black tends to remove tuple parentheses more often.

        In particular, Ruff will always insert parentheses around tuples that expand over multiple lines:

        # Input\n(a, b), (c, d,)\n\n# Black\n(a, b), (\n    c,\n    d,\n)\n\n# Ruff\n(\n    (a, b),\n    (\n        c,\n        d,\n    ),\n)\n

        There's one exception here. In for loops, both Ruff and Black will avoid inserting unnecessary parentheses:

        # Input\nfor a, [b, d,] in c:\n    pass\n\n# Black\nfor a, [\n    b,\n    d,\n] in c:\n    pass\n\n# Ruff\nfor a, [\n    b,\n    d,\n] in c:\n    pass\n
        "},{"location":"formatter/black/#single-element-tuples-are-always-parenthesized","title":"Single-element tuples are always parenthesized","text":"

        Ruff always inserts parentheses around single-element tuples, while Black will omit them in some cases:

        # Input\n(a, b),\n\n# Black\n(a, b),\n\n# Ruff\n((a, b),)\n

        Adding parentheses around single-element tuples adds visual distinction and helps avoid \"accidental\" tuples created by extraneous trailing commas (see, e.g., #17181).

        "},{"location":"formatter/black/#parentheses-around-call-chain-assignment-values-are-not-preserved","title":"Parentheses around call-chain assignment values are not preserved","text":"

        Given:

        def update_emission_strength():\n    (\n        get_rgbw_emission_node_tree(self)\n        .nodes[\"Emission\"]\n        .inputs[\"Strength\"]\n        .default_value\n    ) = (self.emission_strength * 2)\n

        Black will preserve the parentheses in (self.emission_strength * 2), whereas Ruff will remove them.

        Both Black and Ruff remove such parentheses in simpler assignments, like:

        # Input\ndef update_emission_strength():\n    value = (self.emission_strength * 2)\n\n# Black\ndef update_emission_strength():\n    value = self.emission_strength * 2\n\n# Ruff\ndef update_emission_strength():\n    value = self.emission_strength * 2\n
        "},{"location":"formatter/black/#call-chain-calls-break-differently-in-some-cases","title":"Call chain calls break differently in some cases","text":"

        Black occasionally breaks call chains differently than Ruff; in particular, Black occasionally expands the arguments for the last call in the chain, as in:

        # Input\ndf.drop(\n    columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]\n).drop_duplicates().rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(path / \"aaaaaa.csv\", index=False)\n\n# Black\ndf.drop(\n    columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]\n).drop_duplicates().rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(\n    path / \"aaaaaa.csv\", index=False\n)\n\n# Ruff\ndf.drop(\n    columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]\n).drop_duplicates().rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(path / \"aaaaaa.csv\", index=False)\n

        Ruff will only expand the arguments if doing so is necessary to fit within the configured line width.

        Note that Black does not apply this last-call argument breaking universally. For example, both Black and Ruff will format the following identically:

        # Input\ndf.drop(\n    columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]\n).drop_duplicates(a).rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(\n    path / \"aaaaaa.csv\", index=False\n).other(a)\n\n# Black\ndf.drop(columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]).drop_duplicates(a).rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(path / \"aaaaaa.csv\", index=False).other(a)\n\n# Ruff\ndf.drop(columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]).drop_duplicates(a).rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(path / \"aaaaaa.csv\", index=False).other(a)\n

        Similarly, in some cases, Ruff will collapse composite binary expressions more aggressively than Black, if doing so allows the expression to fit within the configured line width:

        # Black\nassert AAAAAAAAAAAAAAAAAAAAAA.bbbbbb.fooo(\n    aaaaaaaaaaaa=aaaaaaaaaaaa\n).ccccc() == (len(aaaaaaaaaa) + 1) * fooooooooooo * (\n    foooooo + 1\n) * foooooo * len(\n    list(foo(bar(4, foo), foo))\n)\n\n# Ruff\nassert AAAAAAAAAAAAAAAAAAAAAA.bbbbbb.fooo(\n    aaaaaaaaaaaa=aaaaaaaaaaaa\n).ccccc() == (len(aaaaaaaaaa) + 1) * fooooooooooo * (\n    foooooo + 1\n) * foooooo * len(list(foo(bar(4, foo), foo)))\n
        "},{"location":"formatter/black/#single-with-item-targeting-python-38-or-older","title":"Single with item targeting Python 3.8 or older","text":"

        Unlike Black, Ruff uses the same layout for with statements with a single context manager as it does for while, if and other compound statements:

        # Input\ndef run(data_path, model_uri):\n    with pyspark.sql.SparkSession.builder.config(\n        key=\"spark.python.worker.reuse\", value=True\n    ).config(key=\"spark.ui.enabled\", value=False).master(\n        \"local-cluster[2, 1, 1024]\"\n    ).getOrCreate():\n        # ignore spark log output\n        spark.sparkContext.setLogLevel(\"OFF\")\n        print(score_model(spark, data_path, model_uri))\n\n# Black\ndef run(data_path, model_uri):\n    with pyspark.sql.SparkSession.builder.config(\n        key=\"spark.python.worker.reuse\", value=True\n    ).config(key=\"spark.ui.enabled\", value=False).master(\n        \"local-cluster[2, 1, 1024]\"\n    ).getOrCreate():\n        # ignore spark log output\n        spark.sparkContext.setLogLevel(\"OFF\")\n        print(score_model(spark, data_path, model_uri))\n\n# Ruff\ndef run(data_path, model_uri):\n    with (\n        pyspark.sql.SparkSession.builder.config(\n            key=\"spark.python.worker.reuse\", value=True\n        )\n        .config(key=\"spark.ui.enabled\", value=False)\n        .master(\"local-cluster[2, 1, 1024]\")\n        .getOrCreate()\n    ):\n        # ignore spark log output\n        spark.sparkContext.setLogLevel(\"OFF\")\n        print(score_model(spark, data_path, model_uri))\n

        Ruff's formatting matches the formatting of other compound statements:

        def test():\n    if (\n        pyspark.sql.SparkSession.builder.config(\n            key=\"spark.python.worker.reuse\", value=True\n        )\n        .config(key=\"spark.ui.enabled\", value=False)\n        .master(\"local-cluster[2, 1, 1024]\")\n        .getOrCreate()\n    ):\n        # ignore spark log output\n        spark.sparkContext.setLogLevel(\"OFF\")\n        print(score_model(spark, data_path, model_uri))\n
        "},{"location":"formatter/black/#the-last-context-manager-in-a-with-statement-may-be-collapsed-onto-a-single-line","title":"The last context manager in a with statement may be collapsed onto a single line","text":"

        When using a with statement with multiple unparenthesized context managers, Ruff may collapse the last context manager onto a single line, if doing so allows the with statement to fit within the configured line width.

        Black, meanwhile, tends to break the last context manager slightly differently, as in the following example:

        # Black\nwith tempfile.TemporaryDirectory() as d1:\n    symlink_path = Path(d1).joinpath(\"testsymlink\")\n    with tempfile.TemporaryDirectory(dir=d1) as d2, tempfile.TemporaryDirectory(\n        dir=d1\n    ) as d4, tempfile.TemporaryDirectory(dir=d2) as d3, tempfile.NamedTemporaryFile(\n        dir=d4\n    ) as source_file, tempfile.NamedTemporaryFile(\n        dir=d3\n    ) as lock_file:\n        pass\n\n# Ruff\nwith tempfile.TemporaryDirectory() as d1:\n    symlink_path = Path(d1).joinpath(\"testsymlink\")\n    with tempfile.TemporaryDirectory(dir=d1) as d2, tempfile.TemporaryDirectory(\n        dir=d1\n    ) as d4, tempfile.TemporaryDirectory(dir=d2) as d3, tempfile.NamedTemporaryFile(\n        dir=d4\n    ) as source_file, tempfile.NamedTemporaryFile(dir=d3) as lock_file:\n        pass\n

        When targeting Python 3.9 or newer, parentheses will be inserted around the context managers to allow for clearer breaks across multiple lines, as in:

        with tempfile.TemporaryDirectory() as d1:\n    symlink_path = Path(d1).joinpath(\"testsymlink\")\n    with (\n        tempfile.TemporaryDirectory(dir=d1) as d2,\n        tempfile.TemporaryDirectory(dir=d1) as d4,\n        tempfile.TemporaryDirectory(dir=d2) as d3,\n        tempfile.NamedTemporaryFile(dir=d4) as source_file,\n        tempfile.NamedTemporaryFile(dir=d3) as lock_file,\n    ):\n        pass\n
        "},{"location":"formatter/black/#preserving-parentheses-around-single-element-lists","title":"Preserving parentheses around single-element lists","text":"

        Ruff preserves at least one parentheses around list elements, even if the list only contains a single element. The Black 2025 or newer, on the other hand, removes the parentheses for single-element lists if they aren't multiline and doing so does not change semantics:

        # Input\nitems = [(True)]\nitems = [(((((True)))))]\nitems = {(123)}\n\n# Black\nitems = [True]\nitems = [True]\nitems = {123}\n\n# Ruff\nitems = [(True)]\nitems = [(True)]\nitems = {(123)}\n
        "},{"location":"rules/abstract-base-class-without-abstract-method/","title":"abstract-base-class-without-abstract-method (B024)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B024"]},{"location":"rules/abstract-base-class-without-abstract-method/#what-it-does","title":"What it does","text":"

        Checks for abstract classes without abstract methods or properties. Annotated but unassigned class variables are regarded as abstract.

        ","tags":["B024"]},{"location":"rules/abstract-base-class-without-abstract-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Abstract base classes are used to define interfaces. If an abstract base class has no abstract methods or properties, you may have forgotten to add an abstract method or property to the class, or omitted an @abstractmethod decorator.

        If the class is not meant to be used as an interface, consider removing the ABC base class from the class definition.

        ","tags":["B024"]},{"location":"rules/abstract-base-class-without-abstract-method/#example","title":"Example","text":"
        from abc import ABC\nfrom typing import ClassVar\n\n\nclass Foo(ABC):\n    class_var: ClassVar[str] = \"assigned\"\n\n    def method(self):\n        bar()\n

        Use instead:

        from abc import ABC, abstractmethod\nfrom typing import ClassVar\n\n\nclass Foo(ABC):\n    class_var: ClassVar[str]  # unassigned\n\n    @abstractmethod\n    def method(self):\n        bar()\n
        ","tags":["B024"]},{"location":"rules/abstract-base-class-without-abstract-method/#references","title":"References","text":"
        • Python documentation: abc
        • Python documentation: typing.ClassVar
        ","tags":["B024"]},{"location":"rules/airflow-dag-no-schedule-argument/","title":"airflow-dag-no-schedule-argument (AIR002)","text":"

        Derived from the Airflow linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["AIR002"]},{"location":"rules/airflow-dag-no-schedule-argument/#what-it-does","title":"What it does","text":"

        Checks for a DAG() class or @dag() decorator without an explicit schedule (or schedule_interval for Airflow 1) parameter.

        ","tags":["AIR002"]},{"location":"rules/airflow-dag-no-schedule-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        The default value of the schedule parameter on Airflow 2 and schedule_interval on Airflow 1 is timedelta(days=1), which is almost never what a user is looking for. Airflow 3 changed the default value to None, and would break existing dags using the implicit default.

        If your dag does not have an explicit schedule / schedule_interval argument, Airflow 2 schedules a run for it every day (at the time determined by start_date). Such a dag will no longer be scheduled on Airflow 3 at all, without any exceptions or other messages visible to the user.

        ","tags":["AIR002"]},{"location":"rules/airflow-dag-no-schedule-argument/#example","title":"Example","text":"
        from airflow import DAG\n\n\n# Using the implicit default schedule.\ndag = DAG(dag_id=\"my_dag\")\n

        Use instead:

        from datetime import timedelta\n\nfrom airflow import DAG\n\n\ndag = DAG(dag_id=\"my_dag\", schedule=timedelta(days=1))\n
        ","tags":["AIR002"]},{"location":"rules/airflow-variable-name-task-id-mismatch/","title":"airflow-variable-name-task-id-mismatch (AIR001)","text":"

        Derived from the Airflow linter.

        ","tags":["AIR001"]},{"location":"rules/airflow-variable-name-task-id-mismatch/#what-it-does","title":"What it does","text":"

        Checks that the task variable name matches the task_id value for Airflow Operators.

        ","tags":["AIR001"]},{"location":"rules/airflow-variable-name-task-id-mismatch/#why-is-this-bad","title":"Why is this bad?","text":"

        When initializing an Airflow Operator, for consistency, the variable name should match the task_id value. This makes it easier to follow the flow of the DAG.

        ","tags":["AIR001"]},{"location":"rules/airflow-variable-name-task-id-mismatch/#example","title":"Example","text":"
        from airflow.operators import PythonOperator\n\n\nincorrect_name = PythonOperator(task_id=\"my_task\")\n

        Use instead:

        from airflow.operators import PythonOperator\n\n\nmy_task = PythonOperator(task_id=\"my_task\")\n
        ","tags":["AIR001"]},{"location":"rules/airflow3-moved-to-provider/","title":"airflow3-moved-to-provider (AIR302)","text":"

        Derived from the Airflow linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["AIR302"]},{"location":"rules/airflow3-moved-to-provider/#what-it-does","title":"What it does","text":"

        Checks for uses of Airflow functions and values that have been moved to it providers. (e.g., apache-airflow-providers-fab)

        ","tags":["AIR302"]},{"location":"rules/airflow3-moved-to-provider/#why-is-this-bad","title":"Why is this bad?","text":"

        Airflow 3.0 moved various deprecated functions, members, and other values to its providers. The user needs to install the corresponding provider and replace the original usage with the one in the provider

        ","tags":["AIR302"]},{"location":"rules/airflow3-moved-to-provider/#example","title":"Example","text":"
        from airflow.auth.managers.fab.fab_auth_manage import FabAuthManager\n

        Use instead:

        from airflow.providers.fab.auth_manager.fab_auth_manage import FabAuthManager\n
        ","tags":["AIR302"]},{"location":"rules/airflow3-removal/","title":"airflow3-removal (AIR301)","text":"

        Derived from the Airflow linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["AIR301"]},{"location":"rules/airflow3-removal/#what-it-does","title":"What it does","text":"

        Checks for uses of deprecated Airflow functions and values.

        ","tags":["AIR301"]},{"location":"rules/airflow3-removal/#why-is-this-bad","title":"Why is this bad?","text":"

        Airflow 3.0 removed various deprecated functions, members, and other values. Some have more modern replacements. Others are considered too niche and not worth to be maintained in Airflow.

        ","tags":["AIR301"]},{"location":"rules/airflow3-removal/#example","title":"Example","text":"
        from airflow.utils.dates import days_ago\n\n\nyesterday = days_ago(today, 1)\n

        Use instead:

        from datetime import timedelta\n\n\nyesterday = today - timedelta(days=1)\n
        ","tags":["AIR301"]},{"location":"rules/airflow3-suggested-to-move-to-provider/","title":"airflow3-suggested-to-move-to-provider (AIR312)","text":"

        Derived from the Airflow linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["AIR312"]},{"location":"rules/airflow3-suggested-to-move-to-provider/#what-it-does","title":"What it does","text":"

        Checks for uses of Airflow functions and values that have been moved to its providers but still have a compatibility layer (e.g., apache-airflow-providers-standard).

        ","tags":["AIR312"]},{"location":"rules/airflow3-suggested-to-move-to-provider/#why-is-this-bad","title":"Why is this bad?","text":"

        Airflow 3.0 moved various deprecated functions, members, and other values to its providers. Even though these symbols still work fine on Airflow 3.0, they are expected to be removed in a future version. The user is suggested to install the corresponding provider and replace the original usage with the one in the provider.

        ","tags":["AIR312"]},{"location":"rules/airflow3-suggested-to-move-to-provider/#example","title":"Example","text":"
        from airflow.operators.python import PythonOperator\n

        Use instead:

        from airflow.providers.standard.operators.python import PythonOperator\n
        ","tags":["AIR312"]},{"location":"rules/airflow3-suggested-update/","title":"airflow3-suggested-update (AIR311)","text":"

        Derived from the Airflow linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["AIR311"]},{"location":"rules/airflow3-suggested-update/#what-it-does","title":"What it does","text":"

        Checks for uses of deprecated Airflow functions and values that still have a compatibility layer.

        ","tags":["AIR311"]},{"location":"rules/airflow3-suggested-update/#why-is-this-bad","title":"Why is this bad?","text":"

        Airflow 3.0 removed various deprecated functions, members, and other values. Some have more modern replacements. Others are considered too niche and not worth to be maintained in Airflow. Even though these symbols still work fine on Airflow 3.0, they are expected to be removed in a future version. The user is suggested to replace the original usage with the new ones.

        ","tags":["AIR311"]},{"location":"rules/airflow3-suggested-update/#example","title":"Example","text":"
        from airflow import Dataset\n\n\nDataset(uri=\"test://test/\")\n

        Use instead:

        from airflow.sdk import Asset\n\n\nAsset(uri=\"test://test/\")\n
        ","tags":["AIR311"]},{"location":"rules/ambiguous-class-name/","title":"ambiguous-class-name (E742)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E742"]},{"location":"rules/ambiguous-class-name/#what-it-does","title":"What it does","text":"

        Checks for the use of the characters 'l', 'O', or 'I' as class names.

        ","tags":["E742"]},{"location":"rules/ambiguous-class-name/#why-is-this-bad","title":"Why is this bad?","text":"

        In some fonts, these characters are indistinguishable from the numerals one and zero. When tempted to use 'l', use 'L' instead.

        ","tags":["E742"]},{"location":"rules/ambiguous-class-name/#example","title":"Example","text":"
        class I(object): ...\n

        Use instead:

        class Integer(object): ...\n
        ","tags":["E742"]},{"location":"rules/ambiguous-function-name/","title":"ambiguous-function-name (E743)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E743"]},{"location":"rules/ambiguous-function-name/#what-it-does","title":"What it does","text":"

        Checks for the use of the characters 'l', 'O', or 'I' as function names.

        ","tags":["E743"]},{"location":"rules/ambiguous-function-name/#why-is-this-bad","title":"Why is this bad?","text":"

        In some fonts, these characters are indistinguishable from the numerals one and zero. When tempted to use 'l', use 'L' instead.

        ","tags":["E743"]},{"location":"rules/ambiguous-function-name/#example","title":"Example","text":"
        def l(x): ...\n

        Use instead:

        def long_name(x): ...\n
        ","tags":["E743"]},{"location":"rules/ambiguous-unicode-character-comment/","title":"ambiguous-unicode-character-comment (RUF003)","text":"","tags":["RUF003"]},{"location":"rules/ambiguous-unicode-character-comment/#what-it-does","title":"What it does","text":"

        Checks for ambiguous Unicode characters in comments.

        ","tags":["RUF003"]},{"location":"rules/ambiguous-unicode-character-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Some Unicode characters are visually similar to ASCII characters, but have different code points. For example, GREEK CAPITAL LETTER ALPHA (U+0391) is visually similar, but not identical, to the ASCII character A.

        The use of ambiguous Unicode characters can confuse readers, cause subtle bugs, and even make malicious code look harmless.

        In preview, this rule will also flag Unicode characters that are confusable with other, non-preferred Unicode characters. For example, the spec recommends GREEK CAPITAL LETTER OMEGA over OHM SIGN.

        You can omit characters from being flagged as ambiguous via the lint.allowed-confusables setting.

        ","tags":["RUF003"]},{"location":"rules/ambiguous-unicode-character-comment/#example","title":"Example","text":"
        foo()  # n\u043eqa  # \"\u043e\" is Cyrillic (`U+043E`)\n

        Use instead:

        foo()  # noqa  # \"o\" is Latin (`U+006F`)\n
        ","tags":["RUF003"]},{"location":"rules/ambiguous-unicode-character-comment/#options","title":"Options","text":"
        • lint.allowed-confusables
        ","tags":["RUF003"]},{"location":"rules/ambiguous-unicode-character-docstring/","title":"ambiguous-unicode-character-docstring (RUF002)","text":"","tags":["RUF002"]},{"location":"rules/ambiguous-unicode-character-docstring/#what-it-does","title":"What it does","text":"

        Checks for ambiguous Unicode characters in docstrings.

        ","tags":["RUF002"]},{"location":"rules/ambiguous-unicode-character-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        Some Unicode characters are visually similar to ASCII characters, but have different code points. For example, GREEK CAPITAL LETTER ALPHA (U+0391) is visually similar, but not identical, to the ASCII character A.

        The use of ambiguous Unicode characters can confuse readers, cause subtle bugs, and even make malicious code look harmless.

        In preview, this rule will also flag Unicode characters that are confusable with other, non-preferred Unicode characters. For example, the spec recommends GREEK CAPITAL LETTER OMEGA over OHM SIGN.

        You can omit characters from being flagged as ambiguous via the lint.allowed-confusables setting.

        ","tags":["RUF002"]},{"location":"rules/ambiguous-unicode-character-docstring/#example","title":"Example","text":"
        \"\"\"A lovely docstring (with a `U+FF09` parenthesis\uff09.\"\"\"\n

        Use instead:

        \"\"\"A lovely docstring (with no strange parentheses).\"\"\"\n
        ","tags":["RUF002"]},{"location":"rules/ambiguous-unicode-character-docstring/#options","title":"Options","text":"
        • lint.allowed-confusables
        ","tags":["RUF002"]},{"location":"rules/ambiguous-unicode-character-string/","title":"ambiguous-unicode-character-string (RUF001)","text":"","tags":["RUF001"]},{"location":"rules/ambiguous-unicode-character-string/#what-it-does","title":"What it does","text":"

        Checks for ambiguous Unicode characters in strings.

        ","tags":["RUF001"]},{"location":"rules/ambiguous-unicode-character-string/#why-is-this-bad","title":"Why is this bad?","text":"

        Some Unicode characters are visually similar to ASCII characters, but have different code points. For example, GREEK CAPITAL LETTER ALPHA (U+0391) is visually similar, but not identical, to the ASCII character A.

        The use of ambiguous Unicode characters can confuse readers, cause subtle bugs, and even make malicious code look harmless.

        In preview, this rule will also flag Unicode characters that are confusable with other, non-preferred Unicode characters. For example, the spec recommends GREEK CAPITAL LETTER OMEGA over OHM SIGN.

        You can omit characters from being flagged as ambiguous via the lint.allowed-confusables setting.

        ","tags":["RUF001"]},{"location":"rules/ambiguous-unicode-character-string/#example","title":"Example","text":"
        print(\"\u0397ello, world!\")  # \"\u0397\" is the Greek eta (`U+0397`).\n

        Use instead:

        print(\"Hello, world!\")  # \"H\" is the Latin capital H (`U+0048`).\n
        ","tags":["RUF001"]},{"location":"rules/ambiguous-unicode-character-string/#options","title":"Options","text":"
        • lint.allowed-confusables
        ","tags":["RUF001"]},{"location":"rules/ambiguous-variable-name/","title":"ambiguous-variable-name (E741)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E741"]},{"location":"rules/ambiguous-variable-name/#what-it-does","title":"What it does","text":"

        Checks for the use of the characters 'l', 'O', or 'I' as variable names.

        Note: This rule is automatically disabled for all stub files (files with .pyi extensions). The rule has little relevance for authors of stubs: a well-written stub should aim to faithfully represent the interface of the equivalent .py file as it exists at runtime, including any ambiguously named variables in the runtime module.

        ","tags":["E741"]},{"location":"rules/ambiguous-variable-name/#why-is-this-bad","title":"Why is this bad?","text":"

        In some fonts, these characters are indistinguishable from the numerals one and zero. When tempted to use 'l', use 'L' instead.

        ","tags":["E741"]},{"location":"rules/ambiguous-variable-name/#example","title":"Example","text":"
        l = 0\nO = 123\nI = 42\n

        Use instead:

        L = 0\no = 123\ni = 42\n
        ","tags":["E741"]},{"location":"rules/and-or-ternary/","title":"and-or-ternary (PLR1706)","text":"

        Derived from the Pylint linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["PLR1706"]},{"location":"rules/and-or-ternary/#removal","title":"Removal","text":"

        This rule was removed from Ruff because it was common for it to introduce behavioral changes. See #9007 for more information.

        ","tags":["PLR1706"]},{"location":"rules/and-or-ternary/#what-it-does","title":"What it does","text":"

        Checks for uses of the known pre-Python 2.5 ternary syntax.

        ","tags":["PLR1706"]},{"location":"rules/and-or-ternary/#why-is-this-bad","title":"Why is this bad?","text":"

        Prior to the introduction of the if-expression (ternary) operator in Python 2.5, the only way to express a conditional expression was to use the and and or operators.

        The if-expression construct is clearer and more explicit, and should be preferred over the use of and and or for ternary expressions.

        ","tags":["PLR1706"]},{"location":"rules/and-or-ternary/#example","title":"Example","text":"
        x, y = 1, 2\nmaximum = x >= y and x or y\n

        Use instead:

        x, y = 1, 2\nmaximum = x if x >= y else y\n
        ","tags":["PLR1706"]},{"location":"rules/any-eq-ne-annotation/","title":"any-eq-ne-annotation (PYI032)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI032"]},{"location":"rules/any-eq-ne-annotation/#what-it-does","title":"What it does","text":"

        Checks for __eq__ and __ne__ implementations that use typing.Any as the type annotation for their second parameter.

        ","tags":["PYI032"]},{"location":"rules/any-eq-ne-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        The Python documentation recommends the use of object to \"indicate that a value could be any type in a typesafe manner\". Any, on the other hand, should be seen as an \"escape hatch when you need to mix dynamically and statically typed code\". Since using Any allows you to write highly unsafe code, you should generally only use Any when the semantics of your code would otherwise be inexpressible to the type checker.

        The expectation in Python is that a comparison of two arbitrary objects using == or != should never raise an exception. This contract can be fully expressed in the type system and does not involve requesting unsound behaviour from a type checker. As such, object is a more appropriate annotation than Any for the second parameter of the methods implementing these comparison operators -- __eq__ and __ne__.

        ","tags":["PYI032"]},{"location":"rules/any-eq-ne-annotation/#example","title":"Example","text":"
        class Foo:\n    def __eq__(self, obj: typing.Any) -> bool: ...\n

        Use instead:

        class Foo:\n    def __eq__(self, obj: object) -> bool: ...\n
        ","tags":["PYI032"]},{"location":"rules/any-eq-ne-annotation/#references","title":"References","text":"
        • Python documentation: The Any type
        • Mypy documentation: Any vs. object
        ","tags":["PYI032"]},{"location":"rules/any-type/","title":"any-type (ANN401)","text":"

        Derived from the flake8-annotations linter.

        ","tags":["ANN401"]},{"location":"rules/any-type/#what-it-does","title":"What it does","text":"

        Checks that function arguments are annotated with a more specific type than Any.

        ","tags":["ANN401"]},{"location":"rules/any-type/#why-is-this-bad","title":"Why is this bad?","text":"

        Any is a special type indicating an unconstrained type. When an expression is annotated with type Any, type checkers will allow all operations on it.

        It's better to be explicit about the type of an expression, and to use Any as an \"escape hatch\" only when it is really needed.

        ","tags":["ANN401"]},{"location":"rules/any-type/#example","title":"Example","text":"
        def foo(x: Any): ...\n

        Use instead:

        def foo(x: int): ...\n
        ","tags":["ANN401"]},{"location":"rules/any-type/#known-problems","title":"Known problems","text":"

        Type aliases are unsupported and can lead to false positives. For example, the following will trigger this rule inadvertently:

        from typing import Any\n\nMyAny = Any\n\n\ndef foo(x: MyAny): ...\n
        ","tags":["ANN401"]},{"location":"rules/any-type/#references","title":"References","text":"
        • Typing spec: Any
        • Python documentation: typing.Any
        • Mypy documentation: The Any type
        ","tags":["ANN401"]},{"location":"rules/argument-default-in-stub/","title":"argument-default-in-stub (PYI014)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI014"]},{"location":"rules/argument-default-in-stub/#what-it-does","title":"What it does","text":"

        Checks for untyped function arguments in stubs with default values that are not \"simple\" /// (i.e., int, float, complex, bytes, str, bool, None, ..., or simple container literals).

        ","tags":["PYI014"]},{"location":"rules/argument-default-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub (.pyi) files exist to define type hints, and are not evaluated at runtime. As such, function arguments in stub files should not have default values, as they are ignored by type checkers.

        However, the use of default values may be useful for IDEs and other consumers of stub files, and so \"simple\" values may be worth including and are permitted by this rule.

        Instead of including and reproducing a complex value, use ... to indicate that the assignment has a default value, but that the value is non-simple or varies according to the current platform or Python version.

        ","tags":["PYI014"]},{"location":"rules/argument-default-in-stub/#example","title":"Example","text":"
        def foo(arg=[]) -> None: ...\n

        Use instead:

        def foo(arg=...) -> None: ...\n
        ","tags":["PYI014"]},{"location":"rules/argument-default-in-stub/#references","title":"References","text":"
        • flake8-pyi
        ","tags":["PYI014"]},{"location":"rules/assert-false/","title":"assert-false (B011)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B011"]},{"location":"rules/assert-false/#what-it-does","title":"What it does","text":"

        Checks for uses of assert False.

        ","tags":["B011"]},{"location":"rules/assert-false/#why-is-this-bad","title":"Why is this bad?","text":"

        Python removes assert statements when running in optimized mode (python -O), making assert False an unreliable means of raising an AssertionError.

        Instead, raise an AssertionError directly.

        ","tags":["B011"]},{"location":"rules/assert-false/#example","title":"Example","text":"
        assert False\n

        Use instead:

        raise AssertionError\n
        ","tags":["B011"]},{"location":"rules/assert-false/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as changing an assert to a raise will change the behavior of your program when running in optimized mode (python -O).

        ","tags":["B011"]},{"location":"rules/assert-false/#references","title":"References","text":"
        • Python documentation: assert
        ","tags":["B011"]},{"location":"rules/assert-on-string-literal/","title":"assert-on-string-literal (PLW0129)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0129"]},{"location":"rules/assert-on-string-literal/#what-it-does","title":"What it does","text":"

        Checks for assert statements that use a string literal as the first argument.

        ","tags":["PLW0129"]},{"location":"rules/assert-on-string-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        An assert on a non-empty string literal will always pass, while an assert on an empty string literal will always fail.

        ","tags":["PLW0129"]},{"location":"rules/assert-on-string-literal/#example","title":"Example","text":"
        assert \"always true\"\n
        ","tags":["PLW0129"]},{"location":"rules/assert-raises-exception/","title":"assert-raises-exception (B017)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B017"]},{"location":"rules/assert-raises-exception/#what-it-does","title":"What it does","text":"

        Checks for assertRaises and pytest.raises context managers that catch Exception or BaseException.

        ","tags":["B017"]},{"location":"rules/assert-raises-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        These forms catch every Exception, which can lead to tests passing even if, e.g., the code under consideration raises a SyntaxError or IndentationError.

        Either assert for a more specific exception (builtin or custom), or use assertRaisesRegex or pytest.raises(..., match=<REGEX>) respectively.

        ","tags":["B017"]},{"location":"rules/assert-raises-exception/#example","title":"Example","text":"
        self.assertRaises(Exception, foo)\n

        Use instead:

        self.assertRaises(SomeSpecificException, foo)\n
        ","tags":["B017"]},{"location":"rules/assert-tuple/","title":"assert-tuple (F631)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F631"]},{"location":"rules/assert-tuple/#what-it-does","title":"What it does","text":"

        Checks for assert statements that use non-empty tuples as test conditions.

        ","tags":["F631"]},{"location":"rules/assert-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        Non-empty tuples are always True, so an assert statement with a non-empty tuple as its test condition will always pass. This is likely a mistake.

        ","tags":["F631"]},{"location":"rules/assert-tuple/#example","title":"Example","text":"
        assert (some_condition,)\n

        Use instead:

        assert some_condition\n
        ","tags":["F631"]},{"location":"rules/assert-tuple/#references","title":"References","text":"
        • Python documentation: The assert statement
        ","tags":["F631"]},{"location":"rules/assert-with-print-message/","title":"assert-with-print-message (RUF030)","text":"

        Fix is always available.

        ","tags":["RUF030"]},{"location":"rules/assert-with-print-message/#what-it-does","title":"What it does","text":"

        Checks for uses of assert expression, print(message).

        ","tags":["RUF030"]},{"location":"rules/assert-with-print-message/#why-is-this-bad","title":"Why is this bad?","text":"

        If an assert x, y assertion fails, the Python interpreter raises an AssertionError, and the evaluated value of y is used as the contents of that assertion error. The print function always returns None, however, so the evaluated value of a call to print will always be None.

        Using a print call in this context will therefore output the message to stdout, before raising an empty AssertionError(None). Instead, remove the print and pass the message directly as the second expression, allowing stderr to capture the message in a well-formatted context.

        ","tags":["RUF030"]},{"location":"rules/assert-with-print-message/#example","title":"Example","text":"
        assert False, print(\"This is a message\")\n

        Use instead:

        assert False, \"This is a message\"\n
        ","tags":["RUF030"]},{"location":"rules/assert-with-print-message/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as changing the second expression will result in a different AssertionError message being raised, as well as a change in stdout output.

        ","tags":["RUF030"]},{"location":"rules/assert-with-print-message/#references","title":"References","text":"
        • Python documentation: assert
        ","tags":["RUF030"]},{"location":"rules/assert/","title":"assert (S101)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S101"]},{"location":"rules/assert/#what-it-does","title":"What it does","text":"

        Checks for uses of the assert keyword.

        ","tags":["S101"]},{"location":"rules/assert/#why-is-this-bad","title":"Why is this bad?","text":"

        Assertions are removed when Python is run with optimization requested (i.e., when the -O flag is present), which is a common practice in production environments. As such, assertions should not be used for runtime validation of user input or to enforce interface constraints.

        Consider raising a meaningful error instead of using assert.

        ","tags":["S101"]},{"location":"rules/assert/#example","title":"Example","text":"
        assert x > 0, \"Expected positive value.\"\n

        Use instead:

        if not x > 0:\n    raise ValueError(\"Expected positive value.\")\n\n# or even better:\nif x <= 0:\n    raise ValueError(\"Expected positive value.\")\n
        ","tags":["S101"]},{"location":"rules/assignment-default-in-stub/","title":"assignment-default-in-stub (PYI015)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI015"]},{"location":"rules/assignment-default-in-stub/#what-it-does","title":"What it does","text":"

        Checks for assignments in stubs with default values that are not \"simple\" (i.e., int, float, complex, bytes, str, bool, None, ..., or simple container literals).

        ","tags":["PYI015"]},{"location":"rules/assignment-default-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub (.pyi) files exist to define type hints, and are not evaluated at runtime. As such, assignments in stub files should not include values, as they are ignored by type checkers.

        However, the use of such values may be useful for IDEs and other consumers of stub files, and so \"simple\" values may be worth including and are permitted by this rule.

        Instead of including and reproducing a complex value, use ... to indicate that the assignment has a default value, but that the value is non-simple or varies according to the current platform or Python version.

        ","tags":["PYI015"]},{"location":"rules/assignment-default-in-stub/#example","title":"Example","text":"
        foo: str = \"...\"\n

        Use instead:

        foo: str = ...\n
        ","tags":["PYI015"]},{"location":"rules/assignment-default-in-stub/#references","title":"References","text":"
        • flake8-pyi
        ","tags":["PYI015"]},{"location":"rules/assignment-in-assert/","title":"assignment-in-assert (RUF018)","text":"","tags":["RUF018"]},{"location":"rules/assignment-in-assert/#what-it-does","title":"What it does","text":"

        Checks for named assignment expressions (e.g., x := 0) in assert statements.

        ","tags":["RUF018"]},{"location":"rules/assignment-in-assert/#why-is-this-bad","title":"Why is this bad?","text":"

        Named assignment expressions (also known as \"walrus operators\") are used to assign a value to a variable as part of a larger expression.

        Named assignments are syntactically valid in assert statements. However, when the Python interpreter is run under the -O flag, assert statements are not executed. In this case, the named assignment will also be ignored, which may result in unexpected behavior (e.g., undefined variable accesses).

        ","tags":["RUF018"]},{"location":"rules/assignment-in-assert/#example","title":"Example","text":"
        assert (x := 0) == 0\nprint(x)\n

        Use instead:

        x = 0\nassert x == 0\nprint(x)\n

        The rule avoids flagging named expressions that define variables which are only referenced from inside assert statements; the following will not trigger the rule:

        assert (x := y**2) > 42, f\"Expected >42 but got {x}\"\n

        Nor will this:

        assert (x := y**2) > 42\nassert x < 1_000_000\n
        ","tags":["RUF018"]},{"location":"rules/assignment-in-assert/#references","title":"References","text":"
        • Python documentation: -O
        ","tags":["RUF018"]},{"location":"rules/assignment-to-os-environ/","title":"assignment-to-os-environ (B003)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B003"]},{"location":"rules/assignment-to-os-environ/#what-it-does","title":"What it does","text":"

        Checks for assignments to os.environ.

        ","tags":["B003"]},{"location":"rules/assignment-to-os-environ/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, os.environ is a mapping that represents the environment of the current process.

        However, reassigning to os.environ does not clear the environment. Instead, it merely updates the os.environ for the current process. This can lead to unexpected behavior, especially when running the program in a subprocess.

        Instead, use os.environ.clear() to clear the environment, or use the env argument of subprocess.Popen to pass a custom environment to a subprocess.

        ","tags":["B003"]},{"location":"rules/assignment-to-os-environ/#example","title":"Example","text":"
        import os\n\nos.environ = {\"foo\": \"bar\"}\n

        Use instead:

        import os\n\nos.environ.clear()\nos.environ[\"foo\"] = \"bar\"\n
        ","tags":["B003"]},{"location":"rules/assignment-to-os-environ/#references","title":"References","text":"
        • Python documentation: os.environ
        • Python documentation: subprocess.Popen
        ","tags":["B003"]},{"location":"rules/async-busy-wait/","title":"async-busy-wait (ASYNC110)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC110"]},{"location":"rules/async-busy-wait/#what-it-does","title":"What it does","text":"

        Checks for the use of an async sleep function in a while loop.

        ","tags":["ASYNC110"]},{"location":"rules/async-busy-wait/#why-is-this-bad","title":"Why is this bad?","text":"

        Instead of sleeping in a while loop, and waiting for a condition to become true, it's preferable to await on an Event object such as: asyncio.Event, trio.Event, or anyio.Event.

        ","tags":["ASYNC110"]},{"location":"rules/async-busy-wait/#example","title":"Example","text":"
        DONE = False\n\n\nasync def func():\n    while not DONE:\n        await asyncio.sleep(1)\n

        Use instead:

        DONE = asyncio.Event()\n\n\nasync def func():\n    await DONE.wait()\n
        ","tags":["ASYNC110"]},{"location":"rules/async-busy-wait/#references","title":"References","text":"
        • asyncio events
        • anyio events
        • trio events
        ","tags":["ASYNC110"]},{"location":"rules/async-function-with-timeout/","title":"async-function-with-timeout (ASYNC109)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC109"]},{"location":"rules/async-function-with-timeout/#what-it-does","title":"What it does","text":"

        Checks for async function definitions with timeout parameters.

        ","tags":["ASYNC109"]},{"location":"rules/async-function-with-timeout/#why-is-this-bad","title":"Why is this bad?","text":"

        Rather than implementing asynchronous timeout behavior manually, prefer built-in timeout functionality, such as asyncio.timeout, trio.fail_after, or anyio.move_on_after, among others.

        This rule is highly opinionated to enforce a design pattern called \"structured concurrency\" that allows for async functions to be oblivious to timeouts, instead letting callers to handle the logic with a context manager.

        ","tags":["ASYNC109"]},{"location":"rules/async-function-with-timeout/#details","title":"Details","text":"

        This rule attempts to detect which async framework your code is using by analysing the imports in the file it's checking. If it sees an anyio import in your code, it will assume anyio is your framework of choice; if it sees a trio import, it will assume trio; if it sees neither, it will assume asyncio. asyncio.timeout was added in Python 3.11, so if asyncio is detected as the framework being used, this rule will be ignored when your configured target-version is set to less than Python 3.11.

        For functions that wrap asyncio.timeout, trio.fail_after or anyio.move_on_after, false positives from this rule can be avoided by using a different parameter name.

        ","tags":["ASYNC109"]},{"location":"rules/async-function-with-timeout/#example","title":"Example","text":"
        async def long_running_task(timeout): ...\n\n\nasync def main():\n    await long_running_task(timeout=2)\n

        Use instead:

        async def long_running_task(): ...\n\n\nasync def main():\n    async with asyncio.timeout(2):\n        await long_running_task()\n
        ","tags":["ASYNC109"]},{"location":"rules/async-function-with-timeout/#references","title":"References","text":"
        • asyncio timeouts
        • anyio timeouts
        • trio timeouts
        ","tags":["ASYNC109"]},{"location":"rules/async-zero-sleep/","title":"async-zero-sleep (ASYNC115)","text":"

        Derived from the flake8-async linter.

        Fix is always available.

        ","tags":["ASYNC115"]},{"location":"rules/async-zero-sleep/#what-it-does","title":"What it does","text":"

        Checks for uses of trio.sleep(0) or anyio.sleep(0).

        ","tags":["ASYNC115"]},{"location":"rules/async-zero-sleep/#why-is-this-bad","title":"Why is this bad?","text":"

        trio.sleep(0) is equivalent to calling trio.lowlevel.checkpoint(). However, the latter better conveys the intent of the code.

        ","tags":["ASYNC115"]},{"location":"rules/async-zero-sleep/#example","title":"Example","text":"
        import trio\n\n\nasync def func():\n    await trio.sleep(0)\n

        Use instead:

        import trio\n\n\nasync def func():\n    await trio.lowlevel.checkpoint()\n
        ","tags":["ASYNC115"]},{"location":"rules/asyncio-dangling-task/","title":"asyncio-dangling-task (RUF006)","text":"","tags":["RUF006"]},{"location":"rules/asyncio-dangling-task/#what-it-does","title":"What it does","text":"

        Checks for asyncio.create_task and asyncio.ensure_future calls that do not store a reference to the returned result.

        ","tags":["RUF006"]},{"location":"rules/asyncio-dangling-task/#why-is-this-bad","title":"Why is this bad?","text":"

        Per the asyncio documentation, the event loop only retains a weak reference to tasks. If the task returned by asyncio.create_task and asyncio.ensure_future is not stored in a variable, or a collection, or otherwise referenced, it may be garbage collected at any time. This can lead to unexpected and inconsistent behavior, as your tasks may or may not run to completion.

        ","tags":["RUF006"]},{"location":"rules/asyncio-dangling-task/#example","title":"Example","text":"
        import asyncio\n\nfor i in range(10):\n    # This creates a weak reference to the task, which may be garbage\n    # collected at any time.\n    asyncio.create_task(some_coro(param=i))\n

        Use instead:

        import asyncio\n\nbackground_tasks = set()\n\nfor i in range(10):\n    task = asyncio.create_task(some_coro(param=i))\n\n    # Add task to the set. This creates a strong reference.\n    background_tasks.add(task)\n\n    # To prevent keeping references to finished tasks forever,\n    # make each task remove its own reference from the set after\n    # completion:\n    task.add_done_callback(background_tasks.discard)\n
        ","tags":["RUF006"]},{"location":"rules/asyncio-dangling-task/#references","title":"References","text":"
        • The Heisenbug lurking in your async code
        • The Python Standard Library
        ","tags":["RUF006"]},{"location":"rules/avoidable-escaped-quote/","title":"avoidable-escaped-quote (Q003)","text":"

        Derived from the flake8-quotes linter.

        Fix is always available.

        ","tags":["Q003"]},{"location":"rules/avoidable-escaped-quote/#what-it-does","title":"What it does","text":"

        Checks for strings that include escaped quotes, and suggests changing the quote style to avoid the need to escape them.

        ","tags":["Q003"]},{"location":"rules/avoidable-escaped-quote/#why-is-this-bad","title":"Why is this bad?","text":"

        It's preferable to avoid escaped quotes in strings. By changing the outer quote style, you can avoid escaping inner quotes.

        ","tags":["Q003"]},{"location":"rules/avoidable-escaped-quote/#example","title":"Example","text":"
        foo = 'bar\\'s'\n

        Use instead:

        foo = \"bar's\"\n
        ","tags":["Q003"]},{"location":"rules/avoidable-escaped-quote/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter automatically removes unnecessary escapes, making the rule redundant.

        ","tags":["Q003"]},{"location":"rules/await-outside-async/","title":"await-outside-async (PLE1142)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1142"]},{"location":"rules/await-outside-async/#what-it-does","title":"What it does","text":"

        Checks for uses of await outside async functions.

        ","tags":["PLE1142"]},{"location":"rules/await-outside-async/#why-is-this-bad","title":"Why is this bad?","text":"

        Using await outside an async function is a syntax error.

        ","tags":["PLE1142"]},{"location":"rules/await-outside-async/#example","title":"Example","text":"
        import asyncio\n\n\ndef foo():\n    await asyncio.sleep(1)\n

        Use instead:

        import asyncio\n\n\nasync def foo():\n    await asyncio.sleep(1)\n
        ","tags":["PLE1142"]},{"location":"rules/await-outside-async/#notebook-behavior","title":"Notebook behavior","text":"

        As an exception, await is allowed at the top level of a Jupyter notebook (see: autoawait).

        ","tags":["PLE1142"]},{"location":"rules/await-outside-async/#references","title":"References","text":"
        • Python documentation: Await expression
        • PEP 492: Await Expression
        ","tags":["PLE1142"]},{"location":"rules/bad-dunder-method-name/","title":"bad-dunder-method-name (PLW3201)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW3201"]},{"location":"rules/bad-dunder-method-name/#what-it-does","title":"What it does","text":"

        Checks for dunder methods that have no special meaning in Python 3.

        ","tags":["PLW3201"]},{"location":"rules/bad-dunder-method-name/#why-is-this-bad","title":"Why is this bad?","text":"

        Misspelled or no longer supported dunder name methods may cause your code to not function as expected.

        Since dunder methods are associated with customizing the behavior of a class in Python, introducing a dunder method such as __foo__ that diverges from standard Python dunder methods could potentially confuse someone reading the code.

        This rule will detect all methods starting and ending with at least one underscore (e.g., _str_), but ignores known dunder methods (like __init__), as well as methods that are marked with @override.

        Additional dunder methods names can be allowed via the lint.pylint.allow-dunder-method-names setting.

        ","tags":["PLW3201"]},{"location":"rules/bad-dunder-method-name/#example","title":"Example","text":"
        class Foo:\n    def __init_(self): ...\n

        Use instead:

        class Foo:\n    def __init__(self): ...\n
        ","tags":["PLW3201"]},{"location":"rules/bad-dunder-method-name/#options","title":"Options","text":"
        • lint.pylint.allow-dunder-method-names
        ","tags":["PLW3201"]},{"location":"rules/bad-exit-annotation/","title":"bad-exit-annotation (PYI036)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI036"]},{"location":"rules/bad-exit-annotation/#what-it-does","title":"What it does","text":"

        Checks for incorrect function signatures on __exit__ and __aexit__ methods.

        ","tags":["PYI036"]},{"location":"rules/bad-exit-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        Improperly annotated __exit__ and __aexit__ methods can cause unexpected behavior when interacting with type checkers.

        ","tags":["PYI036"]},{"location":"rules/bad-exit-annotation/#example","title":"Example","text":"
        from types import TracebackType\n\nclass Foo:\n    def __exit__(\n        self, typ: BaseException, exc: BaseException, tb: TracebackType\n    ) -> None: ...\n

        Use instead:

        from types import TracebackType\n\nclass Foo:\n    def __exit__(\n        self,\n        typ: type[BaseException] | None,\n        exc: BaseException | None,\n        tb: TracebackType | None,\n    ) -> None: ...\n
        ","tags":["PYI036"]},{"location":"rules/bad-file-permissions/","title":"bad-file-permissions (S103)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S103"]},{"location":"rules/bad-file-permissions/#what-it-does","title":"What it does","text":"

        Checks for files with overly permissive permissions.

        ","tags":["S103"]},{"location":"rules/bad-file-permissions/#why-is-this-bad","title":"Why is this bad?","text":"

        Overly permissive file permissions may allow unintended access and arbitrary code execution.

        ","tags":["S103"]},{"location":"rules/bad-file-permissions/#example","title":"Example","text":"
        import os\n\nos.chmod(\"/etc/secrets.txt\", 0o666)  # rw-rw-rw-\n

        Use instead:

        import os\n\nos.chmod(\"/etc/secrets.txt\", 0o600)  # rw-------\n
        ","tags":["S103"]},{"location":"rules/bad-file-permissions/#references","title":"References","text":"
        • Python documentation: os.chmod
        • Python documentation: stat
        • Common Weakness Enumeration: CWE-732
        ","tags":["S103"]},{"location":"rules/bad-open-mode/","title":"bad-open-mode (PLW1501)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW1501"]},{"location":"rules/bad-open-mode/#what-it-does","title":"What it does","text":"

        Check for an invalid mode argument in open calls.

        ","tags":["PLW1501"]},{"location":"rules/bad-open-mode/#why-is-this-bad","title":"Why is this bad?","text":"

        The open function accepts a mode argument that specifies how the file should be opened (e.g., read-only, write-only, append-only, etc.).

        Python supports a variety of open modes: r, w, a, and x, to control reading, writing, appending, and creating, respectively, along with b (binary mode), + (read and write), and U (universal newlines), the latter of which is only valid alongside r. This rule detects both invalid combinations of modes and invalid characters in the mode string itself.

        ","tags":["PLW1501"]},{"location":"rules/bad-open-mode/#example","title":"Example","text":"
        with open(\"file\", \"rwx\") as f:\n    return f.read()\n

        Use instead:

        with open(\"file\", \"r\") as f:\n    return f.read()\n
        ","tags":["PLW1501"]},{"location":"rules/bad-open-mode/#references","title":"References","text":"
        • Python documentation: open
        ","tags":["PLW1501"]},{"location":"rules/bad-quotes-docstring/","title":"bad-quotes-docstring (Q002)","text":"

        Derived from the flake8-quotes linter.

        Fix is sometimes available.

        ","tags":["Q002"]},{"location":"rules/bad-quotes-docstring/#what-it-does","title":"What it does","text":"

        Checks for docstrings that use single quotes or double quotes, depending on the value of the lint.flake8-quotes.docstring-quotes setting.

        ","tags":["Q002"]},{"location":"rules/bad-quotes-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use either single or double quotes for docstring strings, but be consistent.

        ","tags":["Q002"]},{"location":"rules/bad-quotes-docstring/#example","title":"Example","text":"
        '''\nbar\n'''\n

        Assuming docstring-quotes is set to double, use instead:

        \"\"\"\nbar\n\"\"\"\n
        ","tags":["Q002"]},{"location":"rules/bad-quotes-docstring/#options","title":"Options","text":"
        • lint.flake8-quotes.docstring-quotes
        ","tags":["Q002"]},{"location":"rules/bad-quotes-docstring/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces double quotes for docstrings, making the rule redundant.

        ","tags":["Q002"]},{"location":"rules/bad-quotes-inline-string/","title":"bad-quotes-inline-string (Q000)","text":"

        Derived from the flake8-quotes linter.

        Fix is sometimes available.

        ","tags":["Q000"]},{"location":"rules/bad-quotes-inline-string/#what-it-does","title":"What it does","text":"

        Checks for inline strings that use single quotes or double quotes, depending on the value of the lint.flake8-quotes.inline-quotes option.

        ","tags":["Q000"]},{"location":"rules/bad-quotes-inline-string/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use either single or double quotes for inline strings, but be consistent.

        ","tags":["Q000"]},{"location":"rules/bad-quotes-inline-string/#example","title":"Example","text":"
        foo = 'bar'\n

        Assuming inline-quotes is set to double, use instead:

        foo = \"bar\"\n
        ","tags":["Q000"]},{"location":"rules/bad-quotes-inline-string/#options","title":"Options","text":"
        • lint.flake8-quotes.inline-quotes
        ","tags":["Q000"]},{"location":"rules/bad-quotes-inline-string/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent quotes for inline strings, making the rule redundant.

        ","tags":["Q000"]},{"location":"rules/bad-quotes-multiline-string/","title":"bad-quotes-multiline-string (Q001)","text":"

        Derived from the flake8-quotes linter.

        Fix is always available.

        ","tags":["Q001"]},{"location":"rules/bad-quotes-multiline-string/#what-it-does","title":"What it does","text":"

        Checks for multiline strings that use single quotes or double quotes, depending on the value of the lint.flake8-quotes.multiline-quotes setting.

        ","tags":["Q001"]},{"location":"rules/bad-quotes-multiline-string/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use either single or double quotes for multiline strings, but be consistent.

        ","tags":["Q001"]},{"location":"rules/bad-quotes-multiline-string/#example","title":"Example","text":"
        foo = '''\nbar\n'''\n

        Assuming multiline-quotes is set to double, use instead:

        foo = \"\"\"\nbar\n\"\"\"\n
        ","tags":["Q001"]},{"location":"rules/bad-quotes-multiline-string/#options","title":"Options","text":"
        • lint.flake8-quotes.multiline-quotes
        ","tags":["Q001"]},{"location":"rules/bad-quotes-multiline-string/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces double quotes for multiline strings, making the rule redundant.

        ","tags":["Q001"]},{"location":"rules/bad-staticmethod-argument/","title":"bad-staticmethod-argument (PLW0211)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0211"]},{"location":"rules/bad-staticmethod-argument/#what-it-does","title":"What it does","text":"

        Checks for static methods that use self or cls as their first argument. This rule also applies to __new__ methods, which are implicitly static.

        ","tags":["PLW0211"]},{"location":"rules/bad-staticmethod-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the use of self and cls as the first arguments for instance methods and class methods, respectively. Naming the first argument of a static method as self or cls can be misleading, as static methods do not receive an instance or class reference as their first argument.

        ","tags":["PLW0211"]},{"location":"rules/bad-staticmethod-argument/#example","title":"Example","text":"
        class Wolf:\n    @staticmethod\n    def eat(self):\n        pass\n

        Use instead:

        class Wolf:\n    @staticmethod\n    def eat(sheep):\n        pass\n
        ","tags":["PLW0211"]},{"location":"rules/bad-str-strip-call/","title":"bad-str-strip-call (PLE1310)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1310"]},{"location":"rules/bad-str-strip-call/#what-it-does","title":"What it does","text":"

        Checks duplicate characters in str.strip calls.

        ","tags":["PLE1310"]},{"location":"rules/bad-str-strip-call/#why-is-this-bad","title":"Why is this bad?","text":"

        All characters in str.strip calls are removed from both the leading and trailing ends of the string. Including duplicate characters in the call is redundant and often indicative of a mistake.

        In Python 3.9 and later, you can use str.removeprefix and str.removesuffix to remove an exact prefix or suffix from a string, respectively, which should be preferred when possible.

        ","tags":["PLE1310"]},{"location":"rules/bad-str-strip-call/#example","title":"Example","text":"
        # Evaluates to \"foo\".\n\"bar foo baz\".strip(\"bar baz \")\n

        Use instead:

        # Evaluates to \"foo\".\n\"bar foo baz\".strip(\"abrz \")  # \"foo\"\n

        Or:

        # Evaluates to \"foo\".\n\"bar foo baz\".removeprefix(\"bar \").removesuffix(\" baz\")\n
        ","tags":["PLE1310"]},{"location":"rules/bad-str-strip-call/#options","title":"Options","text":"
        • target-version
        ","tags":["PLE1310"]},{"location":"rules/bad-str-strip-call/#references","title":"References","text":"
        • Python documentation: str.strip
        ","tags":["PLE1310"]},{"location":"rules/bad-string-format-character/","title":"bad-string-format-character (PLE1300)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1300"]},{"location":"rules/bad-string-format-character/#what-it-does","title":"What it does","text":"

        Checks for unsupported format types in format strings.

        ","tags":["PLE1300"]},{"location":"rules/bad-string-format-character/#why-is-this-bad","title":"Why is this bad?","text":"

        An invalid format string character will result in an error at runtime.

        ","tags":["PLE1300"]},{"location":"rules/bad-string-format-character/#example","title":"Example","text":"
        # `z` is not a valid format type.\nprint(\"%z\" % \"1\")\n\nprint(\"{:z}\".format(\"1\"))\n
        ","tags":["PLE1300"]},{"location":"rules/bad-string-format-type/","title":"bad-string-format-type (PLE1307)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1307"]},{"location":"rules/bad-string-format-type/#what-it-does","title":"What it does","text":"

        Checks for mismatched argument types in \"old-style\" format strings.

        ","tags":["PLE1307"]},{"location":"rules/bad-string-format-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The format string is not checked at compile time, so it is easy to introduce bugs by mistyping the format string.

        ","tags":["PLE1307"]},{"location":"rules/bad-string-format-type/#example","title":"Example","text":"
        print(\"%d\" % \"1\")\n

        Use instead:

        print(\"%d\" % 1)\n
        ","tags":["PLE1307"]},{"location":"rules/bad-version-info-comparison/","title":"bad-version-info-comparison (PYI006)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI006"]},{"location":"rules/bad-version-info-comparison/#what-it-does","title":"What it does","text":"

        Checks for uses of comparators other than < and >= for sys.version_info checks. All other comparators, such as >, <=, and ==, are banned.

        ","tags":["PYI006"]},{"location":"rules/bad-version-info-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing sys.version_info with == or <= has unexpected behavior and can lead to bugs.

        For example, sys.version_info > (3, 8, 1) will resolve to True if your Python version is 3.8.1; meanwhile, sys.version_info <= (3, 8) will not resolve to True if your Python version is 3.8.10:

        >>> import sys\n>>> print(sys.version_info)\nsys.version_info(major=3, minor=8, micro=10, releaselevel='final', serial=0)\n>>> print(sys.version_info > (3, 8))\nTrue\n>>> print(sys.version_info == (3, 8))\nFalse\n>>> print(sys.version_info <= (3, 8))\nFalse\n>>> print(sys.version_info in (3, 8))\nFalse\n
        ","tags":["PYI006"]},{"location":"rules/bad-version-info-comparison/#example","title":"Example","text":"
        import sys\n\nif sys.version_info > (3, 8): ...\n

        Use instead:

        import sys\n\nif sys.version_info >= (3, 9): ...\n
        ","tags":["PYI006"]},{"location":"rules/bad-version-info-order/","title":"bad-version-info-order (PYI066)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI066"]},{"location":"rules/bad-version-info-order/#what-it-does","title":"What it does","text":"

        Checks for code that branches on sys.version_info comparisons where branches corresponding to older Python versions come before branches corresponding to newer Python versions.

        ","tags":["PYI066"]},{"location":"rules/bad-version-info-order/#why-is-this-bad","title":"Why is this bad?","text":"

        As a convention, branches that correspond to newer Python versions should come first. This makes it easier to understand the desired behavior, which typically corresponds to the latest Python versions.

        This rule enforces the convention by checking for if tests that compare sys.version_info with < rather than >=.

        By default, this rule only applies to stub files. In preview, it will also flag this anti-pattern in non-stub files.

        ","tags":["PYI066"]},{"location":"rules/bad-version-info-order/#example","title":"Example","text":"
        import sys\n\nif sys.version_info < (3, 10):\n    def read_data(x, *, preserve_order=True): ...\n\nelse:\n    def read_data(x): ...\n

        Use instead:

        if sys.version_info >= (3, 10):\n    def read_data(x): ...\n\nelse:\n    def read_data(x, *, preserve_order=True): ...\n
        ","tags":["PYI066"]},{"location":"rules/banned-api/","title":"banned-api (TID251)","text":"

        Derived from the flake8-tidy-imports linter.

        ","tags":["TID251"]},{"location":"rules/banned-api/#what-it-does","title":"What it does","text":"

        Checks for banned imports.

        ","tags":["TID251"]},{"location":"rules/banned-api/#why-is-this-bad","title":"Why is this bad?","text":"

        Projects may want to ensure that specific modules or module members are not imported or accessed.

        Security or other company policies may be a reason to impose restrictions on importing external Python libraries. In some cases, projects may adopt conventions around the use of certain modules or module members that are not enforceable by the language itself.

        This rule enforces certain import conventions project-wide automatically.

        ","tags":["TID251"]},{"location":"rules/banned-api/#options","title":"Options","text":"
        • lint.flake8-tidy-imports.banned-api
        ","tags":["TID251"]},{"location":"rules/banned-import-alias/","title":"banned-import-alias (ICN002)","text":"

        Derived from the flake8-import-conventions linter.

        ","tags":["ICN002"]},{"location":"rules/banned-import-alias/#what-it-does","title":"What it does","text":"

        Checks for imports that use non-standard naming conventions, like import tensorflow.keras.backend as K.

        ","tags":["ICN002"]},{"location":"rules/banned-import-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Avoid using a non-standard naming convention for imports, and, in particular, choosing import aliases that violate PEP 8.

        For example, aliasing via import tensorflow.keras.backend as K violates the guidance of PEP 8, and is thus avoided in some projects.

        ","tags":["ICN002"]},{"location":"rules/banned-import-alias/#example","title":"Example","text":"
        import tensorflow.keras.backend as K\n

        Use instead:

        import tensorflow as tf\n\ntf.keras.backend\n
        ","tags":["ICN002"]},{"location":"rules/banned-import-alias/#options","title":"Options","text":"
        • lint.flake8-import-conventions.banned-aliases
        ","tags":["ICN002"]},{"location":"rules/banned-import-from/","title":"banned-import-from (ICN003)","text":"

        Derived from the flake8-import-conventions linter.

        ","tags":["ICN003"]},{"location":"rules/banned-import-from/#what-it-does","title":"What it does","text":"

        Checks for member imports that should instead be accessed by importing the module.

        ","tags":["ICN003"]},{"location":"rules/banned-import-from/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use a common convention for imports to make your code more readable and idiomatic.

        For example, it's common to import pandas as pd, and then access members like Series via pd.Series, rather than importing Series directly.

        ","tags":["ICN003"]},{"location":"rules/banned-import-from/#example","title":"Example","text":"
        from pandas import Series\n

        Use instead:

        import pandas as pd\n\npd.Series\n
        ","tags":["ICN003"]},{"location":"rules/banned-import-from/#options","title":"Options","text":"
        • lint.flake8-import-conventions.banned-from
        ","tags":["ICN003"]},{"location":"rules/banned-module-level-imports/","title":"banned-module-level-imports (TID253)","text":"

        Derived from the flake8-tidy-imports linter.

        ","tags":["TID253"]},{"location":"rules/banned-module-level-imports/#what-it-does","title":"What it does","text":"

        Checks for module-level imports that should instead be imported lazily (e.g., within a function definition, or an if TYPE_CHECKING: block, or some other nested context).

        ","tags":["TID253"]},{"location":"rules/banned-module-level-imports/#why-is-this-bad","title":"Why is this bad?","text":"

        Some modules are expensive to import. For example, importing torch or tensorflow can introduce a noticeable delay in the startup time of a Python program.

        In such cases, you may want to enforce that the module is imported lazily as needed, rather than at the top of the file. This could involve inlining the import into the function that uses it, rather than importing it unconditionally, to ensure that the module is only imported when necessary.

        ","tags":["TID253"]},{"location":"rules/banned-module-level-imports/#example","title":"Example","text":"
        import tensorflow as tf\n\n\ndef show_version():\n    print(tf.__version__)\n

        Use instead:

        def show_version():\n    import tensorflow as tf\n\n    print(tf.__version__)\n
        ","tags":["TID253"]},{"location":"rules/banned-module-level-imports/#options","title":"Options","text":"
        • lint.flake8-tidy-imports.banned-module-level-imports
        ","tags":["TID253"]},{"location":"rules/bare-except/","title":"bare-except (E722)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E722"]},{"location":"rules/bare-except/#what-it-does","title":"What it does","text":"

        Checks for bare except catches in try-except statements.

        ","tags":["E722"]},{"location":"rules/bare-except/#why-is-this-bad","title":"Why is this bad?","text":"

        A bare except catches BaseException which includes KeyboardInterrupt, SystemExit, Exception, and others. Catching BaseException can make it hard to interrupt the program (e.g., with Ctrl-C) and can disguise other problems.

        ","tags":["E722"]},{"location":"rules/bare-except/#example","title":"Example","text":"
        try:\n    raise KeyboardInterrupt(\"You probably don't mean to break CTRL-C.\")\nexcept:\n    print(\"But a bare `except` will ignore keyboard interrupts.\")\n

        Use instead:

        try:\n    do_something_that_might_break()\nexcept MoreSpecificException as e:\n    handle_error(e)\n

        If you actually need to catch an unknown error, use Exception which will catch regular program errors but not important system exceptions.

        def run_a_function(some_other_fn):\n    try:\n        some_other_fn()\n    except Exception as e:\n        print(f\"How exceptional! {e}\")\n
        ","tags":["E722"]},{"location":"rules/bare-except/#references","title":"References","text":"
        • Python documentation: Exception hierarchy
        • Google Python Style Guide: \"Exceptions\"
        ","tags":["E722"]},{"location":"rules/batched-without-explicit-strict/","title":"batched-without-explicit-strict (B911)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#what-it-does","title":"What it does","text":"

        Checks for itertools.batched calls without an explicit strict parameter.

        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#why-is-this-bad","title":"Why is this bad?","text":"

        By default, if the length of the iterable is not divisible by the second argument to itertools.batched, the last batch will be shorter than the rest.

        In Python 3.13, a strict parameter was added which allows controlling if the batches must be of uniform length. Pass strict=True to raise a ValueError if the batches are of non-uniform length. Otherwise, pass strict=False to make the intention explicit.

        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#example","title":"Example","text":"
        itertools.batched(iterable, n)\n

        Use instead if the batches must be of uniform length:

        itertools.batched(iterable, n, strict=True)\n

        Or if the batches can be of non-uniform length:

        itertools.batched(iterable, n, strict=False)\n
        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#known-deviations","title":"Known deviations","text":"

        Unlike the upstream B911, this rule will not report infinite iterators (e.g., itertools.cycle(...)).

        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#options","title":"Options","text":"
        • target-version
        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#references","title":"References","text":"
        • Python documentation: batched
        ","tags":["B911"]},{"location":"rules/bidirectional-unicode/","title":"bidirectional-unicode (PLE2502)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE2502"]},{"location":"rules/bidirectional-unicode/#what-it-does","title":"What it does","text":"

        Checks for bidirectional unicode characters.

        ","tags":["PLE2502"]},{"location":"rules/bidirectional-unicode/#why-is-this-bad","title":"Why is this bad?","text":"

        The interaction between bidirectional unicode characters and the surrounding code can be surprising to those that are unfamiliar with right-to-left writing systems.

        In some cases, bidirectional unicode characters can also be used to obfuscate code and introduce or mask security vulnerabilities.

        ","tags":["PLE2502"]},{"location":"rules/bidirectional-unicode/#example","title":"Example","text":"
        s = \"\u05d0\" * 100  #  \"\u05d0\" is assigned\nprint(s)  # prints a 100-character string\n
        ","tags":["PLE2502"]},{"location":"rules/bidirectional-unicode/#references","title":"References","text":"
        • PEP 672: Bidirectional Text
        ","tags":["PLE2502"]},{"location":"rules/binary-op-exception/","title":"binary-op-exception (PLW0711)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0711"]},{"location":"rules/binary-op-exception/#what-it-does","title":"What it does","text":"

        Checks for except clauses that attempt to catch multiple exceptions with a binary operation (and or or).

        ","tags":["PLW0711"]},{"location":"rules/binary-op-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        A binary operation will not catch multiple exceptions. Instead, the binary operation will be evaluated first, and the result of that operation will be caught (for an or operation, this is typically the first exception in the list). This is almost never the desired behavior.

        ","tags":["PLW0711"]},{"location":"rules/binary-op-exception/#example","title":"Example","text":"
        try:\n    pass\nexcept A or B:\n    pass\n

        Use instead:

        try:\n    pass\nexcept (A, B):\n    pass\n
        ","tags":["PLW0711"]},{"location":"rules/bit-count/","title":"bit-count (FURB161)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB161"]},{"location":"rules/bit-count/#what-it-does","title":"What it does","text":"

        Checks for uses of bin(...).count(\"1\") to perform a population count.

        ","tags":["FURB161"]},{"location":"rules/bit-count/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3.10, a bit_count() method was added to the int class, which is more concise and efficient than converting to a binary representation via bin(...).

        ","tags":["FURB161"]},{"location":"rules/bit-count/#example","title":"Example","text":"
        x = bin(123).count(\"1\")\ny = bin(0b1111011).count(\"1\")\n

        Use instead:

        x = (123).bit_count()\ny = 0b1111011.bit_count()\n
        ","tags":["FURB161"]},{"location":"rules/bit-count/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe unless the argument to bin can be inferred as an instance of a type that implements the __index__ and bit_count methods because this can change the exception raised at runtime for an invalid argument.

        ","tags":["FURB161"]},{"location":"rules/bit-count/#options","title":"Options","text":"
        • target-version
        ","tags":["FURB161"]},{"location":"rules/bit-count/#references","title":"References","text":"
        • Python documentation:int.bit_count
        ","tags":["FURB161"]},{"location":"rules/blank-line-after-decorator/","title":"blank-line-after-decorator (E304)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E304"]},{"location":"rules/blank-line-after-decorator/#what-it-does","title":"What it does","text":"

        Checks for extraneous blank line(s) after function decorators.

        ","tags":["E304"]},{"location":"rules/blank-line-after-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        There should be no blank lines between a decorator and the object it is decorating.

        ","tags":["E304"]},{"location":"rules/blank-line-after-decorator/#example","title":"Example","text":"
        class User(object):\n\n    @property\n\n    def name(self):\n        pass\n

        Use instead:

        class User(object):\n\n    @property\n    def name(self):\n        pass\n
        ","tags":["E304"]},{"location":"rules/blank-line-after-decorator/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        ","tags":["E304"]},{"location":"rules/blank-line-after-function/","title":"blank-line-after-function (D202)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D202"]},{"location":"rules/blank-line-after-function/#what-it-does","title":"What it does","text":"

        Checks for docstrings on functions that are separated by one or more blank lines from the function body.

        ","tags":["D202"]},{"location":"rules/blank-line-after-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Remove any blank lines between the function body and the function docstring, for consistency.

        ","tags":["D202"]},{"location":"rules/blank-line-after-function/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n\n    return sum(values) / len(values)\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n    return sum(values) / len(values)\n
        ","tags":["D202"]},{"location":"rules/blank-line-after-function/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D202"]},{"location":"rules/blank-line-before-class/","title":"blank-line-before-class (D211)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D211"]},{"location":"rules/blank-line-before-class/#what-it-does","title":"What it does","text":"

        Checks for docstrings on class definitions that are preceded by a blank line.

        ","tags":["D211"]},{"location":"rules/blank-line-before-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Avoid introducing any blank lines between a class definition and its docstring, for consistency.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the google, numpy, and pep257 conventions.

        For an alternative, see D203.

        ","tags":["D211"]},{"location":"rules/blank-line-before-class/#example","title":"Example","text":"
        class PhotoMetadata:\n\n    \"\"\"Metadata about a photo.\"\"\"\n

        Use instead:

        class PhotoMetadata:\n    \"\"\"Metadata about a photo.\"\"\"\n
        ","tags":["D211"]},{"location":"rules/blank-line-before-class/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D211"]},{"location":"rules/blank-line-before-function/","title":"blank-line-before-function (D201)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D201"]},{"location":"rules/blank-line-before-function/#what-it-does","title":"What it does","text":"

        Checks for docstrings on functions that are separated by one or more blank lines from the function definition.

        ","tags":["D201"]},{"location":"rules/blank-line-before-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Remove any blank lines between the function definition and its docstring, for consistency.

        ","tags":["D201"]},{"location":"rules/blank-line-before-function/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n\n    \"\"\"Return the mean of the given values.\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D201"]},{"location":"rules/blank-line-before-function/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D201"]},{"location":"rules/blank-line-between-methods/","title":"blank-line-between-methods (E301)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E301"]},{"location":"rules/blank-line-between-methods/#what-it-does","title":"What it does","text":"

        Checks for missing blank lines between methods of a class.

        ","tags":["E301"]},{"location":"rules/blank-line-between-methods/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends exactly one blank line between methods of a class.

        ","tags":["E301"]},{"location":"rules/blank-line-between-methods/#example","title":"Example","text":"
        class MyClass(object):\n    def func1():\n        pass\n    def func2():\n        pass\n

        Use instead:

        class MyClass(object):\n    def func1():\n        pass\n\n    def func2():\n        pass\n
        ","tags":["E301"]},{"location":"rules/blank-line-between-methods/#typing-stub-files-pyi","title":"Typing stub files (.pyi)","text":"

        The typing style guide recommends to not use blank lines between methods except to group them. That's why this rule is not enabled in typing stub files.

        ","tags":["E301"]},{"location":"rules/blank-line-between-methods/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        • Typing Style Guide
        ","tags":["E301"]},{"location":"rules/blank-line-with-whitespace/","title":"blank-line-with-whitespace (W293)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["W293"]},{"location":"rules/blank-line-with-whitespace/#what-it-does","title":"What it does","text":"

        Checks for superfluous whitespace in blank lines.

        ","tags":["W293"]},{"location":"rules/blank-line-with-whitespace/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"avoid trailing whitespace anywhere. Because it\u2019s usually invisible, it can be confusing\"

        ","tags":["W293"]},{"location":"rules/blank-line-with-whitespace/#example","title":"Example","text":"
        class Foo(object):\\n    \\n    bang = 12\n

        Use instead:

        class Foo(object):\\n\\n    bang = 12\n
        ","tags":["W293"]},{"location":"rules/blank-lines-after-function-or-class/","title":"blank-lines-after-function-or-class (E305)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E305"]},{"location":"rules/blank-lines-after-function-or-class/#what-it-does","title":"What it does","text":"

        Checks for missing blank lines after the end of function or class.

        ","tags":["E305"]},{"location":"rules/blank-lines-after-function-or-class/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends using blank lines as follows:

        • Two blank lines are expected between functions and classes
        • One blank line is expected between methods of a class.
        ","tags":["E305"]},{"location":"rules/blank-lines-after-function-or-class/#example","title":"Example","text":"
        class User(object):\n    pass\nuser = User()\n

        Use instead:

        class User(object):\n    pass\n\n\nuser = User()\n
        ","tags":["E305"]},{"location":"rules/blank-lines-after-function-or-class/#typing-stub-files-pyi","title":"Typing stub files (.pyi)","text":"

        The typing style guide recommends to not use blank lines between statements except to group them. That's why this rule is not enabled in typing stub files.

        ","tags":["E305"]},{"location":"rules/blank-lines-after-function-or-class/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        • Typing Style Guide
        ","tags":["E305"]},{"location":"rules/blank-lines-before-nested-definition/","title":"blank-lines-before-nested-definition (E306)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E306"]},{"location":"rules/blank-lines-before-nested-definition/#what-it-does","title":"What it does","text":"

        Checks for 1 blank line between nested function or class definitions.

        ","tags":["E306"]},{"location":"rules/blank-lines-before-nested-definition/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends using blank lines as follows:

        • Two blank lines are expected between functions and classes
        • One blank line is expected between methods of a class.
        ","tags":["E306"]},{"location":"rules/blank-lines-before-nested-definition/#example","title":"Example","text":"
        def outer():\n    def inner():\n        pass\n    def inner2():\n        pass\n

        Use instead:

        def outer():\n    def inner():\n        pass\n\n    def inner2():\n        pass\n
        ","tags":["E306"]},{"location":"rules/blank-lines-before-nested-definition/#typing-stub-files-pyi","title":"Typing stub files (.pyi)","text":"

        The typing style guide recommends to not use blank lines between classes and functions except to group them. That's why this rule is not enabled in typing stub files.

        ","tags":["E306"]},{"location":"rules/blank-lines-before-nested-definition/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        • Typing Style Guide
        ","tags":["E306"]},{"location":"rules/blank-lines-between-header-and-content/","title":"blank-lines-between-header-and-content (D412)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D412"]},{"location":"rules/blank-lines-between-header-and-content/#what-it-does","title":"What it does","text":"

        Checks for docstring sections that contain blank lines between a section header and a section body.

        ","tags":["D412"]},{"location":"rules/blank-lines-between-header-and-content/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline docstrings.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. There should be no blank lines between a section header and a section body.

        ","tags":["D412"]},{"location":"rules/blank-lines-between-header-and-content/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D412"]},{"location":"rules/blank-lines-between-header-and-content/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D412"]},{"location":"rules/blank-lines-top-level/","title":"blank-lines-top-level (E302)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#what-it-does","title":"What it does","text":"

        Checks for missing blank lines between top level functions and classes.

        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends exactly two blank lines between top level functions and classes.

        The rule respects the lint.isort.lines-after-imports setting when determining the required number of blank lines between top-level import statements and function or class definitions for compatibility with isort.

        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#example","title":"Example","text":"
        def func1():\n    pass\ndef func2():\n    pass\n

        Use instead:

        def func1():\n    pass\n\n\ndef func2():\n    pass\n
        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#typing-stub-files-pyi","title":"Typing stub files (.pyi)","text":"

        The typing style guide recommends to not use blank lines between classes and functions except to group them. That's why this rule is not enabled in typing stub files.

        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#options","title":"Options","text":"
        • lint.isort.lines-after-imports
        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        • Typing Style Guide
        ","tags":["E302"]},{"location":"rules/blanket-noqa/","title":"blanket-noqa (PGH004)","text":"

        Derived from the pygrep-hooks linter.

        Fix is sometimes available.

        ","tags":["PGH004"]},{"location":"rules/blanket-noqa/#what-it-does","title":"What it does","text":"

        Check for noqa annotations that suppress all diagnostics, as opposed to targeting specific diagnostics.

        ","tags":["PGH004"]},{"location":"rules/blanket-noqa/#why-is-this-bad","title":"Why is this bad?","text":"

        Suppressing all diagnostics can hide issues in the code.

        Blanket noqa annotations are also more difficult to interpret and maintain, as the annotation does not clarify which diagnostics are intended to be suppressed.

        ","tags":["PGH004"]},{"location":"rules/blanket-noqa/#example","title":"Example","text":"
        from .base import *  # noqa\n

        Use instead:

        from .base import *  # noqa: F403\n
        ","tags":["PGH004"]},{"location":"rules/blanket-noqa/#fix-safety","title":"Fix safety","text":"

        This rule will attempt to fix blanket noqa annotations that appear to be unintentional. For example, given # noqa F401, the rule will suggest inserting a colon, as in # noqa: F401.

        While modifying noqa comments is generally safe, doing so may introduce additional diagnostics.

        ","tags":["PGH004"]},{"location":"rules/blanket-noqa/#references","title":"References","text":"
        • Ruff documentation
        ","tags":["PGH004"]},{"location":"rules/blanket-type-ignore/","title":"blanket-type-ignore (PGH003)","text":"

        Derived from the pygrep-hooks linter.

        ","tags":["PGH003"]},{"location":"rules/blanket-type-ignore/#what-it-does","title":"What it does","text":"

        Check for type: ignore annotations that suppress all type warnings, as opposed to targeting specific type warnings.

        ","tags":["PGH003"]},{"location":"rules/blanket-type-ignore/#why-is-this-bad","title":"Why is this bad?","text":"

        Suppressing all warnings can hide issues in the code.

        Blanket type: ignore annotations are also more difficult to interpret and maintain, as the annotation does not clarify which warnings are intended to be suppressed.

        ","tags":["PGH003"]},{"location":"rules/blanket-type-ignore/#example","title":"Example","text":"
        from foo import secrets  # type: ignore\n

        Use instead:

        from foo import secrets  # type: ignore[attr-defined]\n
        ","tags":["PGH003"]},{"location":"rules/blanket-type-ignore/#references","title":"References","text":"

        Mypy supports a built-in setting to enforce that all type: ignore annotations include an error code, akin to enabling this rule:

        [tool.mypy]\nenable_error_code = [\"ignore-without-code\"]\n
        ","tags":["PGH003"]},{"location":"rules/blind-except/","title":"blind-except (BLE001)","text":"

        Derived from the flake8-blind-except linter.

        ","tags":["BLE001"]},{"location":"rules/blind-except/#what-it-does","title":"What it does","text":"

        Checks for except clauses that catch all exceptions. This includes bare except, except BaseException and except Exception.

        ","tags":["BLE001"]},{"location":"rules/blind-except/#why-is-this-bad","title":"Why is this bad?","text":"

        Overly broad except clauses can lead to unexpected behavior, such as catching KeyboardInterrupt or SystemExit exceptions that prevent the user from exiting the program.

        Instead of catching all exceptions, catch only those that are expected to be raised in the try block.

        ","tags":["BLE001"]},{"location":"rules/blind-except/#example","title":"Example","text":"
        try:\n    foo()\nexcept BaseException:\n    ...\n

        Use instead:

        try:\n    foo()\nexcept FileNotFoundError:\n    ...\n

        Exceptions that are re-raised will not be flagged, as they're expected to be caught elsewhere:

        try:\n    foo()\nexcept BaseException:\n    raise\n

        Exceptions that are logged via logging.exception() or logging.error() with exc_info enabled will not be flagged, as this is a common pattern for propagating exception traces:

        try:\n    foo()\nexcept BaseException:\n    logging.exception(\"Something went wrong\")\n
        ","tags":["BLE001"]},{"location":"rules/blind-except/#references","title":"References","text":"
        • Python documentation: The try statement
        • Python documentation: Exception hierarchy
        • PEP 8: Programming Recommendations on bare except
        ","tags":["BLE001"]},{"location":"rules/blocking-http-call-in-async-function/","title":"blocking-http-call-in-async-function (ASYNC210)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC210"]},{"location":"rules/blocking-http-call-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not contain blocking HTTP calls.

        ","tags":["ASYNC210"]},{"location":"rules/blocking-http-call-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a blocking HTTP call will block the entire event loop, preventing it from executing other tasks while waiting for the HTTP response, negating the benefits of asynchronous programming.

        Instead of making a blocking HTTP call, use an asynchronous HTTP client library such as aiohttp or httpx.

        ","tags":["ASYNC210"]},{"location":"rules/blocking-http-call-in-async-function/#example","title":"Example","text":"
        async def fetch():\n    urllib.request.urlopen(\"https://example.com/foo/bar\").read()\n

        Use instead:

        async def fetch():\n    async with aiohttp.ClientSession() as session:\n        async with session.get(\"https://example.com/foo/bar\") as resp:\n            ...\n
        ","tags":["ASYNC210"]},{"location":"rules/blocking-open-call-in-async-function/","title":"blocking-open-call-in-async-function (ASYNC230)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC230"]},{"location":"rules/blocking-open-call-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not open files with blocking methods like open.

        ","tags":["ASYNC230"]},{"location":"rules/blocking-open-call-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a blocking call will block the entire event loop, preventing it from executing other tasks while waiting for the call to complete, negating the benefits of asynchronous programming.

        Instead of making a blocking call, use an equivalent asynchronous library or function.

        ","tags":["ASYNC230"]},{"location":"rules/blocking-open-call-in-async-function/#example","title":"Example","text":"
        async def foo():\n    with open(\"bar.txt\") as f:\n        contents = f.read()\n

        Use instead:

        import anyio\n\n\nasync def foo():\n    async with await anyio.open_file(\"bar.txt\") as f:\n        contents = await f.read()\n
        ","tags":["ASYNC230"]},{"location":"rules/blocking-sleep-in-async-function/","title":"blocking-sleep-in-async-function (ASYNC251)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC251"]},{"location":"rules/blocking-sleep-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not call time.sleep.

        ","tags":["ASYNC251"]},{"location":"rules/blocking-sleep-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a time.sleep call will block the entire event loop, preventing it from executing other tasks while waiting for the time.sleep, negating the benefits of asynchronous programming.

        Instead of time.sleep, use asyncio.sleep.

        ","tags":["ASYNC251"]},{"location":"rules/blocking-sleep-in-async-function/#example","title":"Example","text":"
        async def fetch():\n    time.sleep(1)\n

        Use instead:

        async def fetch():\n    await asyncio.sleep(1)\n
        ","tags":["ASYNC251"]},{"location":"rules/boolean-chained-comparison/","title":"boolean-chained-comparison (PLR1716)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLR1716"]},{"location":"rules/boolean-chained-comparison/#what-it-does","title":"What it does","text":"

        Check for chained boolean operations that can be simplified.

        ","tags":["PLR1716"]},{"location":"rules/boolean-chained-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Refactoring the code will improve readability for these cases.

        ","tags":["PLR1716"]},{"location":"rules/boolean-chained-comparison/#example","title":"Example","text":"
        a = int(input())\nb = int(input())\nc = int(input())\nif a < b and b < c:\n    pass\n

        Use instead:

        a = int(input())\nb = int(input())\nc = int(input())\nif a < b < c:\n    pass\n
        ","tags":["PLR1716"]},{"location":"rules/boolean-default-value-positional-argument/","title":"boolean-default-value-positional-argument (FBT002)","text":"

        Derived from the flake8-boolean-trap linter.

        ","tags":["FBT002"]},{"location":"rules/boolean-default-value-positional-argument/#what-it-does","title":"What it does","text":"

        Checks for the use of boolean positional arguments in function definitions, as determined by the presence of a boolean default value.

        ","tags":["FBT002"]},{"location":"rules/boolean-default-value-positional-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling a function with boolean positional arguments is confusing as the meaning of the boolean value is not clear to the caller and to future readers of the code.

        The use of a boolean will also limit the function to only two possible behaviors, which makes the function difficult to extend in the future.

        Instead, consider refactoring into separate implementations for the True and False cases, using an Enum, or making the argument a keyword-only argument, to force callers to be explicit when providing the argument.

        ","tags":["FBT002"]},{"location":"rules/boolean-default-value-positional-argument/#example","title":"Example","text":"
        from math import ceil, floor\n\n\ndef round_number(number, up=True):\n    return ceil(number) if up else floor(number)\n\n\nround_number(1.5, True)  # What does `True` mean?\nround_number(1.5, False)  # What does `False` mean?\n

        Instead, refactor into separate implementations:

        from math import ceil, floor\n\n\ndef round_up(number):\n    return ceil(number)\n\n\ndef round_down(number):\n    return floor(number)\n\n\nround_up(1.5)\nround_down(1.5)\n

        Or, refactor to use an Enum:

        from enum import Enum\n\n\nclass RoundingMethod(Enum):\n    UP = 1\n    DOWN = 2\n\n\ndef round_number(value, method):\n    return ceil(number) if method is RoundingMethod.UP else floor(number)\n\n\nround_number(1.5, RoundingMethod.UP)\nround_number(1.5, RoundingMethod.DOWN)\n

        Or, make the argument a keyword-only argument:

        from math import ceil, floor\n\n\ndef round_number(number, *, up=True):\n    return ceil(number) if up else floor(number)\n\n\nround_number(1.5, up=True)\nround_number(1.5, up=False)\n
        ","tags":["FBT002"]},{"location":"rules/boolean-default-value-positional-argument/#references","title":"References","text":"
        • Python documentation: Calls
        • How to Avoid \u201cThe Boolean Trap\u201d by Adam Johnson
        ","tags":["FBT002"]},{"location":"rules/boolean-positional-value-in-call/","title":"boolean-positional-value-in-call (FBT003)","text":"

        Derived from the flake8-boolean-trap linter.

        ","tags":["FBT003"]},{"location":"rules/boolean-positional-value-in-call/#what-it-does","title":"What it does","text":"

        Checks for boolean positional arguments in function calls.

        Some functions are whitelisted by default. To extend the list of allowed calls configure the lint.flake8-boolean-trap.extend-allowed-calls option.

        ","tags":["FBT003"]},{"location":"rules/boolean-positional-value-in-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling a function with boolean positional arguments is confusing as the meaning of the boolean value is not clear to the caller, and to future readers of the code.

        ","tags":["FBT003"]},{"location":"rules/boolean-positional-value-in-call/#example","title":"Example","text":"
        def func(flag: bool) -> None: ...\n\n\nfunc(True)\n

        Use instead:

        def func(flag: bool) -> None: ...\n\n\nfunc(flag=True)\n
        ","tags":["FBT003"]},{"location":"rules/boolean-positional-value-in-call/#options","title":"Options","text":"
        • lint.flake8-boolean-trap.extend-allowed-calls
        ","tags":["FBT003"]},{"location":"rules/boolean-positional-value-in-call/#references","title":"References","text":"
        • Python documentation: Calls
        • How to Avoid \u201cThe Boolean Trap\u201d by Adam Johnson
        ","tags":["FBT003"]},{"location":"rules/boolean-type-hint-positional-argument/","title":"boolean-type-hint-positional-argument (FBT001)","text":"

        Derived from the flake8-boolean-trap linter.

        ","tags":["FBT001"]},{"location":"rules/boolean-type-hint-positional-argument/#what-it-does","title":"What it does","text":"

        Checks for the use of boolean positional arguments in function definitions, as determined by the presence of a bool type hint.

        ","tags":["FBT001"]},{"location":"rules/boolean-type-hint-positional-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling a function with boolean positional arguments is confusing as the meaning of the boolean value is not clear to the caller and to future readers of the code.

        The use of a boolean will also limit the function to only two possible behaviors, which makes the function difficult to extend in the future.

        Instead, consider refactoring into separate implementations for the True and False cases, using an Enum, or making the argument a keyword-only argument, to force callers to be explicit when providing the argument.

        Dunder methods that define operators are exempt from this rule, as are setters and @override definitions.

        In preview, this rule will also flag annotations that include boolean variants, like bool | int.

        ","tags":["FBT001"]},{"location":"rules/boolean-type-hint-positional-argument/#example","title":"Example","text":"
        from math import ceil, floor\n\n\ndef round_number(number: float, up: bool) -> int:\n    return ceil(number) if up else floor(number)\n\n\nround_number(1.5, True)  # What does `True` mean?\nround_number(1.5, False)  # What does `False` mean?\n

        Instead, refactor into separate implementations:

        from math import ceil, floor\n\n\ndef round_up(number: float) -> int:\n    return ceil(number)\n\n\ndef round_down(number: float) -> int:\n    return floor(number)\n\n\nround_up(1.5)\nround_down(1.5)\n

        Or, refactor to use an Enum:

        from enum import Enum\n\n\nclass RoundingMethod(Enum):\n    UP = 1\n    DOWN = 2\n\n\ndef round_number(value: float, method: RoundingMethod) -> float: ...\n

        Or, make the argument a keyword-only argument:

        from math import ceil, floor\n\n\ndef round_number(number: float, *, up: bool) -> int:\n    return ceil(number) if up else floor(number)\n\n\nround_number(1.5, up=True)\nround_number(1.5, up=False)\n
        ","tags":["FBT001"]},{"location":"rules/boolean-type-hint-positional-argument/#references","title":"References","text":"
        • Python documentation: Calls
        • How to Avoid \u201cThe Boolean Trap\u201d by Adam Johnson
        ","tags":["FBT001"]},{"location":"rules/break-outside-loop/","title":"break-outside-loop (F701)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F701"]},{"location":"rules/break-outside-loop/#what-it-does","title":"What it does","text":"

        Checks for break statements outside of loops.

        ","tags":["F701"]},{"location":"rules/break-outside-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of a break statement outside of a for or while loop will raise a SyntaxError.

        ","tags":["F701"]},{"location":"rules/break-outside-loop/#example","title":"Example","text":"
        def foo():\n    break\n
        ","tags":["F701"]},{"location":"rules/break-outside-loop/#references","title":"References","text":"
        • Python documentation: break
        ","tags":["F701"]},{"location":"rules/builtin-argument-shadowing/","title":"builtin-argument-shadowing (A002)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A002"]},{"location":"rules/builtin-argument-shadowing/#what-it-does","title":"What it does","text":"

        Checks for function arguments that use the same names as builtins.

        ","tags":["A002"]},{"location":"rules/builtin-argument-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a builtin name for the name of an argument increases the difficulty of reading and maintaining the code, and can cause non-obvious errors, as readers may mistake the argument for the builtin and vice versa.

        Builtins can be marked as exceptions to this rule via the lint.flake8-builtins.ignorelist configuration option.

        ","tags":["A002"]},{"location":"rules/builtin-argument-shadowing/#example","title":"Example","text":"
        def remove_duplicates(list, list2):\n    result = set()\n    for value in list:\n        result.add(value)\n    for value in list2:\n        result.add(value)\n    return list(result)  # TypeError: 'list' object is not callable\n

        Use instead:

        def remove_duplicates(list1, list2):\n    result = set()\n    for value in list1:\n        result.add(value)\n    for value in list2:\n        result.add(value)\n    return list(result)\n
        ","tags":["A002"]},{"location":"rules/builtin-argument-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.ignorelist
        ","tags":["A002"]},{"location":"rules/builtin-argument-shadowing/#references","title":"References","text":"
        • Is it bad practice to use a built-in function name as an attribute or method identifier?
        • Why is it a bad idea to name a variable id in Python?
        ","tags":["A002"]},{"location":"rules/builtin-attribute-shadowing/","title":"builtin-attribute-shadowing (A003)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A003"]},{"location":"rules/builtin-attribute-shadowing/#what-it-does","title":"What it does","text":"

        Checks for class attributes and methods that use the same names as Python builtins.

        ","tags":["A003"]},{"location":"rules/builtin-attribute-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a builtin name for the name of an attribute increases the difficulty of reading and maintaining the code, and can cause non-obvious errors, as readers may mistake the attribute for the builtin and vice versa.

        Since methods and class attributes typically cannot be referenced directly from outside the class scope, this rule only applies to those methods and attributes that both shadow a builtin and are referenced from within the class scope, as in the following example, where the list[int] return type annotation resolves to the list method, rather than the builtin:

        class Class:\n    @staticmethod\n    def list() -> None:\n        pass\n\n    @staticmethod\n    def repeat(value: int, times: int) -> list[int]:\n        return [value] * times\n

        Builtins can be marked as exceptions to this rule via the lint.flake8-builtins.ignorelist configuration option, or converted to the appropriate dunder method. Methods decorated with @typing.override or @typing_extensions.override are also ignored.

        ","tags":["A003"]},{"location":"rules/builtin-attribute-shadowing/#example","title":"Example","text":"
        class Class:\n    @staticmethod\n    def list() -> None:\n        pass\n\n    @staticmethod\n    def repeat(value: int, times: int) -> list[int]:\n        return [value] * times\n
        ","tags":["A003"]},{"location":"rules/builtin-attribute-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.ignorelist
        ","tags":["A003"]},{"location":"rules/builtin-import-shadowing/","title":"builtin-import-shadowing (A004)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A004"]},{"location":"rules/builtin-import-shadowing/#what-it-does","title":"What it does","text":"

        Checks for imports that use the same names as builtins.

        ","tags":["A004"]},{"location":"rules/builtin-import-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a builtin for the name of an import increases the difficulty of reading and maintaining the code, and can cause non-obvious errors, as readers may mistake the variable for the builtin and vice versa.

        Builtins can be marked as exceptions to this rule via the lint.flake8-builtins.ignorelist configuration option.

        ","tags":["A004"]},{"location":"rules/builtin-import-shadowing/#example","title":"Example","text":"
        from rich import print\n\nprint(\"Some message\")\n

        Use instead:

        from rich import print as rich_print\n\nrich_print(\"Some message\")\n

        or:

        import rich\n\nrich.print(\"Some message\")\n
        ","tags":["A004"]},{"location":"rules/builtin-import-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.ignorelist
        • target-version
        ","tags":["A004"]},{"location":"rules/builtin-lambda-argument-shadowing/","title":"builtin-lambda-argument-shadowing (A006)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A006"]},{"location":"rules/builtin-lambda-argument-shadowing/#what-it-does","title":"What it does","text":"

        Checks for lambda arguments that use the same names as Python builtins.

        ","tags":["A006"]},{"location":"rules/builtin-lambda-argument-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a builtin name for the name of a lambda argument increases the difficulty of reading and maintaining the code and can cause non-obvious errors. Readers may mistake the variable for the builtin, and vice versa.

        Builtins can be marked as exceptions to this rule via the lint.flake8-builtins.ignorelist configuration option.

        ","tags":["A006"]},{"location":"rules/builtin-lambda-argument-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.ignorelist
        ","tags":["A006"]},{"location":"rules/builtin-open/","title":"builtin-open (PTH123)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH123"]},{"location":"rules/builtin-open/#what-it-does","title":"What it does","text":"

        Checks for uses of the open() builtin.

        ","tags":["PTH123"]},{"location":"rules/builtin-open/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation. When possible, using Path object methods such as Path.open() can improve readability over the open builtin.

        ","tags":["PTH123"]},{"location":"rules/builtin-open/#examples","title":"Examples","text":"
        with open(\"f1.py\", \"wb\") as fp:\n    ...\n

        Use instead:

        from pathlib import Path\n\nwith Path(\"f1.py\").open(\"wb\") as fp:\n    ...\n
        ","tags":["PTH123"]},{"location":"rules/builtin-open/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than working directly with strings, especially on older versions of Python.

        ","tags":["PTH123"]},{"location":"rules/builtin-open/#references","title":"References","text":"
        • Python documentation: Path.open
        • Python documentation: open
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH123"]},{"location":"rules/builtin-variable-shadowing/","title":"builtin-variable-shadowing (A001)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A001"]},{"location":"rules/builtin-variable-shadowing/#what-it-does","title":"What it does","text":"

        Checks for variable (and function) assignments that use the same names as builtins.

        ","tags":["A001"]},{"location":"rules/builtin-variable-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a builtin name for the name of a variable increases the difficulty of reading and maintaining the code, and can cause non-obvious errors, as readers may mistake the variable for the builtin and vice versa.

        Builtins can be marked as exceptions to this rule via the lint.flake8-builtins.ignorelist configuration option.

        ","tags":["A001"]},{"location":"rules/builtin-variable-shadowing/#example","title":"Example","text":"
        def find_max(list_of_lists):\n    max = 0\n    for flat_list in list_of_lists:\n        for value in flat_list:\n            max = max(max, value)  # TypeError: 'int' object is not callable\n    return max\n

        Use instead:

        def find_max(list_of_lists):\n    result = 0\n    for flat_list in list_of_lists:\n        for value in flat_list:\n            result = max(result, value)\n    return result\n
        ","tags":["A001"]},{"location":"rules/builtin-variable-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.ignorelist
        ","tags":["A001"]},{"location":"rules/builtin-variable-shadowing/#references","title":"References","text":"
        • Why is it a bad idea to name a variable id in Python?
        ","tags":["A001"]},{"location":"rules/byte-string-usage/","title":"byte-string-usage (PYI057)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI057"]},{"location":"rules/byte-string-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of typing.ByteString or collections.abc.ByteString.

        ","tags":["PYI057"]},{"location":"rules/byte-string-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        ByteString has been deprecated since Python 3.9 and will be removed in Python 3.14. The Python documentation recommends using either collections.abc.Buffer (or the typing_extensions backport on Python \\<3.12) or a union like bytes | bytearray | memoryview instead.

        ","tags":["PYI057"]},{"location":"rules/byte-string-usage/#example","title":"Example","text":"
        from typing import ByteString\n

        Use instead:

        from collections.abc import Buffer\n
        ","tags":["PYI057"]},{"location":"rules/byte-string-usage/#references","title":"References","text":"
        • Python documentation: The ByteString type
        ","tags":["PYI057"]},{"location":"rules/cached-instance-method/","title":"cached-instance-method (B019)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B019"]},{"location":"rules/cached-instance-method/#what-it-does","title":"What it does","text":"

        Checks for uses of the functools.lru_cache and functools.cache decorators on methods.

        ","tags":["B019"]},{"location":"rules/cached-instance-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Using the functools.lru_cache and functools.cache decorators on methods can lead to memory leaks, as the global cache will retain a reference to the instance, preventing it from being garbage collected.

        Instead, refactor the method to depend only on its arguments and not on the instance of the class, or use the @lru_cache decorator on a function outside of the class.

        This rule ignores instance methods on enumeration classes, as enum members are singletons.

        ","tags":["B019"]},{"location":"rules/cached-instance-method/#example","title":"Example","text":"
        from functools import lru_cache\n\n\ndef square(x: int) -> int:\n    return x * x\n\n\nclass Number:\n    value: int\n\n    @lru_cache\n    def squared(self):\n        return square(self.value)\n

        Use instead:

        from functools import lru_cache\n\n\n@lru_cache\ndef square(x: int) -> int:\n    return x * x\n\n\nclass Number:\n    value: int\n\n    def squared(self):\n        return square(self.value)\n
        ","tags":["B019"]},{"location":"rules/cached-instance-method/#references","title":"References","text":"
        • Python documentation: functools.lru_cache
        • Python documentation: functools.cache
        • don't lru_cache methods!
        ","tags":["B019"]},{"location":"rules/call-date-fromtimestamp/","title":"call-date-fromtimestamp (DTZ012)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ012"]},{"location":"rules/call-date-fromtimestamp/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.date.fromtimestamp().

        ","tags":["DTZ012"]},{"location":"rules/call-date-fromtimestamp/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.date.fromtimestamp(ts) returns a naive datetime object. Instead, use datetime.datetime.fromtimestamp(ts, tz=...) to create a timezone-aware object.

        ","tags":["DTZ012"]},{"location":"rules/call-date-fromtimestamp/#example","title":"Example","text":"
        import datetime\n\ndatetime.date.fromtimestamp(946684800)\n

        Use instead:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.timezone.utc)\n

        Or, for Python 3.11 and later:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.UTC)\n
        ","tags":["DTZ012"]},{"location":"rules/call-date-fromtimestamp/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ012"]},{"location":"rules/call-date-today/","title":"call-date-today (DTZ011)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ011"]},{"location":"rules/call-date-today/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.date.today().

        ","tags":["DTZ011"]},{"location":"rules/call-date-today/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.date.today returns a naive datetime object. Instead, use datetime.datetime.now(tz=...).date() to create a timezone-aware object.

        ","tags":["DTZ011"]},{"location":"rules/call-date-today/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.today()\n

        Use instead:

        import datetime\n\ndatetime.datetime.now(tz=datetime.timezone.utc).date()\n

        Or, for Python 3.11 and later:

        import datetime\n\ndatetime.datetime.now(tz=datetime.UTC).date()\n
        ","tags":["DTZ011"]},{"location":"rules/call-date-today/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ011"]},{"location":"rules/call-datetime-fromtimestamp/","title":"call-datetime-fromtimestamp (DTZ006)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ006"]},{"location":"rules/call-datetime-fromtimestamp/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.datetime.fromtimestamp() that do not specify a timezone.

        ","tags":["DTZ006"]},{"location":"rules/call-datetime-fromtimestamp/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.datetime.fromtimestamp(ts) or datetime.datetime.fromtimestampe(ts, tz=None) returns a naive datetime object. Instead, use datetime.datetime.fromtimestamp(ts, tz=<timezone>) to create a timezone-aware object.

        ","tags":["DTZ006"]},{"location":"rules/call-datetime-fromtimestamp/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.fromtimestamp(946684800)\n

        Use instead:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.timezone.utc)\n

        Or, on Python 3.11 and later:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.UTC)\n
        ","tags":["DTZ006"]},{"location":"rules/call-datetime-fromtimestamp/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ006"]},{"location":"rules/call-datetime-now-without-tzinfo/","title":"call-datetime-now-without-tzinfo (DTZ005)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ005"]},{"location":"rules/call-datetime-now-without-tzinfo/#what-it-does","title":"What it does","text":"

        Checks for usages of datetime.datetime.now() that do not specify a timezone.

        ","tags":["DTZ005"]},{"location":"rules/call-datetime-now-without-tzinfo/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.datetime.now() or datetime.datetime.now(tz=None) returns a naive datetime object. Instead, use datetime.datetime.now(tz=<timezone>) to create a timezone-aware object.

        ","tags":["DTZ005"]},{"location":"rules/call-datetime-now-without-tzinfo/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.now()\n

        Use instead:

        import datetime\n\ndatetime.datetime.now(tz=datetime.timezone.utc)\n

        Or, for Python 3.11 and later:

        import datetime\n\ndatetime.datetime.now(tz=datetime.UTC)\n
        ","tags":["DTZ005"]},{"location":"rules/call-datetime-now-without-tzinfo/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ005"]},{"location":"rules/call-datetime-strptime-without-zone/","title":"call-datetime-strptime-without-zone (DTZ007)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ007"]},{"location":"rules/call-datetime-strptime-without-zone/#what-it-does","title":"What it does","text":"

        Checks for uses of datetime.datetime.strptime() that lead to naive datetime objects.

        ","tags":["DTZ007"]},{"location":"rules/call-datetime-strptime-without-zone/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.datetime.strptime() without %z returns a naive datetime object. Follow it with .replace(tzinfo=<timezone>) or .astimezone().

        ","tags":["DTZ007"]},{"location":"rules/call-datetime-strptime-without-zone/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.strptime(\"2022/01/31\", \"%Y/%m/%d\")\n

        Instead, use .replace(tzinfo=<timezone>):

        import datetime\n\ndatetime.datetime.strptime(\"2022/01/31\", \"%Y/%m/%d\").replace(\n    tzinfo=datetime.timezone.utc\n)\n

        Or, use .astimezone():

        import datetime\n\ndatetime.datetime.strptime(\"2022/01/31\", \"%Y/%m/%d\").astimezone(datetime.timezone.utc)\n

        On Python 3.11 and later, datetime.timezone.utc can be replaced with datetime.UTC.

        ","tags":["DTZ007"]},{"location":"rules/call-datetime-strptime-without-zone/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        • Python documentation: strftime() and strptime() Behavior
        ","tags":["DTZ007"]},{"location":"rules/call-datetime-today/","title":"call-datetime-today (DTZ002)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ002"]},{"location":"rules/call-datetime-today/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.datetime.today().

        ","tags":["DTZ002"]},{"location":"rules/call-datetime-today/#why-is-this-bad","title":"Why is this bad?","text":"

        datetime objects are \"naive\" by default, in that they do not include timezone information. \"Naive\" objects are easy to understand, but ignore some aspects of reality, which can lead to subtle bugs. Timezone-aware datetime objects are preferred, as they represent a specific moment in time, unlike \"naive\" objects.

        datetime.datetime.today() creates a \"naive\" object; instead, use datetime.datetime.now(tz=...) to create a timezone-aware object.

        ","tags":["DTZ002"]},{"location":"rules/call-datetime-today/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.today()\n

        Use instead:

        import datetime\n\ndatetime.datetime.now(tz=datetime.timezone.utc)\n

        Or, for Python 3.11 and later:

        import datetime\n\ndatetime.datetime.now(tz=datetime.UTC)\n
        ","tags":["DTZ002"]},{"location":"rules/call-datetime-utcfromtimestamp/","title":"call-datetime-utcfromtimestamp (DTZ004)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ004"]},{"location":"rules/call-datetime-utcfromtimestamp/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.datetime.utcfromtimestamp().

        ","tags":["DTZ004"]},{"location":"rules/call-datetime-utcfromtimestamp/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.datetime.utcfromtimestamp() returns a naive datetime object; instead, use datetime.datetime.fromtimestamp(ts, tz=...) to create a timezone-aware object.

        ","tags":["DTZ004"]},{"location":"rules/call-datetime-utcfromtimestamp/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.utcfromtimestamp(946684800)\n

        Use instead:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.timezone.utc)\n

        Or, on Python 3.11 and later:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.UTC)\n
        ","tags":["DTZ004"]},{"location":"rules/call-datetime-utcfromtimestamp/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ004"]},{"location":"rules/call-datetime-utcnow/","title":"call-datetime-utcnow (DTZ003)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ003"]},{"location":"rules/call-datetime-utcnow/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.datetime.utcnow().

        ","tags":["DTZ003"]},{"location":"rules/call-datetime-utcnow/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.datetime.utcnow() returns a naive datetime object; instead, use datetime.datetime.now(tz=...) to create a timezone-aware object.

        ","tags":["DTZ003"]},{"location":"rules/call-datetime-utcnow/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.utcnow()\n

        Use instead:

        import datetime\n\ndatetime.datetime.now(tz=datetime.timezone.utc)\n

        Or, for Python 3.11 and later:

        import datetime\n\ndatetime.datetime.now(tz=datetime.UTC)\n
        ","tags":["DTZ003"]},{"location":"rules/call-datetime-utcnow/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ003"]},{"location":"rules/call-datetime-without-tzinfo/","title":"call-datetime-without-tzinfo (DTZ001)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ001"]},{"location":"rules/call-datetime-without-tzinfo/#what-it-does","title":"What it does","text":"

        Checks for datetime instantiations that do not specify a timezone.

        ","tags":["DTZ001"]},{"location":"rules/call-datetime-without-tzinfo/#why-is-this-bad","title":"Why is this bad?","text":"

        datetime objects are \"naive\" by default, in that they do not include timezone information. \"Naive\" objects are easy to understand, but ignore some aspects of reality, which can lead to subtle bugs. Timezone-aware datetime objects are preferred, as they represent a specific moment in time, unlike \"naive\" objects.

        By providing a non-None value for tzinfo, a datetime can be made timezone-aware.

        ","tags":["DTZ001"]},{"location":"rules/call-datetime-without-tzinfo/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime(2000, 1, 1, 0, 0, 0)\n

        Use instead:

        import datetime\n\ndatetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)\n

        Or, on Python 3.11 and later:

        import datetime\n\ndatetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=datetime.UTC)\n
        ","tags":["DTZ001"]},{"location":"rules/call-with-shell-equals-true/","title":"call-with-shell-equals-true (S604)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S604"]},{"location":"rules/call-with-shell-equals-true/#what-it-does","title":"What it does","text":"

        Checks for method calls that set the shell parameter to true or another truthy value when invoking a subprocess.

        ","tags":["S604"]},{"location":"rules/call-with-shell-equals-true/#why-is-this-bad","title":"Why is this bad?","text":"

        Setting the shell parameter to true or another truthy value when invoking a subprocess can introduce security vulnerabilities, as it allows shell metacharacters and whitespace to be passed to child processes, potentially leading to shell injection attacks.

        It is recommended to avoid using shell=True unless absolutely necessary and, when used, to ensure that all inputs are properly sanitized and quoted to prevent such vulnerabilities.

        ","tags":["S604"]},{"location":"rules/call-with-shell-equals-true/#known-problems","title":"Known problems","text":"

        Prone to false positives as it is triggered on any function call with a shell=True parameter.

        ","tags":["S604"]},{"location":"rules/call-with-shell-equals-true/#example","title":"Example","text":"
        import subprocess\n\nuser_input = input(\"Enter a command: \")\nsubprocess.run(user_input, shell=True)\n
        ","tags":["S604"]},{"location":"rules/call-with-shell-equals-true/#references","title":"References","text":"
        • Python documentation: Security Considerations
        ","tags":["S604"]},{"location":"rules/camelcase-imported-as-acronym/","title":"camelcase-imported-as-acronym (N817)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N817"]},{"location":"rules/camelcase-imported-as-acronym/#what-it-does","title":"What it does","text":"

        Checks for CamelCase imports that are aliased as acronyms.

        ","tags":["N817"]},{"location":"rules/camelcase-imported-as-acronym/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends naming conventions for classes, functions, constants, and more. The use of inconsistent naming styles between import and alias names may lead readers to expect an import to be of another type (e.g., confuse a Python class with a constant).

        Import aliases should thus follow the same naming style as the member being imported.

        Note that this rule is distinct from camelcase-imported-as-constant to accommodate selective enforcement.

        Also note that import aliases following an import convention according to the lint.flake8-import-conventions.aliases option are allowed.

        ","tags":["N817"]},{"location":"rules/camelcase-imported-as-acronym/#example","title":"Example","text":"
        from example import MyClassName as MCN\n

        Use instead:

        from example import MyClassName\n
        ","tags":["N817"]},{"location":"rules/camelcase-imported-as-acronym/#options","title":"Options","text":"
        • lint.flake8-import-conventions.aliases
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N817"]},{"location":"rules/camelcase-imported-as-constant/","title":"camelcase-imported-as-constant (N814)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-constant/#what-it-does","title":"What it does","text":"

        Checks for CamelCase imports that are aliased to constant-style names.

        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends naming conventions for classes, functions, constants, and more. The use of inconsistent naming styles between import and alias names may lead readers to expect an import to be of another type (e.g., confuse a Python class with a constant).

        Import aliases should thus follow the same naming style as the member being imported.

        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-constant/#example","title":"Example","text":"
        from example import MyClassName as MY_CLASS_NAME\n

        Use instead:

        from example import MyClassName\n
        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-constant/#note","title":"Note","text":"

        Identifiers consisting of a single uppercase character are ambiguous under the rules of PEP 8, which specifies CamelCase for classes and ALL_CAPS_SNAKE_CASE for constants. Without a second character, it is not possible to reliably guess whether the identifier is intended to be part of a CamelCase string for a class or an ALL_CAPS_SNAKE_CASE string for a constant, since both conventions will produce the same output when given a single input character. Therefore, this lint rule does not apply to cases where the alias for the imported identifier consists of a single uppercase character.

        A common example of a single uppercase character being used for a class name can be found in Django's django.db.models.Q class.

        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-constant/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-lowercase/","title":"camelcase-imported-as-lowercase (N813)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N813"]},{"location":"rules/camelcase-imported-as-lowercase/#what-it-does","title":"What it does","text":"

        Checks for CamelCase imports that are aliased to lowercase names.

        ","tags":["N813"]},{"location":"rules/camelcase-imported-as-lowercase/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends naming conventions for classes, functions, constants, and more. The use of inconsistent naming styles between import and alias names may lead readers to expect an import to be of another type (e.g., confuse a Python class with a constant).

        Import aliases should thus follow the same naming style as the member being imported.

        ","tags":["N813"]},{"location":"rules/camelcase-imported-as-lowercase/#example","title":"Example","text":"
        from example import MyClassName as myclassname\n

        Use instead:

        from example import MyClassName\n
        ","tags":["N813"]},{"location":"rules/camelcase-imported-as-lowercase/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N813"]},{"location":"rules/cancel-scope-no-checkpoint/","title":"cancel-scope-no-checkpoint (ASYNC100)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC100"]},{"location":"rules/cancel-scope-no-checkpoint/#what-it-does","title":"What it does","text":"

        Checks for timeout context managers which do not contain a checkpoint.

        For the purposes of this check, yield is considered a checkpoint, since checkpoints may occur in the caller to which we yield.

        ","tags":["ASYNC100"]},{"location":"rules/cancel-scope-no-checkpoint/#why-is-this-bad","title":"Why is this bad?","text":"

        Some asynchronous context managers, such as asyncio.timeout and trio.move_on_after, have no effect unless they contain a checkpoint. The use of such context managers without an await, async with or async for statement is likely a mistake.

        ","tags":["ASYNC100"]},{"location":"rules/cancel-scope-no-checkpoint/#example","title":"Example","text":"
        async def func():\n    async with asyncio.timeout(2):\n        do_something()\n

        Use instead:

        async def func():\n    async with asyncio.timeout(2):\n        do_something()\n        await awaitable()\n
        ","tags":["ASYNC100"]},{"location":"rules/cancel-scope-no-checkpoint/#references","title":"References","text":"
        • asyncio timeouts
        • anyio timeouts
        • trio timeouts
        ","tags":["ASYNC100"]},{"location":"rules/check-and-remove-from-set/","title":"check-and-remove-from-set (FURB132)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB132"]},{"location":"rules/check-and-remove-from-set/#what-it-does","title":"What it does","text":"

        Checks for uses of set.remove that can be replaced with set.discard.

        ","tags":["FURB132"]},{"location":"rules/check-and-remove-from-set/#why-is-this-bad","title":"Why is this bad?","text":"

        If an element should be removed from a set if it is present, it is more succinct and idiomatic to use discard.

        ","tags":["FURB132"]},{"location":"rules/check-and-remove-from-set/#known-problems","title":"Known problems","text":"

        This rule is prone to false negatives due to type inference limitations, as it will only detect sets that are instantiated as literals or annotated with a type annotation.

        ","tags":["FURB132"]},{"location":"rules/check-and-remove-from-set/#example","title":"Example","text":"
        nums = {123, 456}\n\nif 123 in nums:\n    nums.remove(123)\n

        Use instead:

        nums = {123, 456}\n\nnums.discard(123)\n
        ","tags":["FURB132"]},{"location":"rules/check-and-remove-from-set/#references","title":"References","text":"
        • Python documentation: set.discard()
        ","tags":["FURB132"]},{"location":"rules/class-as-data-structure/","title":"class-as-data-structure (B903)","text":"

        Derived from the flake8-bugbear linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["B903"]},{"location":"rules/class-as-data-structure/#what-it-does","title":"What it does","text":"

        Checks for classes that only have a public __init__ method, without base classes and decorators.

        ","tags":["B903"]},{"location":"rules/class-as-data-structure/#why-is-this-bad","title":"Why is this bad?","text":"

        Classes with just an __init__ are possibly better off being a dataclass or a namedtuple, which have less boilerplate.

        ","tags":["B903"]},{"location":"rules/class-as-data-structure/#example","title":"Example","text":"
        class Point:\n    def __init__(self, x: float, y: float):\n        self.x = x\n        self.y = y\n

        Use instead:

        from dataclasses import dataclass\n\n\n@dataclass\nclass Point:\n    x: float\n    y: float\n
        ","tags":["B903"]},{"location":"rules/class-with-mixed-type-vars/","title":"class-with-mixed-type-vars (RUF053)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF053"]},{"location":"rules/class-with-mixed-type-vars/#what-it-does","title":"What it does","text":"

        Checks for classes that have PEP 695 while also inheriting from typing.Generic or typing_extensions.Generic.

        ","tags":["RUF053"]},{"location":"rules/class-with-mixed-type-vars/#why-is-this-bad","title":"Why is this bad?","text":"

        Such classes cause errors at runtime:

        from typing import Generic, TypeVar\n\nU = TypeVar(\"U\")\n\n# TypeError: Cannot inherit from Generic[...] multiple times.\nclass C[T](Generic[U]): ...\n
        ","tags":["RUF053"]},{"location":"rules/class-with-mixed-type-vars/#example","title":"Example","text":"
        from typing import Generic, ParamSpec, TypeVar, TypeVarTuple\n\nU = TypeVar(\"U\")\nP = ParamSpec(\"P\")\nTs = TypeVarTuple(\"Ts\")\n\n\nclass C[T](Generic[U, P, *Ts]): ...\n

        Use instead:

        class C[T, U, **P, *Ts]: ...\n
        ","tags":["RUF053"]},{"location":"rules/class-with-mixed-type-vars/#fix-safety","title":"Fix safety","text":"

        As the fix changes runtime behaviour, it is always marked as unsafe. Additionally, comments within the fix range will not be preserved.

        ","tags":["RUF053"]},{"location":"rules/class-with-mixed-type-vars/#references","title":"References","text":"
        • Python documentation: User-defined generic types
        • Python documentation: type parameter lists
        • PEP 695 - Type Parameter Syntax
        ","tags":["RUF053"]},{"location":"rules/collapsible-else-if/","title":"collapsible-else-if (PLR5501)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLR5501"]},{"location":"rules/collapsible-else-if/#what-it-does","title":"What it does","text":"

        Checks for else blocks that consist of a single if statement.

        ","tags":["PLR5501"]},{"location":"rules/collapsible-else-if/#why-is-this-bad","title":"Why is this bad?","text":"

        If an else block contains a single if statement, it can be collapsed into an elif, thus reducing the indentation level.

        ","tags":["PLR5501"]},{"location":"rules/collapsible-else-if/#example","title":"Example","text":"
        def check_sign(value: int) -> None:\n    if value > 0:\n        print(\"Number is positive.\")\n    else:\n        if value < 0:\n            print(\"Number is negative.\")\n        else:\n            print(\"Number is zero.\")\n

        Use instead:

        def check_sign(value: int) -> None:\n    if value > 0:\n        print(\"Number is positive.\")\n    elif value < 0:\n        print(\"Number is negative.\")\n    else:\n        print(\"Number is zero.\")\n
        ","tags":["PLR5501"]},{"location":"rules/collapsible-else-if/#references","title":"References","text":"
        • Python documentation: if Statements
        ","tags":["PLR5501"]},{"location":"rules/collapsible-if/","title":"collapsible-if (SIM102)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM102"]},{"location":"rules/collapsible-if/#what-it-does","title":"What it does","text":"

        Checks for nested if statements that can be collapsed into a single if statement.

        ","tags":["SIM102"]},{"location":"rules/collapsible-if/#why-is-this-bad","title":"Why is this bad?","text":"

        Nesting if statements leads to deeper indentation and makes code harder to read. Instead, combine the conditions into a single if statement with an and operator.

        ","tags":["SIM102"]},{"location":"rules/collapsible-if/#example","title":"Example","text":"
        if foo:\n    if bar:\n        ...\n

        Use instead:

        if foo and bar:\n    ...\n
        ","tags":["SIM102"]},{"location":"rules/collapsible-if/#references","title":"References","text":"
        • Python documentation: The if statement
        • Python documentation: Boolean operations
        ","tags":["SIM102"]},{"location":"rules/collection-literal-concatenation/","title":"collection-literal-concatenation (RUF005)","text":"

        Fix is sometimes available.

        ","tags":["RUF005"]},{"location":"rules/collection-literal-concatenation/#what-it-does","title":"What it does","text":"

        Checks for uses of the + operator to concatenate collections.

        ","tags":["RUF005"]},{"location":"rules/collection-literal-concatenation/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the + operator can be used to concatenate collections (e.g., x + y to concatenate the lists x and y).

        However, collections can be concatenated more efficiently using the unpacking operator (e.g., [*x, *y] to concatenate x and y).

        Prefer the unpacking operator to concatenate collections, as it is more readable and flexible. The * operator can unpack any iterable, whereas + operates only on particular sequences which, in many cases, must be of the same type.

        ","tags":["RUF005"]},{"location":"rules/collection-literal-concatenation/#example","title":"Example","text":"
        foo = [2, 3, 4]\nbar = [1] + foo + [5, 6]\n

        Use instead:

        foo = [2, 3, 4]\nbar = [1, *foo, 5, 6]\n
        ","tags":["RUF005"]},{"location":"rules/collection-literal-concatenation/#fix-safety","title":"Fix safety","text":"

        The fix is always marked as unsafe because the + operator uses the __add__ magic method and *-unpacking uses the __iter__ magic method. Both of these could have custom implementations, causing the fix to change program behaviour.

        ","tags":["RUF005"]},{"location":"rules/collection-literal-concatenation/#references","title":"References","text":"
        • PEP 448 \u2013 Additional Unpacking Generalizations
        • Python documentation: Sequence Types \u2014 list, tuple, range
        ","tags":["RUF005"]},{"location":"rules/collections-named-tuple/","title":"collections-named-tuple (PYI024)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI024"]},{"location":"rules/collections-named-tuple/#what-it-does","title":"What it does","text":"

        Checks for uses of collections.namedtuple in stub files.

        ","tags":["PYI024"]},{"location":"rules/collections-named-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        typing.NamedTuple is the \"typed version\" of collections.namedtuple.

        Inheriting from typing.NamedTuple creates a custom tuple subclass in the same way as using the collections.namedtuple factory function. However, using typing.NamedTuple allows you to provide a type annotation for each field in the class. This means that type checkers will have more information to work with, and will be able to analyze your code more precisely.

        ","tags":["PYI024"]},{"location":"rules/collections-named-tuple/#example","title":"Example","text":"
        from collections import namedtuple\n\nperson = namedtuple(\"Person\", [\"name\", \"age\"])\n

        Use instead:

        from typing import NamedTuple\n\nclass Person(NamedTuple):\n    name: str\n    age: int\n
        ","tags":["PYI024"]},{"location":"rules/commented-out-code/","title":"commented-out-code (ERA001)","text":"

        Derived from the eradicate linter.

        ","tags":["ERA001"]},{"location":"rules/commented-out-code/#what-it-does","title":"What it does","text":"

        Checks for commented-out Python code.

        ","tags":["ERA001"]},{"location":"rules/commented-out-code/#why-is-this-bad","title":"Why is this bad?","text":"

        Commented-out code is dead code, and is often included inadvertently. It should be removed.

        ","tags":["ERA001"]},{"location":"rules/commented-out-code/#known-problems","title":"Known problems","text":"

        Prone to false positives when checking comments that resemble Python code, but are not actually Python code (#4845).

        ","tags":["ERA001"]},{"location":"rules/commented-out-code/#example","title":"Example","text":"
        # print(\"Hello, world!\")\n
        ","tags":["ERA001"]},{"location":"rules/commented-out-code/#options","title":"Options","text":"
        • lint.task-tags
        ","tags":["ERA001"]},{"location":"rules/compare-to-empty-string/","title":"compare-to-empty-string (PLC1901)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLC1901"]},{"location":"rules/compare-to-empty-string/#what-it-does","title":"What it does","text":"

        Checks for comparisons to empty strings.

        ","tags":["PLC1901"]},{"location":"rules/compare-to-empty-string/#why-is-this-bad","title":"Why is this bad?","text":"

        An empty string is falsy, so it is unnecessary to compare it to \"\". If the value can be something else Python considers falsy, such as None, 0, or another empty container, then the code is not equivalent.

        ","tags":["PLC1901"]},{"location":"rules/compare-to-empty-string/#known-problems","title":"Known problems","text":"

        High false positive rate, as the check is context-insensitive and does not consider the type of the variable being compared (#4282).

        ","tags":["PLC1901"]},{"location":"rules/compare-to-empty-string/#example","title":"Example","text":"
        x: str = ...\n\nif x == \"\":\n    print(\"x is empty\")\n

        Use instead:

        x: str = ...\n\nif not x:\n    print(\"x is empty\")\n
        ","tags":["PLC1901"]},{"location":"rules/compare-to-empty-string/#references","title":"References","text":"
        • Python documentation: Truth Value Testing
        ","tags":["PLC1901"]},{"location":"rules/compare-with-tuple/","title":"compare-with-tuple (SIM109)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM109"]},{"location":"rules/compare-with-tuple/#what-it-does","title":"What it does","text":"

        Checks for boolean expressions that contain multiple equality comparisons to the same value.

        ","tags":["SIM109"]},{"location":"rules/compare-with-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        To check if an object is equal to any one of multiple values, it's more concise to use the in operator with a tuple of values.

        ","tags":["SIM109"]},{"location":"rules/compare-with-tuple/#example","title":"Example","text":"
        if foo == x or foo == y:\n    ...\n

        Use instead:

        if foo in (x, y):\n    ...\n
        ","tags":["SIM109"]},{"location":"rules/compare-with-tuple/#references","title":"References","text":"
        • Python documentation: Membership test operations
        ","tags":["SIM109"]},{"location":"rules/comparison-of-constant/","title":"comparison-of-constant (PLR0133)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0133"]},{"location":"rules/comparison-of-constant/#what-it-does","title":"What it does","text":"

        Checks for comparisons between constants.

        ","tags":["PLR0133"]},{"location":"rules/comparison-of-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing two constants will always resolve to the same value, so the comparison is redundant. Instead, the expression should be replaced with the result of the comparison.

        ","tags":["PLR0133"]},{"location":"rules/comparison-of-constant/#example","title":"Example","text":"
        foo = 1 == 1\n

        Use instead:

        foo = True\n
        ","tags":["PLR0133"]},{"location":"rules/comparison-of-constant/#references","title":"References","text":"
        • Python documentation: Comparisons
        ","tags":["PLR0133"]},{"location":"rules/comparison-with-itself/","title":"comparison-with-itself (PLR0124)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0124"]},{"location":"rules/comparison-with-itself/#what-it-does","title":"What it does","text":"

        Checks for operations that compare a name to itself.

        ","tags":["PLR0124"]},{"location":"rules/comparison-with-itself/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing a name to itself always results in the same value, and is likely a mistake.

        ","tags":["PLR0124"]},{"location":"rules/comparison-with-itself/#example","title":"Example","text":"
        foo == foo\n

        In some cases, self-comparisons are used to determine whether a float is NaN. Instead, prefer math.isnan:

        import math\n\nmath.isnan(foo)\n
        ","tags":["PLR0124"]},{"location":"rules/comparison-with-itself/#references","title":"References","text":"
        • Python documentation: Comparisons
        ","tags":["PLR0124"]},{"location":"rules/complex-assignment-in-stub/","title":"complex-assignment-in-stub (PYI017)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI017"]},{"location":"rules/complex-assignment-in-stub/#what-it-does","title":"What it does","text":"

        Checks for assignments with multiple or non-name targets in stub files.

        ","tags":["PYI017"]},{"location":"rules/complex-assignment-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        In general, stub files should be thought of as \"data files\" for a type checker, and are not intended to be executed. As such, it's useful to enforce that only a subset of Python syntax is allowed in a stub file, to ensure that everything in the stub is unambiguous for the type checker.

        The need to perform multi-assignment, or assignment to a non-name target, likely indicates a misunderstanding of how stub files are intended to be used.

        ","tags":["PYI017"]},{"location":"rules/complex-assignment-in-stub/#example","title":"Example","text":"
        from typing import TypeAlias\n\na = b = int\n\nclass Klass: ...\n\nKlass.X: TypeAlias = int\n

        Use instead:

        from typing import TypeAlias\n\na: TypeAlias = int\nb: TypeAlias = int\n\nclass Klass:\n    X: TypeAlias = int\n
        ","tags":["PYI017"]},{"location":"rules/complex-if-statement-in-stub/","title":"complex-if-statement-in-stub (PYI002)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI002"]},{"location":"rules/complex-if-statement-in-stub/#what-it-does","title":"What it does","text":"

        Checks for if statements with complex conditionals in stubs.

        ","tags":["PYI002"]},{"location":"rules/complex-if-statement-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Type checkers understand simple conditionals to express variations between different Python versions and platforms. However, complex tests may not be understood by a type checker, leading to incorrect inferences when they analyze your code.

        ","tags":["PYI002"]},{"location":"rules/complex-if-statement-in-stub/#example","title":"Example","text":"
        import sys\n\nif (3, 10) <= sys.version_info < (3, 12): ...\n

        Use instead:

        import sys\n\nif sys.version_info >= (3, 10) and sys.version_info < (3, 12): ...\n
        ","tags":["PYI002"]},{"location":"rules/complex-if-statement-in-stub/#references","title":"References","text":"
        • Typing documentation: Version and platform checking
        ","tags":["PYI002"]},{"location":"rules/complex-structure/","title":"complex-structure (C901)","text":"

        Derived from the mccabe linter.

        ","tags":["C901"]},{"location":"rules/complex-structure/#what-it-does","title":"What it does","text":"

        Checks for functions with a high McCabe complexity.

        ","tags":["C901"]},{"location":"rules/complex-structure/#why-is-this-bad","title":"Why is this bad?","text":"

        The McCabe complexity of a function is a measure of the complexity of the control flow graph of the function. It is calculated by adding one to the number of decision points in the function. A decision point is a place in the code where the program has a choice of two or more paths to follow.

        Functions with a high complexity are hard to understand and maintain.

        ","tags":["C901"]},{"location":"rules/complex-structure/#example","title":"Example","text":"
        def foo(a, b, c):\n    if a:\n        if b:\n            if c:\n                return 1\n            else:\n                return 2\n        else:\n            return 3\n    else:\n        return 4\n

        Use instead:

        def foo(a, b, c):\n    if not a:\n        return 4\n    if not b:\n        return 3\n    if not c:\n        return 2\n    return 1\n
        ","tags":["C901"]},{"location":"rules/complex-structure/#options","title":"Options","text":"
        • lint.mccabe.max-complexity
        ","tags":["C901"]},{"location":"rules/constant-imported-as-non-constant/","title":"constant-imported-as-non-constant (N811)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N811"]},{"location":"rules/constant-imported-as-non-constant/#what-it-does","title":"What it does","text":"

        Checks for constant imports that are aliased to non-constant-style names.

        ","tags":["N811"]},{"location":"rules/constant-imported-as-non-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends naming conventions for classes, functions, constants, and more. The use of inconsistent naming styles between import and alias names may lead readers to expect an import to be of another type (e.g., confuse a Python class with a constant).

        Import aliases should thus follow the same naming style as the member being imported.

        ","tags":["N811"]},{"location":"rules/constant-imported-as-non-constant/#example","title":"Example","text":"
        from example import CONSTANT_VALUE as ConstantValue\n

        Use instead:

        from example import CONSTANT_VALUE\n
        ","tags":["N811"]},{"location":"rules/constant-imported-as-non-constant/#note","title":"Note","text":"

        Identifiers consisting of a single uppercase character are ambiguous under the rules of PEP 8, which specifies CamelCase for classes and ALL_CAPS_SNAKE_CASE for constants. Without a second character, it is not possible to reliably guess whether the identifier is intended to be part of a CamelCase string for a class or an ALL_CAPS_SNAKE_CASE string for a constant, since both conventions will produce the same output when given a single input character. Therefore, this lint rule does not apply to cases where the imported identifier consists of a single uppercase character.

        A common example of a single uppercase character being used for a class name can be found in Django's django.db.models.Q class.

        ","tags":["N811"]},{"location":"rules/constant-imported-as-non-constant/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N811"]},{"location":"rules/continue-in-finally/","title":"continue-in-finally (PLE0116)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0116"]},{"location":"rules/continue-in-finally/#what-it-does","title":"What it does","text":"

        Checks for continue statements inside finally

        ","tags":["PLE0116"]},{"location":"rules/continue-in-finally/#why-is-this-bad","title":"Why is this bad?","text":"

        continue statements were not allowed within finally clauses prior to Python 3.8. Using a continue statement within a finally clause can cause a SyntaxError.

        ","tags":["PLE0116"]},{"location":"rules/continue-in-finally/#example","title":"Example","text":"
        while True:\n    try:\n        pass\n    finally:\n        continue\n

        Use instead:

        while True:\n    try:\n        pass\n    except Exception:\n        pass\n    else:\n        continue\n
        ","tags":["PLE0116"]},{"location":"rules/continue-in-finally/#options","title":"Options","text":"
        • target-version
        ","tags":["PLE0116"]},{"location":"rules/continue-outside-loop/","title":"continue-outside-loop (F702)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F702"]},{"location":"rules/continue-outside-loop/#what-it-does","title":"What it does","text":"

        Checks for continue statements outside of loops.

        ","tags":["F702"]},{"location":"rules/continue-outside-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of a continue statement outside of a for or while loop will raise a SyntaxError.

        ","tags":["F702"]},{"location":"rules/continue-outside-loop/#example","title":"Example","text":"
        def foo():\n    continue  # SyntaxError\n
        ","tags":["F702"]},{"location":"rules/continue-outside-loop/#references","title":"References","text":"
        • Python documentation: continue
        ","tags":["F702"]},{"location":"rules/convert-named-tuple-functional-to-class/","title":"convert-named-tuple-functional-to-class (UP014)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP014"]},{"location":"rules/convert-named-tuple-functional-to-class/#what-it-does","title":"What it does","text":"

        Checks for NamedTuple declarations that use functional syntax.

        ","tags":["UP014"]},{"location":"rules/convert-named-tuple-functional-to-class/#why-is-this-bad","title":"Why is this bad?","text":"

        NamedTuple subclasses can be defined either through a functional syntax (Foo = NamedTuple(...)) or a class syntax (class Foo(NamedTuple): ...).

        The class syntax is more readable and generally preferred over the functional syntax, which exists primarily for backwards compatibility with collections.namedtuple.

        ","tags":["UP014"]},{"location":"rules/convert-named-tuple-functional-to-class/#example","title":"Example","text":"
        from typing import NamedTuple\n\nFoo = NamedTuple(\"Foo\", [(\"a\", int), (\"b\", str)])\n

        Use instead:

        from typing import NamedTuple\n\n\nclass Foo(NamedTuple):\n    a: int\n    b: str\n
        ","tags":["UP014"]},{"location":"rules/convert-named-tuple-functional-to-class/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe if there are any comments within the range of the NamedTuple definition, as these will be dropped by the autofix.

        ","tags":["UP014"]},{"location":"rules/convert-named-tuple-functional-to-class/#references","title":"References","text":"
        • Python documentation: typing.NamedTuple
        ","tags":["UP014"]},{"location":"rules/convert-typed-dict-functional-to-class/","title":"convert-typed-dict-functional-to-class (UP013)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP013"]},{"location":"rules/convert-typed-dict-functional-to-class/#what-it-does","title":"What it does","text":"

        Checks for TypedDict declarations that use functional syntax.

        ","tags":["UP013"]},{"location":"rules/convert-typed-dict-functional-to-class/#why-is-this-bad","title":"Why is this bad?","text":"

        TypedDict types can be defined either through a functional syntax (Foo = TypedDict(...)) or a class syntax (class Foo(TypedDict): ...).

        The class syntax is more readable and generally preferred over the functional syntax.

        Nonetheless, there are some situations in which it is impossible to use the class-based syntax. This rule will not apply to those cases. Namely, it is impossible to use the class-based syntax if any TypedDict fields are:

        • Not valid python identifiers (for example, @x)
        • Python keywords such as in
        • Private names such as __id that would undergo name mangling at runtime if the class-based syntax was used
        • Dunder names such as __int__ that can confuse type checkers if they're used with the class-based syntax.
        ","tags":["UP013"]},{"location":"rules/convert-typed-dict-functional-to-class/#example","title":"Example","text":"
        from typing import TypedDict\n\nFoo = TypedDict(\"Foo\", {\"a\": int, \"b\": str})\n

        Use instead:

        from typing import TypedDict\n\n\nclass Foo(TypedDict):\n    a: int\n    b: str\n
        ","tags":["UP013"]},{"location":"rules/convert-typed-dict-functional-to-class/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe if there are any comments within the range of the TypedDict definition, as these will be dropped by the autofix.

        ","tags":["UP013"]},{"location":"rules/convert-typed-dict-functional-to-class/#references","title":"References","text":"
        • Python documentation: typing.TypedDict
        ","tags":["UP013"]},{"location":"rules/create-subprocess-in-async-function/","title":"create-subprocess-in-async-function (ASYNC220)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC220"]},{"location":"rules/create-subprocess-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not create subprocesses with blocking methods.

        ","tags":["ASYNC220"]},{"location":"rules/create-subprocess-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a blocking call will block the entire event loop, preventing it from executing other tasks while waiting for the call to complete, negating the benefits of asynchronous programming.

        Instead of making a blocking call, use an equivalent asynchronous library or function, like trio.run_process() or anyio.run_process().

        ","tags":["ASYNC220"]},{"location":"rules/create-subprocess-in-async-function/#example","title":"Example","text":"
        async def foo():\n    os.popen(cmd)\n

        Use instead:

        async def foo():\n    asyncio.create_subprocess_shell(cmd)\n
        ","tags":["ASYNC220"]},{"location":"rules/custom-type-var-for-self/","title":"custom-type-var-for-self (PYI019)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#what-it-does","title":"What it does","text":"

        Checks for methods that use custom TypeVars in their annotations when they could use Self instead.

        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#why-is-this-bad","title":"Why is this bad?","text":"

        While the semantics are often identical, using Self is more intuitive and succinct (per PEP 673) than a custom TypeVar. For example, the use of Self will typically allow for the omission of type parameters on the self and cls arguments.

        This check currently applies to instance methods that return self, class methods that return an instance of cls, class methods that return cls, and __new__ methods.

        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#example","title":"Example","text":"
        from typing import TypeVar\n\n_S = TypeVar(\"_S\", bound=\"Foo\")\n\nclass Foo:\n    def __new__(cls: type[_S], *args: str, **kwargs: int) -> _S: ...\n    def foo(self: _S, arg: bytes) -> _S: ...\n    @classmethod\n    def bar(cls: type[_S], arg: int) -> _S: ...\n

        Use instead:

        from typing import Self\n\nclass Foo:\n    def __new__(cls, *args: str, **kwargs: int) -> Self: ...\n    def foo(self, arg: bytes) -> Self: ...\n    @classmethod\n    def bar(cls, arg: int) -> Self: ...\n
        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#fix-behaviour-and-safety","title":"Fix behaviour and safety","text":"

        The fix replaces all references to the custom type variable in the method's header and body with references to Self. The fix also adds an import of Self if neither Self nor typing is already imported in the module. If your target-version setting is set to Python 3.11 or newer, the fix imports Self from the standard-library typing module; otherwise, the fix imports Self from the third-party typing_extensions backport package.

        If the custom type variable is a PEP-695-style TypeVar, the fix also removes the TypeVar declaration from the method's type parameter list. However, if the type variable is an old-style TypeVar, the declaration of the type variable will not be removed by this rule's fix, as the type variable could still be used by other functions, methods or classes. See unused-private-type-var for a rule that will clean up unused private type variables.

        The fix is only marked as unsafe if there is the possibility that it might delete a comment from your code.

        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for Python versions before 3.11, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["PYI019"]},{"location":"rules/dataclass-enum/","title":"dataclass-enum (RUF049)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF049"]},{"location":"rules/dataclass-enum/#what-it-does","title":"What it does","text":"

        Checks for enum classes which are also decorated with @dataclass.

        ","tags":["RUF049"]},{"location":"rules/dataclass-enum/#why-is-this-bad","title":"Why is this bad?","text":"

        Decorating an enum with @dataclass() does not cause any errors at runtime, but may cause erroneous results:

        @dataclass\nclass E(Enum):\n    A = 1\n    B = 2\n\nprint(E.A == E.B)  # True\n
        ","tags":["RUF049"]},{"location":"rules/dataclass-enum/#example","title":"Example","text":"
        from dataclasses import dataclass\nfrom enum import Enum\n\n\n@dataclass\nclass E(Enum): ...\n

        Use instead:

        from enum import Enum\n\n\nclass E(Enum): ...\n
        ","tags":["RUF049"]},{"location":"rules/dataclass-enum/#references","title":"References","text":"
        • Python documentation: Enum HOWTO \u00a7 Dataclass support
        ","tags":["RUF049"]},{"location":"rules/datetime-min-max/","title":"datetime-min-max (DTZ901)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ901"]},{"location":"rules/datetime-min-max/#what-it-does","title":"What it does","text":"

        Checks for uses of datetime.datetime.min and datetime.datetime.max.

        ","tags":["DTZ901"]},{"location":"rules/datetime-min-max/#why-is-this-bad","title":"Why is this bad?","text":"

        datetime.min and datetime.max are non-timezone-aware datetime objects.

        As such, operations on datetime.min and datetime.max may behave unexpectedly, as in:

        # Timezone: UTC-14\ndatetime.min.timestamp()  # ValueError: year 0 is out of range\ndatetime.max.timestamp()  # ValueError: year 10000 is out of range\n
        ","tags":["DTZ901"]},{"location":"rules/datetime-min-max/#example","title":"Example","text":"
        datetime.max\n

        Use instead:

        datetime.max.replace(tzinfo=datetime.UTC)\n
        ","tags":["DTZ901"]},{"location":"rules/datetime-timezone-utc/","title":"datetime-timezone-utc (UP017)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP017"]},{"location":"rules/datetime-timezone-utc/#what-it-does","title":"What it does","text":"

        Checks for uses of datetime.timezone.utc.

        ","tags":["UP017"]},{"location":"rules/datetime-timezone-utc/#why-is-this-bad","title":"Why is this bad?","text":"

        As of Python 3.11, datetime.UTC is an alias for datetime.timezone.utc. The alias is more readable and generally preferred over the full path.

        ","tags":["UP017"]},{"location":"rules/datetime-timezone-utc/#example","title":"Example","text":"
        import datetime\n\ndatetime.timezone.utc\n

        Use instead:

        import datetime\n\ndatetime.UTC\n
        ","tags":["UP017"]},{"location":"rules/datetime-timezone-utc/#options","title":"Options","text":"
        • target-version
        ","tags":["UP017"]},{"location":"rules/datetime-timezone-utc/#references","title":"References","text":"
        • Python documentation: datetime.UTC
        ","tags":["UP017"]},{"location":"rules/debugger/","title":"debugger (T100)","text":"

        Derived from the flake8-debugger linter.

        ","tags":["T100"]},{"location":"rules/debugger/#what-it-does","title":"What it does","text":"

        Checks for the presence of debugger calls and imports.

        ","tags":["T100"]},{"location":"rules/debugger/#why-is-this-bad","title":"Why is this bad?","text":"

        Debugger calls and imports should be used for debugging purposes only. The presence of a debugger call or import in production code is likely a mistake and may cause unintended behavior, such as exposing sensitive information or causing the program to hang.

        Instead, consider using a logging library to log information about the program's state, and writing tests to verify that the program behaves as expected.

        ","tags":["T100"]},{"location":"rules/debugger/#example","title":"Example","text":"
        def foo():\n    breakpoint()\n
        ","tags":["T100"]},{"location":"rules/debugger/#references","title":"References","text":"
        • Python documentation: pdb \u2014 The Python Debugger
        • Python documentation: logging \u2014 Logging facility for Python
        ","tags":["T100"]},{"location":"rules/decimal-from-float-literal/","title":"decimal-from-float-literal (RUF032)","text":"

        Fix is always available.

        ","tags":["RUF032"]},{"location":"rules/decimal-from-float-literal/#what-it-does","title":"What it does","text":"

        Checks for Decimal calls passing a float literal.

        ","tags":["RUF032"]},{"location":"rules/decimal-from-float-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        Float literals have limited precision that can lead to unexpected results. The Decimal class is designed to handle numbers with fixed-point precision, so a string literal should be used instead.

        ","tags":["RUF032"]},{"location":"rules/decimal-from-float-literal/#example","title":"Example","text":"
        num = Decimal(1.2345)\n

        Use instead:

        num = Decimal(\"1.2345\")\n
        ","tags":["RUF032"]},{"location":"rules/decimal-from-float-literal/#fix-safety","title":"Fix Safety","text":"

        This rule's fix is marked as unsafe because it changes the underlying value of the Decimal instance that is constructed. This can lead to unexpected behavior if your program relies on the previous value (whether deliberately or not).

        ","tags":["RUF032"]},{"location":"rules/default-except-not-last/","title":"default-except-not-last (F707)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F707"]},{"location":"rules/default-except-not-last/#what-it-does","title":"What it does","text":"

        Checks for except blocks that handle all exceptions, but are not the last except block in a try statement.

        ","tags":["F707"]},{"location":"rules/default-except-not-last/#why-is-this-bad","title":"Why is this bad?","text":"

        When an exception is raised within a try block, the except blocks are evaluated in order, and the first matching block is executed. If an except block handles all exceptions, but isn't the last block, Python will raise a SyntaxError, as the following blocks would never be executed.

        ","tags":["F707"]},{"location":"rules/default-except-not-last/#example","title":"Example","text":"
        def reciprocal(n):\n    try:\n        reciprocal = 1 / n\n    except:\n        print(\"An exception occurred.\")\n    except ZeroDivisionError:\n        print(\"Cannot divide by zero.\")\n    else:\n        return reciprocal\n

        Use instead:

        def reciprocal(n):\n    try:\n        reciprocal = 1 / n\n    except ZeroDivisionError:\n        print(\"Cannot divide by zero.\")\n    except:\n        print(\"An exception occurred.\")\n    else:\n        return reciprocal\n
        ","tags":["F707"]},{"location":"rules/default-except-not-last/#references","title":"References","text":"
        • Python documentation: except clause
        ","tags":["F707"]},{"location":"rules/default-factory-kwarg/","title":"default-factory-kwarg (RUF026)","text":"

        Fix is sometimes available.

        ","tags":["RUF026"]},{"location":"rules/default-factory-kwarg/#what-it-does","title":"What it does","text":"

        Checks for incorrect usages of default_factory as a keyword argument when initializing a defaultdict.

        ","tags":["RUF026"]},{"location":"rules/default-factory-kwarg/#why-is-this-bad","title":"Why is this bad?","text":"

        The defaultdict constructor accepts a callable as its first argument. For example, it's common to initialize a defaultdict with int or list via defaultdict(int) or defaultdict(list), to create a dictionary that returns 0 or [] respectively when a key is missing.

        The default factory must be provided as a positional argument, as all keyword arguments to defaultdict are interpreted as initial entries in the dictionary. For example, defaultdict(foo=1, bar=2) will create a dictionary with {\"foo\": 1, \"bar\": 2} as its initial entries.

        As such, defaultdict(default_factory=list) will create a dictionary with {\"default_factory\": list} as its initial entry, instead of a dictionary that returns [] when a key is missing. Specifying a default_factory keyword argument is almost always a mistake, and one that type checkers can't reliably detect.

        ","tags":["RUF026"]},{"location":"rules/default-factory-kwarg/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as converting default_factory from a keyword to a positional argument will change the behavior of the code, even if the keyword argument was used erroneously.

        ","tags":["RUF026"]},{"location":"rules/default-factory-kwarg/#example","title":"Example","text":"
        defaultdict(default_factory=int)\ndefaultdict(default_factory=list)\n

        Use instead:

        defaultdict(int)\ndefaultdict(list)\n
        ","tags":["RUF026"]},{"location":"rules/delete-full-slice/","title":"delete-full-slice (FURB131)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB131"]},{"location":"rules/delete-full-slice/#what-it-does","title":"What it does","text":"

        Checks for del statements that delete the entire slice of a list or dictionary.

        ","tags":["FURB131"]},{"location":"rules/delete-full-slice/#why-is-this-bad","title":"Why is this bad?","text":"

        It is faster and more succinct to remove all items via the clear() method.

        ","tags":["FURB131"]},{"location":"rules/delete-full-slice/#known-problems","title":"Known problems","text":"

        This rule is prone to false negatives due to type inference limitations, as it will only detect lists and dictionaries that are instantiated as literals or annotated with a type annotation.

        ","tags":["FURB131"]},{"location":"rules/delete-full-slice/#example","title":"Example","text":"
        names = {\"key\": \"value\"}\nnums = [1, 2, 3]\n\ndel names[:]\ndel nums[:]\n

        Use instead:

        names = {\"key\": \"value\"}\nnums = [1, 2, 3]\n\nnames.clear()\nnums.clear()\n
        ","tags":["FURB131"]},{"location":"rules/delete-full-slice/#references","title":"References","text":"
        • Python documentation: Mutable Sequence Types
        • Python documentation: dict.clear()
        ","tags":["FURB131"]},{"location":"rules/deprecated-c-element-tree/","title":"deprecated-c-element-tree (UP023)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP023"]},{"location":"rules/deprecated-c-element-tree/#what-it-does","title":"What it does","text":"

        Checks for uses of the xml.etree.cElementTree module.

        ","tags":["UP023"]},{"location":"rules/deprecated-c-element-tree/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3.3, xml.etree.cElementTree was deprecated in favor of xml.etree.ElementTree.

        ","tags":["UP023"]},{"location":"rules/deprecated-c-element-tree/#example","title":"Example","text":"
        from xml.etree import cElementTree\n

        Use instead:

        from xml.etree import ElementTree\n
        ","tags":["UP023"]},{"location":"rules/deprecated-c-element-tree/#references","title":"References","text":"
        • Python documentation: xml.etree.ElementTree
        ","tags":["UP023"]},{"location":"rules/deprecated-import/","title":"deprecated-import (UP035)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP035"]},{"location":"rules/deprecated-import/#what-it-does","title":"What it does","text":"

        Checks for uses of deprecated imports based on the minimum supported Python version.

        ","tags":["UP035"]},{"location":"rules/deprecated-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Deprecated imports may be removed in future versions of Python, and should be replaced with their new equivalents.

        Note that, in some cases, it may be preferable to continue importing members from typing_extensions even after they're added to the Python standard library, as typing_extensions can backport bugfixes and optimizations from later Python versions. This rule thus avoids flagging imports from typing_extensions in such cases.

        ","tags":["UP035"]},{"location":"rules/deprecated-import/#example","title":"Example","text":"
        from collections import Sequence\n

        Use instead:

        from collections.abc import Sequence\n
        ","tags":["UP035"]},{"location":"rules/deprecated-log-warn/","title":"deprecated-log-warn (PGH002)","text":"

        Derived from the pygrep-hooks linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        Fix is sometimes available.

        ","tags":["PGH002"]},{"location":"rules/deprecated-log-warn/#removed","title":"Removed","text":"

        This rule is identical to G010 which should be used instead.

        ","tags":["PGH002"]},{"location":"rules/deprecated-log-warn/#what-it-does","title":"What it does","text":"

        Check for usages of the deprecated warn method from the logging module.

        ","tags":["PGH002"]},{"location":"rules/deprecated-log-warn/#why-is-this-bad","title":"Why is this bad?","text":"

        The warn method is deprecated. Use warning instead.

        ","tags":["PGH002"]},{"location":"rules/deprecated-log-warn/#example","title":"Example","text":"
        import logging\n\n\ndef foo():\n    logging.warn(\"Something happened\")\n

        Use instead:

        import logging\n\n\ndef foo():\n    logging.warning(\"Something happened\")\n
        ","tags":["PGH002"]},{"location":"rules/deprecated-log-warn/#references","title":"References","text":"
        • Python documentation: logger.Logger.warning
        ","tags":["PGH002"]},{"location":"rules/deprecated-mock-import/","title":"deprecated-mock-import (UP026)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP026"]},{"location":"rules/deprecated-mock-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the mock module that should be replaced with unittest.mock.

        ","tags":["UP026"]},{"location":"rules/deprecated-mock-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3.3, mock has been a part of the standard library as unittest.mock. The mock package is deprecated; use unittest.mock instead.

        ","tags":["UP026"]},{"location":"rules/deprecated-mock-import/#example","title":"Example","text":"
        import mock\n

        Use instead:

        from unittest import mock\n
        ","tags":["UP026"]},{"location":"rules/deprecated-mock-import/#references","title":"References","text":"
        • Python documentation: unittest.mock
        • PyPI: mock
        ","tags":["UP026"]},{"location":"rules/deprecated-unittest-alias/","title":"deprecated-unittest-alias (UP005)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP005"]},{"location":"rules/deprecated-unittest-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of deprecated methods from the unittest module.

        ","tags":["UP005"]},{"location":"rules/deprecated-unittest-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        The unittest module has deprecated aliases for some of its methods. The deprecated aliases were removed in Python 3.12. Instead of aliases, use their non-deprecated counterparts.

        ","tags":["UP005"]},{"location":"rules/deprecated-unittest-alias/#example","title":"Example","text":"
        from unittest import TestCase\n\n\nclass SomeTest(TestCase):\n    def test_something(self):\n        self.assertEquals(1, 1)\n

        Use instead:

        from unittest import TestCase\n\n\nclass SomeTest(TestCase):\n    def test_something(self):\n        self.assertEqual(1, 1)\n
        ","tags":["UP005"]},{"location":"rules/deprecated-unittest-alias/#references","title":"References","text":"
        • Python 3.11 documentation: Deprecated aliases
        ","tags":["UP005"]},{"location":"rules/dict-get-with-none-default/","title":"dict-get-with-none-default (SIM910)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM910"]},{"location":"rules/dict-get-with-none-default/#what-it-does","title":"What it does","text":"

        Checks for dict.get() calls that pass None as the default value.

        ","tags":["SIM910"]},{"location":"rules/dict-get-with-none-default/#why-is-this-bad","title":"Why is this bad?","text":"

        None is the default value for dict.get(), so it is redundant to pass it explicitly.

        ","tags":["SIM910"]},{"location":"rules/dict-get-with-none-default/#example","title":"Example","text":"
        ages = {\"Tom\": 23, \"Maria\": 23, \"Dog\": 11}\nage = ages.get(\"Cat\", None)\n

        Use instead:

        ages = {\"Tom\": 23, \"Maria\": 23, \"Dog\": 11}\nage = ages.get(\"Cat\")\n
        ","tags":["SIM910"]},{"location":"rules/dict-get-with-none-default/#references","title":"References","text":"
        • Python documentation: dict.get
        ","tags":["SIM910"]},{"location":"rules/dict-index-missing-items/","title":"dict-index-missing-items (PLC0206)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC0206"]},{"location":"rules/dict-index-missing-items/#what-it-does","title":"What it does","text":"

        Checks for dictionary iterations that extract the dictionary value via explicit indexing, instead of using .items().

        ","tags":["PLC0206"]},{"location":"rules/dict-index-missing-items/#why-is-this-bad","title":"Why is this bad?","text":"

        Iterating over a dictionary with .items() is semantically clearer and more efficient than extracting the value with the key.

        ","tags":["PLC0206"]},{"location":"rules/dict-index-missing-items/#example","title":"Example","text":"
        ORCHESTRA = {\n    \"violin\": \"strings\",\n    \"oboe\": \"woodwind\",\n    \"tuba\": \"brass\",\n    \"gong\": \"percussion\",\n}\n\nfor instrument in ORCHESTRA:\n    print(f\"{instrument}: {ORCHESTRA[instrument]}\")\n

        Use instead:

        ORCHESTRA = {\n    \"violin\": \"strings\",\n    \"oboe\": \"woodwind\",\n    \"tuba\": \"brass\",\n    \"gong\": \"percussion\",\n}\n\nfor instrument, section in ORCHESTRA.items():\n    print(f\"{instrument}: {section}\")\n
        ","tags":["PLC0206"]},{"location":"rules/dict-iter-missing-items/","title":"dict-iter-missing-items (PLE1141)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLE1141"]},{"location":"rules/dict-iter-missing-items/#what-it-does","title":"What it does","text":"

        Checks for dictionary unpacking in a for loop without calling .items().

        ","tags":["PLE1141"]},{"location":"rules/dict-iter-missing-items/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over a dictionary in a for loop, if a dictionary is unpacked without calling .items(), it could lead to a runtime error if the keys are not a tuple of two elements.

        It is likely that you're looking for an iteration over (key, value) pairs which can only be achieved when calling .items().

        ","tags":["PLE1141"]},{"location":"rules/dict-iter-missing-items/#example","title":"Example","text":"
        data = {\"Paris\": 2_165_423, \"New York City\": 8_804_190, \"Tokyo\": 13_988_129}\n\nfor city, population in data:\n    print(f\"{city} has population {population}.\")\n

        Use instead:

        data = {\"Paris\": 2_165_423, \"New York City\": 8_804_190, \"Tokyo\": 13_988_129}\n\nfor city, population in data.items():\n    print(f\"{city} has population {population}.\")\n
        ","tags":["PLE1141"]},{"location":"rules/dict-iter-missing-items/#known-problems","title":"Known problems","text":"

        If the dictionary key is a tuple, e.g.:

        d = {(1, 2): 3, (3, 4): 5}\nfor x, y in d:\n    print(x, y)\n

        The tuple key is unpacked into x and y instead of the key and values. This means that the suggested fix of using d.items() would result in different runtime behavior. Ruff cannot consistently infer the type of a dictionary's keys.

        ","tags":["PLE1141"]},{"location":"rules/dict-iter-missing-items/#fix-safety","title":"Fix safety","text":"

        Due to the known problem with tuple keys, this fix is unsafe.

        ","tags":["PLE1141"]},{"location":"rules/direct-logger-instantiation/","title":"direct-logger-instantiation (LOG001)","text":"

        Derived from the flake8-logging linter.

        Fix is sometimes available.

        ","tags":["LOG001"]},{"location":"rules/direct-logger-instantiation/#what-it-does","title":"What it does","text":"

        Checks for direct instantiation of logging.Logger, as opposed to using logging.getLogger().

        ","tags":["LOG001"]},{"location":"rules/direct-logger-instantiation/#why-is-this-bad","title":"Why is this bad?","text":"

        The Logger Objects documentation states that:

        Note that Loggers should NEVER be instantiated directly, but always through the module-level function logging.getLogger(name).

        If a logger is directly instantiated, it won't be added to the logger tree, and will bypass all configuration. Messages logged to it will only be sent to the \"handler of last resort\", skipping any filtering or formatting.

        ","tags":["LOG001"]},{"location":"rules/direct-logger-instantiation/#example","title":"Example","text":"
        import logging\n\nlogger = logging.Logger(__name__)\n

        Use instead:

        import logging\n\nlogger = logging.getLogger(__name__)\n
        ","tags":["LOG001"]},{"location":"rules/django-all-with-model-form/","title":"django-all-with-model-form (DJ007)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ007"]},{"location":"rules/django-all-with-model-form/#what-it-does","title":"What it does","text":"

        Checks for the use of fields = \"__all__\" in Django ModelForm classes.

        ","tags":["DJ007"]},{"location":"rules/django-all-with-model-form/#why-is-this-bad","title":"Why is this bad?","text":"

        If a ModelForm includes the fields = \"__all__\" attribute, any new field that is added to the model will automatically be exposed for modification.

        ","tags":["DJ007"]},{"location":"rules/django-all-with-model-form/#example","title":"Example","text":"
        from django.forms import ModelForm\n\n\nclass PostForm(ModelForm):\n    class Meta:\n        model = Post\n        fields = \"__all__\"\n

        Use instead:

        from django.forms import ModelForm\n\n\nclass PostForm(ModelForm):\n    class Meta:\n        model = Post\n        fields = [\"title\", \"content\"]\n
        ","tags":["DJ007"]},{"location":"rules/django-exclude-with-model-form/","title":"django-exclude-with-model-form (DJ006)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ006"]},{"location":"rules/django-exclude-with-model-form/#what-it-does","title":"What it does","text":"

        Checks for the use of exclude in Django ModelForm classes.

        ","tags":["DJ006"]},{"location":"rules/django-exclude-with-model-form/#why-is-this-bad","title":"Why is this bad?","text":"

        If a ModelForm includes the exclude attribute, any new field that is added to the model will automatically be exposed for modification.

        ","tags":["DJ006"]},{"location":"rules/django-exclude-with-model-form/#example","title":"Example","text":"
        from django.forms import ModelForm\n\n\nclass PostForm(ModelForm):\n    class Meta:\n        model = Post\n        exclude = [\"author\"]\n

        Use instead:

        from django.forms import ModelForm\n\n\nclass PostForm(ModelForm):\n    class Meta:\n        model = Post\n        fields = [\"title\", \"content\"]\n
        ","tags":["DJ006"]},{"location":"rules/django-extra/","title":"django-extra (S610)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S610"]},{"location":"rules/django-extra/#what-it-does","title":"What it does","text":"

        Checks for uses of Django's extra function where one or more arguments passed are not literal expressions.

        ","tags":["S610"]},{"location":"rules/django-extra/#why-is-this-bad","title":"Why is this bad?","text":"

        Django's extra function can be used to execute arbitrary SQL queries, which can in turn lead to SQL injection vulnerabilities.

        ","tags":["S610"]},{"location":"rules/django-extra/#example","title":"Example","text":"
        from django.contrib.auth.models import User\n\n# String interpolation creates a security loophole that could be used\n# for SQL injection:\nUser.objects.all().extra(select={\"test\": \"%secure\" % \"nos\"})\n

        Use instead:

        from django.contrib.auth.models import User\n\n# SQL injection is impossible if all arguments are literal expressions:\nUser.objects.all().extra(select={\"test\": \"secure\"})\n
        ","tags":["S610"]},{"location":"rules/django-extra/#references","title":"References","text":"
        • Django documentation: SQL injection protection
        • Common Weakness Enumeration: CWE-89
        ","tags":["S610"]},{"location":"rules/django-locals-in-render-function/","title":"django-locals-in-render-function (DJ003)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ003"]},{"location":"rules/django-locals-in-render-function/#what-it-does","title":"What it does","text":"

        Checks for the use of locals() in render functions.

        ","tags":["DJ003"]},{"location":"rules/django-locals-in-render-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Using locals() can expose internal variables or other unintentional data to the rendered template.

        ","tags":["DJ003"]},{"location":"rules/django-locals-in-render-function/#example","title":"Example","text":"
        from django.shortcuts import render\n\n\ndef index(request):\n    posts = Post.objects.all()\n    return render(request, \"app/index.html\", locals())\n

        Use instead:

        from django.shortcuts import render\n\n\ndef index(request):\n    posts = Post.objects.all()\n    context = {\"posts\": posts}\n    return render(request, \"app/index.html\", context)\n
        ","tags":["DJ003"]},{"location":"rules/django-model-without-dunder-str/","title":"django-model-without-dunder-str (DJ008)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ008"]},{"location":"rules/django-model-without-dunder-str/#what-it-does","title":"What it does","text":"

        Checks that a __str__ method is defined in Django models.

        ","tags":["DJ008"]},{"location":"rules/django-model-without-dunder-str/#why-is-this-bad","title":"Why is this bad?","text":"

        Django models should define a __str__ method to return a string representation of the model instance, as Django calls this method to display the object in the Django Admin and elsewhere.

        Models without a __str__ method will display a non-meaningful representation of the object in the Django Admin.

        ","tags":["DJ008"]},{"location":"rules/django-model-without-dunder-str/#example","title":"Example","text":"
        from django.db import models\n\n\nclass MyModel(models.Model):\n    field = models.CharField(max_length=255)\n

        Use instead:

        from django.db import models\n\n\nclass MyModel(models.Model):\n    field = models.CharField(max_length=255)\n\n    def __str__(self):\n        return f\"{self.field}\"\n
        ","tags":["DJ008"]},{"location":"rules/django-non-leading-receiver-decorator/","title":"django-non-leading-receiver-decorator (DJ013)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ013"]},{"location":"rules/django-non-leading-receiver-decorator/#what-it-does","title":"What it does","text":"

        Checks that Django's @receiver decorator is listed first, prior to any other decorators.

        ","tags":["DJ013"]},{"location":"rules/django-non-leading-receiver-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        Django's @receiver decorator is special in that it does not return a wrapped function. Rather, @receiver connects the decorated function to a signal. If any other decorators are listed before @receiver, the decorated function will not be connected to the signal.

        ","tags":["DJ013"]},{"location":"rules/django-non-leading-receiver-decorator/#example","title":"Example","text":"
        from django.dispatch import receiver\nfrom django.db.models.signals import post_save\n\n\n@transaction.atomic\n@receiver(post_save, sender=MyModel)\ndef my_handler(sender, instance, created, **kwargs):\n    pass\n

        Use instead:

        from django.dispatch import receiver\nfrom django.db.models.signals import post_save\n\n\n@receiver(post_save, sender=MyModel)\n@transaction.atomic\ndef my_handler(sender, instance, created, **kwargs):\n    pass\n
        ","tags":["DJ013"]},{"location":"rules/django-nullable-model-string-field/","title":"django-nullable-model-string-field (DJ001)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ001"]},{"location":"rules/django-nullable-model-string-field/#what-it-does","title":"What it does","text":"

        Checks nullable string-based fields (like CharField and TextField) in Django models.

        ","tags":["DJ001"]},{"location":"rules/django-nullable-model-string-field/#why-is-this-bad","title":"Why is this bad?","text":"

        If a string-based field is nullable, then your model will have two possible representations for \"no data\": None and the empty string. This can lead to confusion, as clients of the API have to check for both None and the empty string when trying to determine if the field has data.

        The Django convention is to use the empty string in lieu of None for string-based fields.

        ","tags":["DJ001"]},{"location":"rules/django-nullable-model-string-field/#example","title":"Example","text":"
        from django.db import models\n\n\nclass MyModel(models.Model):\n    field = models.CharField(max_length=255, null=True)\n

        Use instead:

        from django.db import models\n\n\nclass MyModel(models.Model):\n    field = models.CharField(max_length=255, default=\"\")\n
        ","tags":["DJ001"]},{"location":"rules/django-raw-sql/","title":"django-raw-sql (S611)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S611"]},{"location":"rules/django-raw-sql/#what-it-does","title":"What it does","text":"

        Checks for uses of Django's RawSQL function.

        ","tags":["S611"]},{"location":"rules/django-raw-sql/#why-is-this-bad","title":"Why is this bad?","text":"

        Django's RawSQL function can be used to execute arbitrary SQL queries, which can in turn lead to SQL injection vulnerabilities.

        ","tags":["S611"]},{"location":"rules/django-raw-sql/#example","title":"Example","text":"
        from django.db.models.expressions import RawSQL\nfrom django.contrib.auth.models import User\n\nUser.objects.annotate(val=RawSQL(\"%s\" % input_param, []))\n
        ","tags":["S611"]},{"location":"rules/django-raw-sql/#references","title":"References","text":"
        • Django documentation: SQL injection protection
        • Common Weakness Enumeration: CWE-89
        ","tags":["S611"]},{"location":"rules/django-unordered-body-content-in-model/","title":"django-unordered-body-content-in-model (DJ012)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ012"]},{"location":"rules/django-unordered-body-content-in-model/#what-it-does","title":"What it does","text":"

        Checks for the order of Model's inner classes, methods, and fields as per the Django Style Guide.

        ","tags":["DJ012"]},{"location":"rules/django-unordered-body-content-in-model/#why-is-this-bad","title":"Why is this bad?","text":"

        The Django Style Guide specifies that the order of Model inner classes, attributes and methods should be as follows:

        1. All database fields
        2. Custom manager attributes
        3. class Meta
        4. def __str__()
        5. def save()
        6. def get_absolute_url()
        7. Any custom methods
        ","tags":["DJ012"]},{"location":"rules/django-unordered-body-content-in-model/#example","title":"Example","text":"
        from django.db import models\n\n\nclass StrBeforeFieldModel(models.Model):\n    class Meta:\n        verbose_name = \"test\"\n        verbose_name_plural = \"tests\"\n\n    def __str__(self):\n        return \"foobar\"\n\n    first_name = models.CharField(max_length=32)\n    last_name = models.CharField(max_length=40)\n

        Use instead:

        from django.db import models\n\n\nclass StrBeforeFieldModel(models.Model):\n    first_name = models.CharField(max_length=32)\n    last_name = models.CharField(max_length=40)\n\n    class Meta:\n        verbose_name = \"test\"\n        verbose_name_plural = \"tests\"\n\n    def __str__(self):\n        return \"foobar\"\n
        ","tags":["DJ012"]},{"location":"rules/doc-line-too-long/","title":"doc-line-too-long (W505)","text":"

        Derived from the pycodestyle linter.

        ","tags":["W505"]},{"location":"rules/doc-line-too-long/#what-it-does","title":"What it does","text":"

        Checks for doc lines that exceed the specified maximum character length.

        ","tags":["W505"]},{"location":"rules/doc-line-too-long/#why-is-this-bad","title":"Why is this bad?","text":"

        For flowing long blocks of text (docstrings or comments), overlong lines can hurt readability. PEP 8, for example, recommends that such lines be limited to 72 characters, while this rule enforces the limit specified by the lint.pycodestyle.max-doc-length setting. (If no value is provided, this rule will be ignored, even if it's added to your --select list.)

        In the context of this rule, a \"doc line\" is defined as a line consisting of either a standalone comment or a standalone string, like a docstring.

        In the interest of pragmatism, this rule makes a few exceptions when determining whether a line is overlong. Namely, it:

        1. Ignores lines that consist of a single \"word\" (i.e., without any whitespace between its characters).
        2. Ignores lines that end with a URL, as long as the URL starts before the line-length threshold.
        3. Ignores line that end with a pragma comment (e.g., # type: ignore or # noqa), as long as the pragma comment starts before the line-length threshold. That is, a line will not be flagged as overlong if a pragma comment causes it to exceed the line length. (This behavior aligns with that of the Ruff formatter.)

        If lint.pycodestyle.ignore-overlong-task-comments is true, this rule will also ignore comments that start with any of the specified lint.task-tags (e.g., # TODO:).

        ","tags":["W505"]},{"location":"rules/doc-line-too-long/#example","title":"Example","text":"
        def function(x):\n    \"\"\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis auctor purus ut ex fermentum, at maximus est hendrerit.\"\"\"\n

        Use instead:

        def function(x):\n    \"\"\"\n    Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n    Duis auctor purus ut ex fermentum, at maximus est hendrerit.\n    \"\"\"\n
        ","tags":["W505"]},{"location":"rules/doc-line-too-long/#error-suppression","title":"Error suppression","text":"

        Hint: when suppressing W505 errors within multi-line strings (like docstrings), the noqa directive should come at the end of the string (after the closing triple quote), and will apply to the entire string, like so:

        \"\"\"Lorem ipsum dolor sit amet.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.\n\"\"\"  # noqa: W505\n
        ","tags":["W505"]},{"location":"rules/doc-line-too-long/#options","title":"Options","text":"
        • lint.task-tags
        • lint.pycodestyle.max-doc-length
        • lint.pycodestyle.ignore-overlong-task-comments
        ","tags":["W505"]},{"location":"rules/docstring-extraneous-exception/","title":"docstring-extraneous-exception (DOC502)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC502"]},{"location":"rules/docstring-extraneous-exception/#what-it-does","title":"What it does","text":"

        Checks for function docstrings that state that exceptions could be raised even though they are not directly raised in the function body.

        ","tags":["DOC502"]},{"location":"rules/docstring-extraneous-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Some conventions prefer non-explicit exceptions be omitted from the docstring.

        This rule is not enforced for abstract methods. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC502"]},{"location":"rules/docstring-extraneous-exception/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        ZeroDivisionError: Divided by zero.\n    \"\"\"\n    return distance / time\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n    \"\"\"\n    return distance / time\n
        ","tags":["DOC502"]},{"location":"rules/docstring-extraneous-exception/#known-issues","title":"Known issues","text":"

        It may often be desirable to document all exceptions that a function could possibly raise, even those which are not explicitly raised using raise statements in the function body.

        ","tags":["DOC502"]},{"location":"rules/docstring-extraneous-returns/","title":"docstring-extraneous-returns (DOC202)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC202"]},{"location":"rules/docstring-extraneous-returns/#what-it-does","title":"What it does","text":"

        Checks for function docstrings with unnecessary \"Returns\" sections.

        ","tags":["DOC202"]},{"location":"rules/docstring-extraneous-returns/#why-is-this-bad","title":"Why is this bad?","text":"

        A function without an explicit return statement should not have a \"Returns\" section in its docstring.

        This rule is not enforced for abstract methods. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC202"]},{"location":"rules/docstring-extraneous-returns/#example","title":"Example","text":"
        def say_hello(n: int) -> None:\n    \"\"\"Says hello to the user.\n\n    Args:\n        n: Number of times to say hello.\n\n    Returns:\n        Doesn't return anything.\n    \"\"\"\n    for _ in range(n):\n        print(\"Hello!\")\n

        Use instead:

        def say_hello(n: int) -> None:\n    \"\"\"Says hello to the user.\n\n    Args:\n        n: Number of times to say hello.\n    \"\"\"\n    for _ in range(n):\n        print(\"Hello!\")\n
        ","tags":["DOC202"]},{"location":"rules/docstring-extraneous-yields/","title":"docstring-extraneous-yields (DOC403)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC403"]},{"location":"rules/docstring-extraneous-yields/#what-it-does","title":"What it does","text":"

        Checks for function docstrings with unnecessary \"Yields\" sections.

        ","tags":["DOC403"]},{"location":"rules/docstring-extraneous-yields/#why-is-this-bad","title":"Why is this bad?","text":"

        A function that doesn't yield anything should not have a \"Yields\" section in its docstring.

        This rule is not enforced for abstract methods. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC403"]},{"location":"rules/docstring-extraneous-yields/#example","title":"Example","text":"
        def say_hello(n: int) -> None:\n    \"\"\"Says hello to the user.\n\n    Args:\n        n: Number of times to say hello.\n\n    Yields:\n        Doesn't yield anything.\n    \"\"\"\n    for _ in range(n):\n        print(\"Hello!\")\n

        Use instead:

        def say_hello(n: int) -> None:\n    \"\"\"Says hello to the user.\n\n    Args:\n        n: Number of times to say hello.\n    \"\"\"\n    for _ in range(n):\n        print(\"Hello!\")\n
        ","tags":["DOC403"]},{"location":"rules/docstring-in-stub/","title":"docstring-in-stub (PYI021)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI021"]},{"location":"rules/docstring-in-stub/#what-it-does","title":"What it does","text":"

        Checks for the presence of docstrings in stub files.

        ","tags":["PYI021"]},{"location":"rules/docstring-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files should omit docstrings, as they're intended to provide type hints, rather than documentation.

        ","tags":["PYI021"]},{"location":"rules/docstring-in-stub/#example","title":"Example","text":"
        def func(param: int) -> str:\n    \"\"\"This is a docstring.\"\"\"\n    ...\n

        Use instead:

        def func(param: int) -> str: ...\n
        ","tags":["PYI021"]},{"location":"rules/docstring-missing-exception/","title":"docstring-missing-exception (DOC501)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC501"]},{"location":"rules/docstring-missing-exception/#what-it-does","title":"What it does","text":"

        Checks for function docstrings that do not document all explicitly raised exceptions.

        ","tags":["DOC501"]},{"location":"rules/docstring-missing-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        A function should document all exceptions that are directly raised in some circumstances. Failing to document an exception that could be raised can be misleading to users and/or a sign of incomplete documentation.

        This rule is not enforced for abstract methods. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC501"]},{"location":"rules/docstring-missing-exception/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["DOC501"]},{"location":"rules/docstring-missing-returns/","title":"docstring-missing-returns (DOC201)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC201"]},{"location":"rules/docstring-missing-returns/#what-it-does","title":"What it does","text":"

        Checks for functions with return statements that do not have \"Returns\" sections in their docstrings.

        ","tags":["DOC201"]},{"location":"rules/docstring-missing-returns/#why-is-this-bad","title":"Why is this bad?","text":"

        A missing \"Returns\" section is a sign of incomplete documentation.

        This rule is not enforced for abstract methods or functions that only return None. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC201"]},{"location":"rules/docstring-missing-returns/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n    \"\"\"\n    return distance / time\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n    \"\"\"\n    return distance / time\n
        ","tags":["DOC201"]},{"location":"rules/docstring-missing-yields/","title":"docstring-missing-yields (DOC402)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC402"]},{"location":"rules/docstring-missing-yields/#what-it-does","title":"What it does","text":"

        Checks for functions with yield statements that do not have \"Yields\" sections in their docstrings.

        ","tags":["DOC402"]},{"location":"rules/docstring-missing-yields/#why-is-this-bad","title":"Why is this bad?","text":"

        A missing \"Yields\" section is a sign of incomplete documentation.

        This rule is not enforced for abstract methods or functions that only yield None. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC402"]},{"location":"rules/docstring-missing-yields/#example","title":"Example","text":"
        def count_to_n(n: int) -> int:\n    \"\"\"Generate integers up to *n*.\n\n    Args:\n        n: The number at which to stop counting.\n    \"\"\"\n    for i in range(1, n + 1):\n        yield i\n

        Use instead:

        def count_to_n(n: int) -> int:\n    \"\"\"Generate integers up to *n*.\n\n    Args:\n        n: The number at which to stop counting.\n\n    Yields:\n        int: The number we're at in the count.\n    \"\"\"\n    for i in range(1, n + 1):\n        yield i\n
        ","tags":["DOC402"]},{"location":"rules/docstring-starts-with-this/","title":"docstring-starts-with-this (D404)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D404"]},{"location":"rules/docstring-starts-with-this/#what-it-does","title":"What it does","text":"

        Checks for docstrings that start with This.

        ","tags":["D404"]},{"location":"rules/docstring-starts-with-this/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that the first line of a docstring be written in the imperative mood, for consistency.

        Hint: to rewrite the docstring in the imperative, phrase the first line as if it were a command.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the numpy convention,, and disabled when using the google and pep257 conventions.

        ","tags":["D404"]},{"location":"rules/docstring-starts-with-this/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"This function returns the mean of the given values.\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D404"]},{"location":"rules/docstring-starts-with-this/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D404"]},{"location":"rules/docstring-starts-with-this/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        ","tags":["D404"]},{"location":"rules/docstring-tab-indentation/","title":"docstring-tab-indentation (D206)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D206"]},{"location":"rules/docstring-tab-indentation/#what-it-does","title":"What it does","text":"

        Checks for docstrings that are indented with tabs.

        ","tags":["D206"]},{"location":"rules/docstring-tab-indentation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends using spaces over tabs for indentation.

        ","tags":["D206"]},{"location":"rules/docstring-tab-indentation/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D206"]},{"location":"rules/docstring-tab-indentation/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        The rule is also incompatible with the formatter when using format.indent-style=\"tab\".

        ","tags":["D206"]},{"location":"rules/docstring-tab-indentation/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D206"]},{"location":"rules/dot-format-in-exception/","title":"dot-format-in-exception (EM103)","text":"

        Derived from the flake8-errmsg linter.

        Fix is sometimes available.

        ","tags":["EM103"]},{"location":"rules/dot-format-in-exception/#what-it-does","title":"What it does","text":"

        Checks for the use of .format calls on string literals in exception constructors.

        ","tags":["EM103"]},{"location":"rules/dot-format-in-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Python includes the raise in the default traceback (and formatters like Rich and IPython do too).

        By using a .format call, the error message will be duplicated in the traceback, which can make the traceback less readable.

        ","tags":["EM103"]},{"location":"rules/dot-format-in-exception/#example","title":"Example","text":"

        Given:

        sub = \"Some value\"\nraise RuntimeError(\"'{}' is incorrect\".format(sub))\n

        Python will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 2, in <module>\n    raise RuntimeError(\"'{}' is incorrect\".format(sub))\nRuntimeError: 'Some value' is incorrect\n

        Instead, assign the string to a variable:

        sub = \"Some value\"\nmsg = \"'{}' is incorrect\".format(sub)\nraise RuntimeError(msg)\n

        Which will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 3, in <module>\n    raise RuntimeError(msg)\nRuntimeError: 'Some value' is incorrect\n
        ","tags":["EM103"]},{"location":"rules/double-negation/","title":"double-negation (SIM208)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM208"]},{"location":"rules/double-negation/#what-it-does","title":"What it does","text":"

        Checks for double negations (i.e., multiple not operators).

        ","tags":["SIM208"]},{"location":"rules/double-negation/#why-is-this-bad","title":"Why is this bad?","text":"

        A double negation is redundant and less readable than omitting the not operators entirely.

        ","tags":["SIM208"]},{"location":"rules/double-negation/#example","title":"Example","text":"
        not (not a)\n

        Use instead:

        a\n
        ","tags":["SIM208"]},{"location":"rules/double-negation/#references","title":"References","text":"
        • Python documentation: Comparisons
        ","tags":["SIM208"]},{"location":"rules/dunder-function-name/","title":"dunder-function-name (N807)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N807"]},{"location":"rules/dunder-function-name/#what-it-does","title":"What it does","text":"

        Checks for functions with \"dunder\" names (that is, names with two leading and trailing underscores) that are not documented.

        ","tags":["N807"]},{"location":"rules/dunder-function-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that only documented \"dunder\" methods are used:

        ...\"magic\" objects or attributes that live in user-controlled namespaces. E.g. __init__, __import__ or __file__. Never invent such names; only use them as documented.

        ","tags":["N807"]},{"location":"rules/dunder-function-name/#example","title":"Example","text":"
        def __my_function__():\n    pass\n

        Use instead:

        def my_function():\n    pass\n
        ","tags":["N807"]},{"location":"rules/dunder-function-name/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N807"]},{"location":"rules/duplicate-bases/","title":"duplicate-bases (PLE0241)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE0241"]},{"location":"rules/duplicate-bases/#what-it-does","title":"What it does","text":"

        Checks for duplicate base classes in class definitions.

        ","tags":["PLE0241"]},{"location":"rules/duplicate-bases/#why-is-this-bad","title":"Why is this bad?","text":"

        Including duplicate base classes will raise a TypeError at runtime.

        ","tags":["PLE0241"]},{"location":"rules/duplicate-bases/#example","title":"Example","text":"
        class Foo:\n    pass\n\n\nclass Bar(Foo, Foo):\n    pass\n

        Use instead:

        class Foo:\n    pass\n\n\nclass Bar(Foo):\n    pass\n
        ","tags":["PLE0241"]},{"location":"rules/duplicate-bases/#references","title":"References","text":"
        • Python documentation: Class definitions
        ","tags":["PLE0241"]},{"location":"rules/duplicate-class-field-definition/","title":"duplicate-class-field-definition (PIE794)","text":"

        Derived from the flake8-pie linter.

        Fix is always available.

        ","tags":["PIE794"]},{"location":"rules/duplicate-class-field-definition/#what-it-does","title":"What it does","text":"

        Checks for duplicate field definitions in classes.

        ","tags":["PIE794"]},{"location":"rules/duplicate-class-field-definition/#why-is-this-bad","title":"Why is this bad?","text":"

        Defining a field multiple times in a class body is redundant and likely a mistake.

        ","tags":["PIE794"]},{"location":"rules/duplicate-class-field-definition/#example","title":"Example","text":"
        class Person:\n    name = Tom\n    ...\n    name = Ben\n

        Use instead:

        class Person:\n    name = Tom\n    ...\n
        ","tags":["PIE794"]},{"location":"rules/duplicate-handler-exception/","title":"duplicate-handler-exception (B014)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B014"]},{"location":"rules/duplicate-handler-exception/#what-it-does","title":"What it does","text":"

        Checks for exception handlers that catch duplicate exceptions.

        ","tags":["B014"]},{"location":"rules/duplicate-handler-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Including the same exception multiple times in the same handler is redundant, as the first exception will catch the exception, making the second exception unreachable. The same applies to exception hierarchies, as a handler for a parent exception (like Exception) will also catch child exceptions (like ValueError).

        ","tags":["B014"]},{"location":"rules/duplicate-handler-exception/#example","title":"Example","text":"
        try:\n    ...\nexcept (Exception, ValueError):  # `Exception` includes `ValueError`.\n    ...\n

        Use instead:

        try:\n    ...\nexcept Exception:\n    ...\n
        ","tags":["B014"]},{"location":"rules/duplicate-handler-exception/#references","title":"References","text":"
        • Python documentation: except clause
        • Python documentation: Exception hierarchy
        ","tags":["B014"]},{"location":"rules/duplicate-isinstance-call/","title":"duplicate-isinstance-call (SIM101)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM101"]},{"location":"rules/duplicate-isinstance-call/#what-it-does","title":"What it does","text":"

        Checks for multiple isinstance calls on the same target.

        ","tags":["SIM101"]},{"location":"rules/duplicate-isinstance-call/#why-is-this-bad","title":"Why is this bad?","text":"

        To check if an object is an instance of any one of multiple types or classes, it is unnecessary to use multiple isinstance calls, as the second argument of the isinstance built-in function accepts a tuple of types and classes.

        Using a single isinstance call implements the same behavior with more concise code and clearer intent.

        ","tags":["SIM101"]},{"location":"rules/duplicate-isinstance-call/#example","title":"Example","text":"
        if isinstance(obj, int) or isinstance(obj, float):\n    pass\n

        Use instead:

        if isinstance(obj, (int, float)):\n    pass\n
        ","tags":["SIM101"]},{"location":"rules/duplicate-isinstance-call/#references","title":"References","text":"
        • Python documentation: isinstance
        ","tags":["SIM101"]},{"location":"rules/duplicate-literal-member/","title":"duplicate-literal-member (PYI062)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI062"]},{"location":"rules/duplicate-literal-member/#what-it-does","title":"What it does","text":"

        Checks for duplicate members in a typing.Literal[] slice.

        ","tags":["PYI062"]},{"location":"rules/duplicate-literal-member/#why-is-this-bad","title":"Why is this bad?","text":"

        Duplicate literal members are redundant and should be removed.

        ","tags":["PYI062"]},{"location":"rules/duplicate-literal-member/#example","title":"Example","text":"
        foo: Literal[\"a\", \"b\", \"a\"]\n

        Use instead:

        foo: Literal[\"a\", \"b\"]\n
        ","tags":["PYI062"]},{"location":"rules/duplicate-literal-member/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the type annotation contains comments.

        Note that while the fix may flatten nested literals into a single top-level literal, the semantics of the annotation will remain unchanged.

        ","tags":["PYI062"]},{"location":"rules/duplicate-literal-member/#references","title":"References","text":"
        • Python documentation: typing.Literal
        ","tags":["PYI062"]},{"location":"rules/duplicate-try-block-exception/","title":"duplicate-try-block-exception (B025)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B025"]},{"location":"rules/duplicate-try-block-exception/#what-it-does","title":"What it does","text":"

        Checks for try-except blocks with duplicate exception handlers.

        ","tags":["B025"]},{"location":"rules/duplicate-try-block-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Duplicate exception handlers are redundant, as the first handler will catch the exception, making the second handler unreachable.

        ","tags":["B025"]},{"location":"rules/duplicate-try-block-exception/#example","title":"Example","text":"
        try:\n    ...\nexcept ValueError:\n    ...\nexcept ValueError:\n    ...\n

        Use instead:

        try:\n    ...\nexcept ValueError:\n    ...\n
        ","tags":["B025"]},{"location":"rules/duplicate-try-block-exception/#references","title":"References","text":"
        • Python documentation: except clause
        ","tags":["B025"]},{"location":"rules/duplicate-union-member/","title":"duplicate-union-member (PYI016)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI016"]},{"location":"rules/duplicate-union-member/#what-it-does","title":"What it does","text":"

        Checks for duplicate union members.

        ","tags":["PYI016"]},{"location":"rules/duplicate-union-member/#why-is-this-bad","title":"Why is this bad?","text":"

        Duplicate union members are redundant and should be removed.

        ","tags":["PYI016"]},{"location":"rules/duplicate-union-member/#example","title":"Example","text":"
        foo: str | str\n

        Use instead:

        foo: str\n
        ","tags":["PYI016"]},{"location":"rules/duplicate-union-member/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe unless the union contains comments.

        For nested union, the fix will flatten type expressions into a single top-level union.

        ","tags":["PYI016"]},{"location":"rules/duplicate-union-member/#references","title":"References","text":"
        • Python documentation: typing.Union
        ","tags":["PYI016"]},{"location":"rules/duplicate-value/","title":"duplicate-value (B033)","text":"

        Derived from the flake8-bugbear linter.

        Fix is sometimes available.

        ","tags":["B033"]},{"location":"rules/duplicate-value/#what-it-does","title":"What it does","text":"

        Checks for set literals that contain duplicate items.

        ","tags":["B033"]},{"location":"rules/duplicate-value/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, sets are unordered collections of unique elements. Including a duplicate item in a set literal is redundant, as the duplicate item will be replaced with a single item at runtime.

        ","tags":["B033"]},{"location":"rules/duplicate-value/#example","title":"Example","text":"
        {1, 2, 3, 1}\n

        Use instead:

        {1, 2, 3}\n
        ","tags":["B033"]},{"location":"rules/ellipsis-in-non-empty-class-body/","title":"ellipsis-in-non-empty-class-body (PYI013)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI013"]},{"location":"rules/ellipsis-in-non-empty-class-body/#what-it-does","title":"What it does","text":"

        Removes ellipses (...) in otherwise non-empty class bodies.

        ","tags":["PYI013"]},{"location":"rules/ellipsis-in-non-empty-class-body/#why-is-this-bad","title":"Why is this bad?","text":"

        An ellipsis in a class body is only necessary if the class body is otherwise empty. If the class body is non-empty, then the ellipsis is redundant.

        ","tags":["PYI013"]},{"location":"rules/ellipsis-in-non-empty-class-body/#example","title":"Example","text":"
        class Foo:\n    ...\n    value: int\n

        Use instead:

        class Foo:\n    value: int\n
        ","tags":["PYI013"]},{"location":"rules/empty-comment/","title":"empty-comment (PLR2044)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLR2044"]},{"location":"rules/empty-comment/#what-it-does","title":"What it does","text":"

        Checks for a # symbol appearing on a line not followed by an actual comment.

        ","tags":["PLR2044"]},{"location":"rules/empty-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Empty comments don't provide any clarity to the code, and just add clutter. Either add a comment or delete the empty comment.

        ","tags":["PLR2044"]},{"location":"rules/empty-comment/#example","title":"Example","text":"
        class Foo:  #\n    pass\n

        Use instead:

        class Foo:\n    pass\n
        ","tags":["PLR2044"]},{"location":"rules/empty-comment/#references","title":"References","text":"
        • Pylint documentation
        ","tags":["PLR2044"]},{"location":"rules/empty-docstring-section/","title":"empty-docstring-section (D414)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D414"]},{"location":"rules/empty-docstring-section/#what-it-does","title":"What it does","text":"

        Checks for docstrings with empty sections.

        ","tags":["D414"]},{"location":"rules/empty-docstring-section/#why-is-this-bad","title":"Why is this bad?","text":"

        An empty section in a multiline docstring likely indicates an unfinished or incomplete docstring.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. Each section body should be non-empty; empty sections should either have content added to them, or be removed entirely.

        ","tags":["D414"]},{"location":"rules/empty-docstring-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D414"]},{"location":"rules/empty-docstring-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Guide
        ","tags":["D414"]},{"location":"rules/empty-docstring/","title":"empty-docstring (D419)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D419"]},{"location":"rules/empty-docstring/#what-it-does","title":"What it does","text":"

        Checks for empty docstrings.

        ","tags":["D419"]},{"location":"rules/empty-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        An empty docstring is indicative of incomplete documentation. It should either be removed or replaced with a meaningful docstring.

        ","tags":["D419"]},{"location":"rules/empty-docstring/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D419"]},{"location":"rules/empty-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D419"]},{"location":"rules/empty-method-without-abstract-decorator/","title":"empty-method-without-abstract-decorator (B027)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B027"]},{"location":"rules/empty-method-without-abstract-decorator/#what-it-does","title":"What it does","text":"

        Checks for empty methods in abstract base classes without an abstract decorator.

        ","tags":["B027"]},{"location":"rules/empty-method-without-abstract-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        Empty methods in abstract base classes without an abstract decorator may be be indicative of a mistake. If the method is meant to be abstract, add an @abstractmethod decorator to the method.

        ","tags":["B027"]},{"location":"rules/empty-method-without-abstract-decorator/#example","title":"Example","text":"
        from abc import ABC\n\n\nclass Foo(ABC):\n    def method(self): ...\n

        Use instead:

        from abc import ABC, abstractmethod\n\n\nclass Foo(ABC):\n    @abstractmethod\n    def method(self): ...\n
        ","tags":["B027"]},{"location":"rules/empty-method-without-abstract-decorator/#references","title":"References","text":"
        • Python documentation: abc
        ","tags":["B027"]},{"location":"rules/empty-type-checking-block/","title":"empty-type-checking-block (TC005)","text":"

        Derived from the flake8-type-checking linter.

        Fix is always available.

        ","tags":["TC005"]},{"location":"rules/empty-type-checking-block/#what-it-does","title":"What it does","text":"

        Checks for an empty type-checking block.

        ","tags":["TC005"]},{"location":"rules/empty-type-checking-block/#why-is-this-bad","title":"Why is this bad?","text":"

        The type-checking block does not do anything and should be removed to avoid confusion.

        ","tags":["TC005"]},{"location":"rules/empty-type-checking-block/#example","title":"Example","text":"
        from typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    pass\n\nprint(\"Hello, world!\")\n

        Use instead:

        print(\"Hello, world!\")\n
        ","tags":["TC005"]},{"location":"rules/empty-type-checking-block/#references","title":"References","text":"
        • PEP 563: Runtime annotation resolution and TYPE_CHECKING
        ","tags":["TC005"]},{"location":"rules/enumerate-for-loop/","title":"enumerate-for-loop (SIM113)","text":"

        Derived from the flake8-simplify linter.

        ","tags":["SIM113"]},{"location":"rules/enumerate-for-loop/#what-it-does","title":"What it does","text":"

        Checks for for loops with explicit loop-index variables that can be replaced with enumerate().

        ","tags":["SIM113"]},{"location":"rules/enumerate-for-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over a sequence, it's often desirable to keep track of the index of each element alongside the element itself. Prefer the enumerate builtin over manually incrementing a counter variable within the loop, as enumerate is more concise and idiomatic.

        ","tags":["SIM113"]},{"location":"rules/enumerate-for-loop/#example","title":"Example","text":"
        fruits = [\"apple\", \"banana\", \"cherry\"]\nfor fruit in fruits:\n    print(f\"{i + 1}. {fruit}\")\n    i += 1\n

        Use instead:

        fruits = [\"apple\", \"banana\", \"cherry\"]\nfor i, fruit in enumerate(fruits):\n    print(f\"{i + 1}. {fruit}\")\n
        ","tags":["SIM113"]},{"location":"rules/enumerate-for-loop/#references","title":"References","text":"
        • Python documentation: enumerate
        ","tags":["SIM113"]},{"location":"rules/eq-without-hash/","title":"eq-without-hash (PLW1641)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW1641"]},{"location":"rules/eq-without-hash/#what-it-does","title":"What it does","text":"

        Checks for classes that implement __eq__ but not __hash__.

        ","tags":["PLW1641"]},{"location":"rules/eq-without-hash/#why-is-this-bad","title":"Why is this bad?","text":"

        A class that implements __eq__ but not __hash__ will have its hash method implicitly set to None, regardless of if a super class defines __hash__. This will cause the class to be unhashable, will in turn cause issues when using the class as a key in a dictionary or a member of a set.

        ","tags":["PLW1641"]},{"location":"rules/eq-without-hash/#example","title":"Example","text":"
        class Person:\n    def __init__(self):\n        self.name = \"monty\"\n\n    def __eq__(self, other):\n        return isinstance(other, Person) and other.name == self.name\n

        Use instead:

        class Person:\n    def __init__(self):\n        self.name = \"monty\"\n\n    def __eq__(self, other):\n        return isinstance(other, Person) and other.name == self.name\n\n    def __hash__(self):\n        return hash(self.name)\n

        This issue is particularly tricky with inheritance. Even if a parent class correctly implements both __eq__ and __hash__, overriding __eq__ in a child class without also implementing __hash__ will make the child class unhashable:

        class Person:\n    def __init__(self):\n        self.name = \"monty\"\n\n    def __eq__(self, other):\n        return isinstance(other, Person) and other.name == self.name\n\n    def __hash__(self):\n        return hash(self.name)\n\n\nclass Developer(Person):\n    def __init__(self):\n        super().__init__()\n        self.language = \"python\"\n\n    def __eq__(self, other):\n        return (\n            super().__eq__(other)\n            and isinstance(other, Developer)\n            and self.language == other.language\n        )\n\n\nhash(Developer())  # TypeError: unhashable type: 'Developer'\n

        One way to fix this is to retain the implementation of __hash__ from the parent class:

        class Developer(Person):\n    def __init__(self):\n        super().__init__()\n        self.language = \"python\"\n\n    def __eq__(self, other):\n        return (\n            super().__eq__(other)\n            and isinstance(other, Developer)\n            and self.language == other.language\n        )\n\n    __hash__ = Person.__hash__\n
        ","tags":["PLW1641"]},{"location":"rules/eq-without-hash/#references","title":"References","text":"
        • Python documentation: object.__hash__
        • Python glossary: hashable
        ","tags":["PLW1641"]},{"location":"rules/error-instead-of-exception/","title":"error-instead-of-exception (TRY400)","text":"

        Derived from the tryceratops linter.

        Fix is sometimes available.

        ","tags":["TRY400"]},{"location":"rules/error-instead-of-exception/#what-it-does","title":"What it does","text":"

        Checks for uses of logging.error instead of logging.exception when logging an exception.

        ","tags":["TRY400"]},{"location":"rules/error-instead-of-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        logging.exception logs the exception and the traceback, while logging.error only logs the exception. The former is more appropriate when logging an exception, as the traceback is often useful for debugging.

        ","tags":["TRY400"]},{"location":"rules/error-instead-of-exception/#example","title":"Example","text":"
        import logging\n\n\ndef func():\n    try:\n        raise NotImplementedError\n    except NotImplementedError:\n        logging.error(\"Exception occurred\")\n

        Use instead:

        import logging\n\n\ndef func():\n    try:\n        raise NotImplementedError\n    except NotImplementedError:\n        logging.exception(\"Exception occurred\")\n
        ","tags":["TRY400"]},{"location":"rules/error-instead-of-exception/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe when run against logging.error calls, but unsafe when marked against other logger-like calls (e.g., logger.error), since the rule is prone to false positives when detecting logger-like calls outside of the logging module.

        ","tags":["TRY400"]},{"location":"rules/error-instead-of-exception/#references","title":"References","text":"
        • Python documentation: logging.exception
        ","tags":["TRY400"]},{"location":"rules/error-suffix-on-exception-name/","title":"error-suffix-on-exception-name (N818)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N818"]},{"location":"rules/error-suffix-on-exception-name/#what-it-does","title":"What it does","text":"

        Checks for custom exception definitions that omit the Error suffix.

        ","tags":["N818"]},{"location":"rules/error-suffix-on-exception-name/#why-is-this-bad","title":"Why is this bad?","text":"

        The Error suffix is recommended by PEP 8:

        Because exceptions should be classes, the class naming convention applies here. However, you should use the suffix \"Error\" on your exception names (if the exception actually is an error).

        ","tags":["N818"]},{"location":"rules/error-suffix-on-exception-name/#example","title":"Example","text":"
        class Validation(Exception): ...\n

        Use instead:

        class ValidationError(Exception): ...\n
        ","tags":["N818"]},{"location":"rules/error-suffix-on-exception-name/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N818"]},{"location":"rules/escape-sequence-in-docstring/","title":"escape-sequence-in-docstring (D301)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D301"]},{"location":"rules/escape-sequence-in-docstring/#what-it-does","title":"What it does","text":"

        Checks for docstrings that include backslashes, but are not defined as raw string literals.

        ","tags":["D301"]},{"location":"rules/escape-sequence-in-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, backslashes are typically used to escape characters in strings. In raw strings (those prefixed with an r), however, backslashes are treated as literal characters.

        PEP 257 recommends the use of raw strings (i.e., r\"\"\"raw triple double quotes\"\"\") for docstrings that include backslashes. The use of a raw string ensures that any backslashes are treated as literal characters, and not as escape sequences, which avoids confusion.

        ","tags":["D301"]},{"location":"rules/escape-sequence-in-docstring/#example","title":"Example","text":"
        def foobar():\n    \"\"\"Docstring for foo\\bar.\"\"\"\n\n\nfoobar.__doc__  # \"Docstring for foar.\"\n

        Use instead:

        def foobar():\n    r\"\"\"Docstring for foo\\bar.\"\"\"\n\n\nfoobar.__doc__  # \"Docstring for foo\\bar.\"\n
        ","tags":["D301"]},{"location":"rules/escape-sequence-in-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • Python documentation: String and Bytes literals
        ","tags":["D301"]},{"location":"rules/eval/","title":"eval (PGH001)","text":"

        Derived from the pygrep-hooks linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["PGH001"]},{"location":"rules/eval/#removed","title":"Removed","text":"

        This rule is identical to S307 which should be used instead.

        ","tags":["PGH001"]},{"location":"rules/eval/#what-it-does","title":"What it does","text":"

        Checks for uses of the builtin eval() function.

        ","tags":["PGH001"]},{"location":"rules/eval/#why-is-this-bad","title":"Why is this bad?","text":"

        The eval() function is insecure as it enables arbitrary code execution.

        ","tags":["PGH001"]},{"location":"rules/eval/#example","title":"Example","text":"
        def foo():\n    x = eval(input(\"Enter a number: \"))\n    ...\n

        Use instead:

        def foo():\n    x = input(\"Enter a number: \")\n    ...\n
        ","tags":["PGH001"]},{"location":"rules/eval/#references","title":"References","text":"
        • Python documentation: eval
        • Eval really is dangerous by Ned Batchelder
        ","tags":["PGH001"]},{"location":"rules/exc-info-outside-except-handler/","title":"exc-info-outside-except-handler (LOG014)","text":"

        Derived from the flake8-logging linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["LOG014"]},{"location":"rules/exc-info-outside-except-handler/#what-it-does","title":"What it does","text":"

        Checks for logging calls with exc_info= outside exception handlers.

        ","tags":["LOG014"]},{"location":"rules/exc-info-outside-except-handler/#why-is-this-bad","title":"Why is this bad?","text":"

        Using exc_info=True outside of an exception handler attaches None as the exception information, leading to confusing messages:

        >>> logging.warning(\"Uh oh\", exc_info=True)\nWARNING:root:Uh oh\nNoneType: None\n
        ","tags":["LOG014"]},{"location":"rules/exc-info-outside-except-handler/#example","title":"Example","text":"
        import logging\n\n\nlogging.warning(\"Foobar\", exc_info=True)\n

        Use instead:

        import logging\n\n\nlogging.warning(\"Foobar\")\n
        ","tags":["LOG014"]},{"location":"rules/exc-info-outside-except-handler/#fix-safety","title":"Fix safety","text":"

        The fix is always marked as unsafe, as it changes runtime behavior.

        ","tags":["LOG014"]},{"location":"rules/except-with-empty-tuple/","title":"except-with-empty-tuple (B029)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B029"]},{"location":"rules/except-with-empty-tuple/#what-it-does","title":"What it does","text":"

        Checks for exception handlers that catch an empty tuple.

        ","tags":["B029"]},{"location":"rules/except-with-empty-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        An exception handler that catches an empty tuple will not catch anything, and is indicative of a mistake. Instead, add exceptions to the except clause.

        ","tags":["B029"]},{"location":"rules/except-with-empty-tuple/#example","title":"Example","text":"
        try:\n    1 / 0\nexcept ():\n    ...\n

        Use instead:

        try:\n    1 / 0\nexcept ZeroDivisionError:\n    ...\n
        ","tags":["B029"]},{"location":"rules/except-with-empty-tuple/#references","title":"References","text":"
        • Python documentation: except clause
        ","tags":["B029"]},{"location":"rules/except-with-non-exception-classes/","title":"except-with-non-exception-classes (B030)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B030"]},{"location":"rules/except-with-non-exception-classes/#what-it-does","title":"What it does","text":"

        Checks for exception handlers that catch non-exception classes.

        ","tags":["B030"]},{"location":"rules/except-with-non-exception-classes/#why-is-this-bad","title":"Why is this bad?","text":"

        Catching classes that do not inherit from BaseException will raise a TypeError.

        ","tags":["B030"]},{"location":"rules/except-with-non-exception-classes/#example","title":"Example","text":"
        try:\n    1 / 0\nexcept 1:\n    ...\n

        Use instead:

        try:\n    1 / 0\nexcept ZeroDivisionError:\n    ...\n
        ","tags":["B030"]},{"location":"rules/except-with-non-exception-classes/#references","title":"References","text":"
        • Python documentation: except clause
        • Python documentation: Built-in Exceptions
        ","tags":["B030"]},{"location":"rules/exception-without-exc-info/","title":"exception-without-exc-info (LOG007)","text":"

        Derived from the flake8-logging linter.

        ","tags":["LOG007"]},{"location":"rules/exception-without-exc-info/#what-it-does","title":"What it does","text":"

        Checks for uses of logging.exception() with exc_info set to False.

        ","tags":["LOG007"]},{"location":"rules/exception-without-exc-info/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging.exception() method captures the exception automatically, but accepts an optional exc_info argument to override this behavior. Setting exc_info to False disables the automatic capture of the exception and stack trace.

        Instead of setting exc_info to False, prefer logging.error(), which has equivalent behavior to logging.exception() with exc_info set to False, but is clearer in intent.

        ","tags":["LOG007"]},{"location":"rules/exception-without-exc-info/#example","title":"Example","text":"
        logging.exception(\"...\", exc_info=False)\n

        Use instead:

        logging.error(\"...\")\n
        ","tags":["LOG007"]},{"location":"rules/exec-builtin/","title":"exec-builtin (S102)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S102"]},{"location":"rules/exec-builtin/#what-it-does","title":"What it does","text":"

        Checks for uses of the builtin exec function.

        ","tags":["S102"]},{"location":"rules/exec-builtin/#why-is-this-bad","title":"Why is this bad?","text":"

        The exec() function is insecure as it allows for arbitrary code execution.

        ","tags":["S102"]},{"location":"rules/exec-builtin/#example","title":"Example","text":"
        exec(\"print('Hello World')\")\n
        ","tags":["S102"]},{"location":"rules/exec-builtin/#references","title":"References","text":"
        • Python documentation: exec
        • Common Weakness Enumeration: CWE-78
        ","tags":["S102"]},{"location":"rules/explicit-f-string-type-conversion/","title":"explicit-f-string-type-conversion (RUF010)","text":"

        Fix is always available.

        ","tags":["RUF010"]},{"location":"rules/explicit-f-string-type-conversion/#what-it-does","title":"What it does","text":"

        Checks for uses of str(), repr(), and ascii() as explicit type conversions within f-strings.

        ","tags":["RUF010"]},{"location":"rules/explicit-f-string-type-conversion/#why-is-this-bad","title":"Why is this bad?","text":"

        f-strings support dedicated conversion flags for these types, which are more succinct and idiomatic.

        Note that, in many cases, calling str() within an f-string is unnecessary and can be removed entirely, as the value will be converted to a string automatically, the notable exception being for classes that implement a custom __format__ method.

        ","tags":["RUF010"]},{"location":"rules/explicit-f-string-type-conversion/#example","title":"Example","text":"
        a = \"some string\"\nf\"{repr(a)}\"\n

        Use instead:

        a = \"some string\"\nf\"{a!r}\"\n
        ","tags":["RUF010"]},{"location":"rules/explicit-string-concatenation/","title":"explicit-string-concatenation (ISC003)","text":"

        Derived from the flake8-implicit-str-concat linter.

        ","tags":["ISC003"]},{"location":"rules/explicit-string-concatenation/#what-it-does","title":"What it does","text":"

        Checks for string literals that are explicitly concatenated (using the + operator).

        ","tags":["ISC003"]},{"location":"rules/explicit-string-concatenation/#why-is-this-bad","title":"Why is this bad?","text":"

        For string literals that wrap across multiple lines, implicit string concatenation within parentheses is preferred over explicit concatenation using the + operator, as the former is more readable.

        ","tags":["ISC003"]},{"location":"rules/explicit-string-concatenation/#example","title":"Example","text":"
        z = (\n    \"The quick brown fox jumps over the lazy \"\n    + \"dog\"\n)\n

        Use instead:

        z = (\n    \"The quick brown fox jumps over the lazy \"\n    \"dog\"\n)\n
        ","tags":["ISC003"]},{"location":"rules/expr-and-false/","title":"expr-and-false (SIM223)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM223"]},{"location":"rules/expr-and-false/#what-it-does","title":"What it does","text":"

        Checks for and expressions that contain falsey values.

        ","tags":["SIM223"]},{"location":"rules/expr-and-false/#why-is-this-bad","title":"Why is this bad?","text":"

        If the expression is used as a condition, it can be replaced in-full with False.

        In other cases, the expression can be short-circuited to the first falsey value.

        By using False (or the first falsey value), the code is more concise and easier to understand, since it no longer contains redundant conditions.

        ","tags":["SIM223"]},{"location":"rules/expr-and-false/#example","title":"Example","text":"
        if x and [] and y:\n    pass\n\na = x and [] and y\n

        Use instead:

        if False:\n    pass\n\na = x and []\n
        ","tags":["SIM223"]},{"location":"rules/expr-and-not-expr/","title":"expr-and-not-expr (SIM220)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM220"]},{"location":"rules/expr-and-not-expr/#what-it-does","title":"What it does","text":"

        Checks for and expressions that include both an expression and its negation.

        ","tags":["SIM220"]},{"location":"rules/expr-and-not-expr/#why-is-this-bad","title":"Why is this bad?","text":"

        An and expression that includes both an expression and its negation will always evaluate to False.

        ","tags":["SIM220"]},{"location":"rules/expr-and-not-expr/#example","title":"Example","text":"
        x and not x\n
        ","tags":["SIM220"]},{"location":"rules/expr-and-not-expr/#references","title":"References","text":"
        • Python documentation: Boolean operations
        ","tags":["SIM220"]},{"location":"rules/expr-or-not-expr/","title":"expr-or-not-expr (SIM221)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM221"]},{"location":"rules/expr-or-not-expr/#what-it-does","title":"What it does","text":"

        Checks for or expressions that include both an expression and its negation.

        ","tags":["SIM221"]},{"location":"rules/expr-or-not-expr/#why-is-this-bad","title":"Why is this bad?","text":"

        An or expression that includes both an expression and its negation will always evaluate to True.

        ","tags":["SIM221"]},{"location":"rules/expr-or-not-expr/#example","title":"Example","text":"
        x or not x\n
        ","tags":["SIM221"]},{"location":"rules/expr-or-not-expr/#references","title":"References","text":"
        • Python documentation: Boolean operations
        ","tags":["SIM221"]},{"location":"rules/expr-or-true/","title":"expr-or-true (SIM222)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM222"]},{"location":"rules/expr-or-true/#what-it-does","title":"What it does","text":"

        Checks for or expressions that contain truthy values.

        ","tags":["SIM222"]},{"location":"rules/expr-or-true/#why-is-this-bad","title":"Why is this bad?","text":"

        If the expression is used as a condition, it can be replaced in-full with True.

        In other cases, the expression can be short-circuited to the first truthy value.

        By using True (or the first truthy value), the code is more concise and easier to understand, since it no longer contains redundant conditions.

        ","tags":["SIM222"]},{"location":"rules/expr-or-true/#example","title":"Example","text":"
        if x or [1] or y:\n    pass\n\na = x or [1] or y\n

        Use instead:

        if True:\n    pass\n\na = x or [1]\n
        ","tags":["SIM222"]},{"location":"rules/expressions-in-star-assignment/","title":"expressions-in-star-assignment (F621)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F621"]},{"location":"rules/expressions-in-star-assignment/#what-it-does","title":"What it does","text":"

        Checks for the use of too many expressions in starred assignment statements.

        ","tags":["F621"]},{"location":"rules/expressions-in-star-assignment/#why-is-this-bad","title":"Why is this bad?","text":"

        In assignment statements, starred expressions can be used to unpack iterables.

        In Python 3, no more than 1 \\<< 8 assignments are allowed before a starred expression, and no more than 1 \\<< 24 expressions are allowed after a starred expression.

        ","tags":["F621"]},{"location":"rules/expressions-in-star-assignment/#references","title":"References","text":"
        • PEP 3132 \u2013 Extended Iterable Unpacking
        ","tags":["F621"]},{"location":"rules/extraneous-parentheses/","title":"extraneous-parentheses (UP034)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP034"]},{"location":"rules/extraneous-parentheses/#what-it-does","title":"What it does","text":"

        Checks for extraneous parentheses.

        ","tags":["UP034"]},{"location":"rules/extraneous-parentheses/#why-is-this-bad","title":"Why is this bad?","text":"

        Extraneous parentheses are redundant, and can be removed to improve readability while retaining identical semantics.

        ","tags":["UP034"]},{"location":"rules/extraneous-parentheses/#example","title":"Example","text":"
        print((\"Hello, world\"))\n

        Use instead:

        print(\"Hello, world\")\n
        ","tags":["UP034"]},{"location":"rules/f-string-docstring/","title":"f-string-docstring (B021)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B021"]},{"location":"rules/f-string-docstring/#what-it-does","title":"What it does","text":"

        Checks for docstrings that are written via f-strings.

        ","tags":["B021"]},{"location":"rules/f-string-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        Python will interpret the f-string as a joined string, rather than as a docstring. As such, the \"docstring\" will not be accessible via the __doc__ attribute, nor will it be picked up by any automated documentation tooling.

        ","tags":["B021"]},{"location":"rules/f-string-docstring/#example","title":"Example","text":"
        def foo():\n    f\"\"\"Not a docstring.\"\"\"\n

        Use instead:

        def foo():\n    \"\"\"A docstring.\"\"\"\n
        ","tags":["B021"]},{"location":"rules/f-string-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • Python documentation: Formatted string literals
        ","tags":["B021"]},{"location":"rules/f-string-in-exception/","title":"f-string-in-exception (EM102)","text":"

        Derived from the flake8-errmsg linter.

        Fix is sometimes available.

        ","tags":["EM102"]},{"location":"rules/f-string-in-exception/#what-it-does","title":"What it does","text":"

        Checks for the use of f-strings in exception constructors.

        ","tags":["EM102"]},{"location":"rules/f-string-in-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Python includes the raise in the default traceback (and formatters like Rich and IPython do too).

        By using an f-string, the error message will be duplicated in the traceback, which can make the traceback less readable.

        ","tags":["EM102"]},{"location":"rules/f-string-in-exception/#example","title":"Example","text":"

        Given:

        sub = \"Some value\"\nraise RuntimeError(f\"{sub!r} is incorrect\")\n

        Python will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 2, in <module>\n    raise RuntimeError(f\"{sub!r} is incorrect\")\nRuntimeError: 'Some value' is incorrect\n

        Instead, assign the string to a variable:

        sub = \"Some value\"\nmsg = f\"{sub!r} is incorrect\"\nraise RuntimeError(msg)\n

        Which will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 3, in <module>\n    raise RuntimeError(msg)\nRuntimeError: 'Some value' is incorrect\n
        ","tags":["EM102"]},{"location":"rules/f-string-in-get-text-func-call/","title":"f-string-in-get-text-func-call (INT001)","text":"

        Derived from the flake8-gettext linter.

        ","tags":["INT001"]},{"location":"rules/f-string-in-get-text-func-call/#what-it-does","title":"What it does","text":"

        Checks for f-strings in gettext function calls.

        ","tags":["INT001"]},{"location":"rules/f-string-in-get-text-func-call/#why-is-this-bad","title":"Why is this bad?","text":"

        In the gettext API, the gettext function (often aliased to _) returns a translation of its input argument by looking it up in a translation catalog.

        Calling gettext with an f-string as its argument can cause unexpected behavior. Since the f-string is resolved before the function call, the translation catalog will look up the formatted string, rather than the f-string template.

        Instead, format the value returned by the function call, rather than its argument.

        ","tags":["INT001"]},{"location":"rules/f-string-in-get-text-func-call/#example","title":"Example","text":"
        from gettext import gettext as _\n\nname = \"Maria\"\n_(f\"Hello, {name}!\")  # Looks for \"Hello, Maria!\".\n

        Use instead:

        from gettext import gettext as _\n\nname = \"Maria\"\n_(\"Hello, %s!\") % name  # Looks for \"Hello, %s!\".\n
        ","tags":["INT001"]},{"location":"rules/f-string-in-get-text-func-call/#references","title":"References","text":"
        • Python documentation: gettext \u2014 Multilingual internationalization services
        ","tags":["INT001"]},{"location":"rules/f-string-missing-placeholders/","title":"f-string-missing-placeholders (F541)","text":"

        Derived from the Pyflakes linter.

        Fix is always available.

        ","tags":["F541"]},{"location":"rules/f-string-missing-placeholders/#what-it-does","title":"What it does","text":"

        Checks for f-strings that do not contain any placeholder expressions.

        ","tags":["F541"]},{"location":"rules/f-string-missing-placeholders/#why-is-this-bad","title":"Why is this bad?","text":"

        f-strings are a convenient way to format strings, but they are not necessary if there are no placeholder expressions to format. In this case, a regular string should be used instead, as an f-string without placeholders can be confusing for readers, who may expect such a placeholder to be present.

        An f-string without any placeholders could also indicate that the author forgot to add a placeholder expression.

        ","tags":["F541"]},{"location":"rules/f-string-missing-placeholders/#example","title":"Example","text":"
        f\"Hello, world!\"\n

        Use instead:

        \"Hello, world!\"\n

        Note: to maintain compatibility with PyFlakes, this rule only flags f-strings that are part of an implicit concatenation if none of the f-string segments contain placeholder expressions.

        For example:

        # Will not be flagged.\n(\n    f\"Hello,\"\n    f\" {name}!\"\n)\n\n# Will be flagged.\n(\n    f\"Hello,\"\n    f\" World!\"\n)\n

        See #10885 for more.

        ","tags":["F541"]},{"location":"rules/f-string-missing-placeholders/#references","title":"References","text":"
        • PEP 498 \u2013 Literal String Interpolation
        ","tags":["F541"]},{"location":"rules/f-string-number-format/","title":"f-string-number-format (FURB116)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB116"]},{"location":"rules/f-string-number-format/#what-it-does","title":"What it does","text":"

        Checks for uses of bin(...)[2:] (or hex, or oct) to convert an integer into a string.

        ","tags":["FURB116"]},{"location":"rules/f-string-number-format/#why-is-this-bad","title":"Why is this bad?","text":"

        When converting an integer to a baseless binary, hexadecimal, or octal string, using f-strings is more concise and readable than using the bin, hex, or oct functions followed by a slice.

        ","tags":["FURB116"]},{"location":"rules/f-string-number-format/#example","title":"Example","text":"
        print(bin(1337)[2:])\n

        Use instead:

        print(f\"{1337:b}\")\n
        ","tags":["FURB116"]},{"location":"rules/f-string-number-format/#fix-safety","title":"Fix safety","text":"

        The fix is only marked as safe for integer literals, all other cases are display-only, as they may change the runtime behaviour of the program or introduce syntax errors.

        ","tags":["FURB116"]},{"location":"rules/f-string/","title":"f-string (UP032)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP032"]},{"location":"rules/f-string/#what-it-does","title":"What it does","text":"

        Checks for str.format calls that can be replaced with f-strings.

        ","tags":["UP032"]},{"location":"rules/f-string/#why-is-this-bad","title":"Why is this bad?","text":"

        f-strings are more readable and generally preferred over str.format calls.

        ","tags":["UP032"]},{"location":"rules/f-string/#example","title":"Example","text":"
        \"{}\".format(foo)\n

        Use instead:

        f\"{foo}\"\n
        ","tags":["UP032"]},{"location":"rules/f-string/#references","title":"References","text":"
        • Python documentation: f-strings
        ","tags":["UP032"]},{"location":"rules/falsy-dict-get-fallback/","title":"falsy-dict-get-fallback (RUF056)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF056"]},{"location":"rules/falsy-dict-get-fallback/#what-it-does","title":"What it does","text":"

        Checks for dict.get(key, falsy_value) calls in boolean test positions.

        ","tags":["RUF056"]},{"location":"rules/falsy-dict-get-fallback/#why-is-this-bad","title":"Why is this bad?","text":"

        The default fallback None is already falsy.

        ","tags":["RUF056"]},{"location":"rules/falsy-dict-get-fallback/#example","title":"Example","text":"
        if dict.get(key, False):\n    ...\n

        Use instead:

        if dict.get(key):\n    ...\n
        ","tags":["RUF056"]},{"location":"rules/falsy-dict-get-fallback/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the dict.get() call contains comments between arguments.

        ","tags":["RUF056"]},{"location":"rules/fast-api-non-annotated-dependency/","title":"fast-api-non-annotated-dependency (FAST002)","text":"

        Derived from the FastAPI linter.

        Fix is sometimes available.

        ","tags":["FAST002"]},{"location":"rules/fast-api-non-annotated-dependency/#what-it-does","title":"What it does","text":"

        Identifies FastAPI routes with deprecated uses of Depends or similar.

        ","tags":["FAST002"]},{"location":"rules/fast-api-non-annotated-dependency/#why-is-this-bad","title":"Why is this bad?","text":"

        The FastAPI documentation recommends the use of typing.Annotated for defining route dependencies and parameters, rather than using Depends, Query or similar as a default value for a parameter. Using this approach everywhere helps ensure consistency and clarity in defining dependencies and parameters.

        Annotated was added to the typing module in Python 3.9; however, the third-party typing_extensions package provides a backport that can be used on older versions of Python.

        ","tags":["FAST002"]},{"location":"rules/fast-api-non-annotated-dependency/#example","title":"Example","text":"
        from fastapi import Depends, FastAPI\n\napp = FastAPI()\n\n\nasync def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):\n    return {\"q\": q, \"skip\": skip, \"limit\": limit}\n\n\n@app.get(\"/items/\")\nasync def read_items(commons: dict = Depends(common_parameters)):\n    return commons\n

        Use instead:

        from typing import Annotated\n\nfrom fastapi import Depends, FastAPI\n\napp = FastAPI()\n\n\nasync def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):\n    return {\"q\": q, \"skip\": skip, \"limit\": limit}\n\n\n@app.get(\"/items/\")\nasync def read_items(commons: Annotated[dict, Depends(common_parameters)]):\n    return commons\n
        ","tags":["FAST002"]},{"location":"rules/fast-api-non-annotated-dependency/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for Python versions before 3.9, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["FAST002"]},{"location":"rules/fast-api-non-annotated-dependency/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["FAST002"]},{"location":"rules/fast-api-redundant-response-model/","title":"fast-api-redundant-response-model (FAST001)","text":"

        Derived from the FastAPI linter.

        Fix is always available.

        ","tags":["FAST001"]},{"location":"rules/fast-api-redundant-response-model/#what-it-does","title":"What it does","text":"

        Checks for FastAPI routes that use the optional response_model parameter with the same type as the return type.

        ","tags":["FAST001"]},{"location":"rules/fast-api-redundant-response-model/#why-is-this-bad","title":"Why is this bad?","text":"

        FastAPI routes automatically infer the response model type from the return type, so specifying it explicitly is redundant.

        The response_model parameter is used to override the default response model type. For example, response_model can be used to specify that a non-serializable response type should instead be serialized via an alternative type.

        For more information, see the FastAPI documentation.

        ","tags":["FAST001"]},{"location":"rules/fast-api-redundant-response-model/#example","title":"Example","text":"
        from fastapi import FastAPI\nfrom pydantic import BaseModel\n\napp = FastAPI()\n\n\nclass Item(BaseModel):\n    name: str\n\n\n@app.post(\"/items/\", response_model=Item)\nasync def create_item(item: Item) -> Item:\n    return item\n

        Use instead:

        from fastapi import FastAPI\nfrom pydantic import BaseModel\n\napp = FastAPI()\n\n\nclass Item(BaseModel):\n    name: str\n\n\n@app.post(\"/items/\")\nasync def create_item(item: Item) -> Item:\n    return item\n
        ","tags":["FAST001"]},{"location":"rules/fast-api-unused-path-parameter/","title":"fast-api-unused-path-parameter (FAST003)","text":"

        Derived from the FastAPI linter.

        Fix is sometimes available.

        ","tags":["FAST003"]},{"location":"rules/fast-api-unused-path-parameter/#what-it-does","title":"What it does","text":"

        Identifies FastAPI routes that declare path parameters in the route path that are not included in the function signature.

        ","tags":["FAST003"]},{"location":"rules/fast-api-unused-path-parameter/#why-is-this-bad","title":"Why is this bad?","text":"

        Path parameters are used to extract values from the URL path.

        If a path parameter is declared in the route path but not in the function signature, it will not be accessible in the function body, which is likely a mistake.

        If a path parameter is declared in the route path, but as a positional-only argument in the function signature, it will also not be accessible in the function body, as FastAPI will not inject the parameter.

        ","tags":["FAST003"]},{"location":"rules/fast-api-unused-path-parameter/#known-problems","title":"Known problems","text":"

        If the path parameter is not a valid Python identifier (e.g., user-id, as opposed to user_id), FastAPI will normalize it. However, this rule simply ignores such path parameters, as FastAPI's normalization behavior is undocumented.

        ","tags":["FAST003"]},{"location":"rules/fast-api-unused-path-parameter/#example","title":"Example","text":"
        from fastapi import FastAPI\n\napp = FastAPI()\n\n\n@app.get(\"/things/{thing_id}\")\nasync def read_thing(query: str): ...\n

        Use instead:

        from fastapi import FastAPI\n\napp = FastAPI()\n\n\n@app.get(\"/things/{thing_id}\")\nasync def read_thing(thing_id: int, query: str): ...\n
        ","tags":["FAST003"]},{"location":"rules/fast-api-unused-path-parameter/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as modifying a function signature can change the behavior of the code.

        ","tags":["FAST003"]},{"location":"rules/first-word-uncapitalized/","title":"first-word-uncapitalized (D403)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D403"]},{"location":"rules/first-word-uncapitalized/#what-it-does","title":"What it does","text":"

        Checks for docstrings that do not start with a capital letter.

        ","tags":["D403"]},{"location":"rules/first-word-uncapitalized/#why-is-this-bad","title":"Why is this bad?","text":"

        The first non-whitespace character in a docstring should be capitalized for grammatical correctness and consistency.

        ","tags":["D403"]},{"location":"rules/first-word-uncapitalized/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"return the mean of the given values.\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D403"]},{"location":"rules/first-word-uncapitalized/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D403"]},{"location":"rules/flask-debug-true/","title":"flask-debug-true (S201)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S201"]},{"location":"rules/flask-debug-true/#what-it-does","title":"What it does","text":"

        Checks for uses of debug=True in Flask.

        ","tags":["S201"]},{"location":"rules/flask-debug-true/#why-is-this-bad","title":"Why is this bad?","text":"

        Enabling debug mode shows an interactive debugger in the browser if an error occurs, and allows running arbitrary Python code from the browser. This could leak sensitive information, or allow an attacker to run arbitrary code.

        ","tags":["S201"]},{"location":"rules/flask-debug-true/#example","title":"Example","text":"
        import flask\n\napp = Flask()\n\napp.run(debug=True)\n

        Use instead:

        import flask\n\napp = Flask()\n\napp.run(debug=os.environ[\"ENV\"] == \"dev\")\n
        ","tags":["S201"]},{"location":"rules/flask-debug-true/#references","title":"References","text":"
        • Flask documentation: Debug Mode
        ","tags":["S201"]},{"location":"rules/for-loop-set-mutations/","title":"for-loop-set-mutations (FURB142)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB142"]},{"location":"rules/for-loop-set-mutations/#what-it-does","title":"What it does","text":"

        Checks for code that updates a set with the contents of an iterable by using a for loop to call .add() or .discard() on each element separately.

        ","tags":["FURB142"]},{"location":"rules/for-loop-set-mutations/#why-is-this-bad","title":"Why is this bad?","text":"

        When adding or removing a batch of elements to or from a set, it's more idiomatic to use a single method call rather than adding or removing elements one by one.

        ","tags":["FURB142"]},{"location":"rules/for-loop-set-mutations/#example","title":"Example","text":"
        s = set()\n\nfor x in (1, 2, 3):\n    s.add(x)\n\nfor x in (1, 2, 3):\n    s.discard(x)\n

        Use instead:

        s = set()\n\ns.update((1, 2, 3))\ns.difference_update((1, 2, 3))\n
        ","tags":["FURB142"]},{"location":"rules/for-loop-set-mutations/#fix-safety","title":"Fix safety","text":"

        The fix will be marked as unsafe if applying the fix would delete any comments. Otherwise, it is marked as safe.

        ","tags":["FURB142"]},{"location":"rules/for-loop-set-mutations/#references","title":"References","text":"
        • Python documentation: set
        ","tags":["FURB142"]},{"location":"rules/for-loop-writes/","title":"for-loop-writes (FURB122)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB122"]},{"location":"rules/for-loop-writes/#what-it-does","title":"What it does","text":"

        Checks for the use of IOBase.write in a for loop.

        ","tags":["FURB122"]},{"location":"rules/for-loop-writes/#why-is-this-bad","title":"Why is this bad?","text":"

        When writing a batch of elements, it's more idiomatic to use a single method call to IOBase.writelines, rather than write elements one by one.

        ","tags":["FURB122"]},{"location":"rules/for-loop-writes/#example","title":"Example","text":"
        with Path(\"file\").open(\"w\") as f:\n    for line in lines:\n        f.write(line)\n\nwith Path(\"file\").open(\"wb\") as f:\n    for line in lines:\n        f.write(line.encode())\n

        Use instead:

        with Path(\"file\").open(\"w\") as f:\n    f.writelines(lines)\n\nwith Path(\"file\").open(\"wb\") as f:\n    f.writelines(line.encode() for line in lines)\n
        ","tags":["FURB122"]},{"location":"rules/for-loop-writes/#references","title":"References","text":"
        • Python documentation: io.IOBase.writelines
        ","tags":["FURB122"]},{"location":"rules/format-in-get-text-func-call/","title":"format-in-get-text-func-call (INT002)","text":"

        Derived from the flake8-gettext linter.

        ","tags":["INT002"]},{"location":"rules/format-in-get-text-func-call/#what-it-does","title":"What it does","text":"

        Checks for str.format calls in gettext function calls.

        ","tags":["INT002"]},{"location":"rules/format-in-get-text-func-call/#why-is-this-bad","title":"Why is this bad?","text":"

        In the gettext API, the gettext function (often aliased to _) returns a translation of its input argument by looking it up in a translation catalog.

        Calling gettext with a formatted string as its argument can cause unexpected behavior. Since the formatted string is resolved before the function call, the translation catalog will look up the formatted string, rather than the str.format-style template.

        Instead, format the value returned by the function call, rather than its argument.

        ","tags":["INT002"]},{"location":"rules/format-in-get-text-func-call/#example","title":"Example","text":"
        from gettext import gettext as _\n\nname = \"Maria\"\n_(\"Hello, {}!\".format(name))  # Looks for \"Hello, Maria!\".\n

        Use instead:

        from gettext import gettext as _\n\nname = \"Maria\"\n_(\"Hello, %s!\") % name  # Looks for \"Hello, %s!\".\n
        ","tags":["INT002"]},{"location":"rules/format-in-get-text-func-call/#references","title":"References","text":"
        • Python documentation: gettext \u2014 Multilingual internationalization services
        ","tags":["INT002"]},{"location":"rules/format-literals/","title":"format-literals (UP030)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP030"]},{"location":"rules/format-literals/#what-it-does","title":"What it does","text":"

        Checks for unnecessary positional indices in format strings.

        ","tags":["UP030"]},{"location":"rules/format-literals/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3.1 and later, format strings can use implicit positional references. For example, \"{0}, {1}\".format(\"Hello\", \"World\") can be rewritten as \"{}, {}\".format(\"Hello\", \"World\").

        If the positional indices appear exactly in-order, they can be omitted in favor of automatic indices to improve readability.

        ","tags":["UP030"]},{"location":"rules/format-literals/#example","title":"Example","text":"
        \"{0}, {1}\".format(\"Hello\", \"World\")  # \"Hello, World\"\n

        Use instead:

        \"{}, {}\".format(\"Hello\", \"World\")  # \"Hello, World\"\n

        This fix is marked as unsafe because:

        • Comments attached to arguments are not moved, which can cause comments to mismatch the actual arguments.
        • If arguments have side effects (e.g., print), reordering may change program behavior.
        ","tags":["UP030"]},{"location":"rules/format-literals/#references","title":"References","text":"
        • Python documentation: Format String Syntax
        • Python documentation: str.format
        ","tags":["UP030"]},{"location":"rules/forward-annotation-syntax-error/","title":"forward-annotation-syntax-error (F722)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F722"]},{"location":"rules/forward-annotation-syntax-error/#what-it-does","title":"What it does","text":"

        Checks for forward annotations that include invalid syntax.

        ","tags":["F722"]},{"location":"rules/forward-annotation-syntax-error/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, type annotations can be quoted as strings literals to enable references to types that have not yet been defined, known as \"forward references\".

        However, these quoted annotations must be valid Python expressions. The use of invalid syntax in a quoted annotation won't raise a SyntaxError, but will instead raise an error when type checking is performed.

        ","tags":["F722"]},{"location":"rules/forward-annotation-syntax-error/#example","title":"Example","text":"
        def foo() -> \"/\": ...\n
        ","tags":["F722"]},{"location":"rules/forward-annotation-syntax-error/#references","title":"References","text":"
        • PEP 563 \u2013 Postponed Evaluation of Annotations
        ","tags":["F722"]},{"location":"rules/fromisoformat-replace-z/","title":"fromisoformat-replace-z (FURB162)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB162"]},{"location":"rules/fromisoformat-replace-z/#what-it-does","title":"What it does","text":"

        Checks for datetime.fromisoformat() calls where the only argument is an inline replacement of Z with a zero offset timezone.

        ","tags":["FURB162"]},{"location":"rules/fromisoformat-replace-z/#why-is-this-bad","title":"Why is this bad?","text":"

        On Python 3.11 and later, datetime.fromisoformat() can handle most ISO 8601 formats including ones affixed with Z, so such an operation is unnecessary.

        More information on unsupported formats can be found in the official documentation.

        ","tags":["FURB162"]},{"location":"rules/fromisoformat-replace-z/#example","title":"Example","text":"
        from datetime import datetime\n\n\ndate = \"2025-01-01T00:00:00Z\"\n\ndatetime.fromisoformat(date.replace(\"Z\", \"+00:00\"))\ndatetime.fromisoformat(date[:-1] + \"-00\")\ndatetime.fromisoformat(date.strip(\"Z\", \"-0000\"))\ndatetime.fromisoformat(date.rstrip(\"Z\", \"-00:00\"))\n

        Use instead:

        from datetime import datetime\n\n\ndate = \"2025-01-01T00:00:00Z\"\n\ndatetime.fromisoformat(date)\n
        ","tags":["FURB162"]},{"location":"rules/fromisoformat-replace-z/#fix-safety","title":"Fix safety","text":"

        The fix is always marked as unsafe, as it might change the program's behaviour.

        For example, working code might become non-working:

        d = \"Z2025-01-01T00:00:00Z\"  # Note the leading `Z`\n\ndatetime.fromisoformat(d.strip(\"Z\") + \"+00:00\")  # Fine\ndatetime.fromisoformat(d)  # Runtime error\n
        ","tags":["FURB162"]},{"location":"rules/fromisoformat-replace-z/#references","title":"References","text":"
        • What\u2019s New In Python 3.11 \u00a7 datetime
        • fromisoformat
        ","tags":["FURB162"]},{"location":"rules/function-call-in-dataclass-default-argument/","title":"function-call-in-dataclass-default-argument (RUF009)","text":"","tags":["RUF009"]},{"location":"rules/function-call-in-dataclass-default-argument/#what-it-does","title":"What it does","text":"

        Checks for function calls in dataclass attribute defaults.

        ","tags":["RUF009"]},{"location":"rules/function-call-in-dataclass-default-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Function calls are only performed once, at definition time. The returned value is then reused by all instances of the dataclass. This can lead to unexpected behavior when the function call returns a mutable object, as changes to the object will be shared across all instances.

        If a field needs to be initialized with a mutable object, use the field(default_factory=...) pattern.

        Attributes whose default arguments are NewType calls where the original type is immutable are ignored.

        ","tags":["RUF009"]},{"location":"rules/function-call-in-dataclass-default-argument/#example","title":"Example","text":"
        from dataclasses import dataclass\n\n\ndef simple_list() -> list[int]:\n    return [1, 2, 3, 4]\n\n\n@dataclass\nclass A:\n    mutable_default: list[int] = simple_list()\n

        Use instead:

        from dataclasses import dataclass, field\n\n\ndef creating_list() -> list[int]:\n    return [1, 2, 3, 4]\n\n\n@dataclass\nclass A:\n    mutable_default: list[int] = field(default_factory=creating_list)\n
        ","tags":["RUF009"]},{"location":"rules/function-call-in-dataclass-default-argument/#options","title":"Options","text":"
        • lint.flake8-bugbear.extend-immutable-calls
        ","tags":["RUF009"]},{"location":"rules/function-call-in-default-argument/","title":"function-call-in-default-argument (B008)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B008"]},{"location":"rules/function-call-in-default-argument/#what-it-does","title":"What it does","text":"

        Checks for function calls in default function arguments.

        ","tags":["B008"]},{"location":"rules/function-call-in-default-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Any function call that's used in a default argument will only be performed once, at definition time. The returned value will then be reused by all calls to the function, which can lead to unexpected behaviour.

        Parameters with immutable type annotations will be ignored by this rule. Those whose default arguments are NewType calls where the original type is immutable are also ignored.

        Calls and types outside of the standard library can be marked as an exception to this rule with the lint.flake8-bugbear.extend-immutable-calls configuration option.

        ","tags":["B008"]},{"location":"rules/function-call-in-default-argument/#example","title":"Example","text":"
        def create_list() -> list[int]:\n    return [1, 2, 3]\n\n\ndef mutable_default(arg: list[int] = create_list()) -> list[int]:\n    arg.append(4)\n    return arg\n

        Use instead:

        def better(arg: list[int] | None = None) -> list[int]:\n    if arg is None:\n        arg = create_list()\n\n    arg.append(4)\n    return arg\n

        If the use of a singleton is intentional, assign the result call to a module-level variable, and use that variable in the default argument:

        ERROR = ValueError(\"Hosts weren't successfully added\")\n\n\ndef add_host(error: Exception = ERROR) -> None: ...\n
        ","tags":["B008"]},{"location":"rules/function-call-in-default-argument/#options","title":"Options","text":"
        • lint.flake8-bugbear.extend-immutable-calls
        ","tags":["B008"]},{"location":"rules/function-uses-loop-variable/","title":"function-uses-loop-variable (B023)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B023"]},{"location":"rules/function-uses-loop-variable/#what-it-does","title":"What it does","text":"

        Checks for function definitions that use a loop variable.

        ","tags":["B023"]},{"location":"rules/function-uses-loop-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        The loop variable is not bound in the function definition, so it will always have the value it had in the last iteration when the function is called.

        Instead, consider using a default argument to bind the loop variable at function definition time. Or, use functools.partial.

        ","tags":["B023"]},{"location":"rules/function-uses-loop-variable/#example","title":"Example","text":"
        adders = [lambda x: x + i for i in range(3)]\nvalues = [adder(1) for adder in adders]  # [3, 3, 3]\n

        Use instead:

        adders = [lambda x, i=i: x + i for i in range(3)]\nvalues = [adder(1) for adder in adders]  # [1, 2, 3]\n

        Or:

        from functools import partial\n\nadders = [partial(lambda x, i: x + i, i=i) for i in range(3)]\nvalues = [adder(1) for adder in adders]  # [1, 2, 3]\n
        ","tags":["B023"]},{"location":"rules/function-uses-loop-variable/#references","title":"References","text":"
        • The Hitchhiker's Guide to Python: Late Binding Closures
        • Python documentation: functools.partial
        ","tags":["B023"]},{"location":"rules/future-annotations-in-stub/","title":"future-annotations-in-stub (PYI044)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI044"]},{"location":"rules/future-annotations-in-stub/#what-it-does","title":"What it does","text":"

        Checks for the presence of the from __future__ import annotations import statement in stub files.

        ","tags":["PYI044"]},{"location":"rules/future-annotations-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files natively support forward references in all contexts, as stubs are never executed at runtime. (They should be thought of as \"data files\" for type checkers.) As such, the from __future__ import annotations import statement has no effect and should be omitted.

        ","tags":["PYI044"]},{"location":"rules/future-annotations-in-stub/#references","title":"References","text":"
        • Static Typing with Python: Type Stubs
        ","tags":["PYI044"]},{"location":"rules/future-feature-not-defined/","title":"future-feature-not-defined (F407)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F407"]},{"location":"rules/future-feature-not-defined/#what-it-does","title":"What it does","text":"

        Checks for __future__ imports that are not defined in the current Python version.

        ","tags":["F407"]},{"location":"rules/future-feature-not-defined/#why-is-this-bad","title":"Why is this bad?","text":"

        Importing undefined or unsupported members from the __future__ module is a SyntaxError.

        ","tags":["F407"]},{"location":"rules/future-feature-not-defined/#references","title":"References","text":"
        • Python documentation: __future__
        ","tags":["F407"]},{"location":"rules/future-required-type-annotation/","title":"future-required-type-annotation (FA102)","text":"

        Derived from the flake8-future-annotations linter.

        Fix is always available.

        ","tags":["FA102"]},{"location":"rules/future-required-type-annotation/#what-it-does","title":"What it does","text":"

        Checks for uses of PEP 585- and PEP 604-style type annotations in Python modules that lack the required from __future__ import annotations import for compatibility with older Python versions.

        ","tags":["FA102"]},{"location":"rules/future-required-type-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        Using PEP 585 and PEP 604 style annotations without a from __future__ import annotations import will cause runtime errors on Python versions prior to 3.9 and 3.10, respectively.

        By adding the __future__ import, the interpreter will no longer interpret annotations at evaluation time, making the code compatible with both past and future Python versions.

        This rule respects the target-version setting. For example, if your project targets Python 3.10 and above, adding from __future__ import annotations does not impact your ability to leverage PEP 604-style unions (e.g., to convert Optional[str] to str | None). As such, this rule will only flag such usages if your project targets Python 3.9 or below.

        ","tags":["FA102"]},{"location":"rules/future-required-type-annotation/#example","title":"Example","text":"
        def func(obj: dict[str, int | None]) -> None: ...\n

        Use instead:

        from __future__ import annotations\n\n\ndef func(obj: dict[str, int | None]) -> None: ...\n
        ","tags":["FA102"]},{"location":"rules/future-required-type-annotation/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as adding from __future__ import annotations may change the semantics of the program.

        ","tags":["FA102"]},{"location":"rules/future-required-type-annotation/#options","title":"Options","text":"
        • target-version
        ","tags":["FA102"]},{"location":"rules/future-rewritable-type-annotation/","title":"future-rewritable-type-annotation (FA100)","text":"

        Derived from the flake8-future-annotations linter.

        ","tags":["FA100"]},{"location":"rules/future-rewritable-type-annotation/#what-it-does","title":"What it does","text":"

        Checks for missing from __future__ import annotations imports upon detecting type annotations that can be written more succinctly under PEP 563.

        ","tags":["FA100"]},{"location":"rules/future-rewritable-type-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 585 enabled the use of a number of convenient type annotations, such as list[str] instead of List[str]. However, these annotations are only available on Python 3.9 and higher, unless the from __future__ import annotations import is present.

        Similarly, PEP 604 enabled the use of the | operator for unions, such as str | None instead of Optional[str]. However, these annotations are only available on Python 3.10 and higher, unless the from __future__ import annotations import is present.

        By adding the __future__ import, the pyupgrade rules can automatically migrate existing code to use the new syntax, even for older Python versions. This rule thus pairs well with pyupgrade and with Ruff's pyupgrade rules.

        This rule respects the target-version setting. For example, if your project targets Python 3.10 and above, adding from __future__ import annotations does not impact your ability to leverage PEP 604-style unions (e.g., to convert Optional[str] to str | None). As such, this rule will only flag such usages if your project targets Python 3.9 or below.

        ","tags":["FA100"]},{"location":"rules/future-rewritable-type-annotation/#example","title":"Example","text":"
        from typing import List, Dict, Optional\n\n\ndef func(obj: Dict[str, Optional[int]]) -> None: ...\n

        Use instead:

        from __future__ import annotations\n\nfrom typing import List, Dict, Optional\n\n\ndef func(obj: Dict[str, Optional[int]]) -> None: ...\n

        After running the additional pyupgrade rules:

        from __future__ import annotations\n\n\ndef func(obj: dict[str, int | None]) -> None: ...\n
        ","tags":["FA100"]},{"location":"rules/future-rewritable-type-annotation/#options","title":"Options","text":"
        • target-version
        ","tags":["FA100"]},{"location":"rules/generator-return-from-iter-method/","title":"generator-return-from-iter-method (PYI058)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI058"]},{"location":"rules/generator-return-from-iter-method/#what-it-does","title":"What it does","text":"

        Checks for simple __iter__ methods that return Generator, and for simple __aiter__ methods that return AsyncGenerator.

        ","tags":["PYI058"]},{"location":"rules/generator-return-from-iter-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Using (Async)Iterator for these methods is simpler and more elegant. More importantly, it also reflects the fact that the precise kind of iterator returned from an __iter__ method is usually an implementation detail that could change at any time. Type annotations help define a contract for a function; implementation details should not leak into that contract.

        For example:

        from collections.abc import AsyncGenerator, Generator\nfrom typing import Any\n\n\nclass CustomIterator:\n    def __iter__(self) -> Generator:\n        yield from range(42)\n\n\nclass CustomIterator2:\n    def __iter__(self) -> Generator[str, Any, None]:\n        yield from \"abcdefg\"\n

        Use instead:

        from collections.abc import Iterator\n\n\nclass CustomIterator:\n    def __iter__(self) -> Iterator:\n        yield from range(42)\n\n\nclass CustomIterator2:\n    def __iter__(self) -> Iterator[str]:\n        yield from \"abdefg\"\n
        ","tags":["PYI058"]},{"location":"rules/generator-return-from-iter-method/#fix-safety","title":"Fix safety","text":"

        This rule tries hard to avoid false-positive errors, and the rule's fix should always be safe for .pyi stub files. However, there is a slightly higher chance that a false positive might be emitted by this rule when applied to runtime Python (.py files). As such, the fix is marked as unsafe for any __iter__ or __aiter__ method in a .py file that has more than two statements (including docstrings) in its body.

        ","tags":["PYI058"]},{"location":"rules/generic-not-last-base-class/","title":"generic-not-last-base-class (PYI059)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PYI059"]},{"location":"rules/generic-not-last-base-class/#what-it-does","title":"What it does","text":"

        Checks for classes inheriting from typing.Generic[] where Generic[] is not the last base class in the bases tuple.

        ","tags":["PYI059"]},{"location":"rules/generic-not-last-base-class/#why-is-this-bad","title":"Why is this bad?","text":"

        If Generic[] is not the final class in the bases tuple, unexpected behaviour can occur at runtime (See this CPython issue for an example). The rule is also applied to stub files, but, unlike at runtime, in stubs it is purely enforced for stylistic consistency.

        For example:

        class LinkedList(Generic[T], Sized):\n    def push(self, item: T) -> None:\n        self._items.append(item)\n\nclass MyMapping(\n    Generic[K, V],\n    Iterable[Tuple[K, V]],\n    Container[Tuple[K, V]],\n):\n    ...\n

        Use instead:

        class LinkedList(Sized, Generic[T]):\n    def push(self, item: T) -> None:\n        self._items.append(item)\n\nclass MyMapping(\n    Iterable[Tuple[K, V]],\n    Container[Tuple[K, V]],\n    Generic[K, V],\n):\n    ...\n
        ","tags":["PYI059"]},{"location":"rules/generic-not-last-base-class/#references","title":"References","text":"
        • typing.Generic documentation
        ","tags":["PYI059"]},{"location":"rules/get-attr-with-constant/","title":"get-attr-with-constant (B009)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B009"]},{"location":"rules/get-attr-with-constant/#what-it-does","title":"What it does","text":"

        Checks for uses of getattr that take a constant attribute value as an argument (e.g., getattr(obj, \"foo\")).

        ","tags":["B009"]},{"location":"rules/get-attr-with-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        getattr is used to access attributes dynamically. If the attribute is defined as a constant, it is no safer than a typical property access. When possible, prefer property access over getattr calls, as the former is more concise and idiomatic.

        ","tags":["B009"]},{"location":"rules/get-attr-with-constant/#example","title":"Example","text":"
        getattr(obj, \"foo\")\n

        Use instead:

        obj.foo\n
        ","tags":["B009"]},{"location":"rules/get-attr-with-constant/#references","title":"References","text":"
        • Python documentation: getattr
        ","tags":["B009"]},{"location":"rules/glob/","title":"glob (PTH207)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH207"]},{"location":"rules/glob/#what-it-does","title":"What it does","text":"

        Checks for the use of glob.glob() and glob.iglob().

        ","tags":["PTH207"]},{"location":"rules/glob/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os and glob.

        When possible, using Path object methods such as Path.glob() can improve readability over their low-level counterparts (e.g., glob.glob()).

        Note that glob.glob() and Path.glob() are not exact equivalents:

        glob-module functions Path.glob() Hidden files Hidden files are excluded by default. On Python 3.11+, the include_hidden keyword can be used to include hidden directories. Includes hidden files by default. Eagerness glob.iglob() returns a lazy iterator. Under the hood, glob.glob() simply converts the iterator to a list. Path.glob() returns a lazy iterator. Working directory glob.glob() and glob.iglob() take a root_dir keyword to set the current working directory. Path.rglob() can be used to return the relative path. Globstar (**) The recursive flag must be set to True for the ** pattern to match any files and zero or more directories, subdirectories, and symbolic links. The ** pattern in Path.glob() means \"this directory and all subdirectories, recursively\". In other words, it enables recursive globbing.","tags":["PTH207"]},{"location":"rules/glob/#example","title":"Example","text":"
        import glob\nimport os\n\nglob.glob(os.path.join(\"my_path\", \"requirements*.txt\"))\n

        Use instead:

        from pathlib import Path\n\nPath(\"my_path\").glob(\"requirements*.txt\")\n
        ","tags":["PTH207"]},{"location":"rules/glob/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH207"]},{"location":"rules/glob/#references","title":"References","text":"
        • Python documentation: Path.glob
        • Python documentation: Path.rglob
        • Python documentation: glob.glob
        • Python documentation: glob.iglob
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH207"]},{"location":"rules/global-at-module-level/","title":"global-at-module-level (PLW0604)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0604"]},{"location":"rules/global-at-module-level/#what-it-does","title":"What it does","text":"

        Checks for uses of the global keyword at the module level.

        ","tags":["PLW0604"]},{"location":"rules/global-at-module-level/#why-is-this-bad","title":"Why is this bad?","text":"

        The global keyword is used within functions to indicate that a name refers to a global variable, rather than a local variable.

        At the module level, all names are global by default, so the global keyword is redundant.

        ","tags":["PLW0604"]},{"location":"rules/global-statement/","title":"global-statement (PLW0603)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0603"]},{"location":"rules/global-statement/#what-it-does","title":"What it does","text":"

        Checks for the use of global statements to update identifiers.

        ","tags":["PLW0603"]},{"location":"rules/global-statement/#why-is-this-bad","title":"Why is this bad?","text":"

        Pylint discourages the use of global variables as global mutable state is a common source of bugs and confusing behavior.

        ","tags":["PLW0603"]},{"location":"rules/global-statement/#example","title":"Example","text":"
        var = 1\n\n\ndef foo():\n    global var  # [global-statement]\n    var = 10\n    print(var)\n\n\nfoo()\nprint(var)\n

        Use instead:

        var = 1\n\n\ndef foo():\n    print(var)\n    return 10\n\n\nvar = foo()\nprint(var)\n
        ","tags":["PLW0603"]},{"location":"rules/global-variable-not-assigned/","title":"global-variable-not-assigned (PLW0602)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0602"]},{"location":"rules/global-variable-not-assigned/#what-it-does","title":"What it does","text":"

        Checks for global variables that are not assigned a value in the current scope.

        ","tags":["PLW0602"]},{"location":"rules/global-variable-not-assigned/#why-is-this-bad","title":"Why is this bad?","text":"

        The global keyword allows an inner scope to modify a variable declared in the outer scope. If the variable is not modified within the inner scope, there is no need to use global.

        ","tags":["PLW0602"]},{"location":"rules/global-variable-not-assigned/#example","title":"Example","text":"
        DEBUG = True\n\n\ndef foo():\n    global DEBUG\n    if DEBUG:\n        print(\"foo() called\")\n    ...\n

        Use instead:

        DEBUG = True\n\n\ndef foo():\n    if DEBUG:\n        print(\"foo() called\")\n    ...\n
        ","tags":["PLW0602"]},{"location":"rules/global-variable-not-assigned/#references","title":"References","text":"
        • Python documentation: The global statement
        ","tags":["PLW0602"]},{"location":"rules/hardcoded-bind-all-interfaces/","title":"hardcoded-bind-all-interfaces (S104)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S104"]},{"location":"rules/hardcoded-bind-all-interfaces/#what-it-does","title":"What it does","text":"

        Checks for hardcoded bindings to all network interfaces (0.0.0.0).

        ","tags":["S104"]},{"location":"rules/hardcoded-bind-all-interfaces/#why-is-this-bad","title":"Why is this bad?","text":"

        Binding to all network interfaces is insecure as it allows access from unintended interfaces, which may be poorly secured or unauthorized.

        Instead, bind to specific interfaces.

        ","tags":["S104"]},{"location":"rules/hardcoded-bind-all-interfaces/#example","title":"Example","text":"
        ALLOWED_HOSTS = [\"0.0.0.0\"]\n

        Use instead:

        ALLOWED_HOSTS = [\"127.0.0.1\", \"localhost\"]\n
        ","tags":["S104"]},{"location":"rules/hardcoded-bind-all-interfaces/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-200
        ","tags":["S104"]},{"location":"rules/hardcoded-password-default/","title":"hardcoded-password-default (S107)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S107"]},{"location":"rules/hardcoded-password-default/#what-it-does","title":"What it does","text":"

        Checks for potential uses of hardcoded passwords in function argument defaults.

        ","tags":["S107"]},{"location":"rules/hardcoded-password-default/#why-is-this-bad","title":"Why is this bad?","text":"

        Including a hardcoded password in source code is a security risk, as an attacker could discover the password and use it to gain unauthorized access.

        Instead, store passwords and other secrets in configuration files, environment variables, or other sources that are excluded from version control.

        ","tags":["S107"]},{"location":"rules/hardcoded-password-default/#example","title":"Example","text":"
        def connect_to_server(password=\"hunter2\"): ...\n

        Use instead:

        import os\n\n\ndef connect_to_server(password=os.environ[\"PASSWORD\"]): ...\n
        ","tags":["S107"]},{"location":"rules/hardcoded-password-default/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-259
        ","tags":["S107"]},{"location":"rules/hardcoded-password-func-arg/","title":"hardcoded-password-func-arg (S106)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S106"]},{"location":"rules/hardcoded-password-func-arg/#what-it-does","title":"What it does","text":"

        Checks for potential uses of hardcoded passwords in function calls.

        ","tags":["S106"]},{"location":"rules/hardcoded-password-func-arg/#why-is-this-bad","title":"Why is this bad?","text":"

        Including a hardcoded password in source code is a security risk, as an attacker could discover the password and use it to gain unauthorized access.

        Instead, store passwords and other secrets in configuration files, environment variables, or other sources that are excluded from version control.

        ","tags":["S106"]},{"location":"rules/hardcoded-password-func-arg/#example","title":"Example","text":"
        connect_to_server(password=\"hunter2\")\n

        Use instead:

        import os\n\nconnect_to_server(password=os.environ[\"PASSWORD\"])\n
        ","tags":["S106"]},{"location":"rules/hardcoded-password-func-arg/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-259
        ","tags":["S106"]},{"location":"rules/hardcoded-password-string/","title":"hardcoded-password-string (S105)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S105"]},{"location":"rules/hardcoded-password-string/#what-it-does","title":"What it does","text":"

        Checks for potential uses of hardcoded passwords in strings.

        ","tags":["S105"]},{"location":"rules/hardcoded-password-string/#why-is-this-bad","title":"Why is this bad?","text":"

        Including a hardcoded password in source code is a security risk, as an attacker could discover the password and use it to gain unauthorized access.

        Instead, store passwords and other secrets in configuration files, environment variables, or other sources that are excluded from version control.

        ","tags":["S105"]},{"location":"rules/hardcoded-password-string/#example","title":"Example","text":"
        SECRET_KEY = \"hunter2\"\n

        Use instead:

        import os\n\nSECRET_KEY = os.environ[\"SECRET_KEY\"]\n
        ","tags":["S105"]},{"location":"rules/hardcoded-password-string/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-259
        ","tags":["S105"]},{"location":"rules/hardcoded-sql-expression/","title":"hardcoded-sql-expression (S608)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S608"]},{"location":"rules/hardcoded-sql-expression/#what-it-does","title":"What it does","text":"

        Checks for strings that resemble SQL statements involved in some form string building operation.

        ","tags":["S608"]},{"location":"rules/hardcoded-sql-expression/#why-is-this-bad","title":"Why is this bad?","text":"

        SQL injection is a common attack vector for web applications. Directly interpolating user input into SQL statements should always be avoided. Instead, favor parameterized queries, in which the SQL statement is provided separately from its parameters, as supported by psycopg3 and other database drivers and ORMs.

        ","tags":["S608"]},{"location":"rules/hardcoded-sql-expression/#example","title":"Example","text":"
        query = \"DELETE FROM foo WHERE id = '%s'\" % identifier\n
        ","tags":["S608"]},{"location":"rules/hardcoded-sql-expression/#references","title":"References","text":"
        • B608: Test for SQL injection
        • psycopg3: Server-side binding
        ","tags":["S608"]},{"location":"rules/hardcoded-string-charset/","title":"hardcoded-string-charset (FURB156)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB156"]},{"location":"rules/hardcoded-string-charset/#what-it-does","title":"What it does","text":"

        Checks for uses of hardcoded charsets, which are defined in Python string module.

        ","tags":["FURB156"]},{"location":"rules/hardcoded-string-charset/#why-is-this-bad","title":"Why is this bad?","text":"

        Usage of named charsets from the standard library is more readable and less error-prone.

        ","tags":["FURB156"]},{"location":"rules/hardcoded-string-charset/#example","title":"Example","text":"
        x = \"0123456789\"\ny in \"abcdefghijklmnopqrstuvwxyz\"\n

        Use instead

        import string\n\nx = string.digits\ny in string.ascii_lowercase\n
        ","tags":["FURB156"]},{"location":"rules/hardcoded-string-charset/#references","title":"References","text":"
        • Python documentation: String constants
        ","tags":["FURB156"]},{"location":"rules/hardcoded-temp-file/","title":"hardcoded-temp-file (S108)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S108"]},{"location":"rules/hardcoded-temp-file/#what-it-does","title":"What it does","text":"

        Checks for the use of hardcoded temporary file or directory paths.

        ","tags":["S108"]},{"location":"rules/hardcoded-temp-file/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of hardcoded paths for temporary files can be insecure. If an attacker discovers the location of a hardcoded path, they can replace the contents of the file or directory with a malicious payload.

        Other programs may also read or write contents to these hardcoded paths, causing unexpected behavior.

        ","tags":["S108"]},{"location":"rules/hardcoded-temp-file/#example","title":"Example","text":"
        with open(\"/tmp/foo.txt\", \"w\") as file:\n    ...\n

        Use instead:

        import tempfile\n\nwith tempfile.NamedTemporaryFile() as file:\n    ...\n
        ","tags":["S108"]},{"location":"rules/hardcoded-temp-file/#options","title":"Options","text":"
        • lint.flake8-bandit.hardcoded-tmp-directory
        • lint.flake8-bandit.hardcoded-tmp-directory-extend
        ","tags":["S108"]},{"location":"rules/hardcoded-temp-file/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-377
        • Common Weakness Enumeration: CWE-379
        • Python documentation: tempfile
        ","tags":["S108"]},{"location":"rules/hashlib-digest-hex/","title":"hashlib-digest-hex (FURB181)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB181"]},{"location":"rules/hashlib-digest-hex/#what-it-does","title":"What it does","text":"

        Checks for the use of .digest().hex() on a hashlib hash, like sha512.

        ","tags":["FURB181"]},{"location":"rules/hashlib-digest-hex/#why-is-this-bad","title":"Why is this bad?","text":"

        When generating a hex digest from a hash, it's preferable to use the .hexdigest() method, rather than calling .digest() and then .hex(), as the former is more concise and readable.

        ","tags":["FURB181"]},{"location":"rules/hashlib-digest-hex/#example","title":"Example","text":"
        from hashlib import sha512\n\nhashed = sha512(b\"some data\").digest().hex()\n

        Use instead:

        from hashlib import sha512\n\nhashed = sha512(b\"some data\").hexdigest()\n
        ","tags":["FURB181"]},{"location":"rules/hashlib-digest-hex/#references","title":"References","text":"
        • Python documentation: hashlib
        ","tags":["FURB181"]},{"location":"rules/hashlib-insecure-hash-function/","title":"hashlib-insecure-hash-function (S324)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S324"]},{"location":"rules/hashlib-insecure-hash-function/#what-it-does","title":"What it does","text":"

        Checks for uses of weak or broken cryptographic hash functions in hashlib and crypt libraries.

        ","tags":["S324"]},{"location":"rules/hashlib-insecure-hash-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Weak or broken cryptographic hash functions may be susceptible to collision attacks (where two different inputs produce the same hash) or pre-image attacks (where an attacker can find an input that produces a given hash). This can lead to security vulnerabilities in applications that rely on these hash functions.

        Avoid using weak or broken cryptographic hash functions in security contexts. Instead, use a known secure hash function such as SHA256.

        ","tags":["S324"]},{"location":"rules/hashlib-insecure-hash-function/#example","title":"Example","text":"
        import hashlib\n\n\ndef certificate_is_valid(certificate: bytes, known_hash: str) -> bool:\n    hash = hashlib.md5(certificate).hexdigest()\n    return hash == known_hash\n

        Use instead:

        import hashlib\n\n\ndef certificate_is_valid(certificate: bytes, known_hash: str) -> bool:\n    hash = hashlib.sha256(certificate).hexdigest()\n    return hash == known_hash\n

        or add usedforsecurity=False if the hashing algorithm is not used in a security context, e.g. as a non-cryptographic one-way compression function:

        import hashlib\n\n\ndef certificate_is_valid(certificate: bytes, known_hash: str) -> bool:\n    hash = hashlib.md5(certificate, usedforsecurity=False).hexdigest()\n    return hash == known_hash\n
        ","tags":["S324"]},{"location":"rules/hashlib-insecure-hash-function/#references","title":"References","text":"
        • Python documentation: hashlib \u2014 Secure hashes and message digests
        • Python documentation: crypt \u2014 Function to check Unix passwords
        • Python documentation: FIPS - FIPS compliant hashlib implementation
        • Common Weakness Enumeration: CWE-327
        • Common Weakness Enumeration: CWE-328
        • Common Weakness Enumeration: CWE-916
        ","tags":["S324"]},{"location":"rules/if-else-block-instead-of-dict-get/","title":"if-else-block-instead-of-dict-get (SIM401)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM401"]},{"location":"rules/if-else-block-instead-of-dict-get/#what-it-does","title":"What it does","text":"

        Checks for if statements that can be replaced with dict.get calls.

        ","tags":["SIM401"]},{"location":"rules/if-else-block-instead-of-dict-get/#why-is-this-bad","title":"Why is this bad?","text":"

        dict.get() calls can be used to replace if statements that assign a value to a variable in both branches, falling back to a default value if the key is not found. When possible, using dict.get is more concise and more idiomatic.

        Under preview mode, this rule will also suggest replacing if-else expressions with dict.get calls.

        ","tags":["SIM401"]},{"location":"rules/if-else-block-instead-of-dict-get/#example","title":"Example","text":"
        if \"bar\" in foo:\n    value = foo[\"bar\"]\nelse:\n    value = 0\n

        Use instead:

        value = foo.get(\"bar\", 0)\n

        If preview mode is enabled:

        value = foo[\"bar\"] if \"bar\" in foo else 0\n

        Use instead:

        value = foo.get(\"bar\", 0)\n
        ","tags":["SIM401"]},{"location":"rules/if-else-block-instead-of-dict-get/#references","title":"References","text":"
        • Python documentation: Mapping Types
        ","tags":["SIM401"]},{"location":"rules/if-else-block-instead-of-dict-lookup/","title":"if-else-block-instead-of-dict-lookup (SIM116)","text":"

        Derived from the flake8-simplify linter.

        ","tags":["SIM116"]},{"location":"rules/if-else-block-instead-of-dict-lookup/#what-it-does","title":"What it does","text":"

        Checks for three or more consecutive if-statements with direct returns

        ","tags":["SIM116"]},{"location":"rules/if-else-block-instead-of-dict-lookup/#why-is-this-bad","title":"Why is this bad?","text":"

        These can be simplified by using a dictionary

        ","tags":["SIM116"]},{"location":"rules/if-else-block-instead-of-dict-lookup/#example","title":"Example","text":"
        if x == 1:\n    return \"Hello\"\nelif x == 2:\n    return \"Goodbye\"\nelse:\n    return \"Goodnight\"\n

        Use instead:

        return {1: \"Hello\", 2: \"Goodbye\"}.get(x, \"Goodnight\")\n
        ","tags":["SIM116"]},{"location":"rules/if-else-block-instead-of-if-exp/","title":"if-else-block-instead-of-if-exp (SIM108)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM108"]},{"location":"rules/if-else-block-instead-of-if-exp/#what-it-does","title":"What it does","text":"

        Check for if-else-blocks that can be replaced with a ternary operator. Moreover, in preview, check if these ternary expressions can be further simplified to binary expressions.

        ","tags":["SIM108"]},{"location":"rules/if-else-block-instead-of-if-exp/#why-is-this-bad","title":"Why is this bad?","text":"

        if-else-blocks that assign a value to a variable in both branches can be expressed more concisely by using a ternary or binary operator.

        ","tags":["SIM108"]},{"location":"rules/if-else-block-instead-of-if-exp/#example","title":"Example","text":"
        if foo:\n    bar = x\nelse:\n    bar = y\n

        Use instead:

        bar = x if foo else y\n

        Or, in preview:

        if cond:\n    z = cond\nelse:\n    z = other_cond\n

        Use instead:

        z = cond or other_cond\n
        ","tags":["SIM108"]},{"location":"rules/if-else-block-instead-of-if-exp/#known-issues","title":"Known issues","text":"

        This is an opinionated style rule that may not always be to everyone's taste, especially for code that makes use of complex if conditions. Ternary operators can also make it harder to measure code coverage with tools that use line profiling.

        ","tags":["SIM108"]},{"location":"rules/if-else-block-instead-of-if-exp/#references","title":"References","text":"
        • Python documentation: Conditional expressions
        ","tags":["SIM108"]},{"location":"rules/if-exp-instead-of-or-operator/","title":"if-exp-instead-of-or-operator (FURB110)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB110"]},{"location":"rules/if-exp-instead-of-or-operator/#what-it-does","title":"What it does","text":"

        Checks for ternary if expressions that can be replaced with the or operator.

        ","tags":["FURB110"]},{"location":"rules/if-exp-instead-of-or-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        Ternary if expressions are more verbose than or expressions while providing the same functionality.

        ","tags":["FURB110"]},{"location":"rules/if-exp-instead-of-or-operator/#example","title":"Example","text":"
        z = x if x else y\n

        Use instead:

        z = x or y\n
        ","tags":["FURB110"]},{"location":"rules/if-exp-instead-of-or-operator/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe in the event that the body of the if expression contains side effects.

        For example, foo will be called twice in foo() if foo() else bar() (assuming foo() returns a truthy value), but only once in foo() or bar().

        ","tags":["FURB110"]},{"location":"rules/if-expr-min-max/","title":"if-expr-min-max (FURB136)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB136"]},{"location":"rules/if-expr-min-max/#what-it-does","title":"What it does","text":"

        Checks for if expressions that can be replaced with min() or max() calls.

        ","tags":["FURB136"]},{"location":"rules/if-expr-min-max/#why-is-this-bad","title":"Why is this bad?","text":"

        An if expression that selects the lesser or greater of two sub-expressions can be replaced with a min() or max() call respectively. When possible, prefer min() and max(), as they're more concise and readable than the equivalent if expression.

        ","tags":["FURB136"]},{"location":"rules/if-expr-min-max/#example","title":"Example","text":"
        highest_score = score1 if score1 > score2 else score2\n

        Use instead:

        highest_score = max(score2, score1)\n
        ","tags":["FURB136"]},{"location":"rules/if-expr-min-max/#references","title":"References","text":"
        • Python documentation: min
        • Python documentation: max
        ","tags":["FURB136"]},{"location":"rules/if-expr-with-false-true/","title":"if-expr-with-false-true (SIM211)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM211"]},{"location":"rules/if-expr-with-false-true/#what-it-does","title":"What it does","text":"

        Checks for if expressions that can be replaced by negating a given condition.

        ","tags":["SIM211"]},{"location":"rules/if-expr-with-false-true/#why-is-this-bad","title":"Why is this bad?","text":"

        if expressions that evaluate to False for a truthy condition and True for a falsey condition can be replaced with not operators, which are more concise and readable.

        ","tags":["SIM211"]},{"location":"rules/if-expr-with-false-true/#example","title":"Example","text":"
        False if a else True\n

        Use instead:

        not a\n
        ","tags":["SIM211"]},{"location":"rules/if-expr-with-false-true/#references","title":"References","text":"
        • Python documentation: Truth Value Testing
        ","tags":["SIM211"]},{"location":"rules/if-expr-with-true-false/","title":"if-expr-with-true-false (SIM210)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM210"]},{"location":"rules/if-expr-with-true-false/#what-it-does","title":"What it does","text":"

        Checks for if expressions that can be replaced with bool() calls.

        ","tags":["SIM210"]},{"location":"rules/if-expr-with-true-false/#why-is-this-bad","title":"Why is this bad?","text":"

        if expressions that evaluate to True for a truthy condition an False for a falsey condition can be replaced with bool() calls, which are more concise and readable.

        ","tags":["SIM210"]},{"location":"rules/if-expr-with-true-false/#example","title":"Example","text":"
        True if a else False\n

        Use instead:

        bool(a)\n
        ","tags":["SIM210"]},{"location":"rules/if-expr-with-true-false/#references","title":"References","text":"
        • Python documentation: Truth Value Testing
        ","tags":["SIM210"]},{"location":"rules/if-expr-with-twisted-arms/","title":"if-expr-with-twisted-arms (SIM212)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM212"]},{"location":"rules/if-expr-with-twisted-arms/#what-it-does","title":"What it does","text":"

        Checks for if expressions that check against a negated condition.

        ","tags":["SIM212"]},{"location":"rules/if-expr-with-twisted-arms/#why-is-this-bad","title":"Why is this bad?","text":"

        if expressions that check against a negated condition are more difficult to read than if expressions that check against the condition directly.

        ","tags":["SIM212"]},{"location":"rules/if-expr-with-twisted-arms/#example","title":"Example","text":"
        b if not a else a\n

        Use instead:

        a if a else b\n
        ","tags":["SIM212"]},{"location":"rules/if-expr-with-twisted-arms/#references","title":"References","text":"
        • Python documentation: Truth Value Testing
        ","tags":["SIM212"]},{"location":"rules/if-key-in-dict-del/","title":"if-key-in-dict-del (RUF051)","text":"

        Fix is always available.

        ","tags":["RUF051"]},{"location":"rules/if-key-in-dict-del/#what-it-does","title":"What it does","text":"

        Checks for if key in dictionary: del dictionary[key].

        ","tags":["RUF051"]},{"location":"rules/if-key-in-dict-del/#why-is-this-bad","title":"Why is this bad?","text":"

        To remove a key-value pair from a dictionary, it's more concise to use .pop(..., None).

        ","tags":["RUF051"]},{"location":"rules/if-key-in-dict-del/#example","title":"Example","text":"
        if key in dictionary:\n    del dictionary[key]\n

        Use instead:

        dictionary.pop(key, None)\n
        ","tags":["RUF051"]},{"location":"rules/if-key-in-dict-del/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the if statement contains comments.

        ","tags":["RUF051"]},{"location":"rules/if-stmt-min-max/","title":"if-stmt-min-max (PLR1730)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLR1730"]},{"location":"rules/if-stmt-min-max/#what-it-does","title":"What it does","text":"

        Checks for if statements that can be replaced with min() or max() calls.

        ","tags":["PLR1730"]},{"location":"rules/if-stmt-min-max/#why-is-this-bad","title":"Why is this bad?","text":"

        An if statement that selects the lesser or greater of two sub-expressions can be replaced with a min() or max() call respectively. Where possible, prefer min() and max(), as they're more concise and readable than the equivalent if statements.

        ","tags":["PLR1730"]},{"location":"rules/if-stmt-min-max/#example","title":"Example","text":"
        if score > highest_score:\n    highest_score = score\n

        Use instead:

        highest_score = max(highest_score, score)\n
        ","tags":["PLR1730"]},{"location":"rules/if-stmt-min-max/#fix-safety","title":"Fix safety","text":"

        This fix is marked unsafe if it would delete any comments within the replacement range.

        An example to illustrate where comments are preserved and where they are not:

        a, b = 0, 10\n\nif a >= b: # deleted comment\n    # deleted comment\n    a = b # preserved comment\n
        ","tags":["PLR1730"]},{"location":"rules/if-stmt-min-max/#references","title":"References","text":"
        • Python documentation: max
        • Python documentation: min
        ","tags":["PLR1730"]},{"location":"rules/if-tuple/","title":"if-tuple (F634)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F634"]},{"location":"rules/if-tuple/#what-it-does","title":"What it does","text":"

        Checks for if statements that use non-empty tuples as test conditions.

        ","tags":["F634"]},{"location":"rules/if-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        Non-empty tuples are always True, so an if statement with a non-empty tuple as its test condition will always pass. This is likely a mistake.

        ","tags":["F634"]},{"location":"rules/if-tuple/#example","title":"Example","text":"
        if (False,):\n    print(\"This will always run\")\n

        Use instead:

        if False:\n    print(\"This will never run\")\n
        ","tags":["F634"]},{"location":"rules/if-tuple/#references","title":"References","text":"
        • Python documentation: The if statement
        ","tags":["F634"]},{"location":"rules/if-with-same-arms/","title":"if-with-same-arms (SIM114)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM114"]},{"location":"rules/if-with-same-arms/#what-it-does","title":"What it does","text":"

        Checks for if branches with identical arm bodies.

        ","tags":["SIM114"]},{"location":"rules/if-with-same-arms/#why-is-this-bad","title":"Why is this bad?","text":"

        If multiple arms of an if statement have the same body, using or better signals the intent of the statement.

        ","tags":["SIM114"]},{"location":"rules/if-with-same-arms/#example","title":"Example","text":"
        if x == 1:\n    print(\"Hello\")\nelif x == 2:\n    print(\"Hello\")\n

        Use instead:

        if x == 1 or x == 2:\n    print(\"Hello\")\n
        ","tags":["SIM114"]},{"location":"rules/implicit-class-var-in-dataclass/","title":"implicit-class-var-in-dataclass (RUF045)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF045"]},{"location":"rules/implicit-class-var-in-dataclass/#what-it-does","title":"What it does","text":"

        Checks for implicit class variables in dataclasses.

        Variables matching the lint.dummy-variable-rgx are excluded from this rule.

        ","tags":["RUF045"]},{"location":"rules/implicit-class-var-in-dataclass/#why-is-this-bad","title":"Why is this bad?","text":"

        Class variables are shared between all instances of that class. In dataclasses, fields with no annotations at all are implicitly considered class variables, and a TypeError is raised if a user attempts to initialize an instance of the class with this field.

        @dataclass\nclass C:\n    a = 1\n    b: str = \"\"\n\nC(a = 42)  # TypeError: C.__init__() got an unexpected keyword argument 'a'\n
        ","tags":["RUF045"]},{"location":"rules/implicit-class-var-in-dataclass/#example","title":"Example","text":"
        @dataclass\nclass C:\n    a = 1\n

        Use instead:

        from typing import ClassVar\n\n\n@dataclass\nclass C:\n    a: ClassVar[int] = 1\n
        ","tags":["RUF045"]},{"location":"rules/implicit-class-var-in-dataclass/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["RUF045"]},{"location":"rules/implicit-cwd/","title":"implicit-cwd (FURB177)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB177"]},{"location":"rules/implicit-cwd/#what-it-does","title":"What it does","text":"

        Checks for current-directory lookups using Path().resolve().

        ","tags":["FURB177"]},{"location":"rules/implicit-cwd/#why-is-this-bad","title":"Why is this bad?","text":"

        When looking up the current directory, prefer Path.cwd() over Path().resolve(), as Path.cwd() is more explicit in its intent.

        ","tags":["FURB177"]},{"location":"rules/implicit-cwd/#example","title":"Example","text":"
        cwd = Path().resolve()\n

        Use instead:

        cwd = Path.cwd()\n
        ","tags":["FURB177"]},{"location":"rules/implicit-cwd/#references","title":"References","text":"
        • Python documentation: Path.cwd
        ","tags":["FURB177"]},{"location":"rules/implicit-namespace-package/","title":"implicit-namespace-package (INP001)","text":"

        Derived from the flake8-no-pep420 linter.

        ","tags":["INP001"]},{"location":"rules/implicit-namespace-package/#what-it-does","title":"What it does","text":"

        Checks for packages that are missing an __init__.py file.

        ","tags":["INP001"]},{"location":"rules/implicit-namespace-package/#why-is-this-bad","title":"Why is this bad?","text":"

        Python packages are directories that contain a file named __init__.py. The existence of this file indicates that the directory is a Python package, and so it can be imported the same way a module can be imported.

        Directories that lack an __init__.py file can still be imported, but they're indicative of a special kind of package, known as a \"namespace package\" (see: PEP 420). Namespace packages are less widely used, so a package that lacks an __init__.py file is typically meant to be a regular package, and the absence of the __init__.py file is probably an oversight.

        ","tags":["INP001"]},{"location":"rules/implicit-namespace-package/#options","title":"Options","text":"
        • namespace-packages
        ","tags":["INP001"]},{"location":"rules/implicit-optional/","title":"implicit-optional (RUF013)","text":"

        Fix is sometimes available.

        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#what-it-does","title":"What it does","text":"

        Checks for the use of implicit Optional in type annotations when the default parameter value is None.

        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#why-is-this-bad","title":"Why is this bad?","text":"

        Implicit Optional is prohibited by PEP 484. It is confusing and inconsistent with the rest of the type system.

        It's recommended to use Optional[T] instead. For Python 3.10 and later, you can also use T | None.

        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#example","title":"Example","text":"
        def foo(arg: int = None):\n    pass\n

        Use instead:

        from typing import Optional\n\n\ndef foo(arg: Optional[int] = None):\n    pass\n

        Or, for Python 3.10 and later:

        def foo(arg: int | None = None):\n    pass\n

        If you want to use the | operator in Python 3.9 and earlier, you can use future imports:

        from __future__ import annotations\n\n\ndef foo(arg: int | None = None):\n    pass\n
        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#limitations","title":"Limitations","text":"

        Type aliases are not supported and could result in false negatives. For example, the following code will not be flagged:

        Text = str | bytes\n\n\ndef foo(arg: Text = None):\n    pass\n
        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#options","title":"Options","text":"
        • target-version
        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#fix-safety","title":"Fix safety","text":"

        This fix is always marked as unsafe because it can change the behavior of code that relies on type hints, and it assumes the default value is always appropriate\u2014which might not be the case.

        ","tags":["RUF013"]},{"location":"rules/implicit-return-value/","title":"implicit-return-value (RET502)","text":"

        Derived from the flake8-return linter.

        Fix is always available.

        ","tags":["RET502"]},{"location":"rules/implicit-return-value/#what-it-does","title":"What it does","text":"

        Checks for the presence of a return statement with no explicit value, for functions that return non-None values elsewhere.

        ","tags":["RET502"]},{"location":"rules/implicit-return-value/#why-is-this-bad","title":"Why is this bad?","text":"

        Including a return statement with no explicit value can cause confusion when other return statements in the function return non-None values. Python implicitly assumes return None if no other return value is present. Adding an explicit return None can make the code more readable by clarifying intent.

        ","tags":["RET502"]},{"location":"rules/implicit-return-value/#example","title":"Example","text":"
        def foo(bar):\n    if not bar:\n        return\n    return 1\n

        Use instead:

        def foo(bar):\n    if not bar:\n        return None\n    return 1\n
        ","tags":["RET502"]},{"location":"rules/implicit-return/","title":"implicit-return (RET503)","text":"

        Derived from the flake8-return linter.

        Fix is always available.

        ","tags":["RET503"]},{"location":"rules/implicit-return/#what-it-does","title":"What it does","text":"

        Checks for missing explicit return statements at the end of functions that can return non-None values.

        ","tags":["RET503"]},{"location":"rules/implicit-return/#why-is-this-bad","title":"Why is this bad?","text":"

        The lack of an explicit return statement at the end of a function that can return non-None values can cause confusion. Python implicitly returns None if no other return value is present. Adding an explicit return None can make the code more readable by clarifying intent.

        ","tags":["RET503"]},{"location":"rules/implicit-return/#example","title":"Example","text":"
        def foo(bar):\n    if not bar:\n        return 1\n

        Use instead:

        def foo(bar):\n    if not bar:\n        return 1\n    return None\n
        ","tags":["RET503"]},{"location":"rules/import-outside-top-level/","title":"import-outside-top-level (PLC0415)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLC0415"]},{"location":"rules/import-outside-top-level/#what-it-does","title":"What it does","text":"

        Checks for import statements outside of a module's top-level scope, such as within a function or class definition.

        ","tags":["PLC0415"]},{"location":"rules/import-outside-top-level/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends placing imports not only at the top-level of a module, but at the very top of the file, \"just after any module comments and docstrings, and before module globals and constants.\"

        import statements have effects that are global in scope; defining them at the top level has a number of benefits. For example, it makes it easier to identify the dependencies of a module, and ensures that any invalid imports are caught regardless of whether a specific function is called or class is instantiated.

        An import statement would typically be placed within a function only to avoid a circular dependency, to defer a costly module load, or to avoid loading a dependency altogether in a certain runtime environment.

        ","tags":["PLC0415"]},{"location":"rules/import-outside-top-level/#example","title":"Example","text":"
        def print_python_version():\n    import platform\n\n    print(python.python_version())\n

        Use instead:

        import platform\n\n\ndef print_python_version():\n    print(python.python_version())\n
        ","tags":["PLC0415"]},{"location":"rules/import-private-name/","title":"import-private-name (PLC2701)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#what-it-does","title":"What it does","text":"

        Checks for import statements that import a private name (a name starting with an underscore _) from another module.

        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 states that names starting with an underscore are private. Thus, they are not intended to be used outside of the module in which they are defined.

        Further, as private imports are not considered part of the public API, they are prone to unexpected changes, especially outside of semantic versioning.

        Instead, consider using the public API of the module.

        This rule ignores private name imports that are exclusively used in type annotations. Ideally, types would be public; however, this is not always possible when using third-party libraries.

        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#known-problems","title":"Known problems","text":"

        Does not ignore private name imports from within the module that defines the private name if the module is defined with PEP 420 namespace packages (i.e., directories that omit the __init__.py file). Namespace packages must be configured via the namespace-packages setting.

        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#example","title":"Example","text":"
        from foo import _bar\n
        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#options","title":"Options","text":"
        • namespace-packages
        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#references","title":"References","text":"
        • PEP 8: Naming Conventions
        • Semantic Versioning
        ","tags":["PLC2701"]},{"location":"rules/import-self/","title":"import-self (PLW0406)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0406"]},{"location":"rules/import-self/#what-it-does","title":"What it does","text":"

        Checks for import statements that import the current module.

        ","tags":["PLW0406"]},{"location":"rules/import-self/#why-is-this-bad","title":"Why is this bad?","text":"

        Importing a module from itself is a circular dependency and results in an ImportError exception.

        ","tags":["PLW0406"]},{"location":"rules/import-self/#example","title":"Example","text":"
        # file: this_file.py\nfrom this_file import foo\n\n\ndef foo(): ...\n
        ","tags":["PLW0406"]},{"location":"rules/import-shadowed-by-loop-var/","title":"import-shadowed-by-loop-var (F402)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F402"]},{"location":"rules/import-shadowed-by-loop-var/#what-it-does","title":"What it does","text":"

        Checks for import bindings that are shadowed by loop variables.

        ","tags":["F402"]},{"location":"rules/import-shadowed-by-loop-var/#why-is-this-bad","title":"Why is this bad?","text":"

        Shadowing an import with loop variables makes the code harder to read and reason about, as the identify of the imported binding is no longer clear. It's also often indicative of a mistake, as it's unlikely that the loop variable is intended to be used as the imported binding.

        Consider using a different name for the loop variable.

        ","tags":["F402"]},{"location":"rules/import-shadowed-by-loop-var/#example","title":"Example","text":"
        from os import path\n\nfor path in files:\n    print(path)\n

        Use instead:

        from os import path\n\n\nfor filename in files:\n    print(filename)\n
        ","tags":["F402"]},{"location":"rules/in-dict-keys/","title":"in-dict-keys (SIM118)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM118"]},{"location":"rules/in-dict-keys/#what-it-does","title":"What it does","text":"

        Checks for key-existence checks against dict.keys() calls.

        ","tags":["SIM118"]},{"location":"rules/in-dict-keys/#why-is-this-bad","title":"Why is this bad?","text":"

        When checking for the existence of a key in a given dictionary, using key in dict is more readable and efficient than key in dict.keys(), while having the same semantics.

        ","tags":["SIM118"]},{"location":"rules/in-dict-keys/#example","title":"Example","text":"
        key in foo.keys()\n

        Use instead:

        key in foo\n
        ","tags":["SIM118"]},{"location":"rules/in-dict-keys/#fix-safety","title":"Fix safety","text":"

        Given key in obj.keys(), obj could be a dictionary, or it could be another type that defines a .keys() method. In the latter case, removing the .keys() attribute could lead to a runtime error. The fix is marked as safe when the type of obj is known to be a dictionary; otherwise, it is marked as unsafe.

        ","tags":["SIM118"]},{"location":"rules/in-dict-keys/#references","title":"References","text":"
        • Python documentation: Mapping Types
        ","tags":["SIM118"]},{"location":"rules/in-empty-collection/","title":"in-empty-collection (RUF060)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF060"]},{"location":"rules/in-empty-collection/#what-it-does","title":"What it does","text":"

        Checks for membership tests on empty collections (such as list, tuple, set or dict).

        ","tags":["RUF060"]},{"location":"rules/in-empty-collection/#why-is-this-bad","title":"Why is this bad?","text":"

        If the collection is always empty, the check is unnecessary, and can be removed.

        ","tags":["RUF060"]},{"location":"rules/in-empty-collection/#example","title":"Example","text":"
        if 1 not in set():\n    print(\"got it!\")\n

        Use instead:

        print(\"got it!\")\n
        ","tags":["RUF060"]},{"location":"rules/incorrect-blank-line-after-class/","title":"incorrect-blank-line-after-class (D204)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-after-class/#what-it-does","title":"What it does","text":"

        Checks for class methods that are not separated from the class's docstring by a blank line.

        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-after-class/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends the use of a blank line to separate a class's docstring from its methods.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the numpy and pep257 conventions, and disabled when using the google convention.

        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-after-class/#example","title":"Example","text":"
        class PhotoMetadata:\n    \"\"\"Metadata about a photo.\"\"\"\n    def __init__(self, file: Path):\n        ...\n

        Use instead:

        class PhotoMetadata:\n    \"\"\"Metadata about a photo.\"\"\"\n\n    def __init__(self, file: Path):\n        ...\n
        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-after-class/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-after-class/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-before-class/","title":"incorrect-blank-line-before-class (D203)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D203"]},{"location":"rules/incorrect-blank-line-before-class/#what-it-does","title":"What it does","text":"

        Checks for docstrings on class definitions that are not preceded by a blank line.

        ","tags":["D203"]},{"location":"rules/incorrect-blank-line-before-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Use a blank line to separate the docstring from the class definition, for consistency.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is disabled when using the google, numpy, and pep257 conventions.

        For an alternative, see D211.

        ","tags":["D203"]},{"location":"rules/incorrect-blank-line-before-class/#example","title":"Example","text":"
        class PhotoMetadata:\n    \"\"\"Metadata about a photo.\"\"\"\n

        Use instead:

        class PhotoMetadata:\n\n    \"\"\"Metadata about a photo.\"\"\"\n
        ","tags":["D203"]},{"location":"rules/incorrect-blank-line-before-class/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D203"]},{"location":"rules/incorrect-dict-iterator/","title":"incorrect-dict-iterator (PERF102)","text":"

        Derived from the Perflint linter.

        Fix is always available.

        ","tags":["PERF102"]},{"location":"rules/incorrect-dict-iterator/#what-it-does","title":"What it does","text":"

        Checks for uses of dict.items() that discard either the key or the value when iterating over the dictionary.

        ","tags":["PERF102"]},{"location":"rules/incorrect-dict-iterator/#why-is-this-bad","title":"Why is this bad?","text":"

        If you only need the keys or values of a dictionary, you should use dict.keys() or dict.values() respectively, instead of dict.items(). These specialized methods are more efficient than dict.items(), as they avoid allocating tuples for every item in the dictionary. They also communicate the intent of the code more clearly.

        Note that, as with all perflint rules, this is only intended as a micro-optimization, and will have a negligible impact on performance in most cases.

        ","tags":["PERF102"]},{"location":"rules/incorrect-dict-iterator/#example","title":"Example","text":"
        obj = {\"a\": 1, \"b\": 2}\nfor key, value in obj.items():\n    print(value)\n

        Use instead:

        obj = {\"a\": 1, \"b\": 2}\nfor value in obj.values():\n    print(value)\n
        ","tags":["PERF102"]},{"location":"rules/incorrect-dict-iterator/#fix-safety","title":"Fix safety","text":"

        The fix does not perform any type analysis and, as such, may suggest an incorrect fix if the object in question does not duck-type as a mapping (e.g., if it is missing a .keys() or .values() method, or if those methods behave differently than they do on standard mapping types).

        ","tags":["PERF102"]},{"location":"rules/incorrectly-parenthesized-tuple-in-subscript/","title":"incorrectly-parenthesized-tuple-in-subscript (RUF031)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF031"]},{"location":"rules/incorrectly-parenthesized-tuple-in-subscript/#what-it-does","title":"What it does","text":"

        Checks for consistent style regarding whether nonempty tuples in subscripts are parenthesized.

        The exact nature of this violation depends on the setting lint.ruff.parenthesize-tuple-in-subscript. By default, the use of parentheses is considered a violation.

        This rule is not applied inside \"typing contexts\" (type annotations, type aliases and subscripted class bases), as these have their own specific conventions around them.

        ","tags":["RUF031"]},{"location":"rules/incorrectly-parenthesized-tuple-in-subscript/#why-is-this-bad","title":"Why is this bad?","text":"

        It is good to be consistent and, depending on the codebase, one or the other convention may be preferred.

        ","tags":["RUF031"]},{"location":"rules/incorrectly-parenthesized-tuple-in-subscript/#example","title":"Example","text":"
        directions = {(0, 1): \"North\", (1, 0): \"East\", (0, -1): \"South\", (-1, 0): \"West\"}\ndirections[(0, 1)]\n

        Use instead (with default setting):

        directions = {(0, 1): \"North\", (1, 0): \"East\", (0, -1): \"South\", (-1, 0): \"West\"}\ndirections[0, 1]\n
        ","tags":["RUF031"]},{"location":"rules/incorrectly-parenthesized-tuple-in-subscript/#options","title":"Options","text":"
        • lint.ruff.parenthesize-tuple-in-subscript
        ","tags":["RUF031"]},{"location":"rules/indentation-with-invalid-multiple-comment/","title":"indentation-with-invalid-multiple-comment (E114)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple-comment/#what-it-does","title":"What it does","text":"

        Checks for indentation of comments with a non-multiple of 4 spaces.

        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, 4 spaces per indentation level should be preferred.

        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple-comment/#example","title":"Example","text":"
        if True:\n   # a = 1\n

        Use instead:

        if True:\n    # a = 1\n
        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple-comment/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        The rule is also incompatible with the formatter when using indent-width with a value other than 4.

        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple-comment/#options","title":"Options","text":"
        • indent-width
        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple/","title":"indentation-with-invalid-multiple (E111)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E111"]},{"location":"rules/indentation-with-invalid-multiple/#what-it-does","title":"What it does","text":"

        Checks for indentation with a non-multiple of 4 spaces.

        ","tags":["E111"]},{"location":"rules/indentation-with-invalid-multiple/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, 4 spaces per indentation level should be preferred.

        ","tags":["E111"]},{"location":"rules/indentation-with-invalid-multiple/#example","title":"Example","text":"
        if True:\n   a = 1\n

        Use instead:

        if True:\n    a = 1\n
        ","tags":["E111"]},{"location":"rules/indentation-with-invalid-multiple/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        The rule is also incompatible with the formatter when using indent-width with a value other than 4.

        ","tags":["E111"]},{"location":"rules/indentation-with-invalid-multiple/#options","title":"Options","text":"
        • indent-width
        ","tags":["E111"]},{"location":"rules/indented-form-feed/","title":"indented-form-feed (RUF054)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF054"]},{"location":"rules/indented-form-feed/#what-it-does","title":"What it does","text":"

        Checks for form feed characters preceded by either a space or a tab.

        ","tags":["RUF054"]},{"location":"rules/indented-form-feed/#why-is-this-bad","title":"Why is this bad?","text":"

        The language reference states:

        A formfeed character may be present at the start of the line; it will be ignored for the indentation calculations above. Formfeed characters occurring elsewhere in the leading whitespace have an undefined effect (for instance, they may reset the space count to zero).

        ","tags":["RUF054"]},{"location":"rules/indented-form-feed/#example","title":"Example","text":"
        if foo():\\n    \\fbar()\n

        Use instead:

        if foo():\\n    bar()\n
        ","tags":["RUF054"]},{"location":"rules/int-on-sliced-str/","title":"int-on-sliced-str (FURB166)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB166"]},{"location":"rules/int-on-sliced-str/#what-it-does","title":"What it does","text":"

        Checks for uses of int with an explicit base in which a string expression is stripped of its leading prefix (i.e., 0b, 0o, or 0x).

        ","tags":["FURB166"]},{"location":"rules/int-on-sliced-str/#why-is-this-bad","title":"Why is this bad?","text":"

        Given an integer string with a prefix (e.g., 0xABC), Python can automatically determine the base of the integer by the prefix without needing to specify it explicitly.

        Instead of int(num[2:], 16), use int(num, 0), which will automatically deduce the base based on the prefix.

        ","tags":["FURB166"]},{"location":"rules/int-on-sliced-str/#example","title":"Example","text":"
        num = \"0xABC\"\n\nif num.startswith(\"0b\"):\n    i = int(num[2:], 2)\nelif num.startswith(\"0o\"):\n    i = int(num[2:], 8)\nelif num.startswith(\"0x\"):\n    i = int(num[2:], 16)\n\nprint(i)\n

        Use instead:

        num = \"0xABC\"\n\ni = int(num, 0)\n\nprint(i)\n
        ","tags":["FURB166"]},{"location":"rules/int-on-sliced-str/#fix-safety","title":"Fix safety","text":"

        The rule's fix is marked as unsafe, as Ruff cannot guarantee that the argument to int will remain valid when its base is included in the function call.

        ","tags":["FURB166"]},{"location":"rules/int-on-sliced-str/#references","title":"References","text":"
        • Python documentation: int
        ","tags":["FURB166"]},{"location":"rules/invalid-all-format/","title":"invalid-all-format (PLE0605)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0605"]},{"location":"rules/invalid-all-format/#what-it-does","title":"What it does","text":"

        Checks for invalid assignments to __all__.

        ","tags":["PLE0605"]},{"location":"rules/invalid-all-format/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, __all__ should contain a sequence of strings that represent the names of all \"public\" symbols exported by a module.

        Assigning anything other than a tuple or list of strings to __all__ is invalid.

        ","tags":["PLE0605"]},{"location":"rules/invalid-all-format/#example","title":"Example","text":"
        __all__ = \"Foo\"\n

        Use instead:

        __all__ = (\"Foo\",)\n
        ","tags":["PLE0605"]},{"location":"rules/invalid-all-format/#references","title":"References","text":"
        • Python documentation: The import statement
        ","tags":["PLE0605"]},{"location":"rules/invalid-all-object/","title":"invalid-all-object (PLE0604)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0604"]},{"location":"rules/invalid-all-object/#what-it-does","title":"What it does","text":"

        Checks for the inclusion of invalid objects in __all__.

        ","tags":["PLE0604"]},{"location":"rules/invalid-all-object/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, __all__ should contain a sequence of strings that represent the names of all \"public\" symbols exported by a module.

        Assigning anything other than a tuple or list of strings to __all__ is invalid.

        ","tags":["PLE0604"]},{"location":"rules/invalid-all-object/#example","title":"Example","text":"
        __all__ = [Foo, 1, None]\n

        Use instead:

        __all__ = [\"Foo\", \"Bar\", \"Baz\"]\n
        ","tags":["PLE0604"]},{"location":"rules/invalid-all-object/#references","title":"References","text":"
        • Python documentation: The import statement
        ","tags":["PLE0604"]},{"location":"rules/invalid-argument-name/","title":"invalid-argument-name (N803)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N803"]},{"location":"rules/invalid-argument-name/#what-it-does","title":"What it does","text":"

        Checks for argument names that do not follow the snake_case convention.

        ","tags":["N803"]},{"location":"rules/invalid-argument-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that function names should be lower case and separated by underscores (also known as snake_case).

        Function names should be lowercase, with words separated by underscores as necessary to improve readability.

        Variable names follow the same convention as function names.

        mixedCase is allowed only in contexts where that\u2019s already the prevailing style (e.g. threading.py), to retain backwards compatibility.

        Methods decorated with @typing.override are ignored.

        ","tags":["N803"]},{"location":"rules/invalid-argument-name/#example","title":"Example","text":"
        def my_function(A, myArg):\n    pass\n

        Use instead:

        def my_function(a, my_arg):\n    pass\n
        ","tags":["N803"]},{"location":"rules/invalid-argument-name/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N803"]},{"location":"rules/invalid-assert-message-literal-argument/","title":"invalid-assert-message-literal-argument (RUF040)","text":"","tags":["RUF040"]},{"location":"rules/invalid-assert-message-literal-argument/#what-it-does","title":"What it does","text":"

        Checks for invalid use of literals in assert message arguments.

        ","tags":["RUF040"]},{"location":"rules/invalid-assert-message-literal-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An assert message which is a non-string literal was likely intended to be used in a comparison assertion, rather than as a message.

        ","tags":["RUF040"]},{"location":"rules/invalid-assert-message-literal-argument/#example","title":"Example","text":"
        fruits = [\"apples\", \"plums\", \"pears\"]\nfruits.filter(lambda fruit: fruit.startwith(\"p\"))\nassert len(fruits), 2  # True unless the list is empty\n

        Use instead:

        fruits = [\"apples\", \"plums\", \"pears\"]\nfruits.filter(lambda fruit: fruit.startwith(\"p\"))\nassert len(fruits) == 2\n
        ","tags":["RUF040"]},{"location":"rules/invalid-bool-return-type/","title":"invalid-bool-return-type (PLE0304)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLE0304"]},{"location":"rules/invalid-bool-return-type/#what-it-does","title":"What it does","text":"

        Checks for __bool__ implementations that return a type other than bool.

        ","tags":["PLE0304"]},{"location":"rules/invalid-bool-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __bool__ method should return a bool object. Returning a different type may cause unexpected behavior.

        ","tags":["PLE0304"]},{"location":"rules/invalid-bool-return-type/#example","title":"Example","text":"
        class Foo:\n    def __bool__(self):\n        return 2\n

        Use instead:

        class Foo:\n    def __bool__(self):\n        return True\n
        ","tags":["PLE0304"]},{"location":"rules/invalid-bool-return-type/#references","title":"References","text":"
        • Python documentation: The __bool__ method
        ","tags":["PLE0304"]},{"location":"rules/invalid-bytes-return-type/","title":"invalid-bytes-return-type (PLE0308)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0308"]},{"location":"rules/invalid-bytes-return-type/#what-it-does","title":"What it does","text":"

        Checks for __bytes__ implementations that return types other than bytes.

        ","tags":["PLE0308"]},{"location":"rules/invalid-bytes-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __bytes__ method should return a bytes object. Returning a different type may cause unexpected behavior.

        ","tags":["PLE0308"]},{"location":"rules/invalid-bytes-return-type/#example","title":"Example","text":"
        class Foo:\n    def __bytes__(self):\n        return 2\n

        Use instead:

        class Foo:\n    def __bytes__(self):\n        return b\"2\"\n
        ","tags":["PLE0308"]},{"location":"rules/invalid-bytes-return-type/#references","title":"References","text":"
        • Python documentation: The __bytes__ method
        ","tags":["PLE0308"]},{"location":"rules/invalid-character-backspace/","title":"invalid-character-backspace (PLE2510)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE2510"]},{"location":"rules/invalid-character-backspace/#what-it-does","title":"What it does","text":"

        Checks for strings that contain the control character BS.

        ","tags":["PLE2510"]},{"location":"rules/invalid-character-backspace/#why-is-this-bad","title":"Why is this bad?","text":"

        Control characters are displayed differently by different text editors and terminals.

        By using the \\b sequence in lieu of the BS control character, the string will contain the same value, but will render visibly in all editors.

        ","tags":["PLE2510"]},{"location":"rules/invalid-character-backspace/#example","title":"Example","text":"
        x = \"\"\n

        Use instead:

        x = \"\\b\"\n
        ","tags":["PLE2510"]},{"location":"rules/invalid-character-esc/","title":"invalid-character-esc (PLE2513)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE2513"]},{"location":"rules/invalid-character-esc/#what-it-does","title":"What it does","text":"

        Checks for strings that contain the raw control character ESC.

        ","tags":["PLE2513"]},{"location":"rules/invalid-character-esc/#why-is-this-bad","title":"Why is this bad?","text":"

        Control characters are displayed differently by different text editors and terminals.

        By using the \\x1B sequence in lieu of the SUB control character, the string will contain the same value, but will render visibly in all editors.

        ","tags":["PLE2513"]},{"location":"rules/invalid-character-esc/#example","title":"Example","text":"
        x = \"\"\n

        Use instead:

        x = \"\\x1b\"\n
        ","tags":["PLE2513"]},{"location":"rules/invalid-character-nul/","title":"invalid-character-nul (PLE2514)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE2514"]},{"location":"rules/invalid-character-nul/#what-it-does","title":"What it does","text":"

        Checks for strings that contain the raw control character NUL (0 byte).

        ","tags":["PLE2514"]},{"location":"rules/invalid-character-nul/#why-is-this-bad","title":"Why is this bad?","text":"

        Control characters are displayed differently by different text editors and terminals.

        By using the \\0 sequence in lieu of the NUL control character, the string will contain the same value, but will render visibly in all editors.

        ","tags":["PLE2514"]},{"location":"rules/invalid-character-nul/#example","title":"Example","text":"
        x = \"\"\n

        Use instead:

        x = \"\\0\"\n
        ","tags":["PLE2514"]},{"location":"rules/invalid-character-sub/","title":"invalid-character-sub (PLE2512)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE2512"]},{"location":"rules/invalid-character-sub/#what-it-does","title":"What it does","text":"

        Checks for strings that contain the raw control character SUB.

        ","tags":["PLE2512"]},{"location":"rules/invalid-character-sub/#why-is-this-bad","title":"Why is this bad?","text":"

        Control characters are displayed differently by different text editors and terminals.

        By using the \\x1A sequence in lieu of the SUB control character, the string will contain the same value, but will render visibly in all editors.

        ","tags":["PLE2512"]},{"location":"rules/invalid-character-sub/#example","title":"Example","text":"
        x = \"\"\n

        Use instead:

        x = \"\\x1a\"\n
        ","tags":["PLE2512"]},{"location":"rules/invalid-character-zero-width-space/","title":"invalid-character-zero-width-space (PLE2515)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE2515"]},{"location":"rules/invalid-character-zero-width-space/#what-it-does","title":"What it does","text":"

        Checks for strings that contain the zero width space character.

        ","tags":["PLE2515"]},{"location":"rules/invalid-character-zero-width-space/#why-is-this-bad","title":"Why is this bad?","text":"

        This character is rendered invisibly in some text editors and terminals.

        By using the \\u200B sequence, the string will contain the same value, but will render visibly in all editors.

        ","tags":["PLE2515"]},{"location":"rules/invalid-character-zero-width-space/#example","title":"Example","text":"
        x = \"Dear Sir/Madam\"\n

        Use instead:

        x = \"Dear Sir\\u200b/\\u200bMadam\"  # zero width space\n
        ","tags":["PLE2515"]},{"location":"rules/invalid-class-name/","title":"invalid-class-name (N801)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N801"]},{"location":"rules/invalid-class-name/#what-it-does","title":"What it does","text":"

        Checks for class names that do not follow the CamelCase convention.

        ","tags":["N801"]},{"location":"rules/invalid-class-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the use of the CapWords (or CamelCase) convention for class names:

        Class names should normally use the CapWords convention.

        The naming convention for functions may be used instead in cases where the interface is documented and used primarily as a callable.

        Note that there is a separate convention for builtin names: most builtin names are single words (or two words run together), with the CapWords convention used only for exception names and builtin constants.

        ","tags":["N801"]},{"location":"rules/invalid-class-name/#example","title":"Example","text":"
        class my_class:\n    pass\n

        Use instead:

        class MyClass:\n    pass\n
        ","tags":["N801"]},{"location":"rules/invalid-class-name/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N801"]},{"location":"rules/invalid-envvar-default/","title":"invalid-envvar-default (PLW1508)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW1508"]},{"location":"rules/invalid-envvar-default/#what-it-does","title":"What it does","text":"

        Checks for os.getenv calls with invalid default values.

        ","tags":["PLW1508"]},{"location":"rules/invalid-envvar-default/#why-is-this-bad","title":"Why is this bad?","text":"

        If an environment variable is set, os.getenv will return its value as a string. If the environment variable is not set, os.getenv will return None, or the default value if one is provided.

        If the default value is not a string or None, then it will be inconsistent with the return type of os.getenv, which can lead to confusing behavior.

        ","tags":["PLW1508"]},{"location":"rules/invalid-envvar-default/#example","title":"Example","text":"
        import os\n\nint(os.getenv(\"FOO\", 1))\n

        Use instead:

        import os\n\nint(os.getenv(\"FOO\", \"1\"))\n
        ","tags":["PLW1508"]},{"location":"rules/invalid-envvar-value/","title":"invalid-envvar-value (PLE1507)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1507"]},{"location":"rules/invalid-envvar-value/#what-it-does","title":"What it does","text":"

        Checks for os.getenv calls with an invalid key argument.

        ","tags":["PLE1507"]},{"location":"rules/invalid-envvar-value/#why-is-this-bad","title":"Why is this bad?","text":"

        os.getenv only supports strings as the first argument (key).

        If the provided argument is not a string, os.getenv will throw a TypeError at runtime.

        ","tags":["PLE1507"]},{"location":"rules/invalid-envvar-value/#example","title":"Example","text":"
        os.getenv(1)\n

        Use instead:

        os.getenv(\"1\")\n
        ","tags":["PLE1507"]},{"location":"rules/invalid-escape-sequence/","title":"invalid-escape-sequence (W605)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["W605"]},{"location":"rules/invalid-escape-sequence/#what-it-does","title":"What it does","text":"

        Checks for invalid escape sequences.

        ","tags":["W605"]},{"location":"rules/invalid-escape-sequence/#why-is-this-bad","title":"Why is this bad?","text":"

        Invalid escape sequences are deprecated in Python 3.6.

        ","tags":["W605"]},{"location":"rules/invalid-escape-sequence/#example","title":"Example","text":"
        regex = \"\\.png$\"\n

        Use instead:

        regex = r\"\\.png$\"\n

        Or, if the string already contains a valid escape sequence:

        value = \"new line\\nand invalid escape \\_ here\"\n

        Use instead:

        value = \"new line\\nand invalid escape \\\\_ here\"\n
        ","tags":["W605"]},{"location":"rules/invalid-escape-sequence/#references","title":"References","text":"
        • Python documentation: String and Bytes literals
        ","tags":["W605"]},{"location":"rules/invalid-first-argument-name-for-class-method/","title":"invalid-first-argument-name-for-class-method (N804)","text":"

        Derived from the pep8-naming linter.

        Fix is sometimes available.

        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-class-method/#what-it-does","title":"What it does","text":"

        Checks for class methods that use a name other than cls for their first argument.

        The method __new__ is exempted from this check and the corresponding violation is caught by bad-staticmethod-argument.

        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-class-method/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the use of cls as the first argument for all class methods:

        Always use cls for the first argument to class methods.

        If a function argument\u2019s name clashes with a reserved keyword, it is generally better to append a single trailing underscore rather than use an abbreviation or spelling corruption. Thus class_ is better than clss. (Perhaps better is to avoid such clashes by using a synonym.)

        Names can be excluded from this rule using the lint.pep8-naming.ignore-names or lint.pep8-naming.extend-ignore-names configuration options. For example, to allow the use of klass as the first argument to class methods, set the lint.pep8-naming.extend-ignore-names option to [\"klass\"].

        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-class-method/#example","title":"Example","text":"
        class Example:\n    @classmethod\n    def function(self, data): ...\n

        Use instead:

        class Example:\n    @classmethod\n    def function(cls, data): ...\n
        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-class-method/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as renaming a method parameter can change the behavior of the program.

        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-class-method/#options","title":"Options","text":"
        • lint.pep8-naming.classmethod-decorators
        • lint.pep8-naming.staticmethod-decorators
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-method/","title":"invalid-first-argument-name-for-method (N805)","text":"

        Derived from the pep8-naming linter.

        Fix is sometimes available.

        ","tags":["N805"]},{"location":"rules/invalid-first-argument-name-for-method/#what-it-does","title":"What it does","text":"

        Checks for instance methods that use a name other than self for their first argument.

        ","tags":["N805"]},{"location":"rules/invalid-first-argument-name-for-method/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the use of self as first argument for all instance methods:

        Always use self for the first argument to instance methods.

        If a function argument\u2019s name clashes with a reserved keyword, it is generally better to append a single trailing underscore rather than use an abbreviation or spelling corruption. Thus class_ is better than clss. (Perhaps better is to avoid such clashes by using a synonym.)

        Names can be excluded from this rule using the lint.pep8-naming.ignore-names or lint.pep8-naming.extend-ignore-names configuration options. For example, to allow the use of this as the first argument to instance methods, set the lint.pep8-naming.extend-ignore-names option to [\"this\"].

        ","tags":["N805"]},{"location":"rules/invalid-first-argument-name-for-method/#example","title":"Example","text":"
        class Example:\n    def function(cls, data): ...\n

        Use instead:

        class Example:\n    def function(self, data): ...\n
        ","tags":["N805"]},{"location":"rules/invalid-first-argument-name-for-method/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as renaming a method parameter can change the behavior of the program.

        ","tags":["N805"]},{"location":"rules/invalid-first-argument-name-for-method/#options","title":"Options","text":"
        • lint.pep8-naming.classmethod-decorators
        • lint.pep8-naming.staticmethod-decorators
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N805"]},{"location":"rules/invalid-formatter-suppression-comment/","title":"invalid-formatter-suppression-comment (RUF028)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF028"]},{"location":"rules/invalid-formatter-suppression-comment/#what-it-does","title":"What it does","text":"

        Checks for formatter suppression comments that are ineffective or incompatible with Ruff's formatter.

        ","tags":["RUF028"]},{"location":"rules/invalid-formatter-suppression-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Suppression comments that do not actually prevent formatting could cause unintended changes when the formatter is run.

        ","tags":["RUF028"]},{"location":"rules/invalid-formatter-suppression-comment/#example","title":"Example","text":"

        In the following example, all suppression comments would cause a rule violation.

        def decorator():\n    pass\n\n\n@decorator\n# fmt: off\ndef example():\n    if True:\n        # fmt: skip\n        expression = [\n            # fmt: off\n            1,\n            2,\n        ]\n        # yapf: disable\n    # fmt: on\n    # yapf: enable\n
        ","tags":["RUF028"]},{"location":"rules/invalid-formatter-suppression-comment/#fix-safety","title":"Fix safety","text":"

        This fix is always marked as unsafe because it deletes the invalid suppression comment, rather than trying to move it to a valid position, which the user more likely intended.

        ","tags":["RUF028"]},{"location":"rules/invalid-function-name/","title":"invalid-function-name (N802)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N802"]},{"location":"rules/invalid-function-name/#what-it-does","title":"What it does","text":"

        Checks for functions names that do not follow the snake_case naming convention.

        ","tags":["N802"]},{"location":"rules/invalid-function-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that function names follow snake_case:

        Function names should be lowercase, with words separated by underscores as necessary to improve readability. mixedCase is allowed only in contexts where that\u2019s already the prevailing style (e.g. threading.py), to retain backwards compatibility.

        Names can be excluded from this rule using the lint.pep8-naming.ignore-names or lint.pep8-naming.extend-ignore-names configuration options. For example, to ignore all functions starting with test_ from this rule, set the lint.pep8-naming.extend-ignore-names option to [\"test_*\"].

        ","tags":["N802"]},{"location":"rules/invalid-function-name/#example","title":"Example","text":"
        def myFunction():\n    pass\n

        Use instead:

        def my_function():\n    pass\n
        ","tags":["N802"]},{"location":"rules/invalid-function-name/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N802"]},{"location":"rules/invalid-get-logger-argument/","title":"invalid-get-logger-argument (LOG002)","text":"

        Derived from the flake8-logging linter.

        Fix is sometimes available.

        ","tags":["LOG002"]},{"location":"rules/invalid-get-logger-argument/#what-it-does","title":"What it does","text":"

        Checks for any usage of __cached__ and __file__ as an argument to logging.getLogger().

        ","tags":["LOG002"]},{"location":"rules/invalid-get-logger-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging documentation recommends this pattern:

        logging.getLogger(__name__)\n

        Here, __name__ is the fully qualified module name, such as foo.bar, which is the intended format for logger names.

        This rule detects probably-mistaken usage of similar module-level dunder constants:

        • __cached__ - the pathname of the module's compiled version, such as foo/__pycache__/bar.cpython-311.pyc.
        • __file__ - the pathname of the module, such as foo/bar.py.
        ","tags":["LOG002"]},{"location":"rules/invalid-get-logger-argument/#example","title":"Example","text":"
        import logging\n\nlogger = logging.getLogger(__file__)\n

        Use instead:

        import logging\n\nlogger = logging.getLogger(__name__)\n
        ","tags":["LOG002"]},{"location":"rules/invalid-hash-return-type/","title":"invalid-hash-return-type (PLE0309)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0309"]},{"location":"rules/invalid-hash-return-type/#what-it-does","title":"What it does","text":"

        Checks for __hash__ implementations that return non-integer values.

        ","tags":["PLE0309"]},{"location":"rules/invalid-hash-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __hash__ method should return an integer. Returning a different type may cause unexpected behavior.

        Note: bool is a subclass of int, so it's technically valid for __hash__ to return True or False. However, for consistency with other rules, Ruff will still emit a diagnostic when __hash__ returns a bool.

        ","tags":["PLE0309"]},{"location":"rules/invalid-hash-return-type/#example","title":"Example","text":"
        class Foo:\n    def __hash__(self):\n        return \"2\"\n

        Use instead:

        class Foo:\n    def __hash__(self):\n        return 2\n
        ","tags":["PLE0309"]},{"location":"rules/invalid-hash-return-type/#references","title":"References","text":"
        • Python documentation: The __hash__ method
        ","tags":["PLE0309"]},{"location":"rules/invalid-index-return-type/","title":"invalid-index-return-type (PLE0305)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0305"]},{"location":"rules/invalid-index-return-type/#what-it-does","title":"What it does","text":"

        Checks for __index__ implementations that return non-integer values.

        ","tags":["PLE0305"]},{"location":"rules/invalid-index-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __index__ method should return an integer. Returning a different type may cause unexpected behavior.

        Note: bool is a subclass of int, so it's technically valid for __index__ to return True or False. However, a DeprecationWarning (DeprecationWarning: __index__ returned non-int (type bool)) for such cases was already introduced, thus this is a conscious difference between the original pylint rule and the current ruff implementation.

        ","tags":["PLE0305"]},{"location":"rules/invalid-index-return-type/#example","title":"Example","text":"
        class Foo:\n    def __index__(self):\n        return \"2\"\n

        Use instead:

        class Foo:\n    def __index__(self):\n        return 2\n
        ","tags":["PLE0305"]},{"location":"rules/invalid-index-return-type/#references","title":"References","text":"
        • Python documentation: The __index__ method
        ","tags":["PLE0305"]},{"location":"rules/invalid-index-type/","title":"invalid-index-type (RUF016)","text":"","tags":["RUF016"]},{"location":"rules/invalid-index-type/#what-it-does","title":"What it does","text":"

        Checks for indexed access to lists, strings, tuples, bytes, and comprehensions using a type other than an integer or slice.

        ","tags":["RUF016"]},{"location":"rules/invalid-index-type/#why-is-this-bad","title":"Why is this bad?","text":"

        Only integers or slices can be used as indices to these types. Using other types will result in a TypeError at runtime and a SyntaxWarning at import time.

        ","tags":["RUF016"]},{"location":"rules/invalid-index-type/#example","title":"Example","text":"
        var = [1, 2, 3][\"x\"]\n

        Use instead:

        var = [1, 2, 3][0]\n
        ","tags":["RUF016"]},{"location":"rules/invalid-length-return-type/","title":"invalid-length-return-type (PLE0303)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0303"]},{"location":"rules/invalid-length-return-type/#what-it-does","title":"What it does","text":"

        Checks for __len__ implementations that return values that are not non-negative integers.

        ","tags":["PLE0303"]},{"location":"rules/invalid-length-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __len__ method should return a non-negative integer. Returning a different value may cause unexpected behavior.

        Note: bool is a subclass of int, so it's technically valid for __len__ to return True or False. However, for consistency with other rules, Ruff will still emit a diagnostic when __len__ returns a bool.

        ","tags":["PLE0303"]},{"location":"rules/invalid-length-return-type/#example","title":"Example","text":"
        class Foo:\n    def __len__(self):\n        return \"2\"\n

        Use instead:

        class Foo:\n    def __len__(self):\n        return 2\n
        ","tags":["PLE0303"]},{"location":"rules/invalid-length-return-type/#references","title":"References","text":"
        • Python documentation: The __len__ method
        ","tags":["PLE0303"]},{"location":"rules/invalid-mock-access/","title":"invalid-mock-access (PGH005)","text":"

        Derived from the pygrep-hooks linter.

        ","tags":["PGH005"]},{"location":"rules/invalid-mock-access/#what-it-does","title":"What it does","text":"

        Checks for common mistakes when using mock objects.

        ","tags":["PGH005"]},{"location":"rules/invalid-mock-access/#why-is-this-bad","title":"Why is this bad?","text":"

        The mock module exposes an assertion API that can be used to verify that mock objects undergo expected interactions. This rule checks for common mistakes when using this API.

        For example, it checks for mock attribute accesses that should be replaced with mock method calls.

        ","tags":["PGH005"]},{"location":"rules/invalid-mock-access/#example","title":"Example","text":"
        my_mock.assert_called\n

        Use instead:

        my_mock.assert_called()\n
        ","tags":["PGH005"]},{"location":"rules/invalid-module-name/","title":"invalid-module-name (N999)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N999"]},{"location":"rules/invalid-module-name/#what-it-does","title":"What it does","text":"

        Checks for module names that do not follow the snake_case naming convention or are otherwise invalid.

        ","tags":["N999"]},{"location":"rules/invalid-module-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the use of the snake_case naming convention for module names:

        Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.

        When an extension module written in C or C++ has an accompanying Python module that provides a higher level (e.g. more object-oriented) interface, the C/C++ module has a leading underscore (e.g. _socket).

        Further, in order for Python modules to be importable, they must be valid identifiers. As such, they cannot start with a digit, or collide with hard keywords, like import or class.

        ","tags":["N999"]},{"location":"rules/invalid-module-name/#example","title":"Example","text":"
        • Instead of example-module-name or example module name, use example_module_name.
        • Instead of ExampleModule, use example_module.
        ","tags":["N999"]},{"location":"rules/invalid-pathlib-with-suffix/","title":"invalid-pathlib-with-suffix (PTH210)","text":"

        Derived from the flake8-use-pathlib linter.

        Fix is sometimes available.

        ","tags":["PTH210"]},{"location":"rules/invalid-pathlib-with-suffix/#what-it-does","title":"What it does","text":"

        Checks for pathlib.Path.with_suffix() calls where the given suffix does not have a leading dot or the given suffix is a single dot \".\".

        ","tags":["PTH210"]},{"location":"rules/invalid-pathlib-with-suffix/#why-is-this-bad","title":"Why is this bad?","text":"

        Path.with_suffix() will raise an error at runtime if the given suffix is not prefixed with a dot or it is a single dot \".\".

        ","tags":["PTH210"]},{"location":"rules/invalid-pathlib-with-suffix/#example","title":"Example","text":"
        path.with_suffix(\"py\")\n

        Use instead:

        path.with_suffix(\".py\")\n
        ","tags":["PTH210"]},{"location":"rules/invalid-pathlib-with-suffix/#known-problems","title":"Known problems","text":"

        This rule is likely to have false negatives, as Ruff can only emit the lint if it can say for sure that a binding refers to a Path object at runtime. Due to type inference limitations, Ruff is currently only confident about this if it can see that the binding originates from a function parameter annotated with Path or from a direct assignment to a Path() constructor call.

        ","tags":["PTH210"]},{"location":"rules/invalid-pathlib-with-suffix/#fix-safety","title":"Fix safety","text":"

        The fix for this rule adds a leading period to the string passed to the with_suffix() call. This fix is marked as unsafe, as it changes runtime behaviour: the call would previously always have raised an exception, but no longer will.

        Moreover, it's impossible to determine if this is the correct fix for a given situation (it's possible that the string was correct but was being passed to the wrong method entirely, for example).

        No fix is offered if the suffix \".\" is given, since the intent is unclear.

        ","tags":["PTH210"]},{"location":"rules/invalid-print-syntax/","title":"invalid-print-syntax (F633)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F633"]},{"location":"rules/invalid-print-syntax/#what-it-does","title":"What it does","text":"

        Checks for print statements that use the >> syntax.

        ","tags":["F633"]},{"location":"rules/invalid-print-syntax/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 2, the print statement can be used with the >> syntax to print to a file-like object. This print >> sys.stderr syntax no longer exists in Python 3, where print is only a function, not a statement.

        Instead, use the file keyword argument to the print function, the sys.stderr.write function, or the logging module.

        ","tags":["F633"]},{"location":"rules/invalid-print-syntax/#example","title":"Example","text":"
        from __future__ import print_function\nimport sys\n\nprint >> sys.stderr, \"Hello, world!\"\n

        Use instead:

        print(\"Hello, world!\", file=sys.stderr)\n

        Or:

        import sys\n\nsys.stderr.write(\"Hello, world!\\n\")\n

        Or:

        import logging\n\nlogging.error(\"Hello, world!\")\n
        ","tags":["F633"]},{"location":"rules/invalid-print-syntax/#references","title":"References","text":"
        • Python documentation: print
        ","tags":["F633"]},{"location":"rules/invalid-pyproject-toml/","title":"invalid-pyproject-toml (RUF200)","text":"","tags":["RUF200"]},{"location":"rules/invalid-pyproject-toml/#what-it-does","title":"What it does","text":"

        Checks for any pyproject.toml that does not conform to the schema from the relevant PEPs.

        ","tags":["RUF200"]},{"location":"rules/invalid-pyproject-toml/#why-is-this-bad","title":"Why is this bad?","text":"

        Your project may contain invalid metadata or configuration without you noticing

        ","tags":["RUF200"]},{"location":"rules/invalid-pyproject-toml/#example","title":"Example","text":"
        [project]\nname = \"crab\"\nversion = \"1.0.0\"\nauthors = [\"Ferris the Crab <ferris@example.org>\"]\n

        Use instead:

        [project]\nname = \"crab\"\nversion = \"1.0.0\"\nauthors = [\n  { name = \"Ferris the Crab\", email = \"ferris@example.org\" }\n]\n
        ","tags":["RUF200"]},{"location":"rules/invalid-pyproject-toml/#references","title":"References","text":"
        • Specification of [project] in pyproject.toml
        • Specification of [build-system] in pyproject.toml
        • Draft but implemented license declaration extensions
        ","tags":["RUF200"]},{"location":"rules/invalid-rule-code/","title":"invalid-rule-code (RUF102)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF102"]},{"location":"rules/invalid-rule-code/#what-it-does","title":"What it does","text":"

        Checks for noqa codes that are invalid.

        ","tags":["RUF102"]},{"location":"rules/invalid-rule-code/#why-is-this-bad","title":"Why is this bad?","text":"

        Invalid rule codes serve no purpose and may indicate outdated code suppressions.

        ","tags":["RUF102"]},{"location":"rules/invalid-rule-code/#example","title":"Example","text":"
        import os  # noqa: XYZ999\n

        Use instead:

        import os\n

        Or if there are still valid codes needed:

        import os  # noqa: E402\n
        ","tags":["RUF102"]},{"location":"rules/invalid-rule-code/#options","title":"Options","text":"
        • lint.external
        ","tags":["RUF102"]},{"location":"rules/invalid-str-return-type/","title":"invalid-str-return-type (PLE0307)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0307"]},{"location":"rules/invalid-str-return-type/#what-it-does","title":"What it does","text":"

        Checks for __str__ implementations that return a type other than str.

        ","tags":["PLE0307"]},{"location":"rules/invalid-str-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __str__ method should return a str object. Returning a different type may cause unexpected behavior.

        ","tags":["PLE0307"]},{"location":"rules/invalid-str-return-type/#example","title":"Example","text":"
        class Foo:\n    def __str__(self):\n        return True\n

        Use instead:

        class Foo:\n    def __str__(self):\n        return \"Foo\"\n
        ","tags":["PLE0307"]},{"location":"rules/invalid-str-return-type/#references","title":"References","text":"
        • Python documentation: The __str__ method
        ","tags":["PLE0307"]},{"location":"rules/invalid-todo-capitalization/","title":"invalid-todo-capitalization (TD006)","text":"

        Derived from the flake8-todos linter.

        Fix is always available.

        ","tags":["TD006"]},{"location":"rules/invalid-todo-capitalization/#what-it-does","title":"What it does","text":"

        Checks that a \"TODO\" tag is properly capitalized (i.e., that the tag is uppercase).

        ","tags":["TD006"]},{"location":"rules/invalid-todo-capitalization/#why-is-this-bad","title":"Why is this bad?","text":"

        Capitalizing the \"TODO\" in a TODO comment is a convention that makes it easier for future readers to identify TODOs.

        ","tags":["TD006"]},{"location":"rules/invalid-todo-capitalization/#example","title":"Example","text":"
        # todo(charlie): capitalize this\n

        Use instead:

        # TODO(charlie): this is capitalized\n
        ","tags":["TD006"]},{"location":"rules/invalid-todo-tag/","title":"invalid-todo-tag (TD001)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD001"]},{"location":"rules/invalid-todo-tag/#what-it-does","title":"What it does","text":"

        Checks that a TODO comment is labelled with \"TODO\".

        ","tags":["TD001"]},{"location":"rules/invalid-todo-tag/#why-is-this-bad","title":"Why is this bad?","text":"

        Ambiguous tags reduce code visibility and can lead to dangling TODOs. For example, if a comment is tagged with \"FIXME\" rather than \"TODO\", it may be overlooked by future readers.

        Note that this rule will only flag \"FIXME\" and \"XXX\" tags as incorrect.

        ","tags":["TD001"]},{"location":"rules/invalid-todo-tag/#example","title":"Example","text":"
        # FIXME(ruff): this should get fixed!\n

        Use instead:

        # TODO(ruff): this is now fixed!\n
        ","tags":["TD001"]},{"location":"rules/io-error/","title":"io-error (E902)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E902"]},{"location":"rules/io-error/#what-it-does","title":"What it does","text":"

        This is not a regular diagnostic; instead, it's raised when a file cannot be read from disk.

        ","tags":["E902"]},{"location":"rules/io-error/#why-is-this-bad","title":"Why is this bad?","text":"

        An IOError indicates an error in the development setup. For example, the user may not have permissions to read a given file, or the filesystem may contain a broken symlink.

        ","tags":["E902"]},{"location":"rules/io-error/#example","title":"Example","text":"

        On Linux or macOS:

        $ echo 'print(\"hello world!\")' > a.py\n$ chmod 000 a.py\n$ ruff a.py\na.py:1:1: E902 Permission denied (os error 13)\nFound 1 error.\n
        ","tags":["E902"]},{"location":"rules/io-error/#references","title":"References","text":"
        • UNIX Permissions introduction
        • Command Line Basics: Symbolic Links
        ","tags":["E902"]},{"location":"rules/is-literal/","title":"is-literal (F632)","text":"

        Derived from the Pyflakes linter.

        Fix is always available.

        ","tags":["F632"]},{"location":"rules/is-literal/#what-it-does","title":"What it does","text":"

        Checks for is and is not comparisons against literals, like integers, strings, or lists.

        ","tags":["F632"]},{"location":"rules/is-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        The is and is not comparators operate on identity, in that they check whether two objects are the same object. If the objects are not the same object, the comparison will always be False. Using is and is not with constant literals often works \"by accident\", but are not guaranteed to produce the expected result.

        As of Python 3.8, using is and is not with constant literals will produce a SyntaxWarning.

        This rule will also flag is and is not comparisons against non-constant literals, like lists, sets, and dictionaries. While such comparisons will not raise a SyntaxWarning, they are still likely to be incorrect, as they will compare the identities of the objects instead of their values, which will always evaluate to False.

        Instead, use == and != to compare literals, which will compare the values of the objects instead of their identities.

        ","tags":["F632"]},{"location":"rules/is-literal/#example","title":"Example","text":"
        x = 200\nif x is 200:\n    print(\"It's 200!\")\n

        Use instead:

        x = 200\nif x == 200:\n    print(\"It's 200!\")\n
        ","tags":["F632"]},{"location":"rules/is-literal/#references","title":"References","text":"
        • Python documentation: Identity comparisons
        • Python documentation: Value comparisons
        • Why does Python log a SyntaxWarning for \u2018is\u2019 with literals? by Adam Johnson
        ","tags":["F632"]},{"location":"rules/isinstance-type-none/","title":"isinstance-type-none (FURB168)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB168"]},{"location":"rules/isinstance-type-none/#what-it-does","title":"What it does","text":"

        Checks for uses of isinstance that check if an object is of type None.

        ","tags":["FURB168"]},{"location":"rules/isinstance-type-none/#why-is-this-bad","title":"Why is this bad?","text":"

        There is only ever one instance of None, so it is more efficient and readable to use the is operator to check if an object is None.

        ","tags":["FURB168"]},{"location":"rules/isinstance-type-none/#example","title":"Example","text":"
        isinstance(obj, type(None))\n

        Use instead:

        obj is None\n
        ","tags":["FURB168"]},{"location":"rules/isinstance-type-none/#fix-safety","title":"Fix safety","text":"

        The fix will be marked as unsafe if there are any comments within the call.

        ","tags":["FURB168"]},{"location":"rules/isinstance-type-none/#references","title":"References","text":"
        • Python documentation: isinstance
        • Python documentation: None
        • Python documentation: type
        • Python documentation: Identity comparisons
        ","tags":["FURB168"]},{"location":"rules/iter-method-return-iterable/","title":"iter-method-return-iterable (PYI045)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI045"]},{"location":"rules/iter-method-return-iterable/#what-it-does","title":"What it does","text":"

        Checks for __iter__ methods in stubs that return Iterable[T] instead of an Iterator[T].

        ","tags":["PYI045"]},{"location":"rules/iter-method-return-iterable/#why-is-this-bad","title":"Why is this bad?","text":"

        __iter__ methods should always should return an Iterator of some kind, not an Iterable.

        In Python, an Iterable is an object that has an __iter__ method; an Iterator is an object that has __iter__ and __next__ methods. All __iter__ methods are expected to return Iterators. Type checkers may not always recognize an object as being iterable if its __iter__ method does not return an Iterator.

        Every Iterator is an Iterable, but not every Iterable is an Iterator. For example, list is an Iterable, but not an Iterator; you can obtain an iterator over a list's elements by passing the list to iter():

        >>> import collections.abc\n>>> x = [42]\n>>> isinstance(x, collections.abc.Iterable)\nTrue\n>>> isinstance(x, collections.abc.Iterator)\nFalse\n>>> next(x)\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: 'list' object is not an iterator\n>>> y = iter(x)\n>>> isinstance(y, collections.abc.Iterable)\nTrue\n>>> isinstance(y, collections.abc.Iterator)\nTrue\n>>> next(y)\n42\n

        Using Iterable rather than Iterator as a return type for an __iter__ methods would imply that you would not necessarily be able to call next() on the returned object, violating the expectations of the interface.

        ","tags":["PYI045"]},{"location":"rules/iter-method-return-iterable/#example","title":"Example","text":"
        import collections.abc\n\n\nclass Klass:\n    def __iter__(self) -> collections.abc.Iterable[str]: ...\n

        Use instead:

        import collections.abc\n\n\nclass Klass:\n    def __iter__(self) -> collections.abc.Iterator[str]: ...\n
        ","tags":["PYI045"]},{"location":"rules/iteration-over-set/","title":"iteration-over-set (PLC0208)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLC0208"]},{"location":"rules/iteration-over-set/#what-it-does","title":"What it does","text":"

        Checks for iteration over a set literal where each element in the set is itself a literal value.

        ","tags":["PLC0208"]},{"location":"rules/iteration-over-set/#why-is-this-bad","title":"Why is this bad?","text":"

        Iterating over a set is less efficient than iterating over a sequence type, like list or tuple.

        ","tags":["PLC0208"]},{"location":"rules/iteration-over-set/#example","title":"Example","text":"
        for number in {1, 2, 3}:\n    ...\n

        Use instead:

        for number in (1, 2, 3):\n    ...\n
        ","tags":["PLC0208"]},{"location":"rules/iteration-over-set/#references","title":"References","text":"
        • Python documentation: set
        ","tags":["PLC0208"]},{"location":"rules/jinja2-autoescape-false/","title":"jinja2-autoescape-false (S701)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S701"]},{"location":"rules/jinja2-autoescape-false/#what-it-does","title":"What it does","text":"

        Checks for jinja2 templates that use autoescape=False.

        ","tags":["S701"]},{"location":"rules/jinja2-autoescape-false/#why-is-this-bad","title":"Why is this bad?","text":"

        jinja2 templates that use autoescape=False are vulnerable to cross-site scripting (XSS) attacks that allow attackers to execute arbitrary JavaScript.

        By default, jinja2 sets autoescape to False, so it is important to set autoescape=True or use the select_autoescape function to mitigate XSS vulnerabilities.

        ","tags":["S701"]},{"location":"rules/jinja2-autoescape-false/#example","title":"Example","text":"
        import jinja2\n\njinja2.Environment(loader=jinja2.FileSystemLoader(\".\"))\n

        Use instead:

        import jinja2\n\njinja2.Environment(loader=jinja2.FileSystemLoader(\".\"), autoescape=True)\n
        ","tags":["S701"]},{"location":"rules/jinja2-autoescape-false/#references","title":"References","text":"
        • Jinja documentation: API
        • Common Weakness Enumeration: CWE-94
        ","tags":["S701"]},{"location":"rules/jump-statement-in-finally/","title":"jump-statement-in-finally (B012)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B012"]},{"location":"rules/jump-statement-in-finally/#what-it-does","title":"What it does","text":"

        Checks for break, continue, and return statements in finally blocks.

        ","tags":["B012"]},{"location":"rules/jump-statement-in-finally/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of break, continue, and return statements in finally blocks can cause exceptions to be silenced.

        finally blocks execute regardless of whether an exception is raised. If a break, continue, or return statement is reached in a finally block, any exception raised in the try or except blocks will be silenced.

        ","tags":["B012"]},{"location":"rules/jump-statement-in-finally/#example","title":"Example","text":"
        def speed(distance, time):\n    try:\n        return distance / time\n    except ZeroDivisionError:\n        raise ValueError(\"Time cannot be zero\")\n    finally:\n        return 299792458  # `ValueError` is silenced\n

        Use instead:

        def speed(distance, time):\n    try:\n        return distance / time\n    except ZeroDivisionError:\n        raise ValueError(\"Time cannot be zero\")\n
        ","tags":["B012"]},{"location":"rules/jump-statement-in-finally/#references","title":"References","text":"
        • Python documentation: The try statement
        ","tags":["B012"]},{"location":"rules/lambda-assignment/","title":"lambda-assignment (E731)","text":"

        Derived from the pycodestyle linter.

        Fix is sometimes available.

        ","tags":["E731"]},{"location":"rules/lambda-assignment/#what-it-does","title":"What it does","text":"

        Checks for lambda expressions which are assigned to a variable.

        ","tags":["E731"]},{"location":"rules/lambda-assignment/#why-is-this-bad","title":"Why is this bad?","text":"

        Per PEP 8, you should \"Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier.\"

        Using a def statement leads to better tracebacks, and the assignment itself negates the primary benefit of using a lambda expression (i.e., that it can be embedded inside another expression).

        ","tags":["E731"]},{"location":"rules/lambda-assignment/#example","title":"Example","text":"
        f = lambda x: 2 * x\n

        Use instead:

        def f(x):\n    return 2 * x\n
        ","tags":["E731"]},{"location":"rules/late-future-import/","title":"late-future-import (F404)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F404"]},{"location":"rules/late-future-import/#what-it-does","title":"What it does","text":"

        Checks for __future__ imports that are not located at the beginning of a file.

        ","tags":["F404"]},{"location":"rules/late-future-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Imports from __future__ must be placed the beginning of the file, before any other statements (apart from docstrings). The use of __future__ imports elsewhere is invalid and will result in a SyntaxError.

        ","tags":["F404"]},{"location":"rules/late-future-import/#example","title":"Example","text":"
        from pathlib import Path\n\nfrom __future__ import annotations\n

        Use instead:

        from __future__ import annotations\n\nfrom pathlib import Path\n
        ","tags":["F404"]},{"location":"rules/late-future-import/#references","title":"References","text":"
        • Python documentation: Future statements
        ","tags":["F404"]},{"location":"rules/len-test/","title":"len-test (PLC1802)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLC1802"]},{"location":"rules/len-test/#what-it-does","title":"What it does","text":"

        Checks for len calls on sequences in a boolean test context.

        ","tags":["PLC1802"]},{"location":"rules/len-test/#why-is-this-bad","title":"Why is this bad?","text":"

        Empty sequences are considered false in a boolean context. You can either remove the call to len or compare the length against a scalar.

        ","tags":["PLC1802"]},{"location":"rules/len-test/#example","title":"Example","text":"
        fruits = [\"orange\", \"apple\"]\nvegetables = []\n\nif len(fruits):\n    print(fruits)\n\nif not len(vegetables):\n    print(vegetables)\n

        Use instead:

        fruits = [\"orange\", \"apple\"]\nvegetables = []\n\nif fruits:\n    print(fruits)\n\nif not vegetables:\n    print(vegetables)\n
        ","tags":["PLC1802"]},{"location":"rules/len-test/#references","title":"References","text":"

        PEP 8: Programming Recommendations

        ","tags":["PLC1802"]},{"location":"rules/line-contains-fixme/","title":"line-contains-fixme (FIX001)","text":"

        Derived from the flake8-fixme linter.

        ","tags":["FIX001"]},{"location":"rules/line-contains-fixme/#what-it-does","title":"What it does","text":"

        Checks for \"FIXME\" comments.

        ","tags":["FIX001"]},{"location":"rules/line-contains-fixme/#why-is-this-bad","title":"Why is this bad?","text":"

        \"FIXME\" comments are used to describe an issue that should be resolved (usually, a bug or unexpected behavior).

        Consider resolving the issue before deploying the code.

        Note that if you use \"FIXME\" comments as a form of documentation, this rule may not be appropriate for your project.

        ","tags":["FIX001"]},{"location":"rules/line-contains-fixme/#example","title":"Example","text":"
        def speed(distance, time):\n    return distance / time  # FIXME: Raises ZeroDivisionError for time = 0.\n
        ","tags":["FIX001"]},{"location":"rules/line-contains-hack/","title":"line-contains-hack (FIX004)","text":"

        Derived from the flake8-fixme linter.

        ","tags":["FIX004"]},{"location":"rules/line-contains-hack/#what-it-does","title":"What it does","text":"

        Checks for \"HACK\" comments.

        ","tags":["FIX004"]},{"location":"rules/line-contains-hack/#why-is-this-bad","title":"Why is this bad?","text":"

        \"HACK\" comments are used to describe an issue that should be resolved (usually, a suboptimal solution or temporary workaround).

        Consider resolving the issue before deploying the code.

        Note that if you use \"HACK\" comments as a form of documentation, this rule may not be appropriate for your project.

        ","tags":["FIX004"]},{"location":"rules/line-contains-hack/#example","title":"Example","text":"
        import os\n\n\ndef running_windows():  # HACK: Use platform module instead.\n    try:\n        os.mkdir(\"C:\\\\Windows\\\\System32\\\\\")\n    except FileExistsError:\n        return True\n    else:\n        os.rmdir(\"C:\\\\Windows\\\\System32\\\\\")\n        return False\n
        ","tags":["FIX004"]},{"location":"rules/line-contains-todo/","title":"line-contains-todo (FIX002)","text":"

        Derived from the flake8-fixme linter.

        ","tags":["FIX002"]},{"location":"rules/line-contains-todo/#what-it-does","title":"What it does","text":"

        Checks for \"TODO\" comments.

        ","tags":["FIX002"]},{"location":"rules/line-contains-todo/#why-is-this-bad","title":"Why is this bad?","text":"

        \"TODO\" comments are used to describe an issue that should be resolved (usually, a missing feature, optimization, or refactoring opportunity).

        Consider resolving the issue before deploying the code.

        Note that if you use \"TODO\" comments as a form of documentation (e.g., to provide context for future work), this rule may not be appropriate for your project.

        ","tags":["FIX002"]},{"location":"rules/line-contains-todo/#example","title":"Example","text":"
        def greet(name):\n    return f\"Hello, {name}!\"  # TODO: Add support for custom greetings.\n
        ","tags":["FIX002"]},{"location":"rules/line-contains-xxx/","title":"line-contains-xxx (FIX003)","text":"

        Derived from the flake8-fixme linter.

        ","tags":["FIX003"]},{"location":"rules/line-contains-xxx/#what-it-does","title":"What it does","text":"

        Checks for \"XXX\" comments.

        ","tags":["FIX003"]},{"location":"rules/line-contains-xxx/#why-is-this-bad","title":"Why is this bad?","text":"

        \"XXX\" comments are used to describe an issue that should be resolved.

        Consider resolving the issue before deploying the code, or, at minimum, using a more descriptive comment tag (e.g, \"TODO\").

        ","tags":["FIX003"]},{"location":"rules/line-contains-xxx/#example","title":"Example","text":"
        def speed(distance, time):\n    return distance / time  # XXX: Raises ZeroDivisionError for time = 0.\n
        ","tags":["FIX003"]},{"location":"rules/line-too-long/","title":"line-too-long (E501)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E501"]},{"location":"rules/line-too-long/#what-it-does","title":"What it does","text":"

        Checks for lines that exceed the specified maximum character length.

        ","tags":["E501"]},{"location":"rules/line-too-long/#why-is-this-bad","title":"Why is this bad?","text":"

        Overlong lines can hurt readability. PEP 8, for example, recommends limiting lines to 79 characters. By default, this rule enforces a limit of 88 characters for compatibility with Black and the Ruff formatter, though that limit is configurable via the line-length setting.

        In the interest of pragmatism, this rule makes a few exceptions when determining whether a line is overlong. Namely, it:

        1. Ignores lines that consist of a single \"word\" (i.e., without any whitespace between its characters).
        2. Ignores lines that end with a URL, as long as the URL starts before the line-length threshold.
        3. Ignores line that end with a pragma comment (e.g., # type: ignore or # noqa), as long as the pragma comment starts before the line-length threshold. That is, a line will not be flagged as overlong if a pragma comment causes it to exceed the line length. (This behavior aligns with that of the Ruff formatter.)
        4. Ignores SPDX license identifiers and copyright notices (e.g., # SPDX-License-Identifier: MIT), which are machine-readable and should not wrap over multiple lines.

        If lint.pycodestyle.ignore-overlong-task-comments is true, this rule will also ignore comments that start with any of the specified lint.task-tags (e.g., # TODO:).

        ","tags":["E501"]},{"location":"rules/line-too-long/#example","title":"Example","text":"
        my_function(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10)\n

        Use instead:

        my_function(\n    param1, param2, param3, param4, param5,\n    param6, param7, param8, param9, param10\n)\n
        ","tags":["E501"]},{"location":"rules/line-too-long/#error-suppression","title":"Error suppression","text":"

        Hint: when suppressing E501 errors within multi-line strings (like docstrings), the noqa directive should come at the end of the string (after the closing triple quote), and will apply to the entire string, like so:

        \"\"\"Lorem ipsum dolor sit amet.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.\n\"\"\"  # noqa: E501\n
        ","tags":["E501"]},{"location":"rules/line-too-long/#options","title":"Options","text":"
        • line-length
        • lint.task-tags
        • lint.pycodestyle.ignore-overlong-task-comments
        • lint.pycodestyle.max-line-length
        ","tags":["E501"]},{"location":"rules/list-reverse-copy/","title":"list-reverse-copy (FURB187)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB187"]},{"location":"rules/list-reverse-copy/#what-it-does","title":"What it does","text":"

        Checks for list reversals that can be performed in-place in lieu of creating a new list.

        ","tags":["FURB187"]},{"location":"rules/list-reverse-copy/#why-is-this-bad","title":"Why is this bad?","text":"

        When reversing a list, it's more efficient to use the in-place method .reverse() instead of creating a new list, if the original list is no longer needed.

        ","tags":["FURB187"]},{"location":"rules/list-reverse-copy/#example","title":"Example","text":"
        l = [1, 2, 3]\nl = reversed(l)\n\nl = [1, 2, 3]\nl = list(reversed(l))\n\nl = [1, 2, 3]\nl = l[::-1]\n

        Use instead:

        l = [1, 2, 3]\nl.reverse()\n
        ","tags":["FURB187"]},{"location":"rules/list-reverse-copy/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as calling .reverse() on a list will mutate the list in-place, unlike reversed, which creates a new list and leaves the original list unchanged.

        If the list is referenced elsewhere, this could lead to unexpected behavior.

        ","tags":["FURB187"]},{"location":"rules/list-reverse-copy/#references","title":"References","text":"
        • Python documentation: More on Lists
        ","tags":["FURB187"]},{"location":"rules/literal-membership/","title":"literal-membership (PLR6201)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR6201"]},{"location":"rules/literal-membership/#what-it-does","title":"What it does","text":"

        Checks for membership tests on list and tuple literals.

        ","tags":["PLR6201"]},{"location":"rules/literal-membership/#why-is-this-bad","title":"Why is this bad?","text":"

        When testing for membership in a static sequence, prefer a set literal over a list or tuple, as Python optimizes set membership tests.

        ","tags":["PLR6201"]},{"location":"rules/literal-membership/#example","title":"Example","text":"
        1 in [1, 2, 3]\n

        Use instead:

        1 in {1, 2, 3}\n
        ","tags":["PLR6201"]},{"location":"rules/literal-membership/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as the use of a set literal will error at runtime if the sequence contains unhashable elements (like lists or dictionaries). While Ruff will attempt to infer the hashability of the elements, it may not always be able to do so.

        ","tags":["PLR6201"]},{"location":"rules/literal-membership/#references","title":"References","text":"
        • What\u2019s New In Python 3.2
        ","tags":["PLR6201"]},{"location":"rules/load-before-global-declaration/","title":"load-before-global-declaration (PLE0118)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0118"]},{"location":"rules/load-before-global-declaration/#what-it-does","title":"What it does","text":"

        Checks for uses of names that are declared as global prior to the relevant global declaration.

        ","tags":["PLE0118"]},{"location":"rules/load-before-global-declaration/#why-is-this-bad","title":"Why is this bad?","text":"

        The global declaration applies to the entire scope. Using a name that's declared as global in a given scope prior to the relevant global declaration is a SyntaxError.

        ","tags":["PLE0118"]},{"location":"rules/load-before-global-declaration/#example","title":"Example","text":"
        counter = 1\n\n\ndef increment():\n    print(f\"Adding 1 to {counter}\")\n    global counter\n    counter += 1\n

        Use instead:

        counter = 1\n\n\ndef increment():\n    global counter\n    print(f\"Adding 1 to {counter}\")\n    counter += 1\n
        ","tags":["PLE0118"]},{"location":"rules/load-before-global-declaration/#references","title":"References","text":"
        • Python documentation: The global statement
        ","tags":["PLE0118"]},{"location":"rules/log-exception-outside-except-handler/","title":"log-exception-outside-except-handler (LOG004)","text":"

        Derived from the flake8-logging linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["LOG004"]},{"location":"rules/log-exception-outside-except-handler/#what-it-does","title":"What it does","text":"

        Checks for .exception() logging calls outside of exception handlers.

        ","tags":["LOG004"]},{"location":"rules/log-exception-outside-except-handler/#why-is-this-bad","title":"Why is this bad?","text":"

        The documentation states:

        This function should only be called from an exception handler.

        Calling .exception() outside of an exception handler attaches None as exception information, leading to confusing messages:

        >>> logging.exception(\"example\")\nERROR:root:example\nNoneType: None\n
        ","tags":["LOG004"]},{"location":"rules/log-exception-outside-except-handler/#example","title":"Example","text":"
        import logging\n\nlogging.exception(\"Foobar\")\n

        Use instead:

        import logging\n\nlogging.error(\"Foobar\")\n
        ","tags":["LOG004"]},{"location":"rules/log-exception-outside-except-handler/#fix-safety","title":"Fix safety","text":"

        The fix, if available, will always be marked as unsafe, as it changes runtime behavior.

        ","tags":["LOG004"]},{"location":"rules/logging-config-insecure-listen/","title":"logging-config-insecure-listen (S612)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S612"]},{"location":"rules/logging-config-insecure-listen/#what-it-does","title":"What it does","text":"

        Checks for insecure logging.config.listen calls.

        ","tags":["S612"]},{"location":"rules/logging-config-insecure-listen/#why-is-this-bad","title":"Why is this bad?","text":"

        logging.config.listen starts a server that listens for logging configuration requests. This is insecure, as parts of the configuration are passed to the built-in eval function, which can be used to execute arbitrary code.

        ","tags":["S612"]},{"location":"rules/logging-config-insecure-listen/#example","title":"Example","text":"
        import logging\n\nlogging.config.listen(9999)\n
        ","tags":["S612"]},{"location":"rules/logging-config-insecure-listen/#references","title":"References","text":"
        • Python documentation: logging.config.listen()
        ","tags":["S612"]},{"location":"rules/logging-exc-info/","title":"logging-exc-info (G201)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G201"]},{"location":"rules/logging-exc-info/#what-it-does","title":"What it does","text":"

        Checks for uses of logging.error that pass exc_info=True.

        ","tags":["G201"]},{"location":"rules/logging-exc-info/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling logging.error with exc_info=True is equivalent to calling logging.exception. Using logging.exception is more concise, more readable, and conveys the intent of the logging statement more clearly.

        ","tags":["G201"]},{"location":"rules/logging-exc-info/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G201"]},{"location":"rules/logging-exc-info/#example","title":"Example","text":"
        import logging\n\ntry:\n    ...\nexcept ValueError:\n    logging.error(\"Exception occurred\", exc_info=True)\n

        Use instead:

        import logging\n\ntry:\n    ...\nexcept ValueError:\n    logging.exception(\"Exception occurred\")\n
        ","tags":["G201"]},{"location":"rules/logging-exc-info/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G201"]},{"location":"rules/logging-exc-info/#references","title":"References","text":"
        • Python documentation: logging.exception
        • Python documentation: exception
        • Python documentation: logging.error
        • Python documentation: error
        ","tags":["G201"]},{"location":"rules/logging-extra-attr-clash/","title":"logging-extra-attr-clash (G101)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#what-it-does","title":"What it does","text":"

        Checks for extra keywords in logging statements that clash with LogRecord attributes.

        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging module provides a mechanism for passing additional values to be logged using the extra keyword argument. These values are then passed to the LogRecord constructor.

        Providing a value via extra that clashes with one of the attributes of the LogRecord constructor will raise a KeyError when the LogRecord is constructed.

        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#example","title":"Example","text":"
        import logging\n\nlogging.basicConfig(format=\"%(name) - %(message)s\", level=logging.INFO)\n\nusername = \"Maria\"\n\nlogging.info(\"Something happened\", extra=dict(name=username))\n

        Use instead:

        import logging\n\nlogging.basicConfig(format=\"%(user_id)s - %(message)s\", level=logging.INFO)\n\nusername = \"Maria\"\n\nlogging.info(\"Something happened\", extra=dict(user_id=username))\n
        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#references","title":"References","text":"
        • Python documentation: LogRecord attributes
        ","tags":["G101"]},{"location":"rules/logging-f-string/","title":"logging-f-string (G004)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G004"]},{"location":"rules/logging-f-string/#what-it-does","title":"What it does","text":"

        Checks for uses of f-strings to format logging messages.

        ","tags":["G004"]},{"location":"rules/logging-f-string/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging module provides a mechanism for passing additional values to be logged using the extra keyword argument. This is more consistent, more efficient, and less error-prone than formatting the string directly.

        Using f-strings to format a logging message requires that Python eagerly format the string, even if the logging statement is never executed (e.g., if the log level is above the level of the logging statement), whereas using the extra keyword argument defers formatting until required.

        Additionally, the use of extra will ensure that the values are made available to all handlers, which can then be configured to log the values in a consistent manner.

        As an alternative to extra, passing values as arguments to the logging method can also be used to defer string formatting until required.

        ","tags":["G004"]},{"location":"rules/logging-f-string/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G004"]},{"location":"rules/logging-f-string/#example","title":"Example","text":"
        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(f\"{user} - Something happened\")\n

        Use instead:

        import logging\n\nlogging.basicConfig(format=\"%(user_id)s - %(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"Something happened\", extra=dict(user_id=user))\n

        Or:

        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"%s - Something happened\", user)\n
        ","tags":["G004"]},{"location":"rules/logging-f-string/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G004"]},{"location":"rules/logging-f-string/#references","title":"References","text":"
        • Python documentation: logging
        • Python documentation: Optimization
        ","tags":["G004"]},{"location":"rules/logging-percent-format/","title":"logging-percent-format (G002)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G002"]},{"location":"rules/logging-percent-format/#what-it-does","title":"What it does","text":"

        Checks for uses of printf-style format strings to format logging messages.

        ","tags":["G002"]},{"location":"rules/logging-percent-format/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging module provides a mechanism for passing additional values to be logged using the extra keyword argument. This is more consistent, more efficient, and less error-prone than formatting the string directly.

        Using printf-style format strings to format a logging message requires that Python eagerly format the string, even if the logging statement is never executed (e.g., if the log level is above the level of the logging statement), whereas using the extra keyword argument defers formatting until required.

        Additionally, the use of extra will ensure that the values are made available to all handlers, which can then be configured to log the values in a consistent manner.

        As an alternative to extra, passing values as arguments to the logging method can also be used to defer string formatting until required.

        ","tags":["G002"]},{"location":"rules/logging-percent-format/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G002"]},{"location":"rules/logging-percent-format/#example","title":"Example","text":"
        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"%s - Something happened\" % user)\n

        Use instead:

        import logging\n\nlogging.basicConfig(format=\"%(user_id)s - %(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"Something happened\", extra=dict(user_id=user))\n

        Or:

        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"%s - Something happened\", user)\n
        ","tags":["G002"]},{"location":"rules/logging-percent-format/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G002"]},{"location":"rules/logging-percent-format/#references","title":"References","text":"
        • Python documentation: logging
        • Python documentation: Optimization
        ","tags":["G002"]},{"location":"rules/logging-redundant-exc-info/","title":"logging-redundant-exc-info (G202)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#what-it-does","title":"What it does","text":"

        Checks for redundant exc_info keyword arguments in logging statements.

        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#why-is-this-bad","title":"Why is this bad?","text":"

        exc_info is True by default for logging.exception, and False by default for logging.error.

        Passing exc_info=True to logging.exception calls is redundant, as is passing exc_info=False to logging.error calls.

        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#example","title":"Example","text":"
        import logging\n\ntry:\n    ...\nexcept ValueError:\n    logging.exception(\"Exception occurred\", exc_info=True)\n

        Use instead:

        import logging\n\ntry:\n    ...\nexcept ValueError:\n    logging.exception(\"Exception occurred\")\n
        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#references","title":"References","text":"
        • Python documentation: logging.exception
        • Python documentation: exception
        • Python documentation: logging.error
        • Python documentation: error
        ","tags":["G202"]},{"location":"rules/logging-string-concat/","title":"logging-string-concat (G003)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G003"]},{"location":"rules/logging-string-concat/#what-it-does","title":"What it does","text":"

        Checks for uses string concatenation via the + operator to format logging messages.

        ","tags":["G003"]},{"location":"rules/logging-string-concat/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging module provides a mechanism for passing additional values to be logged using the extra keyword argument. This is more consistent, more efficient, and less error-prone than formatting the string directly.

        Using concatenation to format a logging message requires that Python eagerly format the string, even if the logging statement is never executed (e.g., if the log level is above the level of the logging statement), whereas using the extra keyword argument defers formatting until required.

        Additionally, the use of extra will ensure that the values are made available to all handlers, which can then be configured to log the values in a consistent manner.

        As an alternative to extra, passing values as arguments to the logging method can also be used to defer string formatting until required.

        ","tags":["G003"]},{"location":"rules/logging-string-concat/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G003"]},{"location":"rules/logging-string-concat/#example","title":"Example","text":"
        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(user + \" - Something happened\")\n

        Use instead:

        import logging\n\nlogging.basicConfig(format=\"%(user_id)s - %(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"Something happened\", extra=dict(user_id=user))\n

        Or:

        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"%s - Something happened\", user)\n
        ","tags":["G003"]},{"location":"rules/logging-string-concat/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G003"]},{"location":"rules/logging-string-concat/#references","title":"References","text":"
        • Python documentation: logging
        • Python documentation: Optimization
        ","tags":["G003"]},{"location":"rules/logging-string-format/","title":"logging-string-format (G001)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G001"]},{"location":"rules/logging-string-format/#what-it-does","title":"What it does","text":"

        Checks for uses of str.format to format logging messages.

        ","tags":["G001"]},{"location":"rules/logging-string-format/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging module provides a mechanism for passing additional values to be logged using the extra keyword argument. This is more consistent, more efficient, and less error-prone than formatting the string directly.

        Using str.format to format a logging message requires that Python eagerly format the string, even if the logging statement is never executed (e.g., if the log level is above the level of the logging statement), whereas using the extra keyword argument defers formatting until required.

        Additionally, the use of extra will ensure that the values are made available to all handlers, which can then be configured to log the values in a consistent manner.

        As an alternative to extra, passing values as arguments to the logging method can also be used to defer string formatting until required.

        ","tags":["G001"]},{"location":"rules/logging-string-format/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G001"]},{"location":"rules/logging-string-format/#example","title":"Example","text":"
        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"{} - Something happened\".format(user))\n

        Use instead:

        import logging\n\nlogging.basicConfig(format=\"%(user_id)s - %(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"Something happened\", extra={\"user_id\": user})\n

        Or:

        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"%s - Something happened\", user)\n
        ","tags":["G001"]},{"location":"rules/logging-string-format/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G001"]},{"location":"rules/logging-string-format/#references","title":"References","text":"
        • Python documentation: logging
        • Python documentation: Optimization
        ","tags":["G001"]},{"location":"rules/logging-too-few-args/","title":"logging-too-few-args (PLE1206)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1206"]},{"location":"rules/logging-too-few-args/#what-it-does","title":"What it does","text":"

        Checks for too few positional arguments for a logging format string.

        ","tags":["PLE1206"]},{"location":"rules/logging-too-few-args/#why-is-this-bad","title":"Why is this bad?","text":"

        A TypeError will be raised if the statement is run.

        ","tags":["PLE1206"]},{"location":"rules/logging-too-few-args/#example","title":"Example","text":"
        import logging\n\ntry:\n    function()\nexcept Exception as e:\n    logging.error(\"%s error occurred: %s\", e)\n    raise\n

        Use instead:

        import logging\n\ntry:\n    function()\nexcept Exception as e:\n    logging.error(\"%s error occurred: %s\", type(e), e)\n    raise\n
        ","tags":["PLE1206"]},{"location":"rules/logging-too-many-args/","title":"logging-too-many-args (PLE1205)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1205"]},{"location":"rules/logging-too-many-args/#what-it-does","title":"What it does","text":"

        Checks for too many positional arguments for a logging format string.

        ","tags":["PLE1205"]},{"location":"rules/logging-too-many-args/#why-is-this-bad","title":"Why is this bad?","text":"

        A TypeError will be raised if the statement is run.

        ","tags":["PLE1205"]},{"location":"rules/logging-too-many-args/#example","title":"Example","text":"
        import logging\n\ntry:\n    function()\nexcept Exception as e:\n    logging.error(\"Error occurred: %s\", type(e), e)\n    raise\n

        Use instead:

        import logging\n\ntry:\n    function()\nexcept Exception as e:\n    logging.error(\"%s error occurred: %s\", type(e), e)\n    raise\n
        ","tags":["PLE1205"]},{"location":"rules/logging-warn/","title":"logging-warn (G010)","text":"

        Derived from the flake8-logging-format linter.

        Fix is always available.

        ","tags":["G010"]},{"location":"rules/logging-warn/#what-it-does","title":"What it does","text":"

        Checks for uses of logging.warn and logging.Logger.warn.

        ","tags":["G010"]},{"location":"rules/logging-warn/#why-is-this-bad","title":"Why is this bad?","text":"

        logging.warn and logging.Logger.warn are deprecated in favor of logging.warning and logging.Logger.warning, which are functionally equivalent.

        ","tags":["G010"]},{"location":"rules/logging-warn/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G010"]},{"location":"rules/logging-warn/#example","title":"Example","text":"
        import logging\n\nlogging.warn(\"Something happened\")\n

        Use instead:

        import logging\n\nlogging.warning(\"Something happened\")\n
        ","tags":["G010"]},{"location":"rules/logging-warn/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G010"]},{"location":"rules/logging-warn/#references","title":"References","text":"
        • Python documentation: logging.warning
        • Python documentation: logging.Logger.warning
        ","tags":["G010"]},{"location":"rules/long-sleep-not-forever/","title":"long-sleep-not-forever (ASYNC116)","text":"

        Derived from the flake8-async linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["ASYNC116"]},{"location":"rules/long-sleep-not-forever/#what-it-does","title":"What it does","text":"

        Checks for uses of trio.sleep() or anyio.sleep() with a delay greater than 24 hours.

        ","tags":["ASYNC116"]},{"location":"rules/long-sleep-not-forever/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling sleep() with a delay greater than 24 hours is usually intended to sleep indefinitely. Instead of using a large delay, trio.sleep_forever() or anyio.sleep_forever() better conveys the intent.

        ","tags":["ASYNC116"]},{"location":"rules/long-sleep-not-forever/#example","title":"Example","text":"
        import trio\n\n\nasync def func():\n    await trio.sleep(86401)\n

        Use instead:

        import trio\n\n\nasync def func():\n    await trio.sleep_forever()\n
        ","tags":["ASYNC116"]},{"location":"rules/long-sleep-not-forever/#fix-safety","title":"Fix safety","text":"

        This fix is marked as unsafe as it changes program behavior.

        ","tags":["ASYNC116"]},{"location":"rules/loop-iterator-mutation/","title":"loop-iterator-mutation (B909)","text":"

        Derived from the flake8-bugbear linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["B909"]},{"location":"rules/loop-iterator-mutation/#what-it-does","title":"What it does","text":"

        Checks for mutations to an iterable during a loop iteration.

        ","tags":["B909"]},{"location":"rules/loop-iterator-mutation/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over an iterable, mutating the iterable can lead to unexpected behavior, like skipping elements or infinite loops.

        ","tags":["B909"]},{"location":"rules/loop-iterator-mutation/#example","title":"Example","text":"
        items = [1, 2, 3]\n\nfor item in items:\n    print(item)\n\n    # Create an infinite loop by appending to the list.\n    items.append(item)\n
        ","tags":["B909"]},{"location":"rules/loop-iterator-mutation/#references","title":"References","text":"
        • Python documentation: Mutable Sequence Types
        ","tags":["B909"]},{"location":"rules/loop-variable-overrides-iterator/","title":"loop-variable-overrides-iterator (B020)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B020"]},{"location":"rules/loop-variable-overrides-iterator/#what-it-does","title":"What it does","text":"

        Checks for loop control variables that override the loop iterable.

        ","tags":["B020"]},{"location":"rules/loop-variable-overrides-iterator/#why-is-this-bad","title":"Why is this bad?","text":"

        Loop control variables should not override the loop iterable, as this can lead to confusing behavior.

        Instead, use a distinct variable name for any loop control variables.

        ","tags":["B020"]},{"location":"rules/loop-variable-overrides-iterator/#example","title":"Example","text":"
        items = [1, 2, 3]\n\nfor items in items:\n    print(items)\n

        Use instead:

        items = [1, 2, 3]\n\nfor item in items:\n    print(item)\n
        ","tags":["B020"]},{"location":"rules/loop-variable-overrides-iterator/#references","title":"References","text":"
        • Python documentation: The for statement
        ","tags":["B020"]},{"location":"rules/lowercase-imported-as-non-lowercase/","title":"lowercase-imported-as-non-lowercase (N812)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N812"]},{"location":"rules/lowercase-imported-as-non-lowercase/#what-it-does","title":"What it does","text":"

        Checks for lowercase imports that are aliased to non-lowercase names.

        ","tags":["N812"]},{"location":"rules/lowercase-imported-as-non-lowercase/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends naming conventions for classes, functions, constants, and more. The use of inconsistent naming styles between import and alias names may lead readers to expect an import to be of another type (e.g., confuse a Python class with a constant).

        Import aliases should thus follow the same naming style as the member being imported.

        ","tags":["N812"]},{"location":"rules/lowercase-imported-as-non-lowercase/#example","title":"Example","text":"
        from example import myclassname as MyClassName\n

        Use instead:

        from example import myclassname\n
        ","tags":["N812"]},{"location":"rules/lowercase-imported-as-non-lowercase/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N812"]},{"location":"rules/lru-cache-with-maxsize-none/","title":"lru-cache-with-maxsize-none (UP033)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP033"]},{"location":"rules/lru-cache-with-maxsize-none/#what-it-does","title":"What it does","text":"

        Checks for uses of functools.lru_cache that set maxsize=None.

        ","tags":["UP033"]},{"location":"rules/lru-cache-with-maxsize-none/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3.9, functools.cache can be used as a drop-in replacement for functools.lru_cache(maxsize=None). When possible, prefer functools.cache as it is more readable and idiomatic.

        ","tags":["UP033"]},{"location":"rules/lru-cache-with-maxsize-none/#example","title":"Example","text":"
        import functools\n\n\n@functools.lru_cache(maxsize=None)\ndef foo(): ...\n

        Use instead:

        import functools\n\n\n@functools.cache\ndef foo(): ...\n
        ","tags":["UP033"]},{"location":"rules/lru-cache-with-maxsize-none/#options","title":"Options","text":"
        • target-version
        ","tags":["UP033"]},{"location":"rules/lru-cache-with-maxsize-none/#references","title":"References","text":"
        • Python documentation: @functools.cache
        ","tags":["UP033"]},{"location":"rules/lru-cache-without-parameters/","title":"lru-cache-without-parameters (UP011)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP011"]},{"location":"rules/lru-cache-without-parameters/#what-it-does","title":"What it does","text":"

        Checks for unnecessary parentheses on functools.lru_cache decorators.

        ","tags":["UP011"]},{"location":"rules/lru-cache-without-parameters/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3.8, functools.lru_cache can be used as a decorator without trailing parentheses, as long as no arguments are passed to it.

        ","tags":["UP011"]},{"location":"rules/lru-cache-without-parameters/#example","title":"Example","text":"
        import functools\n\n\n@functools.lru_cache()\ndef foo(): ...\n

        Use instead:

        import functools\n\n\n@functools.lru_cache\ndef foo(): ...\n
        ","tags":["UP011"]},{"location":"rules/lru-cache-without-parameters/#options","title":"Options","text":"
        • target-version
        ","tags":["UP011"]},{"location":"rules/lru-cache-without-parameters/#references","title":"References","text":"
        • Python documentation: @functools.lru_cache
        • Let lru_cache be used as a decorator with no arguments
        ","tags":["UP011"]},{"location":"rules/magic-value-comparison/","title":"magic-value-comparison (PLR2004)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR2004"]},{"location":"rules/magic-value-comparison/#what-it-does","title":"What it does","text":"

        Checks for the use of unnamed numerical constants (\"magic\") values in comparisons.

        ","tags":["PLR2004"]},{"location":"rules/magic-value-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of \"magic\" values can make code harder to read and maintain, as readers will have to infer the meaning of the value from the context. Such values are discouraged by PEP 8.

        For convenience, this rule excludes a variety of common values from the \"magic\" value definition, such as 0, 1, \"\", and \"__main__\".

        ","tags":["PLR2004"]},{"location":"rules/magic-value-comparison/#example","title":"Example","text":"
        def apply_discount(price: float) -> float:\n    if price <= 100:\n        return price / 2\n    else:\n        return price\n

        Use instead:

        MAX_DISCOUNT = 100\n\n\ndef apply_discount(price: float) -> float:\n    if price <= MAX_DISCOUNT:\n        return price / 2\n    else:\n        return price\n
        ","tags":["PLR2004"]},{"location":"rules/magic-value-comparison/#options","title":"Options","text":"
        • lint.pylint.allow-magic-value-types
        ","tags":["PLR2004"]},{"location":"rules/mako-templates/","title":"mako-templates (S702)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S702"]},{"location":"rules/mako-templates/#what-it-does","title":"What it does","text":"

        Checks for uses of the mako templates.

        ","tags":["S702"]},{"location":"rules/mako-templates/#why-is-this-bad","title":"Why is this bad?","text":"

        Mako templates allow HTML and JavaScript rendering by default, and are inherently open to XSS attacks. Ensure variables in all templates are properly sanitized via the n, h or x flags (depending on context). For example, to HTML escape the variable data, use ${ data |h }.

        ","tags":["S702"]},{"location":"rules/mako-templates/#example","title":"Example","text":"
        from mako.template import Template\n\nTemplate(\"hello\")\n

        Use instead:

        from mako.template import Template\n\nTemplate(\"hello |h\")\n
        ","tags":["S702"]},{"location":"rules/mako-templates/#references","title":"References","text":"
        • Mako documentation
        • OpenStack security: Cross site scripting XSS
        • Common Weakness Enumeration: CWE-80
        ","tags":["S702"]},{"location":"rules/manual-dict-comprehension/","title":"manual-dict-comprehension (PERF403)","text":"

        Derived from the Perflint linter.

        Fix is sometimes available.

        ","tags":["PERF403"]},{"location":"rules/manual-dict-comprehension/#what-it-does","title":"What it does","text":"

        Checks for for loops that can be replaced by a dictionary comprehension.

        ","tags":["PERF403"]},{"location":"rules/manual-dict-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        When creating or extending a dictionary in a for-loop, prefer a dictionary comprehension. Comprehensions are more readable and more performant.

        For example, when comparing {x: x for x in list(range(1000))} to the for loop version, the comprehension is ~10% faster on Python 3.11.

        Note that, as with all perflint rules, this is only intended as a micro-optimization, and will have a negligible impact on performance in most cases.

        ","tags":["PERF403"]},{"location":"rules/manual-dict-comprehension/#example","title":"Example","text":"
        pairs = ((\"a\", 1), (\"b\", 2))\nresult = {}\nfor x, y in pairs:\n    if y % 2:\n        result[x] = y\n

        Use instead:

        pairs = ((\"a\", 1), (\"b\", 2))\nresult = {x: y for x, y in pairs if y % 2}\n

        If you're appending to an existing dictionary, use the update method instead:

        pairs = ((\"a\", 1), (\"b\", 2))\nresult.update({x: y for x, y in pairs if y % 2})\n
        ","tags":["PERF403"]},{"location":"rules/manual-from-import/","title":"manual-from-import (PLR0402)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLR0402"]},{"location":"rules/manual-from-import/#what-it-does","title":"What it does","text":"

        Checks for submodule imports that are aliased to the submodule name.

        ","tags":["PLR0402"]},{"location":"rules/manual-from-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using the from keyword to import the submodule is more concise and readable.

        ","tags":["PLR0402"]},{"location":"rules/manual-from-import/#example","title":"Example","text":"
        import concurrent.futures as futures\n

        Use instead:

        from concurrent import futures\n
        ","tags":["PLR0402"]},{"location":"rules/manual-from-import/#references","title":"References","text":"
        • Python documentation: Submodules
        ","tags":["PLR0402"]},{"location":"rules/manual-list-comprehension/","title":"manual-list-comprehension (PERF401)","text":"

        Derived from the Perflint linter.

        Fix is sometimes available.

        ","tags":["PERF401"]},{"location":"rules/manual-list-comprehension/#what-it-does","title":"What it does","text":"

        Checks for for loops that can be replaced by a list comprehension.

        ","tags":["PERF401"]},{"location":"rules/manual-list-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        When creating a transformed list from an existing list using a for-loop, prefer a list comprehension. List comprehensions are more readable and more performant.

        Using the below as an example, the list comprehension is ~10% faster on Python 3.11, and ~25% faster on Python 3.10.

        Note that, as with all perflint rules, this is only intended as a micro-optimization, and will have a negligible impact on performance in most cases.

        ","tags":["PERF401"]},{"location":"rules/manual-list-comprehension/#example","title":"Example","text":"
        original = list(range(10000))\nfiltered = []\nfor i in original:\n    if i % 2:\n        filtered.append(i)\n

        Use instead:

        original = list(range(10000))\nfiltered = [x for x in original if x % 2]\n

        If you're appending to an existing list, use the extend method instead:

        original = list(range(10000))\nfiltered.extend(x for x in original if x % 2)\n

        Take care that if the original for-loop uses an assignment expression as a conditional, such as if match:=re.match(\"\\d+\",\"123\"), then the corresponding comprehension must wrap the assignment expression in parentheses to avoid a syntax error.

        ","tags":["PERF401"]},{"location":"rules/manual-list-copy/","title":"manual-list-copy (PERF402)","text":"

        Derived from the Perflint linter.

        ","tags":["PERF402"]},{"location":"rules/manual-list-copy/#what-it-does","title":"What it does","text":"

        Checks for for loops that can be replaced by a making a copy of a list.

        ","tags":["PERF402"]},{"location":"rules/manual-list-copy/#why-is-this-bad","title":"Why is this bad?","text":"

        When creating a copy of an existing list using a for-loop, prefer list or list.copy instead. Making a direct copy is more readable and more performant.

        Using the below as an example, the list-based copy is ~2x faster on Python 3.11.

        Note that, as with all perflint rules, this is only intended as a micro-optimization, and will have a negligible impact on performance in most cases.

        ","tags":["PERF402"]},{"location":"rules/manual-list-copy/#example","title":"Example","text":"
        original = list(range(10000))\nfiltered = []\nfor i in original:\n    filtered.append(i)\n

        Use instead:

        original = list(range(10000))\nfiltered = list(original)\n
        ","tags":["PERF402"]},{"location":"rules/map-int-version-parsing/","title":"map-int-version-parsing (RUF048)","text":"","tags":["RUF048"]},{"location":"rules/map-int-version-parsing/#what-it-does","title":"What it does","text":"

        Checks for calls of the form map(int, __version__.split(\".\")).

        ","tags":["RUF048"]},{"location":"rules/map-int-version-parsing/#why-is-this-bad","title":"Why is this bad?","text":"

        __version__ does not always contain integral-like elements.

        import matplotlib  # `__version__ == \"3.9.1.post-1\"` in our environment\n\n# ValueError: invalid literal for int() with base 10: 'post1'\ntuple(map(int, matplotlib.__version__.split(\".\")))\n

        See also Version specifiers | Packaging spec.

        ","tags":["RUF048"]},{"location":"rules/map-int-version-parsing/#example","title":"Example","text":"
        tuple(map(int, matplotlib.__version__.split(\".\")))\n

        Use instead:

        import packaging.version as version\n\nversion.parse(matplotlib.__version__)\n
        ","tags":["RUF048"]},{"location":"rules/math-constant/","title":"math-constant (FURB152)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB152"]},{"location":"rules/math-constant/#what-it-does","title":"What it does","text":"

        Checks for literals that are similar to constants in math module.

        ","tags":["FURB152"]},{"location":"rules/math-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        Hard-coding mathematical constants like \u03c0 increases code duplication, reduces readability, and may lead to a lack of precision.

        ","tags":["FURB152"]},{"location":"rules/math-constant/#example","title":"Example","text":"
        A = 3.141592 * r**2\n

        Use instead:

        A = math.pi * r**2\n
        ","tags":["FURB152"]},{"location":"rules/math-constant/#references","title":"References","text":"
        • Python documentation: math constants
        ","tags":["FURB152"]},{"location":"rules/meta-class-abc-meta/","title":"meta-class-abc-meta (FURB180)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB180"]},{"location":"rules/meta-class-abc-meta/#what-it-does","title":"What it does","text":"

        Checks for uses of metaclass=abc.ABCMeta to define abstract base classes (ABCs).

        ","tags":["FURB180"]},{"location":"rules/meta-class-abc-meta/#why-is-this-bad","title":"Why is this bad?","text":"

        Instead of class C(metaclass=abc.ABCMeta): ..., use class C(ABC): ... to define an abstract base class. Inheriting from the ABC wrapper class is semantically identical to setting metaclass=abc.ABCMeta, but more succinct.

        ","tags":["FURB180"]},{"location":"rules/meta-class-abc-meta/#example","title":"Example","text":"
        class C(metaclass=ABCMeta):\n    pass\n

        Use instead:

        class C(ABC):\n    pass\n
        ","tags":["FURB180"]},{"location":"rules/meta-class-abc-meta/#references","title":"References","text":"
        • Python documentation: abc.ABC
        • Python documentation: abc.ABCMeta
        ","tags":["FURB180"]},{"location":"rules/mismatched-section-underline-length/","title":"mismatched-section-underline-length (D409)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D409"]},{"location":"rules/mismatched-section-underline-length/#what-it-does","title":"What it does","text":"

        Checks for section underlines in docstrings that do not match the length of the corresponding section header.

        ","tags":["D409"]},{"location":"rules/mismatched-section-underline-length/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline numpy-style docstrings, and helps prevent incorrect syntax in docstrings using reStructuredText.

        Multiline numpy-style docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section has a section header and a section body, and there should be a series of underline characters in the line following the header. The length of the underline should exactly match the length of the section header.

        This rule enforces a consistent style for multiline numpy-style docstrings with sections. If your docstring uses reStructuredText, the rule also helps protect against incorrect reStructuredText syntax, which would cause errors if you tried to use a tool such as Sphinx to generate documentation from the docstring.

        This rule is enabled when using the numpy convention, and disabled when using the google or pep257 conventions.

        ","tags":["D409"]},{"location":"rules/mismatched-section-underline-length/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ---\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    ---\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ---\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D409"]},{"location":"rules/mismatched-section-underline-length/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D409"]},{"location":"rules/mismatched-section-underline-length/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D409"]},{"location":"rules/misplaced-bare-raise/","title":"misplaced-bare-raise (PLE0704)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0704"]},{"location":"rules/misplaced-bare-raise/#what-it-does","title":"What it does","text":"

        Checks for bare raise statements outside of exception handlers.

        ","tags":["PLE0704"]},{"location":"rules/misplaced-bare-raise/#why-is-this-bad","title":"Why is this bad?","text":"

        A bare raise statement without an exception object will re-raise the last exception that was active in the current scope, and is typically used within an exception handler to re-raise the caught exception.

        If a bare raise is used outside of an exception handler, it will generate an error due to the lack of an active exception.

        Note that a bare raise within a finally block will work in some cases (namely, when the exception is raised within the try block), but should be avoided as it can lead to confusing behavior.

        ","tags":["PLE0704"]},{"location":"rules/misplaced-bare-raise/#example","title":"Example","text":"
        from typing import Any\n\n\ndef is_some(obj: Any) -> bool:\n    if obj is None:\n        raise\n

        Use instead:

        from typing import Any\n\n\ndef is_some(obj: Any) -> bool:\n    if obj is None:\n        raise ValueError(\"`obj` cannot be `None`\")\n
        ","tags":["PLE0704"]},{"location":"rules/missing-blank-line-after-last-section/","title":"missing-blank-line-after-last-section (D413)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-last-section/#what-it-does","title":"What it does","text":"

        Checks for missing blank lines after the last section of a multiline docstring.

        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-last-section/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline docstrings.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, the rule is disabled when using the google, numpy, and pep257 conventions.

        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-last-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-last-section/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-last-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-summary/","title":"missing-blank-line-after-summary (D205)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D205"]},{"location":"rules/missing-blank-line-after-summary/#what-it-does","title":"What it does","text":"

        Checks for docstring summary lines that are not separated from the docstring description by one blank line.

        ","tags":["D205"]},{"location":"rules/missing-blank-line-after-summary/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that multi-line docstrings consist of \"a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description.\"

        ","tags":["D205"]},{"location":"rules/missing-blank-line-after-summary/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n    Sort the list in ascending order and return a copy of the\n    result using the bubble sort algorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the\n    result using the bubble sort algorithm.\n    \"\"\"\n
        ","tags":["D205"]},{"location":"rules/missing-blank-line-after-summary/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D205"]},{"location":"rules/missing-copyright-notice/","title":"missing-copyright-notice (CPY001)","text":"

        Derived from the flake8-copyright linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["CPY001"]},{"location":"rules/missing-copyright-notice/#what-it-does","title":"What it does","text":"

        Checks for the absence of copyright notices within Python files.

        Note that this check only searches within the first 4096 bytes of the file.

        ","tags":["CPY001"]},{"location":"rules/missing-copyright-notice/#why-is-this-bad","title":"Why is this bad?","text":"

        In some codebases, it's common to have a license header at the top of every file. This rule ensures that the license header is present.

        ","tags":["CPY001"]},{"location":"rules/missing-copyright-notice/#options","title":"Options","text":"
        • lint.flake8-copyright.author
        • lint.flake8-copyright.min-file-size
        • lint.flake8-copyright.notice-rgx
        ","tags":["CPY001"]},{"location":"rules/missing-dashed-underline-after-section/","title":"missing-dashed-underline-after-section (D407)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D407"]},{"location":"rules/missing-dashed-underline-after-section/#what-it-does","title":"What it does","text":"

        Checks for section headers in docstrings that are not followed by underlines.

        ","tags":["D407"]},{"location":"rules/missing-dashed-underline-after-section/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline numpy-style docstrings, and helps prevent incorrect syntax in docstrings using reStructuredText.

        Multiline numpy-style docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section has a section header and a section body, and the header should be followed by a series of underline characters in the following line.

        This rule enforces a consistent style for multiline numpy-style docstrings with sections. If your docstring uses reStructuredText, the rule also helps protect against incorrect reStructuredText syntax, which would cause errors if you tried to use a tool such as Sphinx to generate documentation from the docstring.

        This rule is enabled when using the numpy convention, and disabled when using the google or pep257 conventions.

        ","tags":["D407"]},{"location":"rules/missing-dashed-underline-after-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n\n    float\n        Speed as distance divided by time.\n\n    Raises\n\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D407"]},{"location":"rules/missing-dashed-underline-after-section/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D407"]},{"location":"rules/missing-dashed-underline-after-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D407"]},{"location":"rules/missing-f-string-syntax/","title":"missing-f-string-syntax (RUF027)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF027"]},{"location":"rules/missing-f-string-syntax/#what-it-does","title":"What it does","text":"

        Searches for strings that look like they were meant to be f-strings, but are missing an f prefix.

        ","tags":["RUF027"]},{"location":"rules/missing-f-string-syntax/#why-is-this-bad","title":"Why is this bad?","text":"

        Expressions inside curly braces are only evaluated if the string has an f prefix.

        ","tags":["RUF027"]},{"location":"rules/missing-f-string-syntax/#details","title":"Details","text":"

        There are many possible string literals which are not meant to be f-strings despite containing f-string-like syntax. As such, this lint ignores all strings where one of the following conditions applies:

        1. The string is a standalone expression. For example, the rule ignores all docstrings.
        2. The string is part of a function call with argument names that match at least one variable (for example: format(\"Message: {value}\", value=\"Hello World\"))
        3. The string (or a parent expression of the string) has a direct method call on it (for example: \"{value}\".format(...))
        4. The string has no {...} expression sections, or uses invalid f-string syntax.
        5. The string references variables that are not in scope, or it doesn't capture variables at all.
        6. Any format specifiers in the potential f-string are invalid.
        7. The string is part of a function call that is known to expect a template string rather than an evaluated f-string: for example, a logging call, a gettext call, or a FastAPI path.
        ","tags":["RUF027"]},{"location":"rules/missing-f-string-syntax/#example","title":"Example","text":"
        name = \"Sarah\"\nday_of_week = \"Tuesday\"\nprint(\"Hello {name}! It is {day_of_week} today!\")\n

        Use instead:

        name = \"Sarah\"\nday_of_week = \"Tuesday\"\nprint(f\"Hello {name}! It is {day_of_week} today!\")\n
        ","tags":["RUF027"]},{"location":"rules/missing-f-string-syntax/#fix-safety","title":"Fix safety","text":"

        This fix will always change the behavior of the program and, despite the precautions detailed above, this may be undesired. As such the fix is always marked as unsafe.

        ","tags":["RUF027"]},{"location":"rules/missing-new-line-after-section-name/","title":"missing-new-line-after-section-name (D406)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D406"]},{"location":"rules/missing-new-line-after-section-name/#what-it-does","title":"What it does","text":"

        Checks for section headers in docstrings that are followed by non-newline characters.

        ","tags":["D406"]},{"location":"rules/missing-new-line-after-section-name/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline numpy-style docstrings.

        Multiline numpy-style docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section has a section header and a section body. The section header should be followed by a newline, rather than by some other character (like a colon).

        This rule is enabled when using the numpy convention, and disabled when using the google or pep257 conventions.

        ","tags":["D406"]},{"location":"rules/missing-new-line-after-section-name/#example","title":"Example","text":"
        # The `Parameters`, `Returns` and `Raises` section headers are all followed\n# by a colon in this function's docstring:\ndef calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters:\n    -----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns:\n    --------\n    float\n        Speed as distance divided by time.\n\n    Raises:\n    -------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D406"]},{"location":"rules/missing-new-line-after-section-name/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D406"]},{"location":"rules/missing-new-line-after-section-name/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D406"]},{"location":"rules/missing-newline-at-end-of-file/","title":"missing-newline-at-end-of-file (W292)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["W292"]},{"location":"rules/missing-newline-at-end-of-file/#what-it-does","title":"What it does","text":"

        Checks for files missing a new line at the end of the file.

        ","tags":["W292"]},{"location":"rules/missing-newline-at-end-of-file/#why-is-this-bad","title":"Why is this bad?","text":"

        Trailing blank lines in a file are superfluous.

        However, the last line of the file should end with a newline.

        ","tags":["W292"]},{"location":"rules/missing-newline-at-end-of-file/#example","title":"Example","text":"
        spam(1)\n

        Use instead:

        spam(1)\\n\n
        ","tags":["W292"]},{"location":"rules/missing-required-import/","title":"missing-required-import (I002)","text":"

        Derived from the isort linter.

        Fix is always available.

        ","tags":["I002"]},{"location":"rules/missing-required-import/#what-it-does","title":"What it does","text":"

        Adds any required imports, as specified by the user, to the top of the file.

        ","tags":["I002"]},{"location":"rules/missing-required-import/#why-is-this-bad","title":"Why is this bad?","text":"

        In some projects, certain imports are required to be present in all files. For example, some projects assume that from __future__ import annotations is enabled, and thus require that import to be present in all files. Omitting a \"required\" import (as specified by the user) can cause errors or unexpected behavior.

        ","tags":["I002"]},{"location":"rules/missing-required-import/#example","title":"Example","text":"
        import typing\n

        Use instead:

        from __future__ import annotations\n\nimport typing\n
        ","tags":["I002"]},{"location":"rules/missing-required-import/#options","title":"Options","text":"
        • lint.isort.required-imports
        ","tags":["I002"]},{"location":"rules/missing-return-type-class-method/","title":"missing-return-type-class-method (ANN206)","text":"

        Derived from the flake8-annotations linter.

        Fix is sometimes available.

        ","tags":["ANN206"]},{"location":"rules/missing-return-type-class-method/#what-it-does","title":"What it does","text":"

        Checks that class methods have return type annotations.

        ","tags":["ANN206"]},{"location":"rules/missing-return-type-class-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the return types of functions. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any returned values, and the types expected by callers, match expectation.

        ","tags":["ANN206"]},{"location":"rules/missing-return-type-class-method/#example","title":"Example","text":"
        class Foo:\n    @classmethod\n    def bar(cls):\n        return 1\n

        Use instead:

        class Foo:\n    @classmethod\n    def bar(cls) -> int:\n        return 1\n
        ","tags":["ANN206"]},{"location":"rules/missing-return-type-private-function/","title":"missing-return-type-private-function (ANN202)","text":"

        Derived from the flake8-annotations linter.

        Fix is sometimes available.

        ","tags":["ANN202"]},{"location":"rules/missing-return-type-private-function/#what-it-does","title":"What it does","text":"

        Checks that private functions and methods have return type annotations.

        ","tags":["ANN202"]},{"location":"rules/missing-return-type-private-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the return types of functions. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any returned values, and the types expected by callers, match expectation.

        ","tags":["ANN202"]},{"location":"rules/missing-return-type-private-function/#example","title":"Example","text":"
        def _add(a, b):\n    return a + b\n

        Use instead:

        def _add(a: int, b: int) -> int:\n    return a + b\n
        ","tags":["ANN202"]},{"location":"rules/missing-return-type-private-function/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for some Python versions, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["ANN202"]},{"location":"rules/missing-return-type-private-function/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["ANN202"]},{"location":"rules/missing-return-type-special-method/","title":"missing-return-type-special-method (ANN204)","text":"

        Derived from the flake8-annotations linter.

        Fix is sometimes available.

        ","tags":["ANN204"]},{"location":"rules/missing-return-type-special-method/#what-it-does","title":"What it does","text":"

        Checks that \"special\" methods, like __init__, __new__, and __call__, have return type annotations.

        ","tags":["ANN204"]},{"location":"rules/missing-return-type-special-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the return types of functions. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any returned values, and the types expected by callers, match expectation.

        Note that type checkers often allow you to omit the return type annotation for __init__ methods, as long as at least one argument has a type annotation. To opt in to this behavior, use the mypy-init-return setting in your pyproject.toml or ruff.toml file:

        [tool.ruff.lint.flake8-annotations]\nmypy-init-return = true\n
        ","tags":["ANN204"]},{"location":"rules/missing-return-type-special-method/#example","title":"Example","text":"
        class Foo:\n    def __init__(self, x: int):\n        self.x = x\n

        Use instead:

        class Foo:\n    def __init__(self, x: int) -> None:\n        self.x = x\n
        ","tags":["ANN204"]},{"location":"rules/missing-return-type-static-method/","title":"missing-return-type-static-method (ANN205)","text":"

        Derived from the flake8-annotations linter.

        Fix is sometimes available.

        ","tags":["ANN205"]},{"location":"rules/missing-return-type-static-method/#what-it-does","title":"What it does","text":"

        Checks that static methods have return type annotations.

        ","tags":["ANN205"]},{"location":"rules/missing-return-type-static-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the return types of functions. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any returned values, and the types expected by callers, match expectation.

        ","tags":["ANN205"]},{"location":"rules/missing-return-type-static-method/#example","title":"Example","text":"
        class Foo:\n    @staticmethod\n    def bar():\n        return 1\n

        Use instead:

        class Foo:\n    @staticmethod\n    def bar() -> int:\n        return 1\n
        ","tags":["ANN205"]},{"location":"rules/missing-return-type-undocumented-public-function/","title":"missing-return-type-undocumented-public-function (ANN201)","text":"

        Derived from the flake8-annotations linter.

        Fix is sometimes available.

        ","tags":["ANN201"]},{"location":"rules/missing-return-type-undocumented-public-function/#what-it-does","title":"What it does","text":"

        Checks that public functions and methods have return type annotations.

        ","tags":["ANN201"]},{"location":"rules/missing-return-type-undocumented-public-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the return types of functions. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any returned values, and the types expected by callers, match expectation.

        ","tags":["ANN201"]},{"location":"rules/missing-return-type-undocumented-public-function/#example","title":"Example","text":"
        def add(a, b):\n    return a + b\n

        Use instead:

        def add(a: int, b: int) -> int:\n    return a + b\n
        ","tags":["ANN201"]},{"location":"rules/missing-return-type-undocumented-public-function/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for some Python versions, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["ANN201"]},{"location":"rules/missing-return-type-undocumented-public-function/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["ANN201"]},{"location":"rules/missing-section-name-colon/","title":"missing-section-name-colon (D416)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D416"]},{"location":"rules/missing-section-name-colon/#what-it-does","title":"What it does","text":"

        Checks for docstring section headers that do not end with a colon.

        ","tags":["D416"]},{"location":"rules/missing-section-name-colon/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline Google-style docstrings. If a multiline Google-style docstring consists of multiple sections, each section header should end with a colon.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body.

        This rule is enabled when using the google convention, and disabled when using the pep257 and numpy conventions.

        ","tags":["D416"]},{"location":"rules/missing-section-name-colon/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns\n        Speed as distance divided by time.\n\n    Raises\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D416"]},{"location":"rules/missing-section-name-colon/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D416"]},{"location":"rules/missing-section-name-colon/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • Google Style Guide
        ","tags":["D416"]},{"location":"rules/missing-section-underline-after-name/","title":"missing-section-underline-after-name (D408)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D408"]},{"location":"rules/missing-section-underline-after-name/#what-it-does","title":"What it does","text":"

        Checks for section underlines in docstrings that are not on the line immediately following the section name.

        ","tags":["D408"]},{"location":"rules/missing-section-underline-after-name/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline numpy-style docstrings, and helps prevent incorrect syntax in docstrings using reStructuredText.

        Multiline numpy-style docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section has a header and a body. There should be a series of underline characters in the line immediately below the header.

        This rule enforces a consistent style for multiline numpy-style docstrings with sections. If your docstring uses reStructuredText, the rule also helps protect against incorrect reStructuredText syntax, which would cause errors if you tried to use a tool such as Sphinx to generate documentation from the docstring.

        This rule is enabled when using the numpy convention, and disabled when using the google or pep257 conventions.

        ","tags":["D408"]},{"location":"rules/missing-section-underline-after-name/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D408"]},{"location":"rules/missing-section-underline-after-name/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D408"]},{"location":"rules/missing-section-underline-after-name/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D408"]},{"location":"rules/missing-space-after-todo-colon/","title":"missing-space-after-todo-colon (TD007)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD007"]},{"location":"rules/missing-space-after-todo-colon/#what-it-does","title":"What it does","text":"

        Checks that the colon after a \"TODO\" tag is followed by a space.

        ","tags":["TD007"]},{"location":"rules/missing-space-after-todo-colon/#why-is-this-bad","title":"Why is this bad?","text":"

        \"TODO\" tags are typically followed by a parenthesized author name, a colon, a space, and a description of the issue, in that order.

        Deviating from this pattern can lead to inconsistent and non-idiomatic comments.

        ","tags":["TD007"]},{"location":"rules/missing-space-after-todo-colon/#example","title":"Example","text":"
        # TODO(charlie):fix this\n

        Use instead:

        # TODO(charlie): fix this\n
        ","tags":["TD007"]},{"location":"rules/missing-terminal-punctuation/","title":"missing-terminal-punctuation (D415)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D415"]},{"location":"rules/missing-terminal-punctuation/#what-it-does","title":"What it does","text":"

        Checks for docstrings in which the first line does not end in a punctuation mark, such as a period, question mark, or exclamation point.

        ","tags":["D415"]},{"location":"rules/missing-terminal-punctuation/#why-is-this-bad","title":"Why is this bad?","text":"

        The first line of a docstring should end with a period, question mark, or exclamation point, for grammatical correctness and consistency.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the google convention, and disabled when using the numpy and pep257 conventions.

        ","tags":["D415"]},{"location":"rules/missing-terminal-punctuation/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D415"]},{"location":"rules/missing-terminal-punctuation/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D415"]},{"location":"rules/missing-terminal-punctuation/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D415"]},{"location":"rules/missing-todo-author/","title":"missing-todo-author (TD002)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD002"]},{"location":"rules/missing-todo-author/#what-it-does","title":"What it does","text":"

        Checks that a TODO comment includes an author.

        ","tags":["TD002"]},{"location":"rules/missing-todo-author/#why-is-this-bad","title":"Why is this bad?","text":"

        Including an author on a TODO provides future readers with context around the issue. While the TODO author is not always considered responsible for fixing the issue, they are typically the individual with the most context.

        ","tags":["TD002"]},{"location":"rules/missing-todo-author/#example","title":"Example","text":"
        # TODO: should assign an author here\n

        Use instead

        # TODO(charlie): now an author is assigned\n
        ","tags":["TD002"]},{"location":"rules/missing-todo-colon/","title":"missing-todo-colon (TD004)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD004"]},{"location":"rules/missing-todo-colon/#what-it-does","title":"What it does","text":"

        Checks that a \"TODO\" tag is followed by a colon.

        ","tags":["TD004"]},{"location":"rules/missing-todo-colon/#why-is-this-bad","title":"Why is this bad?","text":"

        \"TODO\" tags are typically followed by a parenthesized author name, a colon, a space, and a description of the issue, in that order.

        Deviating from this pattern can lead to inconsistent and non-idiomatic comments.

        ","tags":["TD004"]},{"location":"rules/missing-todo-colon/#example","title":"Example","text":"
        # TODO(charlie) fix this colon\n

        Used instead:

        # TODO(charlie): colon fixed\n
        ","tags":["TD004"]},{"location":"rules/missing-todo-description/","title":"missing-todo-description (TD005)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD005"]},{"location":"rules/missing-todo-description/#what-it-does","title":"What it does","text":"

        Checks that a \"TODO\" tag contains a description of the issue following the tag itself.

        ","tags":["TD005"]},{"location":"rules/missing-todo-description/#why-is-this-bad","title":"Why is this bad?","text":"

        TODO comments should include a description of the issue to provide context for future readers.

        ","tags":["TD005"]},{"location":"rules/missing-todo-description/#example","title":"Example","text":"
        # TODO(charlie)\n

        Use instead:

        # TODO(charlie): fix some issue\n
        ","tags":["TD005"]},{"location":"rules/missing-todo-link/","title":"missing-todo-link (TD003)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD003"]},{"location":"rules/missing-todo-link/#what-it-does","title":"What it does","text":"

        Checks that a TODO comment is associated with a link to a relevant issue or ticket.

        ","tags":["TD003"]},{"location":"rules/missing-todo-link/#why-is-this-bad","title":"Why is this bad?","text":"

        Including an issue link near a TODO makes it easier for resolvers to get context around the issue.

        ","tags":["TD003"]},{"location":"rules/missing-todo-link/#example","title":"Example","text":"
        # TODO: this link has no issue\n

        Use one of these instead:

        # TODO(charlie): this comment has an issue link\n# https://github.com/astral-sh/ruff/issues/3870\n\n# TODO(charlie): this comment has a 3-digit issue code\n# 003\n\n# TODO(charlie): https://github.com/astral-sh/ruff/issues/3870\n# this comment has an issue link\n\n# TODO(charlie): #003 this comment has a 3-digit issue code\n# with leading character `#`\n\n# TODO(charlie): this comment has an issue code (matches the regex `[A-Z]+\\-?\\d+`)\n# SIXCHR-003\n
        ","tags":["TD003"]},{"location":"rules/missing-trailing-comma/","title":"missing-trailing-comma (COM812)","text":"

        Derived from the flake8-commas linter.

        Fix is always available.

        ","tags":["COM812"]},{"location":"rules/missing-trailing-comma/#what-it-does","title":"What it does","text":"

        Checks for the absence of trailing commas.

        ","tags":["COM812"]},{"location":"rules/missing-trailing-comma/#why-is-this-bad","title":"Why is this bad?","text":"

        The presence of a trailing comma can reduce diff size when parameters or elements are added or removed from function calls, function definitions, literals, etc.

        ","tags":["COM812"]},{"location":"rules/missing-trailing-comma/#example","title":"Example","text":"
        foo = {\n    \"bar\": 1,\n    \"baz\": 2\n}\n

        Use instead:

        foo = {\n    \"bar\": 1,\n    \"baz\": 2,\n}\n
        ","tags":["COM812"]},{"location":"rules/missing-trailing-comma/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent use of trailing commas, making the rule redundant.

        ","tags":["COM812"]},{"location":"rules/missing-trailing-period/","title":"missing-trailing-period (D400)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D400"]},{"location":"rules/missing-trailing-period/#what-it-does","title":"What it does","text":"

        Checks for docstrings in which the first line does not end in a period.

        ","tags":["D400"]},{"location":"rules/missing-trailing-period/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that the first line of a docstring is written in the form of a command, ending in a period.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the numpy and pep257 conventions, and disabled when using the google convention.

        ","tags":["D400"]},{"location":"rules/missing-trailing-period/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D400"]},{"location":"rules/missing-trailing-period/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D400"]},{"location":"rules/missing-trailing-period/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D400"]},{"location":"rules/missing-type-args/","title":"missing-type-args (ANN002)","text":"

        Derived from the flake8-annotations linter.

        ","tags":["ANN002"]},{"location":"rules/missing-type-args/#what-it-does","title":"What it does","text":"

        Checks that function *args arguments have type annotations.

        ","tags":["ANN002"]},{"location":"rules/missing-type-args/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the types of function arguments. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any provided arguments match expectation.

        ","tags":["ANN002"]},{"location":"rules/missing-type-args/#example","title":"Example","text":"
        def foo(*args): ...\n

        Use instead:

        def foo(*args: int): ...\n
        ","tags":["ANN002"]},{"location":"rules/missing-type-args/#options","title":"Options","text":"
        • lint.flake8-annotations.suppress-dummy-args
        ","tags":["ANN002"]},{"location":"rules/missing-type-cls/","title":"missing-type-cls (ANN102)","text":"

        Derived from the flake8-annotations linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["ANN102"]},{"location":"rules/missing-type-cls/#removed","title":"Removed","text":"

        This rule has been removed because type checkers can infer this type without annotation.

        ","tags":["ANN102"]},{"location":"rules/missing-type-cls/#what-it-does","title":"What it does","text":"

        Checks that class method cls arguments have type annotations.

        ","tags":["ANN102"]},{"location":"rules/missing-type-cls/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the types of function arguments. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any provided arguments match expectation.

        Note that many type checkers will infer the type of cls automatically, so this annotation is not strictly necessary.

        ","tags":["ANN102"]},{"location":"rules/missing-type-cls/#example","title":"Example","text":"
        class Foo:\n    @classmethod\n    def bar(cls): ...\n

        Use instead:

        class Foo:\n    @classmethod\n    def bar(cls: Type[\"Foo\"]): ...\n
        ","tags":["ANN102"]},{"location":"rules/missing-type-function-argument/","title":"missing-type-function-argument (ANN001)","text":"

        Derived from the flake8-annotations linter.

        ","tags":["ANN001"]},{"location":"rules/missing-type-function-argument/#what-it-does","title":"What it does","text":"

        Checks that function arguments have type annotations.

        ","tags":["ANN001"]},{"location":"rules/missing-type-function-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the types of function arguments. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any provided arguments match expectation.

        ","tags":["ANN001"]},{"location":"rules/missing-type-function-argument/#example","title":"Example","text":"
        def foo(x): ...\n

        Use instead:

        def foo(x: int): ...\n
        ","tags":["ANN001"]},{"location":"rules/missing-type-function-argument/#options","title":"Options","text":"
        • lint.flake8-annotations.suppress-dummy-args
        ","tags":["ANN001"]},{"location":"rules/missing-type-kwargs/","title":"missing-type-kwargs (ANN003)","text":"

        Derived from the flake8-annotations linter.

        ","tags":["ANN003"]},{"location":"rules/missing-type-kwargs/#what-it-does","title":"What it does","text":"

        Checks that function **kwargs arguments have type annotations.

        ","tags":["ANN003"]},{"location":"rules/missing-type-kwargs/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the types of function arguments. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any provided arguments match expectation.

        ","tags":["ANN003"]},{"location":"rules/missing-type-kwargs/#example","title":"Example","text":"
        def foo(**kwargs): ...\n

        Use instead:

        def foo(**kwargs: int): ...\n
        ","tags":["ANN003"]},{"location":"rules/missing-type-kwargs/#options","title":"Options","text":"
        • lint.flake8-annotations.suppress-dummy-args
        ","tags":["ANN003"]},{"location":"rules/missing-type-self/","title":"missing-type-self (ANN101)","text":"

        Derived from the flake8-annotations linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["ANN101"]},{"location":"rules/missing-type-self/#removed","title":"Removed","text":"

        This rule has been removed because type checkers can infer this type without annotation.

        ","tags":["ANN101"]},{"location":"rules/missing-type-self/#what-it-does","title":"What it does","text":"

        Checks that instance method self arguments have type annotations.

        ","tags":["ANN101"]},{"location":"rules/missing-type-self/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the types of function arguments. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any provided arguments match expectation.

        Note that many type checkers will infer the type of self automatically, so this annotation is not strictly necessary.

        ","tags":["ANN101"]},{"location":"rules/missing-type-self/#example","title":"Example","text":"
        class Foo:\n    def bar(self): ...\n

        Use instead:

        class Foo:\n    def bar(self: \"Foo\"): ...\n
        ","tags":["ANN101"]},{"location":"rules/missing-whitespace-after-keyword/","title":"missing-whitespace-after-keyword (E275)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E275"]},{"location":"rules/missing-whitespace-after-keyword/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace after keywords.

        ","tags":["E275"]},{"location":"rules/missing-whitespace-after-keyword/#why-is-this-bad","title":"Why is this bad?","text":"

        Missing whitespace after keywords makes the code harder to read.

        ","tags":["E275"]},{"location":"rules/missing-whitespace-after-keyword/#example","title":"Example","text":"
        if(True):\n    pass\n

        Use instead:

        if (True):\n    pass\n
        ","tags":["E275"]},{"location":"rules/missing-whitespace-after-keyword/#references","title":"References","text":"
        • Python documentation: Keywords
        ","tags":["E275"]},{"location":"rules/missing-whitespace-around-arithmetic-operator/","title":"missing-whitespace-around-arithmetic-operator (E226)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E226"]},{"location":"rules/missing-whitespace-around-arithmetic-operator/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace arithmetic operators.

        ","tags":["E226"]},{"location":"rules/missing-whitespace-around-arithmetic-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, there should be one space before and after an arithmetic operator (+, -, /, and *).

        ","tags":["E226"]},{"location":"rules/missing-whitespace-around-arithmetic-operator/#example","title":"Example","text":"
        number = 40+2\n

        Use instead:

        number = 40 + 2\n
        ","tags":["E226"]},{"location":"rules/missing-whitespace-around-bitwise-or-shift-operator/","title":"missing-whitespace-around-bitwise-or-shift-operator (E227)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E227"]},{"location":"rules/missing-whitespace-around-bitwise-or-shift-operator/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace around bitwise and shift operators.

        ","tags":["E227"]},{"location":"rules/missing-whitespace-around-bitwise-or-shift-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, there should be one space before and after bitwise and shift operators (\\<<, >>, &, |, ^).

        ","tags":["E227"]},{"location":"rules/missing-whitespace-around-bitwise-or-shift-operator/#example","title":"Example","text":"
        x = 128<<1\n

        Use instead:

        x = 128 << 1\n
        ","tags":["E227"]},{"location":"rules/missing-whitespace-around-modulo-operator/","title":"missing-whitespace-around-modulo-operator (E228)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E228"]},{"location":"rules/missing-whitespace-around-modulo-operator/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace around the modulo operator.

        ","tags":["E228"]},{"location":"rules/missing-whitespace-around-modulo-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, the modulo operator (%) should have whitespace on either side of it.

        ","tags":["E228"]},{"location":"rules/missing-whitespace-around-modulo-operator/#example","title":"Example","text":"
        remainder = 10%2\n

        Use instead:

        remainder = 10 % 2\n
        ","tags":["E228"]},{"location":"rules/missing-whitespace-around-operator/","title":"missing-whitespace-around-operator (E225)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E225"]},{"location":"rules/missing-whitespace-around-operator/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace around all operators.

        ","tags":["E225"]},{"location":"rules/missing-whitespace-around-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, there should be one space before and after all operators.

        ","tags":["E225"]},{"location":"rules/missing-whitespace-around-operator/#example","title":"Example","text":"
        if number==42:\n    print('you have found the meaning of life')\n

        Use instead:

        if number == 42:\n    print('you have found the meaning of life')\n
        ","tags":["E225"]},{"location":"rules/missing-whitespace-around-parameter-equals/","title":"missing-whitespace-around-parameter-equals (E252)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E252"]},{"location":"rules/missing-whitespace-around-parameter-equals/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace around the equals sign in an annotated function keyword parameter.

        ","tags":["E252"]},{"location":"rules/missing-whitespace-around-parameter-equals/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, the spaces around the equals sign in a keyword parameter should only be omitted when the parameter is unannotated:

        Don\u2019t use spaces around the = sign when used to indicate a keyword argument, or when used to indicate a default value for an unannotated function parameter.

        ","tags":["E252"]},{"location":"rules/missing-whitespace-around-parameter-equals/#example","title":"Example","text":"
        def add(a: int=0) -> int:\n    return a + 1\n

        Use instead:

        def add(a: int = 0) -> int:\n    return a + 1\n
        ","tags":["E252"]},{"location":"rules/missing-whitespace/","title":"missing-whitespace (E231)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E231"]},{"location":"rules/missing-whitespace/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace after ,, ;, and :.

        ","tags":["E231"]},{"location":"rules/missing-whitespace/#why-is-this-bad","title":"Why is this bad?","text":"

        Missing whitespace after ,, ;, and : makes the code harder to read.

        ","tags":["E231"]},{"location":"rules/missing-whitespace/#example","title":"Example","text":"
        a = (1,2)\n

        Use instead:

        a = (1, 2)\n
        ","tags":["E231"]},{"location":"rules/mixed-case-variable-in-class-scope/","title":"mixed-case-variable-in-class-scope (N815)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N815"]},{"location":"rules/mixed-case-variable-in-class-scope/#what-it-does","title":"What it does","text":"

        Checks for class variable names that follow the mixedCase convention.

        ","tags":["N815"]},{"location":"rules/mixed-case-variable-in-class-scope/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that variable names should be lower case and separated by underscores (also known as snake_case).

        Function names should be lowercase, with words separated by underscores as necessary to improve readability.

        Variable names follow the same convention as function names.

        mixedCase is allowed only in contexts where that\u2019s already the prevailing style (e.g. threading.py), to retain backwards compatibility.

        ","tags":["N815"]},{"location":"rules/mixed-case-variable-in-class-scope/#example","title":"Example","text":"
        class MyClass:\n    myVariable = \"hello\"\n    another_variable = \"world\"\n

        Use instead:

        class MyClass:\n    my_variable = \"hello\"\n    another_variable = \"world\"\n
        ","tags":["N815"]},{"location":"rules/mixed-case-variable-in-class-scope/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N815"]},{"location":"rules/mixed-case-variable-in-global-scope/","title":"mixed-case-variable-in-global-scope (N816)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#what-it-does","title":"What it does","text":"

        Checks for global variable names that follow the mixedCase convention.

        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that global variable names should be lower case and separated by underscores (also known as snake_case).

        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#global-variable-names","title":"Global Variable Names","text":"

        (Let\u2019s hope that these variables are meant for use inside one module only.) The conventions are about the same as those for functions.

        Modules that are designed for use via from M import * should use the all mechanism to prevent exporting globals, or use the older convention of prefixing such globals with an underscore (which you might want to do to indicate these globals are \u201cmodule non-public\u201d).

        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#function-and-variable-names","title":"Function and Variable Names","text":"

        Function names should be lowercase, with words separated by underscores as necessary to improve readability.

        Variable names follow the same convention as function names.

        mixedCase is allowed only in contexts where that\u2019s already the prevailing style (e.g. threading.py), to retain backwards compatibility.

        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#example","title":"Example","text":"
        myVariable = \"hello\"\nanother_variable = \"world\"\nyet_anotherVariable = \"foo\"\n

        Use instead:

        my_variable = \"hello\"\nanother_variable = \"world\"\nyet_another_variable = \"foo\"\n
        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N816"]},{"location":"rules/mixed-spaces-and-tabs/","title":"mixed-spaces-and-tabs (E101)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E101"]},{"location":"rules/mixed-spaces-and-tabs/#what-it-does","title":"What it does","text":"

        Checks for mixed tabs and spaces in indentation.

        ","tags":["E101"]},{"location":"rules/mixed-spaces-and-tabs/#why-is-this-bad","title":"Why is this bad?","text":"

        Never mix tabs and spaces.

        The most popular way of indenting Python is with spaces only. The second-most popular way is with tabs only. Code indented with a mixture of tabs and spaces should be converted to using spaces exclusively.

        ","tags":["E101"]},{"location":"rules/mixed-spaces-and-tabs/#example","title":"Example","text":"
        if a == 0:\\n        a = 1\\n\\tb = 1\n

        Use instead:

        if a == 0:\\n    a = 1\\n    b = 1\n
        ","tags":["E101"]},{"location":"rules/modified-iterating-set/","title":"modified-iterating-set (PLE4703)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#what-it-does","title":"What it does","text":"

        Checks for loops in which a set is modified during iteration.

        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#why-is-this-bad","title":"Why is this bad?","text":"

        If a set is modified during iteration, it will cause a RuntimeError.

        If you need to modify a set within a loop, consider iterating over a copy of the set instead.

        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#known-problems","title":"Known problems","text":"

        This rule favors false negatives over false positives. Specifically, it will only detect variables that can be inferred to be a set type based on local type inference, and will only detect modifications that are made directly on the variable itself (e.g., set.add()), as opposed to modifications within other function calls (e.g., some_function(set)).

        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#example","title":"Example","text":"
        nums = {1, 2, 3}\nfor num in nums:\n    nums.add(num + 5)\n

        Use instead:

        nums = {1, 2, 3}\nfor num in nums.copy():\n    nums.add(num + 5)\n
        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#fix-safety","title":"Fix safety","text":"

        This fix is always unsafe because it changes the program\u2019s behavior. Replacing the original set with a copy during iteration allows code that would previously raise a RuntimeError to run without error.

        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#references","title":"References","text":"
        • Python documentation: set
        ","tags":["PLE4703"]},{"location":"rules/module-import-not-at-top-of-file/","title":"module-import-not-at-top-of-file (E402)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E402"]},{"location":"rules/module-import-not-at-top-of-file/#what-it-does","title":"What it does","text":"

        Checks for imports that are not at the top of the file.

        ","tags":["E402"]},{"location":"rules/module-import-not-at-top-of-file/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants.\"

        This rule makes an exception for both sys.path modifications (allowing for sys.path.insert, sys.path.append, etc.) and os.environ modifications between imports.

        ","tags":["E402"]},{"location":"rules/module-import-not-at-top-of-file/#example","title":"Example","text":"
        \"One string\"\n\"Two string\"\na = 1\nimport os\nfrom sys import x\n

        Use instead:

        import os\nfrom sys import x\n\n\"One string\"\n\"Two string\"\na = 1\n
        ","tags":["E402"]},{"location":"rules/module-import-not-at-top-of-file/#notebook-behavior","title":"Notebook behavior","text":"

        For Jupyter notebooks, this rule checks for imports that are not at the top of a cell.

        ","tags":["E402"]},{"location":"rules/multi-line-implicit-string-concatenation/","title":"multi-line-implicit-string-concatenation (ISC002)","text":"

        Derived from the flake8-implicit-str-concat linter.

        ","tags":["ISC002"]},{"location":"rules/multi-line-implicit-string-concatenation/#what-it-does","title":"What it does","text":"

        Checks for implicitly concatenated strings that span multiple lines.

        ","tags":["ISC002"]},{"location":"rules/multi-line-implicit-string-concatenation/#why-is-this-bad","title":"Why is this bad?","text":"

        For string literals that wrap across multiple lines, PEP 8 recommends the use of implicit string concatenation within parentheses instead of using a backslash for line continuation, as the former is more readable than the latter.

        By default, this rule will only trigger if the string literal is concatenated via a backslash. To disallow implicit string concatenation altogether, set the lint.flake8-implicit-str-concat.allow-multiline option to false.

        ","tags":["ISC002"]},{"location":"rules/multi-line-implicit-string-concatenation/#example","title":"Example","text":"
        z = \"The quick brown fox jumps over the lazy \"\\\n    \"dog.\"\n

        Use instead:

        z = (\n    \"The quick brown fox jumps over the lazy \"\n    \"dog.\"\n)\n
        ","tags":["ISC002"]},{"location":"rules/multi-line-implicit-string-concatenation/#options","title":"Options","text":"
        • lint.flake8-implicit-str-concat.allow-multiline
        ","tags":["ISC002"]},{"location":"rules/multi-line-implicit-string-concatenation/#formatter-compatibility","title":"Formatter compatibility","text":"

        Using this rule with allow-multiline = false can be incompatible with the formatter because the formatter can introduce new multi-line implicitly concatenated strings. We recommend to either:

        • Enable ISC001 to disallow all implicit concatenated strings
        • Setting allow-multiline = true
        ","tags":["ISC002"]},{"location":"rules/multi-line-summary-first-line/","title":"multi-line-summary-first-line (D212)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D212"]},{"location":"rules/multi-line-summary-first-line/#what-it-does","title":"What it does","text":"

        Checks for docstring summary lines that are not positioned on the first physical line of the docstring.

        ","tags":["D212"]},{"location":"rules/multi-line-summary-first-line/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that multi-line docstrings consist of \"a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description.\"

        The summary line should be located on the first physical line of the docstring, immediately after the opening quotes.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the google convention, and disabled when using the numpy and pep257 conventions.

        For an alternative, see D213.

        ","tags":["D212"]},{"location":"rules/multi-line-summary-first-line/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"\n    Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the\n    bubble sort algorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D212"]},{"location":"rules/multi-line-summary-first-line/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D212"]},{"location":"rules/multi-line-summary-first-line/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D212"]},{"location":"rules/multi-line-summary-second-line/","title":"multi-line-summary-second-line (D213)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D213"]},{"location":"rules/multi-line-summary-second-line/#what-it-does","title":"What it does","text":"

        Checks for docstring summary lines that are not positioned on the second physical line of the docstring.

        ","tags":["D213"]},{"location":"rules/multi-line-summary-second-line/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that multi-line docstrings consist of \"a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description.\"

        The summary line should be located on the second physical line of the docstring, immediately after the opening quotes and the blank line.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is disabled when using the google, numpy, and pep257 conventions.

        For an alternative, see D212.

        ","tags":["D213"]},{"location":"rules/multi-line-summary-second-line/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the\n    bubble sort algorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"\n    Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D213"]},{"location":"rules/multi-line-summary-second-line/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D213"]},{"location":"rules/multi-line-summary-second-line/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D213"]},{"location":"rules/multi-value-repeated-key-literal/","title":"multi-value-repeated-key-literal (F601)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-literal/#what-it-does","title":"What it does","text":"

        Checks for dictionary literals that associate multiple values with the same key.

        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        Dictionary keys should be unique. If a key is associated with multiple values, the earlier values will be overwritten. Including multiple values for the same key in a dictionary literal is likely a mistake.

        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-literal/#example","title":"Example","text":"
        foo = {\n    \"bar\": 1,\n    \"baz\": 2,\n    \"baz\": 3,\n}\nfoo[\"baz\"]  # 3\n

        Use instead:

        foo = {\n    \"bar\": 1,\n    \"baz\": 2,\n}\nfoo[\"baz\"]  # 2\n
        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-literal/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because removing a repeated dictionary key may delete comments that are attached to the removed key-value pair. This can also change the program's behavior if the value expressions have side effects.

        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-literal/#references","title":"References","text":"
        • Python documentation: Dictionaries
        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-variable/","title":"multi-value-repeated-key-variable (F602)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F602"]},{"location":"rules/multi-value-repeated-key-variable/#what-it-does","title":"What it does","text":"

        Checks for dictionary keys that are repeated with different values.

        ","tags":["F602"]},{"location":"rules/multi-value-repeated-key-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        Dictionary keys should be unique. If a key is repeated with a different value, the first values will be overwritten and the key will correspond to the last value. This is likely a mistake.

        ","tags":["F602"]},{"location":"rules/multi-value-repeated-key-variable/#example","title":"Example","text":"
        foo = {\n    bar: 1,\n    baz: 2,\n    baz: 3,\n}\nfoo[baz]  # 3\n

        Use instead:

        foo = {\n    bar: 1,\n    baz: 2,\n}\nfoo[baz]  # 2\n
        ","tags":["F602"]},{"location":"rules/multi-value-repeated-key-variable/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because removing a repeated dictionary key may delete comments that are attached to the removed key-value pair. This can also change the program's behavior if the value expressions have side effects.

        ","tags":["F602"]},{"location":"rules/multi-value-repeated-key-variable/#references","title":"References","text":"
        • Python documentation: Dictionaries
        ","tags":["F602"]},{"location":"rules/multiple-imports-on-one-line/","title":"multiple-imports-on-one-line (E401)","text":"

        Derived from the pycodestyle linter.

        Fix is sometimes available.

        ","tags":["E401"]},{"location":"rules/multiple-imports-on-one-line/#what-it-does","title":"What it does","text":"

        Check for multiple imports on one line.

        ","tags":["E401"]},{"location":"rules/multiple-imports-on-one-line/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"imports should usually be on separate lines.\"

        ","tags":["E401"]},{"location":"rules/multiple-imports-on-one-line/#example","title":"Example","text":"
        import sys, os\n

        Use instead:

        import os\nimport sys\n
        ","tags":["E401"]},{"location":"rules/multiple-leading-hashes-for-block-comment/","title":"multiple-leading-hashes-for-block-comment (E266)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E266"]},{"location":"rules/multiple-leading-hashes-for-block-comment/#what-it-does","title":"What it does","text":"

        Checks for block comments that start with multiple leading # characters.

        ","tags":["E266"]},{"location":"rules/multiple-leading-hashes-for-block-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Per PEP 8, \"Block comments generally consist of one or more paragraphs built out of complete sentences, with each sentence ending in a period.\"

        Each line of a block comment should start with a # followed by a single space.

        Shebangs (lines starting with #!, at the top of a file) are exempt from this rule.

        ","tags":["E266"]},{"location":"rules/multiple-leading-hashes-for-block-comment/#example","title":"Example","text":"
        ### Block comment\n

        Use instead:

        # Block comment\n

        Alternatively, this rule makes an exception for comments that consist solely of # characters, as in:

        ##############\n# Block header\n##############\n
        ","tags":["E266"]},{"location":"rules/multiple-spaces-after-comma/","title":"multiple-spaces-after-comma (E241)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E241"]},{"location":"rules/multiple-spaces-after-comma/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace after a comma.

        ","tags":["E241"]},{"location":"rules/multiple-spaces-after-comma/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. This rule helps ensure you have a consistent formatting style across your project.

        ","tags":["E241"]},{"location":"rules/multiple-spaces-after-comma/#example","title":"Example","text":"
        a = 4,    5\n

        Use instead:

        a = 4, 5\n
        ","tags":["E241"]},{"location":"rules/multiple-spaces-after-keyword/","title":"multiple-spaces-after-keyword (E271)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E271"]},{"location":"rules/multiple-spaces-after-keyword/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace after keywords.

        ","tags":["E271"]},{"location":"rules/multiple-spaces-after-keyword/#why-is-this-bad","title":"Why is this bad?","text":"","tags":["E271"]},{"location":"rules/multiple-spaces-after-keyword/#example","title":"Example","text":"
        True and  False\n

        Use instead:

        True and False\n
        ","tags":["E271"]},{"location":"rules/multiple-spaces-after-operator/","title":"multiple-spaces-after-operator (E222)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E222"]},{"location":"rules/multiple-spaces-after-operator/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace after an operator.

        ","tags":["E222"]},{"location":"rules/multiple-spaces-after-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, operators should be surrounded by at most a single space on either side.

        ","tags":["E222"]},{"location":"rules/multiple-spaces-after-operator/#example","title":"Example","text":"
        a = 4 +  5\n

        Use instead:

        a = 4 + 5\n
        ","tags":["E222"]},{"location":"rules/multiple-spaces-before-keyword/","title":"multiple-spaces-before-keyword (E272)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E272"]},{"location":"rules/multiple-spaces-before-keyword/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace before keywords.

        ","tags":["E272"]},{"location":"rules/multiple-spaces-before-keyword/#why-is-this-bad","title":"Why is this bad?","text":"","tags":["E272"]},{"location":"rules/multiple-spaces-before-keyword/#example","title":"Example","text":"
        True  and False\n

        Use instead:

        True and False\n
        ","tags":["E272"]},{"location":"rules/multiple-spaces-before-operator/","title":"multiple-spaces-before-operator (E221)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E221"]},{"location":"rules/multiple-spaces-before-operator/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace before an operator.

        ","tags":["E221"]},{"location":"rules/multiple-spaces-before-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, operators should be surrounded by at most a single space on either side.

        ","tags":["E221"]},{"location":"rules/multiple-spaces-before-operator/#example","title":"Example","text":"
        a = 4  + 5\n

        Use instead:

        a = 4 + 5\n
        ","tags":["E221"]},{"location":"rules/multiple-starred-expressions/","title":"multiple-starred-expressions (F622)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F622"]},{"location":"rules/multiple-starred-expressions/#what-it-does","title":"What it does","text":"

        Checks for the use of multiple starred expressions in assignment statements.

        ","tags":["F622"]},{"location":"rules/multiple-starred-expressions/#why-is-this-bad","title":"Why is this bad?","text":"

        In assignment statements, starred expressions can be used to unpack iterables. Including more than one starred expression on the left-hand-side of an assignment will cause a SyntaxError, as it is unclear which expression should receive the remaining values.

        ","tags":["F622"]},{"location":"rules/multiple-starred-expressions/#example","title":"Example","text":"
        *foo, *bar, baz = (1, 2, 3)\n
        ","tags":["F622"]},{"location":"rules/multiple-starred-expressions/#references","title":"References","text":"
        • PEP 3132 \u2013 Extended Iterable Unpacking
        ","tags":["F622"]},{"location":"rules/multiple-starts-ends-with/","title":"multiple-starts-ends-with (PIE810)","text":"

        Derived from the flake8-pie linter.

        Fix is always available.

        ","tags":["PIE810"]},{"location":"rules/multiple-starts-ends-with/#what-it-does","title":"What it does","text":"

        Checks for startswith or endswith calls on the same value with different prefixes or suffixes.

        ","tags":["PIE810"]},{"location":"rules/multiple-starts-ends-with/#why-is-this-bad","title":"Why is this bad?","text":"

        The startswith and endswith methods accept tuples of prefixes or suffixes respectively. Passing a tuple of prefixes or suffixes is more efficient and readable than calling the method multiple times.

        ","tags":["PIE810"]},{"location":"rules/multiple-starts-ends-with/#example","title":"Example","text":"
        msg = \"Hello, world!\"\nif msg.startswith(\"Hello\") or msg.startswith(\"Hi\"):\n    print(\"Greetings!\")\n

        Use instead:

        msg = \"Hello, world!\"\nif msg.startswith((\"Hello\", \"Hi\")):\n    print(\"Greetings!\")\n
        ","tags":["PIE810"]},{"location":"rules/multiple-starts-ends-with/#fix-safety","title":"Fix safety","text":"

        This rule's fix is unsafe, as in some cases, it will be unable to determine whether the argument to an existing .startswith or .endswith call is a tuple. For example, given msg.startswith(x) or msg.startswith(y), if x or y is a tuple, and the semantic model is unable to detect it as such, the rule will suggest msg.startswith((x, y)), which will error at runtime.

        ","tags":["PIE810"]},{"location":"rules/multiple-starts-ends-with/#references","title":"References","text":"
        • Python documentation: str.startswith
        • Python documentation: str.endswith
        ","tags":["PIE810"]},{"location":"rules/multiple-statements-on-one-line-colon/","title":"multiple-statements-on-one-line-colon (E701)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E701"]},{"location":"rules/multiple-statements-on-one-line-colon/#what-it-does","title":"What it does","text":"

        Checks for compound statements (multiple statements on the same line).

        ","tags":["E701"]},{"location":"rules/multiple-statements-on-one-line-colon/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"compound statements are generally discouraged\".

        ","tags":["E701"]},{"location":"rules/multiple-statements-on-one-line-colon/#example","title":"Example","text":"
        if foo == \"blah\": do_blah_thing()\n

        Use instead:

        if foo == \"blah\":\n    do_blah_thing()\n
        ","tags":["E701"]},{"location":"rules/multiple-statements-on-one-line-semicolon/","title":"multiple-statements-on-one-line-semicolon (E702)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E702"]},{"location":"rules/multiple-statements-on-one-line-semicolon/#what-it-does","title":"What it does","text":"

        Checks for multiline statements on one line.

        ","tags":["E702"]},{"location":"rules/multiple-statements-on-one-line-semicolon/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, including multi-clause statements on the same line is discouraged.

        ","tags":["E702"]},{"location":"rules/multiple-statements-on-one-line-semicolon/#example","title":"Example","text":"
        do_one(); do_two(); do_three()\n

        Use instead:

        do_one()\ndo_two()\ndo_three()\n
        ","tags":["E702"]},{"location":"rules/multiple-with-statements/","title":"multiple-with-statements (SIM117)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM117"]},{"location":"rules/multiple-with-statements/#what-it-does","title":"What it does","text":"

        Checks for the unnecessary nesting of multiple consecutive context managers.

        ","tags":["SIM117"]},{"location":"rules/multiple-with-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3, a single with block can include multiple context managers.

        Combining multiple context managers into a single with statement will minimize the indentation depth of the code, making it more readable.

        The following context managers are exempt when used as standalone statements:

        • anyio.{CancelScope, fail_after, move_on_after}
        • asyncio.{timeout, timeout_at}
        • trio.{fail_after, fail_at, move_on_after, move_on_at}
        ","tags":["SIM117"]},{"location":"rules/multiple-with-statements/#example","title":"Example","text":"
        with A() as a:\n    with B() as b:\n        pass\n

        Use instead:

        with A() as a, B() as b:\n    pass\n
        ","tags":["SIM117"]},{"location":"rules/multiple-with-statements/#references","title":"References","text":"
        • Python documentation: The with statement
        ","tags":["SIM117"]},{"location":"rules/mutable-argument-default/","title":"mutable-argument-default (B006)","text":"

        Derived from the flake8-bugbear linter.

        Fix is sometimes available.

        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#what-it-does","title":"What it does","text":"

        Checks for uses of mutable objects as function argument defaults.

        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#why-is-this-bad","title":"Why is this bad?","text":"

        Function defaults are evaluated once, when the function is defined.

        The same mutable object is then shared across all calls to the function. If the object is modified, those modifications will persist across calls, which can lead to unexpected behavior.

        Instead, prefer to use immutable data structures, or take None as a default, and initialize a new mutable object inside the function body for each call.

        Arguments with immutable type annotations will be ignored by this rule. Types outside of the standard library can be marked as immutable with the lint.flake8-bugbear.extend-immutable-calls configuration option.

        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#known-problems","title":"Known problems","text":"

        Mutable argument defaults can be used intentionally to cache computation results. Replacing the default with None or an immutable data structure does not work for such usages. Instead, prefer the @functools.lru_cache decorator from the standard library.

        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#example","title":"Example","text":"
        def add_to_list(item, some_list=[]):\n    some_list.append(item)\n    return some_list\n\n\nl1 = add_to_list(0)  # [0]\nl2 = add_to_list(1)  # [0, 1]\n

        Use instead:

        def add_to_list(item, some_list=None):\n    if some_list is None:\n        some_list = []\n    some_list.append(item)\n    return some_list\n\n\nl1 = add_to_list(0)  # [0]\nl2 = add_to_list(1)  # [1]\n
        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#options","title":"Options","text":"
        • lint.flake8-bugbear.extend-immutable-calls
        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#references","title":"References","text":"
        • Python documentation: Default Argument Values
        ","tags":["B006"]},{"location":"rules/mutable-class-default/","title":"mutable-class-default (RUF012)","text":"","tags":["RUF012"]},{"location":"rules/mutable-class-default/#what-it-does","title":"What it does","text":"

        Checks for mutable default values in class attributes.

        ","tags":["RUF012"]},{"location":"rules/mutable-class-default/#why-is-this-bad","title":"Why is this bad?","text":"

        Mutable default values share state across all instances of the class, while not being obvious. This can lead to bugs when the attributes are changed in one instance, as those changes will unexpectedly affect all other instances.

        Generally speaking, you probably want to avoid having mutable default values in the class body at all; instead, these variables should usually be initialized in __init__. However, other possible fixes for the issue can include:

        • Explicitly annotating the variable with typing.ClassVar to indicate that it is intended to be shared across all instances.
        • Using an immutable data type (e.g. a tuple instead of a list) for the default value.
        ","tags":["RUF012"]},{"location":"rules/mutable-class-default/#example","title":"Example","text":"
        class A:\n    variable_1: list[int] = []\n    variable_2: set[int] = set()\n    variable_3: dict[str, int] = {}\n

        Use instead:

        class A:\n    def __init__(self) -> None:\n        self.variable_1: list[int] = []\n        self.variable_2: set[int] = set()\n        self.variable_3: dict[str, int] = {}\n

        Or:

        from typing import ClassVar\n\n\nclass A:\n    variable_1: ClassVar[list[int]] = []\n    variable_2: ClassVar[set[int]] = set()\n    variable_3: ClassVar[dict[str, int]] = {}\n

        Or:

        class A:\n    variable_1: list[int] | None = None\n    variable_2: set[int] | None = None\n    variable_3: dict[str, int] | None = None\n

        Or:

        from collections.abc import Sequence, Mapping, Set as AbstractSet\nfrom types import MappingProxyType\n\n\nclass A:\n    variable_1: Sequence[int] = ()\n    variable_2: AbstractSet[int] = frozenset()\n    variable_3: Mapping[str, int] = MappingProxyType({})\n
        ","tags":["RUF012"]},{"location":"rules/mutable-contextvar-default/","title":"mutable-contextvar-default (B039)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B039"]},{"location":"rules/mutable-contextvar-default/#what-it-does","title":"What it does","text":"

        Checks for uses of mutable objects as ContextVar defaults.

        ","tags":["B039"]},{"location":"rules/mutable-contextvar-default/#why-is-this-bad","title":"Why is this bad?","text":"

        The ContextVar default is evaluated once, when the ContextVar is defined.

        The same mutable object is then shared across all .get() method calls to the ContextVar. If the object is modified, those modifications will persist across calls, which can lead to unexpected behavior.

        Instead, prefer to use immutable data structures. Alternatively, take None as a default, and initialize a new mutable object inside for each call using the .set() method.

        Types outside the standard library can be marked as immutable with the lint.flake8-bugbear.extend-immutable-calls configuration option.

        ","tags":["B039"]},{"location":"rules/mutable-contextvar-default/#example","title":"Example","text":"
        from contextvars import ContextVar\n\n\ncv: ContextVar[list] = ContextVar(\"cv\", default=[])\n

        Use instead:

        from contextvars import ContextVar\n\n\ncv: ContextVar[list | None] = ContextVar(\"cv\", default=None)\n\n...\n\nif cv.get() is None:\n    cv.set([])\n
        ","tags":["B039"]},{"location":"rules/mutable-contextvar-default/#options","title":"Options","text":"
        • lint.flake8-bugbear.extend-immutable-calls
        ","tags":["B039"]},{"location":"rules/mutable-contextvar-default/#references","title":"References","text":"
        • Python documentation: contextvars \u2014 Context Variables
        ","tags":["B039"]},{"location":"rules/mutable-dataclass-default/","title":"mutable-dataclass-default (RUF008)","text":"","tags":["RUF008"]},{"location":"rules/mutable-dataclass-default/#what-it-does","title":"What it does","text":"

        Checks for mutable default values in dataclass attributes.

        ","tags":["RUF008"]},{"location":"rules/mutable-dataclass-default/#why-is-this-bad","title":"Why is this bad?","text":"

        Mutable default values share state across all instances of the dataclass. This can lead to bugs when the attributes are changed in one instance, as those changes will unexpectedly affect all other instances.

        Instead of sharing mutable defaults, use the field(default_factory=...) pattern.

        If the default value is intended to be mutable, it must be annotated with typing.ClassVar; otherwise, a ValueError will be raised.

        ","tags":["RUF008"]},{"location":"rules/mutable-dataclass-default/#example","title":"Example","text":"
        from dataclasses import dataclass\n\n\n@dataclass\nclass A:\n    # A list without a `default_factory` or `ClassVar` annotation\n    # will raise a `ValueError`.\n    mutable_default: list[int] = []\n

        Use instead:

        from dataclasses import dataclass, field\n\n\n@dataclass\nclass A:\n    mutable_default: list[int] = field(default_factory=list)\n

        Or:

        from dataclasses import dataclass\nfrom typing import ClassVar\n\n\n@dataclass\nclass A:\n    mutable_default: ClassVar[list[int]] = []\n
        ","tags":["RUF008"]},{"location":"rules/mutable-fromkeys-value/","title":"mutable-fromkeys-value (RUF024)","text":"

        Fix is sometimes available.

        ","tags":["RUF024"]},{"location":"rules/mutable-fromkeys-value/#what-it-does","title":"What it does","text":"

        Checks for mutable objects passed as a value argument to dict.fromkeys.

        ","tags":["RUF024"]},{"location":"rules/mutable-fromkeys-value/#why-is-this-bad","title":"Why is this bad?","text":"

        All values in the dictionary created by the dict.fromkeys method refer to the same instance of the provided object. If that object is modified, all values are modified, which can lead to unexpected behavior. For example, if the empty list ([]) is provided as the default value, all values in the dictionary will use the same list; as such, appending to any one entry will append to all entries.

        Instead, use a comprehension to generate a dictionary with distinct instances of the default value.

        ","tags":["RUF024"]},{"location":"rules/mutable-fromkeys-value/#example","title":"Example","text":"
        cities = dict.fromkeys([\"UK\", \"Poland\"], [])\ncities[\"UK\"].append(\"London\")\ncities[\"Poland\"].append(\"Poznan\")\nprint(cities)  # {'UK': ['London', 'Poznan'], 'Poland': ['London', 'Poznan']}\n

        Use instead:

        cities = {country: [] for country in [\"UK\", \"Poland\"]}\ncities[\"UK\"].append(\"London\")\ncities[\"Poland\"].append(\"Poznan\")\nprint(cities)  # {'UK': ['London'], 'Poland': ['Poznan']}\n
        ","tags":["RUF024"]},{"location":"rules/mutable-fromkeys-value/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as the edit will change the behavior of the program by using a distinct object for every value in the dictionary, rather than a shared mutable instance. In some cases, programs may rely on the previous behavior.

        ","tags":["RUF024"]},{"location":"rules/mutable-fromkeys-value/#references","title":"References","text":"
        • Python documentation: dict.fromkeys
        ","tags":["RUF024"]},{"location":"rules/named-expr-without-context/","title":"named-expr-without-context (PLW0131)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0131"]},{"location":"rules/named-expr-without-context/#what-it-does","title":"What it does","text":"

        Checks for uses of named expressions (e.g., a := 42) that can be replaced by regular assignment statements (e.g., a = 42).

        ","tags":["PLW0131"]},{"location":"rules/named-expr-without-context/#why-is-this-bad","title":"Why is this bad?","text":"

        While a top-level named expression is syntactically and semantically valid, it's less clear than a regular assignment statement. Named expressions are intended to be used in comprehensions and generator expressions, where assignment statements are not allowed.

        ","tags":["PLW0131"]},{"location":"rules/named-expr-without-context/#example","title":"Example","text":"
        (a := 42)\n

        Use instead:

        a = 42\n
        ","tags":["PLW0131"]},{"location":"rules/nan-comparison/","title":"nan-comparison (PLW0177)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW0177"]},{"location":"rules/nan-comparison/#what-it-does","title":"What it does","text":"

        Checks for comparisons against NaN values.

        ","tags":["PLW0177"]},{"location":"rules/nan-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing against a NaN value can lead to unexpected results. For example, float(\"NaN\") == float(\"NaN\") will return False and, in general, x == float(\"NaN\") will always return False, even if x is NaN.

        To determine whether a value is NaN, use math.isnan or np.isnan instead of comparing against NaN directly.

        ","tags":["PLW0177"]},{"location":"rules/nan-comparison/#example","title":"Example","text":"
        if x == float(\"NaN\"):\n    pass\n

        Use instead:

        import math\n\nif math.isnan(x):\n    pass\n
        ","tags":["PLW0177"]},{"location":"rules/native-literals/","title":"native-literals (UP018)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP018"]},{"location":"rules/native-literals/#what-it-does","title":"What it does","text":"

        Checks for unnecessary calls to str, bytes, int, float, and bool.

        ","tags":["UP018"]},{"location":"rules/native-literals/#why-is-this-bad","title":"Why is this bad?","text":"

        The mentioned constructors can be replaced with their respective literal forms, which are more readable and idiomatic.

        ","tags":["UP018"]},{"location":"rules/native-literals/#example","title":"Example","text":"
        str(\"foo\")\n

        Use instead:

        \"foo\"\n
        ","tags":["UP018"]},{"location":"rules/native-literals/#fix-safety","title":"Fix safety","text":"

        The fix is marked as unsafe if it might remove comments.

        ","tags":["UP018"]},{"location":"rules/native-literals/#references","title":"References","text":"
        • Python documentation: str
        • Python documentation: bytes
        • Python documentation: int
        • Python documentation: float
        • Python documentation: bool
        ","tags":["UP018"]},{"location":"rules/needless-bool/","title":"needless-bool (SIM103)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM103"]},{"location":"rules/needless-bool/#what-it-does","title":"What it does","text":"

        Checks for if statements that can be replaced with bool.

        ","tags":["SIM103"]},{"location":"rules/needless-bool/#why-is-this-bad","title":"Why is this bad?","text":"

        if statements that return True for a truthy condition and False for a falsy condition can be replaced with boolean casts.

        ","tags":["SIM103"]},{"location":"rules/needless-bool/#example","title":"Example","text":"

        Given:

        def foo(x: int) -> bool:\n    if x > 0:\n        return True\n    else:\n        return False\n

        Use instead:

        def foo(x: int) -> bool:\n    return x > 0\n

        Or, given:

        def foo(x: int) -> bool:\n    if x > 0:\n        return True\n    return False\n

        Use instead:

        def foo(x: int) -> bool:\n    return x > 0\n
        ","tags":["SIM103"]},{"location":"rules/needless-bool/#fix-safety","title":"Fix safety","text":"

        This fix is marked as unsafe because it may change the program\u2019s behavior if the condition does not return a proper Boolean. While the fix will try to wrap non-boolean values in a call to bool, custom implementations of comparison functions like __eq__ can avoid the bool call and still lead to altered behavior.

        ","tags":["SIM103"]},{"location":"rules/needless-bool/#references","title":"References","text":"
        • Python documentation: Truth Value Testing
        ","tags":["SIM103"]},{"location":"rules/needless-else/","title":"needless-else (RUF047)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF047"]},{"location":"rules/needless-else/#what-it-does","title":"What it does","text":"

        Checks for else clauses that only contains pass and ... statements.

        ","tags":["RUF047"]},{"location":"rules/needless-else/#why-is-this-bad","title":"Why is this bad?","text":"

        Such an else clause does nothing and can be removed.

        ","tags":["RUF047"]},{"location":"rules/needless-else/#example","title":"Example","text":"
        if foo:\n    bar()\nelse:\n    pass\n

        Use instead:

        if foo:\n    bar()\n
        ","tags":["RUF047"]},{"location":"rules/negate-equal-op/","title":"negate-equal-op (SIM201)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM201"]},{"location":"rules/negate-equal-op/#what-it-does","title":"What it does","text":"

        Checks for negated == operators.

        ","tags":["SIM201"]},{"location":"rules/negate-equal-op/#why-is-this-bad","title":"Why is this bad?","text":"

        Negated == operators are less readable than != operators. When testing for non-equality, it is more common to use != than ==.

        ","tags":["SIM201"]},{"location":"rules/negate-equal-op/#example","title":"Example","text":"
        not a == b\n

        Use instead:

        a != b\n
        ","tags":["SIM201"]},{"location":"rules/negate-equal-op/#fix-safety","title":"Fix safety","text":"

        The fix is marked as unsafe, as it might change the behaviour if a and/or b overrides __eq__/__ne__ in such a manner that they don't return booleans.

        ","tags":["SIM201"]},{"location":"rules/negate-equal-op/#references","title":"References","text":"
        • Python documentation: Comparisons
        ","tags":["SIM201"]},{"location":"rules/negate-not-equal-op/","title":"negate-not-equal-op (SIM202)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM202"]},{"location":"rules/negate-not-equal-op/#what-it-does","title":"What it does","text":"

        Checks for negated != operators.

        ","tags":["SIM202"]},{"location":"rules/negate-not-equal-op/#why-is-this-bad","title":"Why is this bad?","text":"

        Negated != operators are less readable than == operators, as they avoid a double negation.

        ","tags":["SIM202"]},{"location":"rules/negate-not-equal-op/#example","title":"Example","text":"
        not a != b\n

        Use instead:

        a == b\n
        ","tags":["SIM202"]},{"location":"rules/negate-not-equal-op/#fix-safety","title":"Fix safety","text":"

        The fix is marked as unsafe, as it might change the behaviour if a and/or b overrides __ne__/__eq__ in such a manner that they don't return booleans.

        ","tags":["SIM202"]},{"location":"rules/negate-not-equal-op/#references","title":"References","text":"
        • Python documentation: Comparisons
        ","tags":["SIM202"]},{"location":"rules/nested-min-max/","title":"nested-min-max (PLW3301)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLW3301"]},{"location":"rules/nested-min-max/#what-it-does","title":"What it does","text":"

        Checks for nested min and max calls.

        ","tags":["PLW3301"]},{"location":"rules/nested-min-max/#why-is-this-bad","title":"Why is this bad?","text":"

        Nested min and max calls can be flattened into a single call to improve readability.

        ","tags":["PLW3301"]},{"location":"rules/nested-min-max/#example","title":"Example","text":"
        minimum = min(1, 2, min(3, 4, 5))\nmaximum = max(1, 2, max(3, 4, 5))\ndiff = maximum - minimum\n

        Use instead:

        minimum = min(1, 2, 3, 4, 5)\nmaximum = max(1, 2, 3, 4, 5)\ndiff = maximum - minimum\n
        ","tags":["PLW3301"]},{"location":"rules/nested-min-max/#fix-safety","title":"Fix safety","text":"

        This fix is always unsafe and may change the program's behavior for types without full equivalence relations, such as float comparisons involving NaN.

        print(min(2.0, min(float(\"nan\"), 1.0)))  # before fix: 2.0\nprint(min(2.0, float(\"nan\"), 1.0))  # after fix: 1.0\n\nprint(max(1.0, max(float(\"nan\"), 2.0)))  # before fix: 1.0\nprint(max(1.0, float(\"nan\"), 2.0))  # after fix: 2.0\n
        ","tags":["PLW3301"]},{"location":"rules/nested-min-max/#references","title":"References","text":"
        • Python documentation: min
        • Python documentation: max
        ","tags":["PLW3301"]},{"location":"rules/never-union/","title":"never-union (RUF020)","text":"

        Fix is sometimes available.

        ","tags":["RUF020"]},{"location":"rules/never-union/#what-it-does","title":"What it does","text":"

        Checks for uses of typing.NoReturn and typing.Never in union types.

        ","tags":["RUF020"]},{"location":"rules/never-union/#why-is-this-bad","title":"Why is this bad?","text":"

        typing.NoReturn and typing.Never are special types, used to indicate that a function never returns, or that a type has no values.

        Including typing.NoReturn or typing.Never in a union type is redundant, as, e.g., typing.Never | T is equivalent to T.

        ","tags":["RUF020"]},{"location":"rules/never-union/#example","title":"Example","text":"
        from typing import Never\n\n\ndef func() -> Never | int: ...\n

        Use instead:

        def func() -> int: ...\n
        ","tags":["RUF020"]},{"location":"rules/never-union/#references","title":"References","text":"
        • Python documentation: typing.Never
        • Python documentation: typing.NoReturn
        ","tags":["RUF020"]},{"location":"rules/new-line-after-last-paragraph/","title":"new-line-after-last-paragraph (D209)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D209"]},{"location":"rules/new-line-after-last-paragraph/#what-it-does","title":"What it does","text":"

        Checks for multi-line docstrings whose closing quotes are not on their own line.

        ","tags":["D209"]},{"location":"rules/new-line-after-last-paragraph/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that the closing quotes of a multi-line docstring be on their own line, for consistency and compatibility with documentation tools that may need to parse the docstring.

        ","tags":["D209"]},{"location":"rules/new-line-after-last-paragraph/#example","title":"Example","text":"
        def sort_list(l: List[int]) -> List[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the\n    bubble sort algorithm.\"\"\"\n

        Use instead:

        def sort_list(l: List[int]) -> List[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D209"]},{"location":"rules/new-line-after-last-paragraph/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D209"]},{"location":"rules/no-blank-line-after-section/","title":"no-blank-line-after-section (D410)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D410"]},{"location":"rules/no-blank-line-after-section/#what-it-does","title":"What it does","text":"

        Checks for docstring sections that are not separated by a single blank line.

        ","tags":["D410"]},{"location":"rules/no-blank-line-after-section/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces consistency in your docstrings, and helps ensure compatibility with documentation tooling.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. If a multiline numpy-style or Google-style docstring consists of multiple sections, each section should be separated by a single blank line.

        This rule is enabled when using the numpy and google conventions, and disabled when using the pep257 convention.

        ","tags":["D410"]},{"location":"rules/no-blank-line-after-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D410"]},{"location":"rules/no-blank-line-after-section/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D410"]},{"location":"rules/no-blank-line-after-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Guide
        ","tags":["D410"]},{"location":"rules/no-blank-line-before-section/","title":"no-blank-line-before-section (D411)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D411"]},{"location":"rules/no-blank-line-before-section/#what-it-does","title":"What it does","text":"

        Checks for docstring sections that are not separated by a blank line.

        ","tags":["D411"]},{"location":"rules/no-blank-line-before-section/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces consistency in numpy-style and Google-style docstrings, and helps ensure compatibility with documentation tooling.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. Sections should be separated by a single blank line.

        This rule is enabled when using the numpy and google conventions, and disabled when using the pep257 convention.

        ","tags":["D411"]},{"location":"rules/no-blank-line-before-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D411"]},{"location":"rules/no-blank-line-before-section/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D411"]},{"location":"rules/no-blank-line-before-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D411"]},{"location":"rules/no-classmethod-decorator/","title":"no-classmethod-decorator (PLR0202)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0202"]},{"location":"rules/no-classmethod-decorator/#what-it-does","title":"What it does","text":"

        Checks for the use of a classmethod being made without the decorator.

        ","tags":["PLR0202"]},{"location":"rules/no-classmethod-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        When it comes to consistency and readability, it's preferred to use the decorator.

        ","tags":["PLR0202"]},{"location":"rules/no-classmethod-decorator/#example","title":"Example","text":"
        class Foo:\n    def bar(cls): ...\n\n    bar = classmethod(bar)\n

        Use instead:

        class Foo:\n    @classmethod\n    def bar(cls): ...\n
        ","tags":["PLR0202"]},{"location":"rules/no-explicit-stacklevel/","title":"no-explicit-stacklevel (B028)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B028"]},{"location":"rules/no-explicit-stacklevel/#what-it-does","title":"What it does","text":"

        Checks for warnings.warn calls without an explicit stacklevel keyword argument.

        ","tags":["B028"]},{"location":"rules/no-explicit-stacklevel/#why-is-this-bad","title":"Why is this bad?","text":"

        The warnings.warn method uses a stacklevel of 1 by default, which will output a stack frame of the line on which the \"warn\" method is called. Setting it to a higher number will output a stack frame from higher up the stack.

        It's recommended to use a stacklevel of 2 or higher, to give the caller more context about the warning.

        ","tags":["B028"]},{"location":"rules/no-explicit-stacklevel/#example","title":"Example","text":"
        warnings.warn(\"This is a warning\")\n

        Use instead:

        warnings.warn(\"This is a warning\", stacklevel=2)\n
        ","tags":["B028"]},{"location":"rules/no-explicit-stacklevel/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because it changes the behavior of the code. Moreover, the fix will assign a stacklevel of 2, while the user may wish to assign a higher stacklevel to address the diagnostic.

        ","tags":["B028"]},{"location":"rules/no-explicit-stacklevel/#references","title":"References","text":"
        • Python documentation: warnings.warn
        ","tags":["B028"]},{"location":"rules/no-indented-block-comment/","title":"no-indented-block-comment (E115)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E115"]},{"location":"rules/no-indented-block-comment/#what-it-does","title":"What it does","text":"

        Checks for comments in a code blocks that are lacking indentation.

        ","tags":["E115"]},{"location":"rules/no-indented-block-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Comments within an indented block should themselves be indented, to indicate that they are part of the block.

        ","tags":["E115"]},{"location":"rules/no-indented-block-comment/#example","title":"Example","text":"
        for item in items:\n# Hi\n    pass\n

        Use instead:

        for item in items:\n    # Hi\n    pass\n
        ","tags":["E115"]},{"location":"rules/no-indented-block/","title":"no-indented-block (E112)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E112"]},{"location":"rules/no-indented-block/#what-it-does","title":"What it does","text":"

        Checks for indented blocks that are lacking indentation.

        ","tags":["E112"]},{"location":"rules/no-indented-block/#why-is-this-bad","title":"Why is this bad?","text":"

        All indented blocks should be indented; otherwise, they are not valid Python syntax.

        ","tags":["E112"]},{"location":"rules/no-indented-block/#example","title":"Example","text":"
        for item in items:\npass\n

        Use instead:

        for item in items:\n    pass\n
        ","tags":["E112"]},{"location":"rules/no-return-argument-annotation-in-stub/","title":"no-return-argument-annotation-in-stub (PYI050)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI050"]},{"location":"rules/no-return-argument-annotation-in-stub/#what-it-does","title":"What it does","text":"

        Checks for uses of typing.NoReturn (and typing_extensions.NoReturn) for parameter annotations.

        ","tags":["PYI050"]},{"location":"rules/no-return-argument-annotation-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefer Never over NoReturn for parameter annotations. Never has a clearer name in these contexts, since it makes little sense to talk about a parameter annotation \"not returning\".

        This is a purely stylistic lint: the two types have identical semantics for type checkers. Both represent Python's \"bottom type\" (a type that has no members).

        ","tags":["PYI050"]},{"location":"rules/no-return-argument-annotation-in-stub/#example","title":"Example","text":"
        from typing import NoReturn\n\ndef foo(x: NoReturn): ...\n

        Use instead:

        from typing import Never\n\ndef foo(x: Never): ...\n
        ","tags":["PYI050"]},{"location":"rules/no-return-argument-annotation-in-stub/#references","title":"References","text":"
        • Python documentation: typing.Never
        • Python documentation: typing.NoReturn
        ","tags":["PYI050"]},{"location":"rules/no-self-use/","title":"no-self-use (PLR6301)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR6301"]},{"location":"rules/no-self-use/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused self parameter in methods definitions.

        ","tags":["PLR6301"]},{"location":"rules/no-self-use/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused self parameters are usually a sign of a method that could be replaced by a function, class method, or static method.

        ","tags":["PLR6301"]},{"location":"rules/no-self-use/#example","title":"Example","text":"
        class Person:\n    def greeting(self):\n        print(\"Greetings friend!\")\n

        Use instead:

        def greeting():\n    print(\"Greetings friend!\")\n

        or

        class Person:\n    @staticmethod\n    def greeting():\n        print(\"Greetings friend!\")\n
        ","tags":["PLR6301"]},{"location":"rules/no-slots-in-namedtuple-subclass/","title":"no-slots-in-namedtuple-subclass (SLOT002)","text":"

        Derived from the flake8-slots linter.

        ","tags":["SLOT002"]},{"location":"rules/no-slots-in-namedtuple-subclass/#what-it-does","title":"What it does","text":"

        Checks for subclasses of collections.namedtuple or typing.NamedTuple that lack a __slots__ definition.

        ","tags":["SLOT002"]},{"location":"rules/no-slots-in-namedtuple-subclass/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the __slots__ attribute allows you to explicitly define the attributes (instance variables) that a class can have. By default, Python uses a dictionary to store an object's attributes, which incurs some memory overhead. However, when __slots__ is defined, Python uses a more compact internal structure to store the object's attributes, resulting in memory savings.

        Subclasses of namedtuple inherit all the attributes and methods of the built-in namedtuple class. Since tuples are typically immutable, they don't require additional attributes beyond what the namedtuple class provides. Defining __slots__ for subclasses of namedtuple prevents the creation of a dictionary for each instance, reducing memory consumption.

        ","tags":["SLOT002"]},{"location":"rules/no-slots-in-namedtuple-subclass/#example","title":"Example","text":"
        from collections import namedtuple\n\n\nclass Foo(namedtuple(\"foo\", [\"str\", \"int\"])):\n    pass\n

        Use instead:

        from collections import namedtuple\n\n\nclass Foo(namedtuple(\"foo\", [\"str\", \"int\"])):\n    __slots__ = ()\n
        ","tags":["SLOT002"]},{"location":"rules/no-slots-in-namedtuple-subclass/#references","title":"References","text":"
        • Python documentation: __slots__
        ","tags":["SLOT002"]},{"location":"rules/no-slots-in-str-subclass/","title":"no-slots-in-str-subclass (SLOT000)","text":"

        Derived from the flake8-slots linter.

        ","tags":["SLOT000"]},{"location":"rules/no-slots-in-str-subclass/#what-it-does","title":"What it does","text":"

        Checks for subclasses of str that lack a __slots__ definition.

        ","tags":["SLOT000"]},{"location":"rules/no-slots-in-str-subclass/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the __slots__ attribute allows you to explicitly define the attributes (instance variables) that a class can have. By default, Python uses a dictionary to store an object's attributes, which incurs some memory overhead. However, when __slots__ is defined, Python uses a more compact internal structure to store the object's attributes, resulting in memory savings.

        Subclasses of str inherit all the attributes and methods of the built-in str class. Since strings are typically immutable, they don't require additional attributes beyond what the str class provides. Defining __slots__ for subclasses of str prevents the creation of a dictionary for each instance, reducing memory consumption.

        ","tags":["SLOT000"]},{"location":"rules/no-slots-in-str-subclass/#example","title":"Example","text":"
        class Foo(str):\n    pass\n

        Use instead:

        class Foo(str):\n    __slots__ = ()\n
        ","tags":["SLOT000"]},{"location":"rules/no-slots-in-str-subclass/#references","title":"References","text":"
        • Python documentation: __slots__
        ","tags":["SLOT000"]},{"location":"rules/no-slots-in-tuple-subclass/","title":"no-slots-in-tuple-subclass (SLOT001)","text":"

        Derived from the flake8-slots linter.

        ","tags":["SLOT001"]},{"location":"rules/no-slots-in-tuple-subclass/#what-it-does","title":"What it does","text":"

        Checks for subclasses of tuple that lack a __slots__ definition.

        ","tags":["SLOT001"]},{"location":"rules/no-slots-in-tuple-subclass/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the __slots__ attribute allows you to explicitly define the attributes (instance variables) that a class can have. By default, Python uses a dictionary to store an object's attributes, which incurs some memory overhead. However, when __slots__ is defined, Python uses a more compact internal structure to store the object's attributes, resulting in memory savings.

        Subclasses of tuple inherit all the attributes and methods of the built-in tuple class. Since tuples are typically immutable, they don't require additional attributes beyond what the tuple class provides. Defining __slots__ for subclasses of tuple prevents the creation of a dictionary for each instance, reducing memory consumption.

        ","tags":["SLOT001"]},{"location":"rules/no-slots-in-tuple-subclass/#example","title":"Example","text":"
        class Foo(tuple):\n    pass\n

        Use instead:

        class Foo(tuple):\n    __slots__ = ()\n
        ","tags":["SLOT001"]},{"location":"rules/no-slots-in-tuple-subclass/#references","title":"References","text":"
        • Python documentation: __slots__
        ","tags":["SLOT001"]},{"location":"rules/no-space-after-block-comment/","title":"no-space-after-block-comment (E265)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E265"]},{"location":"rules/no-space-after-block-comment/#what-it-does","title":"What it does","text":"

        Checks for block comments that lack a single space after the leading # character.

        ","tags":["E265"]},{"location":"rules/no-space-after-block-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Per PEP 8, \"Block comments generally consist of one or more paragraphs built out of complete sentences, with each sentence ending in a period.\"

        Block comments should start with a # followed by a single space.

        Shebangs (lines starting with #!, at the top of a file) are exempt from this rule.

        ","tags":["E265"]},{"location":"rules/no-space-after-block-comment/#example","title":"Example","text":"
        #Block comment\n

        Use instead:

        # Block comment\n
        ","tags":["E265"]},{"location":"rules/no-space-after-inline-comment/","title":"no-space-after-inline-comment (E262)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E262"]},{"location":"rules/no-space-after-inline-comment/#what-it-does","title":"What it does","text":"

        Checks if one space is used after inline comments.

        ","tags":["E262"]},{"location":"rules/no-space-after-inline-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        An inline comment is a comment on the same line as a statement.

        Per PEP 8, inline comments should start with a # and a single space.

        ","tags":["E262"]},{"location":"rules/no-space-after-inline-comment/#example","title":"Example","text":"
        x = x + 1  #Increment x\nx = x + 1  #  Increment x\nx = x + 1  # \\xa0Increment x\n

        Use instead:

        x = x + 1  # Increment x\nx = x + 1    # Increment x\n
        ","tags":["E262"]},{"location":"rules/no-staticmethod-decorator/","title":"no-staticmethod-decorator (PLR0203)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0203"]},{"location":"rules/no-staticmethod-decorator/#what-it-does","title":"What it does","text":"

        Checks for the use of a staticmethod being made without the decorator.

        ","tags":["PLR0203"]},{"location":"rules/no-staticmethod-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        When it comes to consistency and readability, it's preferred to use the decorator.

        ","tags":["PLR0203"]},{"location":"rules/no-staticmethod-decorator/#example","title":"Example","text":"
        class Foo:\n    def bar(arg1, arg2): ...\n\n    bar = staticmethod(bar)\n

        Use instead:

        class Foo:\n    @staticmethod\n    def bar(arg1, arg2): ...\n
        ","tags":["PLR0203"]},{"location":"rules/non-ascii-import-name/","title":"non-ascii-import-name (PLC2403)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC2403"]},{"location":"rules/non-ascii-import-name/#what-it-does","title":"What it does","text":"

        Checks for the use of non-ASCII characters in import statements.

        ","tags":["PLC2403"]},{"location":"rules/non-ascii-import-name/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of non-ASCII characters in import statements can cause confusion and compatibility issues (see: PEP 672).

        ","tags":["PLC2403"]},{"location":"rules/non-ascii-import-name/#example","title":"Example","text":"
        import b\u00e1r\n

        Use instead:

        import bar\n

        If the module is third-party, use an ASCII-only alias:

        import b\u00e1r as bar\n
        ","tags":["PLC2403"]},{"location":"rules/non-ascii-name/","title":"non-ascii-name (PLC2401)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC2401"]},{"location":"rules/non-ascii-name/#what-it-does","title":"What it does","text":"

        Checks for the use of non-ASCII characters in variable names.

        ","tags":["PLC2401"]},{"location":"rules/non-ascii-name/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of non-ASCII characters in variable names can cause confusion and compatibility issues (see: PEP 672).

        ","tags":["PLC2401"]},{"location":"rules/non-ascii-name/#example","title":"Example","text":"
        \u00e1pple_count: int\n

        Use instead:

        apple_count: int\n
        ","tags":["PLC2401"]},{"location":"rules/non-augmented-assignment/","title":"non-augmented-assignment (PLR6104)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR6104"]},{"location":"rules/non-augmented-assignment/#what-it-does","title":"What it does","text":"

        Checks for assignments that can be replaced with augmented assignment statements.

        ","tags":["PLR6104"]},{"location":"rules/non-augmented-assignment/#why-is-this-bad","title":"Why is this bad?","text":"

        If the right-hand side of an assignment statement consists of a binary operation in which one operand is the same as the assignment target, it can be rewritten as an augmented assignment. For example, x = x + 1 can be rewritten as x += 1.

        When performing such an operation, an augmented assignment is more concise and idiomatic.

        ","tags":["PLR6104"]},{"location":"rules/non-augmented-assignment/#known-problems","title":"Known problems","text":"

        In some cases, this rule will not detect assignments in which the target is on the right-hand side of a binary operation (e.g., x = y + x, as opposed to x = x + y), as such operations are not commutative for certain data types, like strings.

        For example, x = \"prefix-\" + x is not equivalent to x += \"prefix-\", while x = 1 + x is equivalent to x += 1.

        If the type of the left-hand side cannot be trivially inferred, the rule will ignore the assignment.

        ","tags":["PLR6104"]},{"location":"rules/non-augmented-assignment/#example","title":"Example","text":"
        x = x + 1\n

        Use instead:

        x += 1\n
        ","tags":["PLR6104"]},{"location":"rules/non-augmented-assignment/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as augmented assignments have different semantics when the target is a mutable data type, like a list or dictionary.

        For example, consider the following:

        foo = [1]\nbar = foo\nfoo = foo + [2]\nassert (foo, bar) == ([1, 2], [1])\n

        If the assignment is replaced with an augmented assignment, the update operation will apply to both foo and bar, as they refer to the same object:

        foo = [1]\nbar = foo\nfoo += [2]\nassert (foo, bar) == ([1, 2], [1, 2])\n
        ","tags":["PLR6104"]},{"location":"rules/non-capitalized-section-name/","title":"non-capitalized-section-name (D405)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D405"]},{"location":"rules/non-capitalized-section-name/#what-it-does","title":"What it does","text":"

        Checks for section headers in docstrings that do not begin with capital letters.

        ","tags":["D405"]},{"location":"rules/non-capitalized-section-name/#why-is-this-bad","title":"Why is this bad?","text":"

        For stylistic consistency, all section headers in a docstring should be capitalized.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section typically has a header and a body.

        This rule is enabled when using the numpy and google conventions, and disabled when using the pep257 convention.

        ","tags":["D405"]},{"location":"rules/non-capitalized-section-name/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    returns:\n        Speed as distance divided by time.\n\n    raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D405"]},{"location":"rules/non-capitalized-section-name/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D405"]},{"location":"rules/non-capitalized-section-name/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D405"]},{"location":"rules/non-empty-stub-body/","title":"non-empty-stub-body (PYI010)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI010"]},{"location":"rules/non-empty-stub-body/#what-it-does","title":"What it does","text":"

        Checks for non-empty function stub bodies.

        ","tags":["PYI010"]},{"location":"rules/non-empty-stub-body/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files are never executed at runtime; they should be thought of as \"data files\" for type checkers or IDEs. Function bodies are redundant for this purpose.

        ","tags":["PYI010"]},{"location":"rules/non-empty-stub-body/#example","title":"Example","text":"
        def double(x: int) -> int:\n    return x * 2\n

        Use instead:

        def double(x: int) -> int: ...\n
        ","tags":["PYI010"]},{"location":"rules/non-empty-stub-body/#references","title":"References","text":"
        • Typing documentation - Writing and Maintaining Stub Files
        ","tags":["PYI010"]},{"location":"rules/non-imperative-mood/","title":"non-imperative-mood (D401)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D401"]},{"location":"rules/non-imperative-mood/#what-it-does","title":"What it does","text":"

        Checks for docstring first lines that are not in an imperative mood.

        ","tags":["D401"]},{"location":"rules/non-imperative-mood/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that the first line of a docstring be written in the imperative mood, for consistency.

        Hint: to rewrite the docstring in the imperative, phrase the first line as if it were a command.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the numpy and pep257 conventions, and disabled when using the google conventions.

        ","tags":["D401"]},{"location":"rules/non-imperative-mood/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"Returns the mean of the given values.\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D401"]},{"location":"rules/non-imperative-mood/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        • lint.pydocstyle.property-decorators
        • lint.pydocstyle.ignore-decorators
        ","tags":["D401"]},{"location":"rules/non-imperative-mood/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        ","tags":["D401"]},{"location":"rules/non-lowercase-variable-in-function/","title":"non-lowercase-variable-in-function (N806)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N806"]},{"location":"rules/non-lowercase-variable-in-function/#what-it-does","title":"What it does","text":"

        Checks for the use of non-lowercase variable names in functions.

        ","tags":["N806"]},{"location":"rules/non-lowercase-variable-in-function/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that all function variables use lowercase names:

        Function names should be lowercase, with words separated by underscores as necessary to improve readability. Variable names follow the same convention as function names. mixedCase is allowed only in contexts where that's already the prevailing style (e.g. threading.py), to retain backwards compatibility.

        ","tags":["N806"]},{"location":"rules/non-lowercase-variable-in-function/#example","title":"Example","text":"
        def my_function(a):\n    B = a + 3\n    return B\n

        Use instead:

        def my_function(a):\n    b = a + 3\n    return b\n
        ","tags":["N806"]},{"location":"rules/non-lowercase-variable-in-function/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N806"]},{"location":"rules/non-pep585-annotation/","title":"non-pep585-annotation (UP006)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP006"]},{"location":"rules/non-pep585-annotation/#what-it-does","title":"What it does","text":"

        Checks for the use of generics that can be replaced with standard library variants based on PEP 585.

        ","tags":["UP006"]},{"location":"rules/non-pep585-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 585 enabled collections in the Python standard library (like list) to be used as generics directly, instead of importing analogous members from the typing module (like typing.List).

        When available, the PEP 585 syntax should be used instead of importing members from the typing module, as it's more concise and readable. Importing those members from typing is considered deprecated as of PEP 585.

        This rule is enabled when targeting Python 3.9 or later (see: target-version). By default, it's also enabled for earlier Python versions if from __future__ import annotations is present, as __future__ annotations are not evaluated at runtime. If your code relies on runtime type annotations (either directly or via a library like Pydantic), you can disable this behavior for Python versions prior to 3.9 by setting lint.pyupgrade.keep-runtime-typing to true.

        ","tags":["UP006"]},{"location":"rules/non-pep585-annotation/#example","title":"Example","text":"
        from typing import List\n\nfoo: List[int] = [1, 2, 3]\n

        Use instead:

        foo: list[int] = [1, 2, 3]\n
        ","tags":["UP006"]},{"location":"rules/non-pep585-annotation/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may lead to runtime errors when alongside libraries that rely on runtime type annotations, like Pydantic, on Python versions prior to Python 3.9.

        ","tags":["UP006"]},{"location":"rules/non-pep585-annotation/#options","title":"Options","text":"
        • target-version
        • lint.pyupgrade.keep-runtime-typing
        ","tags":["UP006"]},{"location":"rules/non-pep604-annotation-optional/","title":"non-pep604-annotation-optional (UP045)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-optional/#what-it-does","title":"What it does","text":"

        Check for typing.Optional annotations that can be rewritten based on PEP 604 syntax.

        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-optional/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 604 introduced a new syntax for union type annotations based on the | operator. This syntax is more concise and readable than the previous typing.Optional syntax.

        This rule is enabled when targeting Python 3.10 or later (see: target-version). By default, it's also enabled for earlier Python versions if from __future__ import annotations is present, as __future__ annotations are not evaluated at runtime. If your code relies on runtime type annotations (either directly or via a library like Pydantic), you can disable this behavior for Python versions prior to 3.10 by setting lint.pyupgrade.keep-runtime-typing to true.

        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-optional/#example","title":"Example","text":"
        from typing import Optional\n\nfoo: Optional[int] = None\n

        Use instead:

        foo: int | None = None\n
        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-optional/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may lead to runtime errors when alongside libraries that rely on runtime type annotations, like Pydantic, on Python versions prior to Python 3.10. It may also lead to runtime errors in unusual and likely incorrect type annotations where the type does not support the | operator.

        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-optional/#options","title":"Options","text":"
        • target-version
        • lint.pyupgrade.keep-runtime-typing
        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-union/","title":"non-pep604-annotation-union (UP007)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#what-it-does","title":"What it does","text":"

        Check for type annotations that can be rewritten based on PEP 604 syntax.

        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 604 introduced a new syntax for union type annotations based on the | operator. This syntax is more concise and readable than the previous typing.Union and typing.Optional syntaxes.

        This rule is enabled when targeting Python 3.10 or later (see: target-version). By default, it's also enabled for earlier Python versions if from __future__ import annotations is present, as __future__ annotations are not evaluated at runtime. If your code relies on runtime type annotations (either directly or via a library like Pydantic), you can disable this behavior for Python versions prior to 3.10 by setting lint.pyupgrade.keep-runtime-typing to true.

        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#example","title":"Example","text":"
        from typing import Union\n\nfoo: Union[int, str] = 1\n

        Use instead:

        foo: int | str = 1\n
        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#preview","title":"Preview","text":"

        In preview mode, this rule only checks for usages of typing.Union, while UP045 checks for typing.Optional.

        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may lead to runtime errors when alongside libraries that rely on runtime type annotations, like Pydantic, on Python versions prior to Python 3.10. It may also lead to runtime errors in unusual and likely incorrect type annotations where the type does not support the | operator.

        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#options","title":"Options","text":"
        • target-version
        • lint.pyupgrade.keep-runtime-typing
        ","tags":["UP007"]},{"location":"rules/non-pep604-isinstance/","title":"non-pep604-isinstance (UP038)","text":"

        Derived from the pyupgrade linter.

        Warning: This rule is deprecated and will be removed in a future release.

        Fix is always available.

        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#deprecation","title":"Deprecation","text":"

        This rule was deprecated as using PEP 604 syntax in isinstance and issubclass calls isn't recommended practice, and it incorrectly suggests that other typing syntaxes like PEP 695 would be supported by isinstance and issubclass. Using the PEP 604 syntax is also slightly slower.

        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#what-it-does","title":"What it does","text":"

        Checks for uses of isinstance and issubclass that take a tuple of types for comparison.

        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3.10, isinstance and issubclass can be passed a |-separated union of types, which is consistent with the union operator introduced in PEP 604.

        Note that this results in slower code. Ignore this rule if the performance of an isinstance or issubclass check is a concern, e.g., in a hot loop.

        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#example","title":"Example","text":"
        isinstance(x, (int, float))\n

        Use instead:

        isinstance(x, int | float)\n
        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#options","title":"Options","text":"
        • target-version
        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#references","title":"References","text":"
        • Python documentation: isinstance
        • Python documentation: issubclass
        ","tags":["UP038"]},{"location":"rules/non-pep646-unpack/","title":"non-pep646-unpack (UP044)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP044"]},{"location":"rules/non-pep646-unpack/#what-it-does","title":"What it does","text":"

        Checks for uses of Unpack[] on Python 3.11 and above, and suggests using * instead.

        ","tags":["UP044"]},{"location":"rules/non-pep646-unpack/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 646 introduced a new syntax for unpacking sequences based on the * operator. This syntax is more concise and readable than the previous Unpack[] syntax.

        ","tags":["UP044"]},{"location":"rules/non-pep646-unpack/#example","title":"Example","text":"
        from typing import Unpack\n\n\ndef foo(*args: Unpack[tuple[int, ...]]) -> None:\n    pass\n

        Use instead:

        def foo(*args: *tuple[int, ...]) -> None:\n    pass\n
        ","tags":["UP044"]},{"location":"rules/non-pep646-unpack/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as Unpack[T] and *T are considered different values when introspecting types at runtime. However, in most cases, the fix should be safe to apply.

        ","tags":["UP044"]},{"location":"rules/non-pep695-generic-class/","title":"non-pep695-generic-class (UP046)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#what-it-does","title":"What it does","text":"

        Checks for use of standalone type variables and parameter specifications in generic classes.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Special type parameter syntax was introduced in Python 3.12 by PEP 695 for defining generic classes. This syntax is easier to read and provides cleaner support for generics.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#known-problems","title":"Known problems","text":"

        The rule currently skips generic classes nested inside of other functions or classes. It also skips type parameters with the default argument introduced in PEP 696 and implemented in Python 3.13.

        This rule can only offer a fix if all of the generic types in the class definition are defined in the current module. For external type parameters, a diagnostic is emitted without a suggested fix.

        Not all type checkers fully support PEP 695 yet, so even valid fixes suggested by this rule may cause type checking to fail.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#fix-safety","title":"Fix safety","text":"

        This fix is marked as unsafe, as PEP 695 uses inferred variance for type parameters, instead of the covariant and contravariant keywords used by TypeVar variables. As such, replacing a TypeVar variable with an inline type parameter may change its variance.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"T\")\n\n\nclass GenericClass(Generic[T]):\n    var: T\n

        Use instead:

        class GenericClass[T]:\n    var: T\n
        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#see-also","title":"See also","text":"

        This rule replaces standalone type variables in classes but doesn't remove the corresponding type variables even if they are unused after the fix. See unused-private-type-var for a rule to clean up unused private type variables.

        This rule will not rename private type variables to remove leading underscores, even though the new type parameters are restricted in scope to their associated class. See private-type-parameter for a rule to update these names.

        This rule will correctly handle classes with multiple base classes, as long as the single Generic base class is at the end of the argument list, as checked by generic-not-last-base-class. If a Generic base class is found outside of the last position, a diagnostic is emitted without a suggested fix.

        This rule only applies to generic classes and does not include generic functions. See non-pep695-generic-function for the function version.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-function/","title":"non-pep695-generic-function (UP047)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#what-it-does","title":"What it does","text":"

        Checks for use of standalone type variables and parameter specifications in generic functions.

        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Special type parameter syntax was introduced in Python 3.12 by PEP 695 for defining generic functions. This syntax is easier to read and provides cleaner support for generics.

        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#known-problems","title":"Known problems","text":"

        The rule currently skips generic functions nested inside of other functions or classes and those with type parameters containing the default argument introduced in PEP 696 and implemented in Python 3.13.

        Not all type checkers fully support PEP 695 yet, so even valid fixes suggested by this rule may cause type checking to fail.

        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#fix-safety","title":"Fix safety","text":"

        This fix is marked unsafe, as PEP 695 uses inferred variance for type parameters, instead of the covariant and contravariant keywords used by TypeVar variables. As such, replacing a TypeVar variable with an inline type parameter may change its variance.

        Additionally, if the rule cannot determine whether a parameter annotation corresponds to a type variable (e.g. for a type imported from another module), it will not add the type to the generic type parameter list. This causes the function to have a mix of old-style type variables and new-style generic type parameters, which will be rejected by type checkers.

        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"T\")\n\n\ndef generic_function(var: T) -> T:\n    return var\n

        Use instead:

        def generic_function[T](var: T) -> T:\n    return var\n
        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#see-also","title":"See also","text":"

        This rule replaces standalone type variables in function signatures but doesn't remove the corresponding type variables even if they are unused after the fix. See unused-private-type-var for a rule to clean up unused private type variables.

        This rule will not rename private type variables to remove leading underscores, even though the new type parameters are restricted in scope to their associated function. See private-type-parameter for a rule to update these names.

        This rule only applies to generic functions and does not include generic classes. See non-pep695-generic-class for the class version.

        ","tags":["UP047"]},{"location":"rules/non-pep695-type-alias/","title":"non-pep695-type-alias (UP040)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#what-it-does","title":"What it does","text":"

        Checks for use of TypeAlias annotations and TypeAliasType assignments for declaring type aliases.

        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        The type keyword was introduced in Python 3.12 by PEP 695 for defining type aliases. The type keyword is easier to read and provides cleaner support for generics.

        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#known-problems","title":"Known problems","text":"

        PEP 695 uses inferred variance for type parameters, instead of the covariant and contravariant keywords used by TypeVar variables. As such, rewriting a type alias using a PEP-695 type statement may change the variance of the alias's type parameters.

        Unlike type aliases that use simple assignments, definitions created using PEP 695 type statements cannot be used as drop-in replacements at runtime for the value on the right-hand side of the statement. This means that while for some simple old-style type aliases you can use them as the second argument to an isinstance() call (for example), doing the same with a PEP 695 type statement will always raise TypeError at runtime.

        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#example","title":"Example","text":"
        ListOfInt: TypeAlias = list[int]\nPositiveInt = TypeAliasType(\"PositiveInt\", Annotated[int, Gt(0)])\n

        Use instead:

        type ListOfInt = list[int]\ntype PositiveInt = Annotated[int, Gt(0)]\n
        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#fix-safety","title":"Fix safety","text":"

        This fix is marked unsafe for TypeAlias assignments outside of stub files because of the runtime behavior around isinstance() calls noted above. The fix is also unsafe for TypeAliasType assignments if there are any comments in the replacement range that would be deleted.

        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#see-also","title":"See also","text":"

        This rule only applies to TypeAliases and TypeAliasTypes. See non-pep695-generic-class and non-pep695-generic-function for similar transformations for generic classes and functions.

        This rule replaces standalone type variables in aliases but doesn't remove the corresponding type variables even if they are unused after the fix. See unused-private-type-var for a rule to clean up unused private type variables.

        This rule will not rename private type variables to remove leading underscores, even though the new type parameters are restricted in scope to their associated aliases. See private-type-parameter for a rule to update these names.

        ","tags":["UP040"]},{"location":"rules/non-self-return-type/","title":"non-self-return-type (PYI034)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#what-it-does","title":"What it does","text":"

        Checks for methods that are annotated with a fixed return type which should instead be returning Self.

        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        If methods that generally return self at runtime are annotated with a fixed return type, and the class is subclassed, type checkers will not be able to infer the correct return type.

        For example:

        class Shape:\n    def set_scale(self, scale: float) -> Shape:\n        self.scale = scale\n        return self\n\nclass Circle(Shape):\n    def set_radius(self, radius: float) -> Circle:\n        self.radius = radius\n        return self\n\n# Type checker infers return type as `Shape`, not `Circle`.\nCircle().set_scale(0.5)\n\n# Thus, this expression is invalid, as `Shape` has no attribute `set_radius`.\nCircle().set_scale(0.5).set_radius(2.7)\n

        Specifically, this check enforces that the return type of the following methods is Self:

        1. In-place binary-operation dunder methods, like __iadd__, __imul__, etc.
        2. __new__, __enter__, and __aenter__, if those methods return the class name.
        3. __iter__ methods that return Iterator, despite the class inheriting directly from Iterator.
        4. __aiter__ methods that return AsyncIterator, despite the class inheriting directly from AsyncIterator.
        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#example","title":"Example","text":"
        class Foo:\n    def __new__(cls, *args: Any, **kwargs: Any) -> Foo: ...\n    def __enter__(self) -> Foo: ...\n    async def __aenter__(self) -> Foo: ...\n    def __iadd__(self, other: Foo) -> Foo: ...\n

        Use instead:

        from typing_extensions import Self\n\nclass Foo:\n    def __new__(cls, *args: Any, **kwargs: Any) -> Self: ...\n    def __enter__(self) -> Self: ...\n    async def __aenter__(self) -> Self: ...\n    def __iadd__(self, other: Foo) -> Self: ...\n
        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe as it changes the meaning of your type annotations.

        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for Python versions before 3.11, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#references","title":"References","text":"
        • Python documentation: typing.Self
        ","tags":["PYI034"]},{"location":"rules/non-slot-assignment/","title":"non-slot-assignment (PLE0237)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0237"]},{"location":"rules/non-slot-assignment/#what-it-does","title":"What it does","text":"

        Checks for assignments to attributes that are not defined in __slots__.

        ","tags":["PLE0237"]},{"location":"rules/non-slot-assignment/#why-is-this-bad","title":"Why is this bad?","text":"

        When using __slots__, only the specified attributes are allowed. Attempting to assign to an attribute that is not defined in __slots__ will result in an AttributeError at runtime.

        ","tags":["PLE0237"]},{"location":"rules/non-slot-assignment/#known-problems","title":"Known problems","text":"

        This rule can't detect __slots__ implementations in superclasses, and so limits its analysis to classes that inherit from (at most) object.

        ","tags":["PLE0237"]},{"location":"rules/non-slot-assignment/#example","title":"Example","text":"
        class Student:\n    __slots__ = (\"name\",)\n\n    def __init__(self, name, surname):\n        self.name = name\n        self.surname = surname  # [assigning-non-slot]\n        self.setup()\n\n    def setup(self):\n        pass\n

        Use instead:

        class Student:\n    __slots__ = (\"name\", \"surname\")\n\n    def __init__(self, name, surname):\n        self.name = name\n        self.surname = surname\n        self.setup()\n\n    def setup(self):\n        pass\n
        ","tags":["PLE0237"]},{"location":"rules/non-unique-enums/","title":"non-unique-enums (PIE796)","text":"

        Derived from the flake8-pie linter.

        ","tags":["PIE796"]},{"location":"rules/non-unique-enums/#what-it-does","title":"What it does","text":"

        Checks for enums that contain duplicate values.

        ","tags":["PIE796"]},{"location":"rules/non-unique-enums/#why-is-this-bad","title":"Why is this bad?","text":"

        Enum values should be unique. Non-unique values are redundant and likely a mistake.

        ","tags":["PIE796"]},{"location":"rules/non-unique-enums/#example","title":"Example","text":"
        from enum import Enum\n\n\nclass Foo(Enum):\n    A = 1\n    B = 2\n    C = 1\n

        Use instead:

        from enum import Enum\n\n\nclass Foo(Enum):\n    A = 1\n    B = 2\n    C = 3\n
        ","tags":["PIE796"]},{"location":"rules/non-unique-enums/#references","title":"References","text":"
        • Python documentation: enum.Enum
        ","tags":["PIE796"]},{"location":"rules/none-comparison/","title":"none-comparison (E711)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["E711"]},{"location":"rules/none-comparison/#what-it-does","title":"What it does","text":"

        Checks for comparisons to None which are not using the is operator.

        ","tags":["E711"]},{"location":"rules/none-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"Comparisons to singletons like None should always be done with is or is not, never the equality operators.\"

        ","tags":["E711"]},{"location":"rules/none-comparison/#example","title":"Example","text":"
        if arg != None:\n    pass\nif None == arg:\n    pass\n

        Use instead:

        if arg is not None:\n    pass\n
        ","tags":["E711"]},{"location":"rules/none-comparison/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may alter runtime behavior when used with libraries that override the ==/__eq__ or !=/__ne__ operators. In these cases, is/is not may not be equivalent to ==/!=. For more information, see this issue.

        ","tags":["E711"]},{"location":"rules/none-not-at-end-of-union/","title":"none-not-at-end-of-union (RUF036)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF036"]},{"location":"rules/none-not-at-end-of-union/#what-it-does","title":"What it does","text":"

        Checks for type annotations where None is not at the end of an union.

        ","tags":["RUF036"]},{"location":"rules/none-not-at-end-of-union/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotation unions are associative, meaning that the order of the elements does not matter. The None literal represents the absence of a value. For readability, it's preferred to write the more informative type expressions first.

        ","tags":["RUF036"]},{"location":"rules/none-not-at-end-of-union/#example","title":"Example","text":"
        def func(arg: None | int): ...\n

        Use instead:

        def func(arg: int | None): ...\n
        ","tags":["RUF036"]},{"location":"rules/none-not-at-end-of-union/#references","title":"References","text":"
        • Python documentation: Union type
        • Python documentation: typing.Optional
        • Python documentation: None
        ","tags":["RUF036"]},{"location":"rules/nonlocal-and-global/","title":"nonlocal-and-global (PLE0115)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0115"]},{"location":"rules/nonlocal-and-global/#what-it-does","title":"What it does","text":"

        Checks for variables which are both declared as both nonlocal and global.

        ","tags":["PLE0115"]},{"location":"rules/nonlocal-and-global/#why-is-this-bad","title":"Why is this bad?","text":"

        A nonlocal variable is a variable that is defined in the nearest enclosing scope, but not in the global scope, while a global variable is a variable that is defined in the global scope.

        Declaring a variable as both nonlocal and global is contradictory and will raise a SyntaxError.

        ","tags":["PLE0115"]},{"location":"rules/nonlocal-and-global/#example","title":"Example","text":"
        counter = 0\n\n\ndef increment():\n    global counter\n    nonlocal counter\n    counter += 1\n

        Use instead:

        counter = 0\n\n\ndef increment():\n    global counter\n    counter += 1\n
        ","tags":["PLE0115"]},{"location":"rules/nonlocal-and-global/#references","title":"References","text":"
        • Python documentation: The global statement
        • Python documentation: The nonlocal statement
        ","tags":["PLE0115"]},{"location":"rules/nonlocal-without-binding/","title":"nonlocal-without-binding (PLE0117)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0117"]},{"location":"rules/nonlocal-without-binding/#what-it-does","title":"What it does","text":"

        Checks for nonlocal names without bindings.

        ","tags":["PLE0117"]},{"location":"rules/nonlocal-without-binding/#why-is-this-bad","title":"Why is this bad?","text":"

        nonlocal names must be bound to a name in an outer scope. Violating this rule leads to a SyntaxError at runtime.

        ","tags":["PLE0117"]},{"location":"rules/nonlocal-without-binding/#example","title":"Example","text":"
        def foo():\n    def get_bar(self):\n        nonlocal bar\n        ...\n

        Use instead:

        def foo():\n    bar = 1\n\n    def get_bar(self):\n        nonlocal bar\n        ...\n
        ","tags":["PLE0117"]},{"location":"rules/nonlocal-without-binding/#references","title":"References","text":"
        • Python documentation: The nonlocal statement
        • PEP 3104 \u2013 Access to Names in Outer Scopes
        ","tags":["PLE0117"]},{"location":"rules/not-in-test/","title":"not-in-test (E713)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["E713"]},{"location":"rules/not-in-test/#what-it-does","title":"What it does","text":"

        Checks for membership tests using not {element} in {collection}.

        ","tags":["E713"]},{"location":"rules/not-in-test/#why-is-this-bad","title":"Why is this bad?","text":"

        Testing membership with {element} not in {collection} is more readable.

        ","tags":["E713"]},{"location":"rules/not-in-test/#example","title":"Example","text":"
        Z = not X in Y\nif not X.B in Y:\n    pass\n

        Use instead:

        Z = X not in Y\nif X.B not in Y:\n    pass\n
        ","tags":["E713"]},{"location":"rules/not-is-test/","title":"not-is-test (E714)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["E714"]},{"location":"rules/not-is-test/#what-it-does","title":"What it does","text":"

        Checks for identity comparisons using not {foo} is {bar}.

        ","tags":["E714"]},{"location":"rules/not-is-test/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP8, testing for an object's identity with is not is more readable.

        ","tags":["E714"]},{"location":"rules/not-is-test/#example","title":"Example","text":"
        if not X is Y:\n    pass\nZ = not X.B is Y\n

        Use instead:

        if X is not Y:\n    pass\nZ = X.B is not Y\n
        ","tags":["E714"]},{"location":"rules/numeric-literal-too-long/","title":"numeric-literal-too-long (PYI054)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI054"]},{"location":"rules/numeric-literal-too-long/#what-it-does","title":"What it does","text":"

        Checks for numeric literals with a string representation longer than ten characters.

        ","tags":["PYI054"]},{"location":"rules/numeric-literal-too-long/#why-is-this-bad","title":"Why is this bad?","text":"

        If a function has a default value where the literal representation is greater than 10 characters, the value is likely to be an implementation detail or a constant that varies depending on the system you're running on.

        Default values like these should generally be omitted from stubs. Use ellipses (...) instead.

        ","tags":["PYI054"]},{"location":"rules/numeric-literal-too-long/#example","title":"Example","text":"
        def foo(arg: int = 693568516352839939918568862861217771399698285293568) -> None: ...\n

        Use instead:

        def foo(arg: int = ...) -> None: ...\n
        ","tags":["PYI054"]},{"location":"rules/numpy-deprecated-function/","title":"numpy-deprecated-function (NPY003)","text":"

        Fix is sometimes available.

        ","tags":["NPY003"]},{"location":"rules/numpy-deprecated-function/#what-it-does","title":"What it does","text":"

        Checks for uses of deprecated NumPy functions.

        ","tags":["NPY003"]},{"location":"rules/numpy-deprecated-function/#why-is-this-bad","title":"Why is this bad?","text":"

        When NumPy functions are deprecated, they are usually replaced with newer, more efficient versions, or with functions that are more consistent with the rest of the NumPy API.

        Prefer newer APIs over deprecated ones.

        ","tags":["NPY003"]},{"location":"rules/numpy-deprecated-function/#example","title":"Example","text":"
        import numpy as np\n\nnp.alltrue([True, False])\n

        Use instead:

        import numpy as np\n\nnp.all([True, False])\n
        ","tags":["NPY003"]},{"location":"rules/numpy-deprecated-type-alias/","title":"numpy-deprecated-type-alias (NPY001)","text":"

        Fix is sometimes available.

        ","tags":["NPY001"]},{"location":"rules/numpy-deprecated-type-alias/#what-it-does","title":"What it does","text":"

        Checks for deprecated NumPy type aliases.

        ","tags":["NPY001"]},{"location":"rules/numpy-deprecated-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        NumPy's np.int has long been an alias of the builtin int; the same is true of np.float and others. These aliases exist primarily for historic reasons, and have been a cause of frequent confusion for newcomers.

        These aliases were deprecated in 1.20, and removed in 1.24. Note, however, that np.bool and np.long were reintroduced in 2.0 with different semantics, and are thus omitted from this rule.

        ","tags":["NPY001"]},{"location":"rules/numpy-deprecated-type-alias/#example","title":"Example","text":"
        import numpy as np\n\nnp.int\n

        Use instead:

        int\n
        ","tags":["NPY001"]},{"location":"rules/numpy-legacy-random/","title":"numpy-legacy-random (NPY002)","text":"","tags":["NPY002"]},{"location":"rules/numpy-legacy-random/#what-it-does","title":"What it does","text":"

        Checks for the use of legacy np.random function calls.

        ","tags":["NPY002"]},{"location":"rules/numpy-legacy-random/#why-is-this-bad","title":"Why is this bad?","text":"

        According to the NumPy documentation's Legacy Random Generation:

        The RandomState provides access to legacy generators... This class should only be used if it is essential to have randoms that are identical to what would have been produced by previous versions of NumPy.

        The members exposed directly on the random module are convenience functions that alias to methods on a global singleton RandomState instance. NumPy recommends using a dedicated Generator instance rather than the random variate generation methods exposed directly on the random module, as the new Generator is both faster and has better statistical properties.

        See the documentation on Random Sampling and NEP 19 for further details.

        ","tags":["NPY002"]},{"location":"rules/numpy-legacy-random/#example","title":"Example","text":"
        import numpy as np\n\nnp.random.seed(1337)\nnp.random.normal()\n

        Use instead:

        rng = np.random.default_rng(1337)\nrng.normal()\n
        ","tags":["NPY002"]},{"location":"rules/numpy2-deprecation/","title":"numpy2-deprecation (NPY201)","text":"

        Fix is sometimes available.

        ","tags":["NPY201"]},{"location":"rules/numpy2-deprecation/#what-it-does","title":"What it does","text":"

        Checks for uses of NumPy functions and constants that were removed from the main namespace in NumPy 2.0.

        ","tags":["NPY201"]},{"location":"rules/numpy2-deprecation/#why-is-this-bad","title":"Why is this bad?","text":"

        NumPy 2.0 includes an overhaul of NumPy's Python API, intended to remove redundant aliases and routines, and establish unambiguous mechanisms for accessing constants, dtypes, and functions.

        As part of this overhaul, a variety of deprecated NumPy functions and constants were removed from the main namespace.

        The majority of these functions and constants can be automatically replaced by other members of the NumPy API or by equivalents from the Python standard library. With the exception of renaming numpy.byte_bounds to numpy.lib.array_utils.byte_bounds, all such replacements are backwards compatible with earlier versions of NumPy.

        This rule flags all uses of removed members, along with automatic fixes for any backwards-compatible replacements.

        ","tags":["NPY201"]},{"location":"rules/numpy2-deprecation/#example","title":"Example","text":"
        import numpy as np\n\narr1 = [np.Infinity, np.NaN, np.nan, np.PINF, np.inf]\narr2 = [np.float_(1.5), np.float64(5.1)]\nnp.round_(arr2)\n

        Use instead:

        import numpy as np\n\narr1 = [np.inf, np.nan, np.nan, np.inf, np.inf]\narr2 = [np.float64(1.5), np.float64(5.1)]\nnp.round(arr2)\n
        ","tags":["NPY201"]},{"location":"rules/open-alias/","title":"open-alias (UP020)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP020"]},{"location":"rules/open-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of io.open.

        ","tags":["UP020"]},{"location":"rules/open-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3, io.open is an alias for open. Prefer using open directly, as it is more idiomatic.

        ","tags":["UP020"]},{"location":"rules/open-alias/#example","title":"Example","text":"
        import io\n\nwith io.open(\"file.txt\") as f:\n    ...\n

        Use instead:

        with open(\"file.txt\") as f:\n    ...\n
        ","tags":["UP020"]},{"location":"rules/open-alias/#references","title":"References","text":"
        • Python documentation: io.open
        ","tags":["UP020"]},{"location":"rules/open-file-with-context-handler/","title":"open-file-with-context-handler (SIM115)","text":"

        Derived from the flake8-simplify linter.

        ","tags":["SIM115"]},{"location":"rules/open-file-with-context-handler/#what-it-does","title":"What it does","text":"

        Checks for cases where files are opened (e.g., using the builtin open() function) without using a context manager.

        ","tags":["SIM115"]},{"location":"rules/open-file-with-context-handler/#why-is-this-bad","title":"Why is this bad?","text":"

        If a file is opened without a context manager, it is not guaranteed that the file will be closed (e.g., if an exception is raised), which can cause resource leaks. The rule detects a wide array of IO calls where context managers could be used, such as open, pathlib.Path(...).open(), tempfile.TemporaryFile() ortarfile.TarFile(...).gzopen().

        ","tags":["SIM115"]},{"location":"rules/open-file-with-context-handler/#example","title":"Example","text":"
        file = open(\"foo.txt\")\n...\nfile.close()\n

        Use instead:

        with open(\"foo.txt\") as file:\n    ...\n
        ","tags":["SIM115"]},{"location":"rules/open-file-with-context-handler/#references","title":"References","text":"
        • Python documentation: open
        ","tags":["SIM115"]},{"location":"rules/os-chmod/","title":"os-chmod (PTH101)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH101"]},{"location":"rules/os-chmod/#what-it-does","title":"What it does","text":"

        Checks for uses of os.chmod.

        ","tags":["PTH101"]},{"location":"rules/os-chmod/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.chmod() can improve readability over the os module's counterparts (e.g., os.chmod()).

        ","tags":["PTH101"]},{"location":"rules/os-chmod/#examples","title":"Examples","text":"
        import os\n\nos.chmod(\"file.py\", 0o444)\n

        Use instead:

        from pathlib import Path\n\nPath(\"file.py\").chmod(0o444)\n
        ","tags":["PTH101"]},{"location":"rules/os-chmod/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH101"]},{"location":"rules/os-chmod/#references","title":"References","text":"
        • Python documentation: Path.chmod
        • Python documentation: os.chmod
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH101"]},{"location":"rules/os-error-alias/","title":"os-error-alias (UP024)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP024"]},{"location":"rules/os-error-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of exceptions that alias OSError.

        ","tags":["UP024"]},{"location":"rules/os-error-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        OSError is the builtin error type used for exceptions that relate to the operating system.

        In Python 3.3, a variety of other exceptions, like WindowsError were aliased to OSError. These aliases remain in place for compatibility with older versions of Python, but may be removed in future versions.

        Prefer using OSError directly, as it is more idiomatic and future-proof.

        ","tags":["UP024"]},{"location":"rules/os-error-alias/#example","title":"Example","text":"
        raise IOError\n

        Use instead:

        raise OSError\n
        ","tags":["UP024"]},{"location":"rules/os-error-alias/#references","title":"References","text":"
        • Python documentation: OSError
        ","tags":["UP024"]},{"location":"rules/os-getcwd/","title":"os-getcwd (PTH109)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH109"]},{"location":"rules/os-getcwd/#what-it-does","title":"What it does","text":"

        Checks for uses of os.getcwd and os.getcwdb.

        ","tags":["PTH109"]},{"location":"rules/os-getcwd/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.cwd() can improve readability over the os module's counterparts (e.g., os.getcwd()).

        ","tags":["PTH109"]},{"location":"rules/os-getcwd/#examples","title":"Examples","text":"
        import os\n\ncwd = os.getcwd()\n

        Use instead:

        from pathlib import Path\n\ncwd = Path.cwd()\n
        ","tags":["PTH109"]},{"location":"rules/os-getcwd/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH109"]},{"location":"rules/os-getcwd/#references","title":"References","text":"
        • Python documentation: Path.cwd
        • Python documentation: os.getcwd
        • Python documentation: os.getcwdb
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH109"]},{"location":"rules/os-listdir/","title":"os-listdir (PTH208)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH208"]},{"location":"rules/os-listdir/#what-it-does","title":"What it does","text":"

        Checks for uses of os.listdir.

        ","tags":["PTH208"]},{"location":"rules/os-listdir/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using pathlib's Path.iterdir() can improve readability over os.listdir().

        ","tags":["PTH208"]},{"location":"rules/os-listdir/#example","title":"Example","text":"
        p = \".\"\nfor d in os.listdir(p):\n    ...\n\nif os.listdir(p):\n    ...\n\nif \"file\" in os.listdir(p):\n    ...\n

        Use instead:

        p = Path(\".\")\nfor d in p.iterdir():\n    ...\n\nif any(p.iterdir()):\n    ...\n\nif (p / \"file\").exists():\n    ...\n
        ","tags":["PTH208"]},{"location":"rules/os-listdir/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH208"]},{"location":"rules/os-listdir/#references","title":"References","text":"
        • Python documentation: Path.iterdir
        • Python documentation: os.listdir
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH208"]},{"location":"rules/os-makedirs/","title":"os-makedirs (PTH103)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH103"]},{"location":"rules/os-makedirs/#what-it-does","title":"What it does","text":"

        Checks for uses of os.makedirs.

        ","tags":["PTH103"]},{"location":"rules/os-makedirs/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.mkdir(parents=True) can improve readability over the os module's counterparts (e.g., os.makedirs().

        ","tags":["PTH103"]},{"location":"rules/os-makedirs/#examples","title":"Examples","text":"
        import os\n\nos.makedirs(\"./nested/directory/\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"./nested/directory/\").mkdir(parents=True)\n
        ","tags":["PTH103"]},{"location":"rules/os-makedirs/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH103"]},{"location":"rules/os-makedirs/#references","title":"References","text":"
        • Python documentation: Path.mkdir
        • Python documentation: os.makedirs
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH103"]},{"location":"rules/os-mkdir/","title":"os-mkdir (PTH102)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH102"]},{"location":"rules/os-mkdir/#what-it-does","title":"What it does","text":"

        Checks for uses of os.mkdir.

        ","tags":["PTH102"]},{"location":"rules/os-mkdir/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.mkdir() can improve readability over the os module's counterparts (e.g., os.mkdir()).

        ","tags":["PTH102"]},{"location":"rules/os-mkdir/#examples","title":"Examples","text":"
        import os\n\nos.mkdir(\"./directory/\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"./directory/\").mkdir()\n
        ","tags":["PTH102"]},{"location":"rules/os-mkdir/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH102"]},{"location":"rules/os-mkdir/#references","title":"References","text":"
        • Python documentation: Path.mkdir
        • Python documentation: os.mkdir
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH102"]},{"location":"rules/os-path-abspath/","title":"os-path-abspath (PTH100)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH100"]},{"location":"rules/os-path-abspath/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.abspath.

        ","tags":["PTH100"]},{"location":"rules/os-path-abspath/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.resolve() can improve readability over the os.path module's counterparts (e.g., os.path.abspath()).

        ","tags":["PTH100"]},{"location":"rules/os-path-abspath/#examples","title":"Examples","text":"
        import os\n\nfile_path = os.path.abspath(\"../path/to/file\")\n

        Use instead:

        from pathlib import Path\n\nfile_path = Path(\"../path/to/file\").resolve()\n
        ","tags":["PTH100"]},{"location":"rules/os-path-abspath/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH100"]},{"location":"rules/os-path-abspath/#references","title":"References","text":"
        • Python documentation: Path.resolve
        • Python documentation: os.path.abspath
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH100"]},{"location":"rules/os-path-basename/","title":"os-path-basename (PTH119)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH119"]},{"location":"rules/os-path-basename/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.basename.

        ","tags":["PTH119"]},{"location":"rules/os-path-basename/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.name can improve readability over the os.path module's counterparts (e.g., os.path.basename()).

        ","tags":["PTH119"]},{"location":"rules/os-path-basename/#examples","title":"Examples","text":"
        import os\n\nos.path.basename(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).name\n
        ","tags":["PTH119"]},{"location":"rules/os-path-basename/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH119"]},{"location":"rules/os-path-basename/#references","title":"References","text":"
        • Python documentation: PurePath.name
        • Python documentation: os.path.basename
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH119"]},{"location":"rules/os-path-dirname/","title":"os-path-dirname (PTH120)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH120"]},{"location":"rules/os-path-dirname/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.dirname.

        ","tags":["PTH120"]},{"location":"rules/os-path-dirname/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.parent can improve readability over the os.path module's counterparts (e.g., os.path.dirname()).

        ","tags":["PTH120"]},{"location":"rules/os-path-dirname/#examples","title":"Examples","text":"
        import os\n\nos.path.dirname(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).parent\n
        ","tags":["PTH120"]},{"location":"rules/os-path-dirname/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH120"]},{"location":"rules/os-path-dirname/#references","title":"References","text":"
        • Python documentation: PurePath.parent
        • Python documentation: os.path.dirname
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH120"]},{"location":"rules/os-path-exists/","title":"os-path-exists (PTH110)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH110"]},{"location":"rules/os-path-exists/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.exists.

        ","tags":["PTH110"]},{"location":"rules/os-path-exists/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.exists() can improve readability over the os.path module's counterparts (e.g., os.path.exists()).

        ","tags":["PTH110"]},{"location":"rules/os-path-exists/#examples","title":"Examples","text":"
        import os\n\nos.path.exists(\"file.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"file.py\").exists()\n
        ","tags":["PTH110"]},{"location":"rules/os-path-exists/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH110"]},{"location":"rules/os-path-exists/#references","title":"References","text":"
        • Python documentation: Path.exists
        • Python documentation: os.path.exists
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH110"]},{"location":"rules/os-path-expanduser/","title":"os-path-expanduser (PTH111)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH111"]},{"location":"rules/os-path-expanduser/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.expanduser.

        ","tags":["PTH111"]},{"location":"rules/os-path-expanduser/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.expanduser() can improve readability over the os.path module's counterparts (e.g., as os.path.expanduser()).

        ","tags":["PTH111"]},{"location":"rules/os-path-expanduser/#examples","title":"Examples","text":"
        import os\n\nos.path.expanduser(\"~/films/Monty Python\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"~/films/Monty Python\").expanduser()\n
        ","tags":["PTH111"]},{"location":"rules/os-path-expanduser/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH111"]},{"location":"rules/os-path-expanduser/#references","title":"References","text":"
        • Python documentation: Path.expanduser
        • Python documentation: os.path.expanduser
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH111"]},{"location":"rules/os-path-getatime/","title":"os-path-getatime (PTH203)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH203"]},{"location":"rules/os-path-getatime/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.getatime.

        ","tags":["PTH203"]},{"location":"rules/os-path-getatime/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path.

        When possible, using Path object methods such as Path.stat() can improve readability over the os.path module's counterparts (e.g., os.path.getatime()).

        ","tags":["PTH203"]},{"location":"rules/os-path-getatime/#example","title":"Example","text":"
        import os\n\nos.path.getatime(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).stat().st_atime\n
        ","tags":["PTH203"]},{"location":"rules/os-path-getatime/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH203"]},{"location":"rules/os-path-getatime/#references","title":"References","text":"
        • Python documentation: Path.stat
        • Python documentation: os.path.getatime
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH203"]},{"location":"rules/os-path-getctime/","title":"os-path-getctime (PTH205)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH205"]},{"location":"rules/os-path-getctime/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.getctime.

        ","tags":["PTH205"]},{"location":"rules/os-path-getctime/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path.

        When possible, using Path object methods such as Path.stat() can improve readability over the os.path module's counterparts (e.g., os.path.getctime()).

        ","tags":["PTH205"]},{"location":"rules/os-path-getctime/#example","title":"Example","text":"
        import os\n\nos.path.getctime(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).stat().st_ctime\n
        ","tags":["PTH205"]},{"location":"rules/os-path-getctime/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH205"]},{"location":"rules/os-path-getctime/#references","title":"References","text":"
        • Python documentation: Path.stat
        • Python documentation: os.path.getctime
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH205"]},{"location":"rules/os-path-getmtime/","title":"os-path-getmtime (PTH204)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH204"]},{"location":"rules/os-path-getmtime/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.getmtime.

        ","tags":["PTH204"]},{"location":"rules/os-path-getmtime/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path.

        When possible, using Path object methods such as Path.stat() can improve readability over the os.path module's counterparts (e.g., os.path.getmtime()).

        ","tags":["PTH204"]},{"location":"rules/os-path-getmtime/#example","title":"Example","text":"
        import os\n\nos.path.getmtime(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).stat().st_mtime\n
        ","tags":["PTH204"]},{"location":"rules/os-path-getmtime/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH204"]},{"location":"rules/os-path-getmtime/#references","title":"References","text":"
        • Python documentation: Path.stat
        • Python documentation: os.path.getmtime
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH204"]},{"location":"rules/os-path-getsize/","title":"os-path-getsize (PTH202)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH202"]},{"location":"rules/os-path-getsize/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.getsize.

        ","tags":["PTH202"]},{"location":"rules/os-path-getsize/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path.

        When possible, using Path object methods such as Path.stat() can improve readability over the os.path module's counterparts (e.g., os.path.getsize()).

        ","tags":["PTH202"]},{"location":"rules/os-path-getsize/#example","title":"Example","text":"
        import os\n\nos.path.getsize(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).stat().st_size\n
        ","tags":["PTH202"]},{"location":"rules/os-path-getsize/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH202"]},{"location":"rules/os-path-getsize/#references","title":"References","text":"
        • Python documentation: Path.stat
        • Python documentation: os.path.getsize
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH202"]},{"location":"rules/os-path-isabs/","title":"os-path-isabs (PTH117)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH117"]},{"location":"rules/os-path-isabs/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.isabs.

        ","tags":["PTH117"]},{"location":"rules/os-path-isabs/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.is_absolute() can improve readability over the os.path module's counterparts (e.g., as os.path.isabs()).

        ","tags":["PTH117"]},{"location":"rules/os-path-isabs/#examples","title":"Examples","text":"
        import os\n\nif os.path.isabs(file_name):\n    print(\"Absolute path!\")\n

        Use instead:

        from pathlib import Path\n\nif Path(file_name).is_absolute():\n    print(\"Absolute path!\")\n
        ","tags":["PTH117"]},{"location":"rules/os-path-isabs/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH117"]},{"location":"rules/os-path-isabs/#references","title":"References","text":"
        • Python documentation: PurePath.is_absolute
        • Python documentation: os.path.isabs
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH117"]},{"location":"rules/os-path-isdir/","title":"os-path-isdir (PTH112)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH112"]},{"location":"rules/os-path-isdir/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.isdir.

        ","tags":["PTH112"]},{"location":"rules/os-path-isdir/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.is_dir() can improve readability over the os.path module's counterparts (e.g., os.path.isdir()).

        ","tags":["PTH112"]},{"location":"rules/os-path-isdir/#examples","title":"Examples","text":"
        import os\n\nos.path.isdir(\"docs\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"docs\").is_dir()\n
        ","tags":["PTH112"]},{"location":"rules/os-path-isdir/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH112"]},{"location":"rules/os-path-isdir/#references","title":"References","text":"
        • Python documentation: Path.is_dir
        • Python documentation: os.path.isdir
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH112"]},{"location":"rules/os-path-isfile/","title":"os-path-isfile (PTH113)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH113"]},{"location":"rules/os-path-isfile/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.isfile.

        ","tags":["PTH113"]},{"location":"rules/os-path-isfile/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.is_file() can improve readability over the os.path module's counterparts (e.g., os.path.isfile()).

        ","tags":["PTH113"]},{"location":"rules/os-path-isfile/#examples","title":"Examples","text":"
        import os\n\nos.path.isfile(\"docs\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"docs\").is_file()\n
        ","tags":["PTH113"]},{"location":"rules/os-path-isfile/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH113"]},{"location":"rules/os-path-isfile/#references","title":"References","text":"
        • Python documentation: Path.is_file
        • Python documentation: os.path.isfile
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH113"]},{"location":"rules/os-path-islink/","title":"os-path-islink (PTH114)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH114"]},{"location":"rules/os-path-islink/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.islink.

        ","tags":["PTH114"]},{"location":"rules/os-path-islink/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.is_symlink() can improve readability over the os.path module's counterparts (e.g., os.path.islink()).

        ","tags":["PTH114"]},{"location":"rules/os-path-islink/#examples","title":"Examples","text":"
        import os\n\nos.path.islink(\"docs\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"docs\").is_symlink()\n
        ","tags":["PTH114"]},{"location":"rules/os-path-islink/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH114"]},{"location":"rules/os-path-islink/#references","title":"References","text":"
        • Python documentation: Path.is_symlink
        • Python documentation: os.path.islink
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH114"]},{"location":"rules/os-path-join/","title":"os-path-join (PTH118)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH118"]},{"location":"rules/os-path-join/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.join.

        ","tags":["PTH118"]},{"location":"rules/os-path-join/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.joinpath() or the / operator can improve readability over the os.path module's counterparts (e.g., os.path.join()).

        ","tags":["PTH118"]},{"location":"rules/os-path-join/#examples","title":"Examples","text":"
        import os\n\nos.path.join(os.path.join(ROOT_PATH, \"folder\"), \"file.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(ROOT_PATH) / \"folder\" / \"file.py\"\n
        ","tags":["PTH118"]},{"location":"rules/os-path-join/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH118"]},{"location":"rules/os-path-join/#references","title":"References","text":"
        • Python documentation: PurePath.joinpath
        • Python documentation: os.path.join
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH118"]},{"location":"rules/os-path-samefile/","title":"os-path-samefile (PTH121)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH121"]},{"location":"rules/os-path-samefile/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.samefile.

        ","tags":["PTH121"]},{"location":"rules/os-path-samefile/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.samefile() can improve readability over the os.path module's counterparts (e.g., os.path.samefile()).

        ","tags":["PTH121"]},{"location":"rules/os-path-samefile/#examples","title":"Examples","text":"
        import os\n\nos.path.samefile(\"f1.py\", \"f2.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"f1.py\").samefile(\"f2.py\")\n
        ","tags":["PTH121"]},{"location":"rules/os-path-samefile/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH121"]},{"location":"rules/os-path-samefile/#references","title":"References","text":"
        • Python documentation: Path.samefile
        • Python documentation: os.path.samefile
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH121"]},{"location":"rules/os-path-splitext/","title":"os-path-splitext (PTH122)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH122"]},{"location":"rules/os-path-splitext/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.splitext.

        ","tags":["PTH122"]},{"location":"rules/os-path-splitext/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.suffix and Path.stem can improve readability over the os.path module's counterparts (e.g., os.path.splitext()).

        os.path.splitext() specifically returns a tuple of the file root and extension (e.g., given splitext('/foo/bar.py'), os.path.splitext() returns (\"foo/bar\", \".py\"). These outputs can be reconstructed through a combination of Path.suffix (\".py\"), Path.stem (\"bar\"), and Path.parent (\"foo\").

        ","tags":["PTH122"]},{"location":"rules/os-path-splitext/#examples","title":"Examples","text":"
        import os\n\n(root, ext) = os.path.splitext(\"foo/bar.py\")\n

        Use instead:

        from pathlib import Path\n\npath = Path(\"foo/bar.py\")\nroot = path.parent / path.stem\next = path.suffix\n
        ","tags":["PTH122"]},{"location":"rules/os-path-splitext/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH122"]},{"location":"rules/os-path-splitext/#references","title":"References","text":"
        • Python documentation: Path.suffix
        • Python documentation: Path.suffixes
        • Python documentation: os.path.splitext
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH122"]},{"location":"rules/os-readlink/","title":"os-readlink (PTH115)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH115"]},{"location":"rules/os-readlink/#what-it-does","title":"What it does","text":"

        Checks for uses of os.readlink.

        ","tags":["PTH115"]},{"location":"rules/os-readlink/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.readlink() can improve readability over the os module's counterparts (e.g., os.readlink()).

        ","tags":["PTH115"]},{"location":"rules/os-readlink/#examples","title":"Examples","text":"
        import os\n\nos.readlink(file_name)\n

        Use instead:

        from pathlib import Path\n\nPath(file_name).readlink()\n
        ","tags":["PTH115"]},{"location":"rules/os-readlink/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH115"]},{"location":"rules/os-readlink/#references","title":"References","text":"
        • Python documentation: Path.readlink
        • Python documentation: os.readlink
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH115"]},{"location":"rules/os-remove/","title":"os-remove (PTH107)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH107"]},{"location":"rules/os-remove/#what-it-does","title":"What it does","text":"

        Checks for uses of os.remove.

        ","tags":["PTH107"]},{"location":"rules/os-remove/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.unlink() can improve readability over the os module's counterparts (e.g., os.remove()).

        ","tags":["PTH107"]},{"location":"rules/os-remove/#examples","title":"Examples","text":"
        import os\n\nos.remove(\"file.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"file.py\").unlink()\n
        ","tags":["PTH107"]},{"location":"rules/os-remove/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH107"]},{"location":"rules/os-remove/#references","title":"References","text":"
        • Python documentation: Path.unlink
        • Python documentation: os.remove
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH107"]},{"location":"rules/os-rename/","title":"os-rename (PTH104)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH104"]},{"location":"rules/os-rename/#what-it-does","title":"What it does","text":"

        Checks for uses of os.rename.

        ","tags":["PTH104"]},{"location":"rules/os-rename/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.rename() can improve readability over the os module's counterparts (e.g., os.rename()).

        ","tags":["PTH104"]},{"location":"rules/os-rename/#examples","title":"Examples","text":"
        import os\n\nos.rename(\"old.py\", \"new.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"old.py\").rename(\"new.py\")\n
        ","tags":["PTH104"]},{"location":"rules/os-rename/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH104"]},{"location":"rules/os-rename/#references","title":"References","text":"
        • Python documentation: Path.rename
        • Python documentation: os.rename
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH104"]},{"location":"rules/os-replace/","title":"os-replace (PTH105)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH105"]},{"location":"rules/os-replace/#what-it-does","title":"What it does","text":"

        Checks for uses of os.replace.

        ","tags":["PTH105"]},{"location":"rules/os-replace/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.replace() can improve readability over the os module's counterparts (e.g., os.replace()).

        Note that os functions may be preferable if performance is a concern, e.g., in hot loops.

        ","tags":["PTH105"]},{"location":"rules/os-replace/#examples","title":"Examples","text":"
        import os\n\nos.replace(\"old.py\", \"new.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"old.py\").replace(\"new.py\")\n
        ","tags":["PTH105"]},{"location":"rules/os-replace/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH105"]},{"location":"rules/os-replace/#references","title":"References","text":"
        • Python documentation: Path.replace
        • Python documentation: os.replace
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH105"]},{"location":"rules/os-rmdir/","title":"os-rmdir (PTH106)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH106"]},{"location":"rules/os-rmdir/#what-it-does","title":"What it does","text":"

        Checks for uses of os.rmdir.

        ","tags":["PTH106"]},{"location":"rules/os-rmdir/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.rmdir() can improve readability over the os module's counterparts (e.g., os.rmdir()).

        ","tags":["PTH106"]},{"location":"rules/os-rmdir/#examples","title":"Examples","text":"
        import os\n\nos.rmdir(\"folder/\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"folder/\").rmdir()\n
        ","tags":["PTH106"]},{"location":"rules/os-rmdir/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH106"]},{"location":"rules/os-rmdir/#references","title":"References","text":"
        • Python documentation: Path.rmdir
        • Python documentation: os.rmdir
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH106"]},{"location":"rules/os-sep-split/","title":"os-sep-split (PTH206)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH206"]},{"location":"rules/os-sep-split/#what-it-does","title":"What it does","text":"

        Checks for uses of .split(os.sep)

        ","tags":["PTH206"]},{"location":"rules/os-sep-split/#why-is-this-bad","title":"Why is this bad?","text":"

        The pathlib module in the standard library should be used for path manipulation. It provides a high-level API with the functionality needed for common operations on Path objects.

        ","tags":["PTH206"]},{"location":"rules/os-sep-split/#example","title":"Example","text":"

        If not all parts of the path are needed, then the name and parent attributes of the Path object should be used. Otherwise, the parts attribute can be used as shown in the last example.

        import os\n\n\"path/to/file_name.txt\".split(os.sep)[-1]\n\n\"path/to/file_name.txt\".split(os.sep)[-2]\n\n# Iterating over the path parts\nif any(part in blocklist for part in \"my/file/path\".split(os.sep)):\n    ...\n

        Use instead:

        from pathlib import Path\n\nPath(\"path/to/file_name.txt\").name\n\nPath(\"path/to/file_name.txt\").parent.name\n\n# Iterating over the path parts\nif any(part in blocklist for part in Path(\"my/file/path\").parts):\n    ...\n
        ","tags":["PTH206"]},{"location":"rules/os-sep-split/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than working directly with strings, especially on older versions of Python.

        ","tags":["PTH206"]},{"location":"rules/os-sep-split/#references","title":"References","text":"
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH206"]},{"location":"rules/os-stat/","title":"os-stat (PTH116)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH116"]},{"location":"rules/os-stat/#what-it-does","title":"What it does","text":"

        Checks for uses of os.stat.

        ","tags":["PTH116"]},{"location":"rules/os-stat/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.stat() can improve readability over the os module's counterparts (e.g., os.path.stat()).

        ","tags":["PTH116"]},{"location":"rules/os-stat/#examples","title":"Examples","text":"
        import os\nfrom pwd import getpwuid\nfrom grp import getgrgid\n\nstat = os.stat(file_name)\nowner_name = getpwuid(stat.st_uid).pw_name\ngroup_name = getgrgid(stat.st_gid).gr_name\n

        Use instead:

        from pathlib import Path\n\nfile_path = Path(file_name)\nstat = file_path.stat()\nowner_name = file_path.owner()\ngroup_name = file_path.group()\n
        ","tags":["PTH116"]},{"location":"rules/os-stat/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH116"]},{"location":"rules/os-stat/#references","title":"References","text":"
        • Python documentation: Path.stat
        • Python documentation: Path.group
        • Python documentation: Path.owner
        • Python documentation: os.stat
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH116"]},{"location":"rules/os-unlink/","title":"os-unlink (PTH108)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH108"]},{"location":"rules/os-unlink/#what-it-does","title":"What it does","text":"

        Checks for uses of os.unlink.

        ","tags":["PTH108"]},{"location":"rules/os-unlink/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.unlink() can improve readability over the os module's counterparts (e.g., os.unlink()).

        ","tags":["PTH108"]},{"location":"rules/os-unlink/#examples","title":"Examples","text":"
        import os\n\nos.unlink(\"file.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"file.py\").unlink()\n
        ","tags":["PTH108"]},{"location":"rules/os-unlink/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH108"]},{"location":"rules/os-unlink/#references","title":"References","text":"
        • Python documentation: Path.unlink
        • Python documentation: os.unlink
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH108"]},{"location":"rules/outdated-version-block/","title":"outdated-version-block (UP036)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#what-it-does","title":"What it does","text":"

        Checks for conditional blocks gated on sys.version_info comparisons that are outdated for the minimum supported Python version.

        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, code can be conditionally executed based on the active Python version by comparing against the sys.version_info tuple.

        If a code block is only executed for Python versions older than the minimum supported version, it should be removed.

        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#example","title":"Example","text":"
        import sys\n\nif sys.version_info < (3, 0):\n    print(\"py2\")\nelse:\n    print(\"py3\")\n

        Use instead:

        print(\"py3\")\n
        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#options","title":"Options","text":"
        • target-version
        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because it will remove all code, comments, and annotations within unreachable version blocks.

        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#references","title":"References","text":"
        • Python documentation: sys.version_info
        ","tags":["UP036"]},{"location":"rules/over-indentation/","title":"over-indentation (D208)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D208"]},{"location":"rules/over-indentation/#what-it-does","title":"What it does","text":"

        Checks for over-indented docstrings.

        ","tags":["D208"]},{"location":"rules/over-indentation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that docstrings be indented to the same level as their opening quotes. Avoid over-indenting docstrings, for consistency.

        ","tags":["D208"]},{"location":"rules/over-indentation/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n        Sort the list in ascending order and return a copy of the result using the\n        bubble sort algorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D208"]},{"location":"rules/over-indentation/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        ","tags":["D208"]},{"location":"rules/over-indentation/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D208"]},{"location":"rules/over-indented/","title":"over-indented (E117)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E117"]},{"location":"rules/over-indented/#what-it-does","title":"What it does","text":"

        Checks for over-indented code.

        ","tags":["E117"]},{"location":"rules/over-indented/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, 4 spaces per indentation level should be preferred. Increased indentation can lead to inconsistent formatting, which can hurt readability.

        ","tags":["E117"]},{"location":"rules/over-indented/#example","title":"Example","text":"
        for item in items:\n      pass\n

        Use instead:

        for item in items:\n    pass\n
        ","tags":["E117"]},{"location":"rules/over-indented/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        ","tags":["E117"]},{"location":"rules/overindented-section-underline/","title":"overindented-section-underline (D215)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D215"]},{"location":"rules/overindented-section-underline/#what-it-does","title":"What it does","text":"

        Checks for over-indented section underlines in docstrings.

        ","tags":["D215"]},{"location":"rules/overindented-section-underline/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline numpy-style docstrings, and helps prevent incorrect syntax in docstrings using reStructuredText.

        Multiline numpy-style docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section has a section header and a section body, and there should be a series of underline characters in the line following the header. The underline should have the same indentation as the header.

        This rule enforces a consistent style for multiline numpy-style docstrings with sections. If your docstring uses reStructuredText, the rule also helps protect against incorrect reStructuredText syntax, which would cause errors if you tried to use a tool such as Sphinx to generate documentation from the docstring.

        This rule is enabled when using the numpy convention, and disabled when using the google or pep257 conventions.

        ","tags":["D215"]},{"location":"rules/overindented-section-underline/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n        ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n          -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n      ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D215"]},{"location":"rules/overindented-section-underline/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D215"]},{"location":"rules/overindented-section-underline/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D215"]},{"location":"rules/overindented-section/","title":"overindented-section (D214)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D214"]},{"location":"rules/overindented-section/#what-it-does","title":"What it does","text":"

        Checks for over-indented sections in docstrings.

        ","tags":["D214"]},{"location":"rules/overindented-section/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for docstrings with multiple sections.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. The convention is that all sections should use consistent indentation. In each section, the header should match the indentation of the docstring's opening quotes, and the body should be indented one level further.

        This rule is enabled when using the numpy and google conventions, and disabled when using the pep257 convention.

        ","tags":["D214"]},{"location":"rules/overindented-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n        Args:\n            distance: Distance traveled.\n            time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D214"]},{"location":"rules/overindented-section/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D214"]},{"location":"rules/overindented-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D214"]},{"location":"rules/overload-with-docstring/","title":"overload-with-docstring (D418)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D418"]},{"location":"rules/overload-with-docstring/#what-it-does","title":"What it does","text":"

        Checks for @overload function definitions that contain a docstring.

        ","tags":["D418"]},{"location":"rules/overload-with-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        The @overload decorator is used to define multiple compatible signatures for a given function, to support type-checking. A series of @overload definitions should be followed by a single non-decorated definition that contains the implementation of the function.

        @overload function definitions should not contain a docstring; instead, the docstring should be placed on the non-decorated definition that contains the implementation.

        ","tags":["D418"]},{"location":"rules/overload-with-docstring/#example","title":"Example","text":"
        from typing import overload\n\n\n@overload\ndef factorial(n: int) -> int:\n    \"\"\"Return the factorial of n.\"\"\"\n\n\n@overload\ndef factorial(n: float) -> float:\n    \"\"\"Return the factorial of n.\"\"\"\n\n\ndef factorial(n):\n    \"\"\"Return the factorial of n.\"\"\"\n\n\nfactorial.__doc__  # \"Return the factorial of n.\"\n

        Use instead:

        from typing import overload\n\n\n@overload\ndef factorial(n: int) -> int: ...\n\n\n@overload\ndef factorial(n: float) -> float: ...\n\n\ndef factorial(n):\n    \"\"\"Return the factorial of n.\"\"\"\n\n\nfactorial.__doc__  # \"Return the factorial of n.\"\n
        ","tags":["D418"]},{"location":"rules/overload-with-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • Python documentation: typing.overload
        ","tags":["D418"]},{"location":"rules/p-print/","title":"p-print (T203)","text":"

        Derived from the flake8-print linter.

        Fix is sometimes available.

        ","tags":["T203"]},{"location":"rules/p-print/#what-it-does","title":"What it does","text":"

        Checks for pprint statements.

        ","tags":["T203"]},{"location":"rules/p-print/#why-is-this-bad","title":"Why is this bad?","text":"

        Like print statements, pprint statements are useful in some situations (e.g., debugging), but should typically be omitted from production code. pprint statements can lead to the accidental inclusion of sensitive information in logs, and are not configurable by clients, unlike logging statements.

        ","tags":["T203"]},{"location":"rules/p-print/#example","title":"Example","text":"
        import pprint\n\n\ndef merge_dicts(dict_a, dict_b):\n    dict_c = {**dict_a, **dict_b}\n    pprint.pprint(dict_c)\n    return dict_c\n

        Use instead:

        def merge_dicts(dict_a, dict_b):\n    dict_c = {**dict_a, **dict_b}\n    return dict_c\n
        ","tags":["T203"]},{"location":"rules/p-print/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may remove pprint statements that are used beyond debugging purposes.

        ","tags":["T203"]},{"location":"rules/pandas-df-variable-name/","title":"pandas-df-variable-name (PD901)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD901"]},{"location":"rules/pandas-df-variable-name/#what-it-does","title":"What it does","text":"

        Checks for assignments to the variable df.

        ","tags":["PD901"]},{"location":"rules/pandas-df-variable-name/#why-is-this-bad","title":"Why is this bad?","text":"

        Although df is a common variable name for a Pandas DataFrame, it's not a great variable name for production code, as it's non-descriptive and prone to name conflicts.

        Instead, use a more descriptive variable name.

        ","tags":["PD901"]},{"location":"rules/pandas-df-variable-name/#example","title":"Example","text":"
        import pandas as pd\n\ndf = pd.read_csv(\"animals.csv\")\n

        Use instead:

        import pandas as pd\n\nanimals = pd.read_csv(\"animals.csv\")\n
        ","tags":["PD901"]},{"location":"rules/pandas-nunique-constant-series-check/","title":"pandas-nunique-constant-series-check (PD101)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD101"]},{"location":"rules/pandas-nunique-constant-series-check/#what-it-does","title":"What it does","text":"

        Check for uses of .nunique() to check if a Pandas Series is constant (i.e., contains only one unique value).

        ","tags":["PD101"]},{"location":"rules/pandas-nunique-constant-series-check/#why-is-this-bad","title":"Why is this bad?","text":"

        .nunique() is computationally inefficient for checking if a Series is constant.

        Consider, for example, a Series of length n that consists of increasing integer values (e.g., 1, 2, 3, 4). The .nunique() method will iterate over the entire Series to count the number of unique values. But in this case, we can detect that the Series is non-constant after visiting the first two values, which are non-equal.

        In general, .nunique() requires iterating over the entire Series, while a more efficient approach allows short-circuiting the operation as soon as a non-equal value is found.

        Instead of calling .nunique(), convert the Series to a NumPy array, and check if all values in the array are equal to the first observed value.

        ","tags":["PD101"]},{"location":"rules/pandas-nunique-constant-series-check/#example","title":"Example","text":"
        import pandas as pd\n\ndata = pd.Series(range(1000))\nif data.nunique() <= 1:\n    print(\"Series is constant\")\n

        Use instead:

        import pandas as pd\n\ndata = pd.Series(range(1000))\narray = data.to_numpy()\nif array.shape[0] == 0 or (array[0] == array).all():\n    print(\"Series is constant\")\n
        ","tags":["PD101"]},{"location":"rules/pandas-nunique-constant-series-check/#references","title":"References","text":"
        • Pandas Cookbook: \"Constant Series\"
        • Pandas documentation: nunique
        ","tags":["PD101"]},{"location":"rules/pandas-use-of-dot-at/","title":"pandas-use-of-dot-at (PD008)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD008"]},{"location":"rules/pandas-use-of-dot-at/#what-it-does","title":"What it does","text":"

        Checks for uses of .at on Pandas objects.

        ","tags":["PD008"]},{"location":"rules/pandas-use-of-dot-at/#why-is-this-bad","title":"Why is this bad?","text":"

        The .at method selects a single value from a DataFrame or Series based on a label index, and is slightly faster than using .loc. However, .loc is more idiomatic and versatile, as it can be used to select multiple values at once.

        If performance is an important consideration, convert the object to a NumPy array, which will provide a much greater performance boost than using .at over .loc.

        ","tags":["PD008"]},{"location":"rules/pandas-use-of-dot-at/#example","title":"Example","text":"
        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.at[\"Maria\"]\n

        Use instead:

        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.loc[\"Maria\"]\n
        ","tags":["PD008"]},{"location":"rules/pandas-use-of-dot-at/#references","title":"References","text":"
        • Pandas documentation: loc
        • Pandas documentation: at
        ","tags":["PD008"]},{"location":"rules/pandas-use-of-dot-iat/","title":"pandas-use-of-dot-iat (PD009)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD009"]},{"location":"rules/pandas-use-of-dot-iat/#what-it-does","title":"What it does","text":"

        Checks for uses of .iat on Pandas objects.

        ","tags":["PD009"]},{"location":"rules/pandas-use-of-dot-iat/#why-is-this-bad","title":"Why is this bad?","text":"

        The .iat method selects a single value from a DataFrame or Series based on an ordinal index, and is slightly faster than using .iloc. However, .iloc is more idiomatic and versatile, as it can be used to select multiple values at once.

        If performance is an important consideration, convert the object to a NumPy array, which will provide a much greater performance boost than using .iat over .iloc.

        ","tags":["PD009"]},{"location":"rules/pandas-use-of-dot-iat/#example","title":"Example","text":"
        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.iat[0]\n

        Use instead:

        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.iloc[0]\n

        Or, using NumPy:

        import numpy as np\nimport pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.to_numpy()[0]\n
        ","tags":["PD009"]},{"location":"rules/pandas-use-of-dot-iat/#references","title":"References","text":"
        • Pandas documentation: iloc
        • Pandas documentation: iat
        ","tags":["PD009"]},{"location":"rules/pandas-use-of-dot-is-null/","title":"pandas-use-of-dot-is-null (PD003)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD003"]},{"location":"rules/pandas-use-of-dot-is-null/#what-it-does","title":"What it does","text":"

        Checks for uses of .isnull on Pandas objects.

        ","tags":["PD003"]},{"location":"rules/pandas-use-of-dot-is-null/#why-is-this-bad","title":"Why is this bad?","text":"

        In the Pandas API, .isna and .isnull are equivalent. For consistency, prefer .isna over .isnull.

        As a name, .isna more accurately reflects the behavior of the method, since these methods check for NaN and NaT values in addition to None values.

        ","tags":["PD003"]},{"location":"rules/pandas-use-of-dot-is-null/#example","title":"Example","text":"
        import pandas as pd\n\nanimals_df = pd.read_csv(\"animals.csv\")\npd.isnull(animals_df)\n

        Use instead:

        import pandas as pd\n\nanimals_df = pd.read_csv(\"animals.csv\")\npd.isna(animals_df)\n
        ","tags":["PD003"]},{"location":"rules/pandas-use-of-dot-is-null/#references","title":"References","text":"
        • Pandas documentation: isnull
        • Pandas documentation: isna
        ","tags":["PD003"]},{"location":"rules/pandas-use-of-dot-ix/","title":"pandas-use-of-dot-ix (PD007)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD007"]},{"location":"rules/pandas-use-of-dot-ix/#what-it-does","title":"What it does","text":"

        Checks for uses of .ix on Pandas objects.

        ","tags":["PD007"]},{"location":"rules/pandas-use-of-dot-ix/#why-is-this-bad","title":"Why is this bad?","text":"

        The .ix method is deprecated as its behavior is ambiguous. Specifically, it's often unclear whether .ix is indexing by label or by ordinal position.

        Instead, prefer the .loc method for label-based indexing, and .iloc for ordinal indexing.

        ","tags":["PD007"]},{"location":"rules/pandas-use-of-dot-ix/#example","title":"Example","text":"
        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.ix[0]  # 0th row or row with label 0?\n

        Use instead:

        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.iloc[0]  # 0th row.\n
        ","tags":["PD007"]},{"location":"rules/pandas-use-of-dot-ix/#references","title":"References","text":"
        • Pandas release notes: Deprecate .ix
        • Pandas documentation: loc
        • Pandas documentation: iloc
        ","tags":["PD007"]},{"location":"rules/pandas-use-of-dot-not-null/","title":"pandas-use-of-dot-not-null (PD004)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD004"]},{"location":"rules/pandas-use-of-dot-not-null/#what-it-does","title":"What it does","text":"

        Checks for uses of .notnull on Pandas objects.

        ","tags":["PD004"]},{"location":"rules/pandas-use-of-dot-not-null/#why-is-this-bad","title":"Why is this bad?","text":"

        In the Pandas API, .notna and .notnull are equivalent. For consistency, prefer .notna over .notnull.

        As a name, .notna more accurately reflects the behavior of the method, since these methods check for NaN and NaT values in addition to None values.

        ","tags":["PD004"]},{"location":"rules/pandas-use-of-dot-not-null/#example","title":"Example","text":"
        import pandas as pd\n\nanimals_df = pd.read_csv(\"animals.csv\")\npd.notnull(animals_df)\n

        Use instead:

        import pandas as pd\n\nanimals_df = pd.read_csv(\"animals.csv\")\npd.notna(animals_df)\n
        ","tags":["PD004"]},{"location":"rules/pandas-use-of-dot-not-null/#references","title":"References","text":"
        • Pandas documentation: notnull
        • Pandas documentation: notna
        ","tags":["PD004"]},{"location":"rules/pandas-use-of-dot-pivot-or-unstack/","title":"pandas-use-of-dot-pivot-or-unstack (PD010)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD010"]},{"location":"rules/pandas-use-of-dot-pivot-or-unstack/#what-it-does","title":"What it does","text":"

        Checks for uses of .pivot or .unstack on Pandas objects.

        ","tags":["PD010"]},{"location":"rules/pandas-use-of-dot-pivot-or-unstack/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefer .pivot_table to .pivot or .unstack. .pivot_table is more general and can be used to implement the same behavior as .pivot and .unstack.

        ","tags":["PD010"]},{"location":"rules/pandas-use-of-dot-pivot-or-unstack/#example","title":"Example","text":"
        import pandas as pd\n\ndf = pd.read_csv(\"cities.csv\")\ndf.pivot(index=\"city\", columns=\"year\", values=\"population\")\n

        Use instead:

        import pandas as pd\n\ndf = pd.read_csv(\"cities.csv\")\ndf.pivot_table(index=\"city\", columns=\"year\", values=\"population\")\n
        ","tags":["PD010"]},{"location":"rules/pandas-use-of-dot-pivot-or-unstack/#references","title":"References","text":"
        • Pandas documentation: Reshaping and pivot tables
        • Pandas documentation: pivot_table
        ","tags":["PD010"]},{"location":"rules/pandas-use-of-dot-read-table/","title":"pandas-use-of-dot-read-table (PD012)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD012"]},{"location":"rules/pandas-use-of-dot-read-table/#what-it-does","title":"What it does","text":"

        Checks for uses of pd.read_table to read CSV files.

        ","tags":["PD012"]},{"location":"rules/pandas-use-of-dot-read-table/#why-is-this-bad","title":"Why is this bad?","text":"

        In the Pandas API, pd.read_csv and pd.read_table are equivalent apart from their default separator: pd.read_csv defaults to a comma (,), while pd.read_table defaults to a tab (\\t) as the default separator.

        Prefer pd.read_csv over pd.read_table when reading comma-separated data (like CSV files), as it is more idiomatic.

        ","tags":["PD012"]},{"location":"rules/pandas-use-of-dot-read-table/#example","title":"Example","text":"
        import pandas as pd\n\ncities_df = pd.read_table(\"cities.csv\", sep=\",\")\n

        Use instead:

        import pandas as pd\n\ncities_df = pd.read_csv(\"cities.csv\")\n
        ","tags":["PD012"]},{"location":"rules/pandas-use-of-dot-read-table/#references","title":"References","text":"
        • Pandas documentation: read_csv
        • Pandas documentation: read_table
        ","tags":["PD012"]},{"location":"rules/pandas-use-of-dot-stack/","title":"pandas-use-of-dot-stack (PD013)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD013"]},{"location":"rules/pandas-use-of-dot-stack/#what-it-does","title":"What it does","text":"

        Checks for uses of .stack on Pandas objects.

        ","tags":["PD013"]},{"location":"rules/pandas-use-of-dot-stack/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefer .melt to .stack, which has the same functionality but with support for direct column renaming and no dependence on MultiIndex.

        ","tags":["PD013"]},{"location":"rules/pandas-use-of-dot-stack/#example","title":"Example","text":"
        import pandas as pd\n\ncities_df = pd.read_csv(\"cities.csv\")\ncities_df.set_index(\"city\").stack()\n

        Use instead:

        import pandas as pd\n\ncities_df = pd.read_csv(\"cities.csv\")\ncities_df.melt(id_vars=\"city\")\n
        ","tags":["PD013"]},{"location":"rules/pandas-use-of-dot-stack/#references","title":"References","text":"
        • Pandas documentation: melt
        • Pandas documentation: stack
        ","tags":["PD013"]},{"location":"rules/pandas-use-of-dot-values/","title":"pandas-use-of-dot-values (PD011)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD011"]},{"location":"rules/pandas-use-of-dot-values/#what-it-does","title":"What it does","text":"

        Checks for uses of .values on Pandas Series and Index objects.

        ","tags":["PD011"]},{"location":"rules/pandas-use-of-dot-values/#why-is-this-bad","title":"Why is this bad?","text":"

        The .values attribute is ambiguous as its return type is unclear. As such, it is no longer recommended by the Pandas documentation.

        Instead, use .to_numpy() to return a NumPy array, or .array to return a Pandas ExtensionArray.

        ","tags":["PD011"]},{"location":"rules/pandas-use-of-dot-values/#example","title":"Example","text":"
        import pandas as pd\n\nanimals = pd.read_csv(\"animals.csv\").values  # Ambiguous.\n

        Use instead:

        import pandas as pd\n\nanimals = pd.read_csv(\"animals.csv\").to_numpy()  # Explicit.\n
        ","tags":["PD011"]},{"location":"rules/pandas-use-of-dot-values/#references","title":"References","text":"
        • Pandas documentation: Accessing the values in a Series or Index
        ","tags":["PD011"]},{"location":"rules/pandas-use-of-inplace-argument/","title":"pandas-use-of-inplace-argument (PD002)","text":"

        Derived from the pandas-vet linter.

        Fix is sometimes available.

        ","tags":["PD002"]},{"location":"rules/pandas-use-of-inplace-argument/#what-it-does","title":"What it does","text":"

        Checks for inplace=True usages in pandas function and method calls.

        ","tags":["PD002"]},{"location":"rules/pandas-use-of-inplace-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Using inplace=True encourages mutation rather than immutable data, which is harder to reason about and may cause bugs. It also removes the ability to use the method chaining style for pandas operations.

        Further, in many cases, inplace=True does not provide a performance benefit, as pandas will often copy DataFrames in the background.

        ","tags":["PD002"]},{"location":"rules/pandas-use-of-inplace-argument/#example","title":"Example","text":"
        df.sort_values(\"col1\", inplace=True)\n

        Use instead:

        sorted_df = df.sort_values(\"col1\")\n
        ","tags":["PD002"]},{"location":"rules/pandas-use-of-inplace-argument/#references","title":"References","text":"
        • Why You Should Probably Never Use pandas inplace=True
        ","tags":["PD002"]},{"location":"rules/pandas-use-of-pd-merge/","title":"pandas-use-of-pd-merge (PD015)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD015"]},{"location":"rules/pandas-use-of-pd-merge/#what-it-does","title":"What it does","text":"

        Checks for uses of pd.merge on Pandas objects.

        ","tags":["PD015"]},{"location":"rules/pandas-use-of-pd-merge/#why-is-this-bad","title":"Why is this bad?","text":"

        In Pandas, the .merge method (exposed on, e.g., DataFrame objects) and the pd.merge function (exposed on the Pandas module) are equivalent.

        For consistency, prefer calling .merge on an object over calling pd.merge on the Pandas module, as the former is more idiomatic.

        Further, pd.merge is not a method, but a function, which prohibits it from being used in method chains, a common pattern in Pandas code.

        ","tags":["PD015"]},{"location":"rules/pandas-use-of-pd-merge/#example","title":"Example","text":"
        import pandas as pd\n\ncats_df = pd.read_csv(\"cats.csv\")\ndogs_df = pd.read_csv(\"dogs.csv\")\nrabbits_df = pd.read_csv(\"rabbits.csv\")\npets_df = pd.merge(pd.merge(cats_df, dogs_df), rabbits_df)  # Hard to read.\n

        Use instead:

        import pandas as pd\n\ncats_df = pd.read_csv(\"cats.csv\")\ndogs_df = pd.read_csv(\"dogs.csv\")\nrabbits_df = pd.read_csv(\"rabbits.csv\")\npets_df = cats_df.merge(dogs_df).merge(rabbits_df)\n
        ","tags":["PD015"]},{"location":"rules/pandas-use-of-pd-merge/#references","title":"References","text":"
        • Pandas documentation: merge
        • Pandas documentation: pd.merge
        ","tags":["PD015"]},{"location":"rules/paramiko-call/","title":"paramiko-call (S601)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S601"]},{"location":"rules/paramiko-call/#what-it-does","title":"What it does","text":"

        Checks for paramiko calls.

        ","tags":["S601"]},{"location":"rules/paramiko-call/#why-is-this-bad","title":"Why is this bad?","text":"

        paramiko calls allow users to execute arbitrary shell commands on a remote machine. If the inputs to these calls are not properly sanitized, they can be vulnerable to shell injection attacks.

        ","tags":["S601"]},{"location":"rules/paramiko-call/#example","title":"Example","text":"
        import paramiko\n\nclient = paramiko.SSHClient()\nclient.exec_command(\"echo $HOME\")\n
        ","tags":["S601"]},{"location":"rules/paramiko-call/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-78
        • Paramiko documentation: SSHClient.exec_command()
        ","tags":["S601"]},{"location":"rules/parenthesize-chained-operators/","title":"parenthesize-chained-operators (RUF021)","text":"

        Fix is always available.

        ","tags":["RUF021"]},{"location":"rules/parenthesize-chained-operators/#what-it-does","title":"What it does","text":"

        Checks for chained operators where adding parentheses could improve the clarity of the code.

        ","tags":["RUF021"]},{"location":"rules/parenthesize-chained-operators/#why-is-this-bad","title":"Why is this bad?","text":"

        and always binds more tightly than or when chaining the two together, but this can be hard to remember (and sometimes surprising). Adding parentheses in these situations can greatly improve code readability, with no change to semantics or performance.

        For example:

        a, b, c = 1, 0, 2\nx = a or b and c\n\nd, e, f = 0, 1, 2\ny = d and e or f\n

        Use instead:

        a, b, c = 1, 0, 2\nx = a or (b and c)\n\nd, e, f = 0, 1, 2\ny = (d and e) or f\n
        ","tags":["RUF021"]},{"location":"rules/pass-in-class-body/","title":"pass-in-class-body (PYI012)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI012"]},{"location":"rules/pass-in-class-body/#what-it-does","title":"What it does","text":"

        Checks for the presence of the pass statement in non-empty class bodies in .pyi files.

        ","tags":["PYI012"]},{"location":"rules/pass-in-class-body/#why-is-this-bad","title":"Why is this bad?","text":"

        The pass statement is always unnecessary in non-empty class bodies in stubs.

        ","tags":["PYI012"]},{"location":"rules/pass-in-class-body/#example","title":"Example","text":"
        class MyClass:\n    x: int\n    pass\n

        Use instead:

        class MyClass:\n    x: int\n
        ","tags":["PYI012"]},{"location":"rules/pass-statement-stub-body/","title":"pass-statement-stub-body (PYI009)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI009"]},{"location":"rules/pass-statement-stub-body/#what-it-does","title":"What it does","text":"

        Checks for pass statements in empty stub bodies.

        ","tags":["PYI009"]},{"location":"rules/pass-statement-stub-body/#why-is-this-bad","title":"Why is this bad?","text":"

        For stylistic consistency, ... should always be used rather than pass in stub files.

        ","tags":["PYI009"]},{"location":"rules/pass-statement-stub-body/#example","title":"Example","text":"
        def foo(bar: int) -> list[int]: pass\n

        Use instead:

        def foo(bar: int) -> list[int]: ...\n
        ","tags":["PYI009"]},{"location":"rules/pass-statement-stub-body/#references","title":"References","text":"
        • Typing documentation - Writing and Maintaining Stub Files
        ","tags":["PYI009"]},{"location":"rules/patch-version-comparison/","title":"patch-version-comparison (PYI004)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI004"]},{"location":"rules/patch-version-comparison/#what-it-does","title":"What it does","text":"

        Checks for Python version comparisons in stubs that compare against patch versions (e.g., Python 3.8.3) instead of major and minor versions (e.g., Python 3.8).

        ","tags":["PYI004"]},{"location":"rules/patch-version-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files support simple conditionals to test for differences in Python versions and platforms. However, type checkers only understand a limited subset of these conditionals. In particular, type checkers don't support patch versions (e.g., Python 3.8.3), only major and minor versions (e.g., Python 3.8). Therefore, version checks in stubs should only use the major and minor versions.

        ","tags":["PYI004"]},{"location":"rules/patch-version-comparison/#example","title":"Example","text":"
        import sys\n\nif sys.version_info >= (3, 4, 3): ...\n

        Use instead:

        import sys\n\nif sys.version_info >= (3, 4): ...\n
        ","tags":["PYI004"]},{"location":"rules/patch-version-comparison/#references","title":"References","text":"
        • Typing documentation: Version and Platform checking
        ","tags":["PYI004"]},{"location":"rules/path-constructor-current-directory/","title":"path-constructor-current-directory (PTH201)","text":"

        Derived from the flake8-use-pathlib linter.

        Fix is always available.

        ","tags":["PTH201"]},{"location":"rules/path-constructor-current-directory/#what-it-does","title":"What it does","text":"

        Checks for pathlib.Path objects that are initialized with the current directory.

        ","tags":["PTH201"]},{"location":"rules/path-constructor-current-directory/#why-is-this-bad","title":"Why is this bad?","text":"

        The Path() constructor defaults to the current directory, so passing it in explicitly (as \".\") is unnecessary.

        ","tags":["PTH201"]},{"location":"rules/path-constructor-current-directory/#example","title":"Example","text":"
        from pathlib import Path\n\n_ = Path(\".\")\n

        Use instead:

        from pathlib import Path\n\n_ = Path()\n
        ","tags":["PTH201"]},{"location":"rules/path-constructor-current-directory/#references","title":"References","text":"
        • Python documentation: Path
        ","tags":["PTH201"]},{"location":"rules/pep484-style-positional-only-parameter/","title":"pep484-style-positional-only-parameter (PYI063)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI063"]},{"location":"rules/pep484-style-positional-only-parameter/#what-it-does","title":"What it does","text":"

        Checks for the presence of PEP 484-style positional-only parameters.

        ","tags":["PYI063"]},{"location":"rules/pep484-style-positional-only-parameter/#why-is-this-bad","title":"Why is this bad?","text":"

        Historically, PEP 484 recommended prefixing parameter names with double underscores (__) to indicate to a type checker that they were positional-only. However, PEP 570 (introduced in Python 3.8) introduced dedicated syntax for positional-only arguments. If a forward slash (/) is present in a function signature on Python 3.8+, all parameters prior to the slash are interpreted as positional-only.

        The new syntax should be preferred as it is more widely used, more concise and more readable. It is also respected by Python at runtime, whereas the old-style syntax was only understood by type checkers.

        ","tags":["PYI063"]},{"location":"rules/pep484-style-positional-only-parameter/#example","title":"Example","text":"
        def foo(__x: int) -> None: ...\n

        Use instead:

        def foo(x: int, /) -> None: ...\n
        ","tags":["PYI063"]},{"location":"rules/pep484-style-positional-only-parameter/#options","title":"Options","text":"
        • target-version
        ","tags":["PYI063"]},{"location":"rules/percent-format-expected-mapping/","title":"percent-format-expected-mapping (F502)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F502"]},{"location":"rules/percent-format-expected-mapping/#what-it-does","title":"What it does","text":"

        Checks for named placeholders in printf-style format strings without mapping-type values.

        ","tags":["F502"]},{"location":"rules/percent-format-expected-mapping/#why-is-this-bad","title":"Why is this bad?","text":"

        When using named placeholders in printf-style format strings, the values must be a map type (such as a dictionary). Otherwise, the expression will raise a TypeError.

        ","tags":["F502"]},{"location":"rules/percent-format-expected-mapping/#example","title":"Example","text":"
        \"%(greeting)s, %(name)s\" % (\"Hello\", \"World\")\n

        Use instead:

        \"%(greeting)s, %(name)s\" % {\"greeting\": \"Hello\", \"name\": \"World\"}\n

        Or:

        \"%s, %s\" % (\"Hello\", \"World\")\n
        ","tags":["F502"]},{"location":"rules/percent-format-expected-mapping/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F502"]},{"location":"rules/percent-format-expected-sequence/","title":"percent-format-expected-sequence (F503)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F503"]},{"location":"rules/percent-format-expected-sequence/#what-it-does","title":"What it does","text":"

        Checks for uses of mapping-type values in printf-style format strings without named placeholders.

        ","tags":["F503"]},{"location":"rules/percent-format-expected-sequence/#why-is-this-bad","title":"Why is this bad?","text":"

        When using mapping-type values (such as dict) in printf-style format strings, the keys must be named. Otherwise, the expression will raise a TypeError.

        ","tags":["F503"]},{"location":"rules/percent-format-expected-sequence/#example","title":"Example","text":"
        \"%s, %s\" % {\"greeting\": \"Hello\", \"name\": \"World\"}\n

        Use instead:

        \"%(greeting)s, %(name)s\" % {\"greeting\": \"Hello\", \"name\": \"World\"}\n

        Or:

        \"%s, %s\" % (\"Hello\", \"World\")\n
        ","tags":["F503"]},{"location":"rules/percent-format-expected-sequence/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F503"]},{"location":"rules/percent-format-extra-named-arguments/","title":"percent-format-extra-named-arguments (F504)","text":"

        Derived from the Pyflakes linter.

        Fix is always available.

        ","tags":["F504"]},{"location":"rules/percent-format-extra-named-arguments/#what-it-does","title":"What it does","text":"

        Checks for unused mapping keys in printf-style format strings.

        ","tags":["F504"]},{"location":"rules/percent-format-extra-named-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused named placeholders in printf-style format strings are unnecessary, and likely indicative of a mistake. They should be removed.

        ","tags":["F504"]},{"location":"rules/percent-format-extra-named-arguments/#example","title":"Example","text":"
        \"Hello, %(name)s\" % {\"greeting\": \"Hello\", \"name\": \"World\"}\n

        Use instead:

        \"Hello, %(name)s\" % {\"name\": \"World\"}\n
        ","tags":["F504"]},{"location":"rules/percent-format-extra-named-arguments/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F504"]},{"location":"rules/percent-format-invalid-format/","title":"percent-format-invalid-format (F501)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F501"]},{"location":"rules/percent-format-invalid-format/#what-it-does","title":"What it does","text":"

        Checks for invalid printf-style format strings.

        ","tags":["F501"]},{"location":"rules/percent-format-invalid-format/#why-is-this-bad","title":"Why is this bad?","text":"

        Conversion specifiers are required for printf-style format strings. These specifiers must contain a % character followed by a conversion type.

        ","tags":["F501"]},{"location":"rules/percent-format-invalid-format/#example","title":"Example","text":"
        \"Hello, %\" % \"world\"\n

        Use instead:

        \"Hello, %s\" % \"world\"\n
        ","tags":["F501"]},{"location":"rules/percent-format-invalid-format/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F501"]},{"location":"rules/percent-format-missing-argument/","title":"percent-format-missing-argument (F505)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F505"]},{"location":"rules/percent-format-missing-argument/#what-it-does","title":"What it does","text":"

        Checks for named placeholders in printf-style format strings that are not present in the provided mapping.

        ","tags":["F505"]},{"location":"rules/percent-format-missing-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Named placeholders that lack a corresponding value in the provided mapping will raise a KeyError.

        ","tags":["F505"]},{"location":"rules/percent-format-missing-argument/#example","title":"Example","text":"
        \"%(greeting)s, %(name)s\" % {\"name\": \"world\"}\n

        Use instead:

        \"Hello, %(name)s\" % {\"name\": \"world\"}\n
        ","tags":["F505"]},{"location":"rules/percent-format-missing-argument/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F505"]},{"location":"rules/percent-format-mixed-positional-and-named/","title":"percent-format-mixed-positional-and-named (F506)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F506"]},{"location":"rules/percent-format-mixed-positional-and-named/#what-it-does","title":"What it does","text":"

        Checks for printf-style format strings that have mixed positional and named placeholders.

        ","tags":["F506"]},{"location":"rules/percent-format-mixed-positional-and-named/#why-is-this-bad","title":"Why is this bad?","text":"

        Python does not support mixing positional and named placeholders in printf-style format strings. The use of mixed placeholders will raise a TypeError at runtime.

        ","tags":["F506"]},{"location":"rules/percent-format-mixed-positional-and-named/#example","title":"Example","text":"
        \"%s, %(name)s\" % (\"Hello\", {\"name\": \"World\"})\n

        Use instead:

        \"%s, %s\" % (\"Hello\", \"World\")\n

        Or:

        \"%(greeting)s, %(name)s\" % {\"greeting\": \"Hello\", \"name\": \"World\"}\n
        ","tags":["F506"]},{"location":"rules/percent-format-mixed-positional-and-named/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F506"]},{"location":"rules/percent-format-positional-count-mismatch/","title":"percent-format-positional-count-mismatch (F507)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F507"]},{"location":"rules/percent-format-positional-count-mismatch/#what-it-does","title":"What it does","text":"

        Checks for printf-style format strings that have a mismatch between the number of positional placeholders and the number of substitution values.

        ","tags":["F507"]},{"location":"rules/percent-format-positional-count-mismatch/#why-is-this-bad","title":"Why is this bad?","text":"

        When a printf-style format string is provided with too many or too few substitution values, it will raise a TypeError at runtime.

        ","tags":["F507"]},{"location":"rules/percent-format-positional-count-mismatch/#example","title":"Example","text":"
        \"%s, %s\" % (\"Hello\", \"world\", \"!\")\n

        Use instead:

        \"%s, %s\" % (\"Hello\", \"world\")\n
        ","tags":["F507"]},{"location":"rules/percent-format-positional-count-mismatch/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F507"]},{"location":"rules/percent-format-star-requires-sequence/","title":"percent-format-star-requires-sequence (F508)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F508"]},{"location":"rules/percent-format-star-requires-sequence/#what-it-does","title":"What it does","text":"

        Checks for printf-style format strings that use the * specifier with non-tuple values.

        ","tags":["F508"]},{"location":"rules/percent-format-star-requires-sequence/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of the * specifier with non-tuple values will raise a TypeError at runtime.

        ","tags":["F508"]},{"location":"rules/percent-format-star-requires-sequence/#example","title":"Example","text":"
        from math import pi\n\n\"%(n).*f\" % {\"n\": (2, pi)}\n

        Use instead:

        from math import pi\n\n\"%.*f\" % (2, pi)  # 3.14\n
        ","tags":["F508"]},{"location":"rules/percent-format-star-requires-sequence/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F508"]},{"location":"rules/percent-format-unsupported-format-character/","title":"percent-format-unsupported-format-character (F509)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F509"]},{"location":"rules/percent-format-unsupported-format-character/#what-it-does","title":"What it does","text":"

        Checks for printf-style format strings with invalid format characters.

        ","tags":["F509"]},{"location":"rules/percent-format-unsupported-format-character/#why-is-this-bad","title":"Why is this bad?","text":"

        In printf-style format strings, the % character is used to indicate placeholders. If a % character is not followed by a valid format character, it will raise a ValueError at runtime.

        ","tags":["F509"]},{"location":"rules/percent-format-unsupported-format-character/#example","title":"Example","text":"
        \"Hello, %S\" % \"world\"\n

        Use instead:

        \"Hello, %s\" % \"world\"\n
        ","tags":["F509"]},{"location":"rules/percent-format-unsupported-format-character/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F509"]},{"location":"rules/post-init-default/","title":"post-init-default (RUF033)","text":"

        Fix is sometimes available.

        ","tags":["RUF033"]},{"location":"rules/post-init-default/#what-it-does","title":"What it does","text":"

        Checks for __post_init__ dataclass methods with parameter defaults.

        ","tags":["RUF033"]},{"location":"rules/post-init-default/#why-is-this-bad","title":"Why is this bad?","text":"

        Adding a default value to a parameter in a __post_init__ method has no impact on whether the parameter will have a default value in the dataclass's generated __init__ method. To create an init-only dataclass parameter with a default value, you should use an InitVar field in the dataclass's class body and give that InitVar field a default value.

        As the documentation states:

        Init-only fields are added as parameters to the generated __init__() method, and are passed to the optional __post_init__() method. They are not otherwise used by dataclasses.

        ","tags":["RUF033"]},{"location":"rules/post-init-default/#example","title":"Example","text":"
        from dataclasses import InitVar, dataclass\n\n\n@dataclass\nclass Foo:\n    bar: InitVar[int] = 0\n\n    def __post_init__(self, bar: int = 1, baz: int = 2) -> None:\n        print(bar, baz)\n\n\nfoo = Foo()  # Prints '0 2'.\n

        Use instead:

        from dataclasses import InitVar, dataclass\n\n\n@dataclass\nclass Foo:\n    bar: InitVar[int] = 1\n    baz: InitVar[int] = 2\n\n    def __post_init__(self, bar: int, baz: int) -> None:\n        print(bar, baz)\n\n\nfoo = Foo()  # Prints '1 2'.\n
        ","tags":["RUF033"]},{"location":"rules/post-init-default/#fix-safety","title":"Fix safety","text":"

        This fix is always marked as unsafe because, although switching to InitVar is usually correct, it is incorrect when the parameter is not intended to be part of the public API or when the value is meant to be shared across all instances.

        ","tags":["RUF033"]},{"location":"rules/post-init-default/#references","title":"References","text":"
        • Python documentation: Post-init processing
        • Python documentation: Init-only variables
        ","tags":["RUF033"]},{"location":"rules/potential-index-error/","title":"potential-index-error (PLE0643)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0643"]},{"location":"rules/potential-index-error/#what-it-does","title":"What it does","text":"

        Checks for hard-coded sequence accesses that are known to be out of bounds.

        ","tags":["PLE0643"]},{"location":"rules/potential-index-error/#why-is-this-bad","title":"Why is this bad?","text":"

        Attempting to access a sequence with an out-of-bounds index will cause an IndexError to be raised at runtime. When the sequence and index are defined statically (e.g., subscripts on list and tuple literals, with integer indexes), such errors can be detected ahead of time.

        ","tags":["PLE0643"]},{"location":"rules/potential-index-error/#example","title":"Example","text":"
        print([0, 1, 2][3])\n
        ","tags":["PLE0643"]},{"location":"rules/print-empty-string/","title":"print-empty-string (FURB105)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB105"]},{"location":"rules/print-empty-string/#what-it-does","title":"What it does","text":"

        Checks for print calls with unnecessary empty strings as positional arguments and unnecessary sep keyword arguments.

        ","tags":["FURB105"]},{"location":"rules/print-empty-string/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefer calling print without any positional arguments, which is equivalent and more concise.

        Similarly, when printing one or fewer items, the sep keyword argument, (used to define the string that separates the print arguments) can be omitted, as it's redundant when there are no items to separate.

        ","tags":["FURB105"]},{"location":"rules/print-empty-string/#example","title":"Example","text":"
        print(\"\")\n

        Use instead:

        print()\n
        ","tags":["FURB105"]},{"location":"rules/print-empty-string/#references","title":"References","text":"
        • Python documentation: print
        ","tags":["FURB105"]},{"location":"rules/print/","title":"print (T201)","text":"

        Derived from the flake8-print linter.

        Fix is sometimes available.

        ","tags":["T201"]},{"location":"rules/print/#what-it-does","title":"What it does","text":"

        Checks for print statements.

        ","tags":["T201"]},{"location":"rules/print/#why-is-this-bad","title":"Why is this bad?","text":"

        print statements are useful in some situations (e.g., debugging), but should typically be omitted from production code. print statements can lead to the accidental inclusion of sensitive information in logs, and are not configurable by clients, unlike logging statements.

        ","tags":["T201"]},{"location":"rules/print/#example","title":"Example","text":"
        def add_numbers(a, b):\n    print(f\"The sum of {a} and {b} is {a + b}\")\n    return a + b\n

        Use instead:

        def add_numbers(a, b):\n    return a + b\n
        ","tags":["T201"]},{"location":"rules/print/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may remove print statements that are used beyond debugging purposes.

        ","tags":["T201"]},{"location":"rules/printf-in-get-text-func-call/","title":"printf-in-get-text-func-call (INT003)","text":"

        Derived from the flake8-gettext linter.

        ","tags":["INT003"]},{"location":"rules/printf-in-get-text-func-call/#what-it-does","title":"What it does","text":"

        Checks for printf-style formatted strings in gettext function calls.

        ","tags":["INT003"]},{"location":"rules/printf-in-get-text-func-call/#why-is-this-bad","title":"Why is this bad?","text":"

        In the gettext API, the gettext function (often aliased to _) returns a translation of its input argument by looking it up in a translation catalog.

        Calling gettext with a formatted string as its argument can cause unexpected behavior. Since the formatted string is resolved before the function call, the translation catalog will look up the formatted string, rather than the printf-style template.

        Instead, format the value returned by the function call, rather than its argument.

        ","tags":["INT003"]},{"location":"rules/printf-in-get-text-func-call/#example","title":"Example","text":"
        from gettext import gettext as _\n\nname = \"Maria\"\n_(\"Hello, %s!\" % name)  # Looks for \"Hello, Maria!\".\n

        Use instead:

        from gettext import gettext as _\n\nname = \"Maria\"\n_(\"Hello, %s!\") % name  # Looks for \"Hello, %s!\".\n
        ","tags":["INT003"]},{"location":"rules/printf-in-get-text-func-call/#references","title":"References","text":"
        • Python documentation: gettext \u2014 Multilingual internationalization services
        ","tags":["INT003"]},{"location":"rules/printf-string-formatting/","title":"printf-string-formatting (UP031)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP031"]},{"location":"rules/printf-string-formatting/#what-it-does","title":"What it does","text":"

        Checks for printf-style string formatting, and offers to replace it with str.format calls.

        ","tags":["UP031"]},{"location":"rules/printf-string-formatting/#why-is-this-bad","title":"Why is this bad?","text":"

        printf-style string formatting has a number of quirks, and leads to less readable code than using str.format calls or f-strings. In general, prefer the newer str.format and f-strings constructs over printf-style string formatting.

        ","tags":["UP031"]},{"location":"rules/printf-string-formatting/#example","title":"Example","text":"
        \"%s, %s\" % (\"Hello\", \"World\")  # \"Hello, World\"\n

        Use instead:

        \"{}, {}\".format(\"Hello\", \"World\")  # \"Hello, World\"\n
        f\"{'Hello'}, {'World'}\"  # \"Hello, World\"\n
        ","tags":["UP031"]},{"location":"rules/printf-string-formatting/#fix-safety","title":"Fix safety","text":"

        In cases where the format string contains a single generic format specifier (e.g. %s), and the right-hand side is an ambiguous expression, we cannot offer a safe fix.

        For example, given:

        \"%s\" % val\n

        val could be a single-element tuple, or a single value (not contained in a tuple). Both of these would resolve to the same formatted string when using printf-style formatting, but resolve differently when using f-strings:

        val = 1\nprint(\"%s\" % val)  # \"1\"\nprint(\"{}\".format(val))  # \"1\"\n\nval = (1,)\nprint(\"%s\" % val)  # \"1\"\nprint(\"{}\".format(val))  # \"(1,)\"\n
        ","tags":["UP031"]},{"location":"rules/printf-string-formatting/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        • Python documentation: str.format
        ","tags":["UP031"]},{"location":"rules/private-member-access/","title":"private-member-access (SLF001)","text":"

        Derived from the flake8-self linter.

        ","tags":["SLF001"]},{"location":"rules/private-member-access/#what-it-does","title":"What it does","text":"

        Checks for accesses on \"private\" class members.

        ","tags":["SLF001"]},{"location":"rules/private-member-access/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the convention is such that class members that are prefixed with a single underscore, or prefixed but not suffixed with a double underscore, are considered private and intended for internal use.

        Using such \"private\" members is considered a misuse of the class, as there are no guarantees that the member will be present in future versions, that it will have the same type, or that it will have the same behavior. Instead, use the class's public interface.

        This rule ignores accesses on dunder methods (e.g., __init__) and sunder methods (e.g., _missing_).

        ","tags":["SLF001"]},{"location":"rules/private-member-access/#example","title":"Example","text":"
        class Class:\n    def __init__(self):\n        self._private_member = \"...\"\n\n\nvar = Class()\nprint(var._private_member)\n

        Use instead:

        class Class:\n    def __init__(self):\n        self.public_member = \"...\"\n\n\nvar = Class()\nprint(var.public_member)\n
        ","tags":["SLF001"]},{"location":"rules/private-member-access/#options","title":"Options","text":"
        • lint.flake8-self.ignore-names
        ","tags":["SLF001"]},{"location":"rules/private-member-access/#references","title":"References","text":"
        • What is the meaning of single or double underscores before an object name?
        ","tags":["SLF001"]},{"location":"rules/private-type-parameter/","title":"private-type-parameter (UP049)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["UP049"]},{"location":"rules/private-type-parameter/#what-it-does","title":"What it does","text":"

        Checks for use of PEP 695 type parameters with leading underscores in generic classes and functions.

        ","tags":["UP049"]},{"location":"rules/private-type-parameter/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 695 type parameters are already restricted in scope to the class or function in which they appear, so leading underscores just hurt readability without the usual privacy benefits.

        However, neither a diagnostic nor a fix will be emitted for \"sunder\" (_T_) or \"dunder\" (__T__) type parameter names as these are not considered private.

        ","tags":["UP049"]},{"location":"rules/private-type-parameter/#example","title":"Example","text":"
        class GenericClass[_T]:\n    var: _T\n\n\ndef generic_function[_T](var: _T) -> list[_T]:\n    return var[0]\n

        Use instead:

        class GenericClass[T]:\n    var: T\n\n\ndef generic_function[T](var: T) -> list[T]:\n    return var[0]\n
        ","tags":["UP049"]},{"location":"rules/private-type-parameter/#fix-availability","title":"Fix availability","text":"

        If the name without an underscore would shadow a builtin or another variable, would be a keyword, or would otherwise be an invalid identifier, a fix will not be available. In these situations, you can consider using a trailing underscore or a different name entirely to satisfy the lint rule.

        ","tags":["UP049"]},{"location":"rules/private-type-parameter/#see-also","title":"See also","text":"

        This rule renames private PEP 695 type parameters but doesn't convert pre-PEP 695 generics to the new format. See non-pep695-generic-function and non-pep695-generic-class for rules that will make this transformation. Those rules do not remove unused type variables after their changes, so you may also want to consider enabling unused-private-type-var to complete the transition to PEP 695 generics.

        ","tags":["UP049"]},{"location":"rules/prohibited-trailing-comma/","title":"prohibited-trailing-comma (COM819)","text":"

        Derived from the flake8-commas linter.

        Fix is always available.

        ","tags":["COM819"]},{"location":"rules/prohibited-trailing-comma/#what-it-does","title":"What it does","text":"

        Checks for the presence of prohibited trailing commas.

        ","tags":["COM819"]},{"location":"rules/prohibited-trailing-comma/#why-is-this-bad","title":"Why is this bad?","text":"

        Trailing commas are not essential in some cases and can therefore be viewed as unnecessary.

        ","tags":["COM819"]},{"location":"rules/prohibited-trailing-comma/#example","title":"Example","text":"
        foo = (1, 2, 3,)\n

        Use instead:

        foo = (1, 2, 3)\n
        ","tags":["COM819"]},{"location":"rules/prohibited-trailing-comma/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent use of trailing commas, making the rule redundant.

        ","tags":["COM819"]},{"location":"rules/property-with-parameters/","title":"property-with-parameters (PLR0206)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0206"]},{"location":"rules/property-with-parameters/#what-it-does","title":"What it does","text":"

        Checks for property definitions that accept function parameters.

        ","tags":["PLR0206"]},{"location":"rules/property-with-parameters/#why-is-this-bad","title":"Why is this bad?","text":"

        Properties cannot be called with parameters.

        If you need to pass parameters to a property, create a method with the desired parameters and call that method instead.

        ","tags":["PLR0206"]},{"location":"rules/property-with-parameters/#example","title":"Example","text":"
        class Cat:\n    @property\n    def purr(self, volume): ...\n

        Use instead:

        class Cat:\n    @property\n    def purr(self): ...\n\n    def purr_volume(self, volume): ...\n
        ","tags":["PLR0206"]},{"location":"rules/property-with-parameters/#references","title":"References","text":"
        • Python documentation: property
        ","tags":["PLR0206"]},{"location":"rules/py-path/","title":"py-path (PTH124)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH124"]},{"location":"rules/py-path/#what-it-does","title":"What it does","text":"

        Checks for uses of the py.path library.

        ","tags":["PTH124"]},{"location":"rules/py-path/#why-is-this-bad","title":"Why is this bad?","text":"

        The py.path library is in maintenance mode. Instead, prefer the standard library's pathlib module, or third-party modules like path (formerly py.path).

        ","tags":["PTH124"]},{"location":"rules/py-path/#examples","title":"Examples","text":"
        import py.path\n\np = py.path.local(\"/foo/bar\").join(\"baz/qux\")\n

        Use instead:

        from pathlib import Path\n\np = Path(\"/foo/bar\") / \"bar\" / \"qux\"\n
        ","tags":["PTH124"]},{"location":"rules/py-path/#references","title":"References","text":"
        • Python documentation: Pathlib
        • Path repository
        ","tags":["PTH124"]},{"location":"rules/pytest-assert-always-false/","title":"pytest-assert-always-false (PT015)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT015"]},{"location":"rules/pytest-assert-always-false/#what-it-does","title":"What it does","text":"

        Checks for assert statements whose test expression is a falsy value.

        ","tags":["PT015"]},{"location":"rules/pytest-assert-always-false/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.fail conveys the intent more clearly than assert falsy_value.

        ","tags":["PT015"]},{"location":"rules/pytest-assert-always-false/#example","title":"Example","text":"
        def test_foo():\n    if some_condition:\n        assert False, \"some_condition was True\"\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    if some_condition:\n        pytest.fail(\"some_condition was True\")\n    ...\n
        ","tags":["PT015"]},{"location":"rules/pytest-assert-always-false/#references","title":"References","text":"
        • pytest documentation: pytest.fail
        ","tags":["PT015"]},{"location":"rules/pytest-assert-in-except/","title":"pytest-assert-in-except (PT017)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT017"]},{"location":"rules/pytest-assert-in-except/#what-it-does","title":"What it does","text":"

        Checks for assert statements in except clauses.

        ","tags":["PT017"]},{"location":"rules/pytest-assert-in-except/#why-is-this-bad","title":"Why is this bad?","text":"

        When testing for exceptions, pytest.raises() should be used instead of assert statements in except clauses, as it's more explicit and idiomatic. Further, pytest.raises() will fail if the exception is not raised, unlike the assert statement.

        ","tags":["PT017"]},{"location":"rules/pytest-assert-in-except/#example","title":"Example","text":"
        def test_foo():\n    try:\n        1 / 0\n    except ZeroDivisionError as e:\n        assert e.args\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    with pytest.raises(ZeroDivisionError) as exc_info:\n        1 / 0\n    assert exc_info.value.args\n
        ","tags":["PT017"]},{"location":"rules/pytest-assert-in-except/#references","title":"References","text":"
        • pytest documentation: pytest.raises
        ","tags":["PT017"]},{"location":"rules/pytest-composite-assertion/","title":"pytest-composite-assertion (PT018)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT018"]},{"location":"rules/pytest-composite-assertion/#what-it-does","title":"What it does","text":"

        Checks for assertions that combine multiple independent conditions.

        ","tags":["PT018"]},{"location":"rules/pytest-composite-assertion/#why-is-this-bad","title":"Why is this bad?","text":"

        Composite assertion statements are harder to debug upon failure, as the failure message will not indicate which condition failed.

        ","tags":["PT018"]},{"location":"rules/pytest-composite-assertion/#example","title":"Example","text":"
        def test_foo():\n    assert something and something_else\n\n\ndef test_bar():\n    assert not (something or something_else)\n

        Use instead:

        def test_foo():\n    assert something\n    assert something_else\n\n\ndef test_bar():\n    assert not something\n    assert not something_else\n
        ","tags":["PT018"]},{"location":"rules/pytest-deprecated-yield-fixture/","title":"pytest-deprecated-yield-fixture (PT020)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT020"]},{"location":"rules/pytest-deprecated-yield-fixture/#what-it-does","title":"What it does","text":"

        Checks for pytest.yield_fixture usage.

        ","tags":["PT020"]},{"location":"rules/pytest-deprecated-yield-fixture/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.yield_fixture is deprecated. pytest.fixture should be used instead.

        ","tags":["PT020"]},{"location":"rules/pytest-deprecated-yield-fixture/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.yield_fixture()\ndef my_fixture():\n    obj = SomeClass()\n    yield obj\n    obj.cleanup()\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef my_fixture():\n    obj = SomeClass()\n    yield obj\n    obj.cleanup()\n
        ","tags":["PT020"]},{"location":"rules/pytest-deprecated-yield-fixture/#references","title":"References","text":"
        • pytest documentation: yield_fixture functions
        ","tags":["PT020"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/","title":"pytest-duplicate-parametrize-test-cases (PT014)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT014"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/#what-it-does","title":"What it does","text":"

        Checks for duplicate test cases in pytest.mark.parametrize.

        ","tags":["PT014"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/#why-is-this-bad","title":"Why is this bad?","text":"

        Duplicate test cases are redundant and should be removed.

        ","tags":["PT014"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.mark.parametrize(\n    (\"param1\", \"param2\"),\n    [\n        (1, 2),\n        (1, 2),\n    ],\n)\ndef test_foo(param1, param2): ...\n

        Use instead:

        import pytest\n\n\n@pytest.mark.parametrize(\n    (\"param1\", \"param2\"),\n    [\n        (1, 2),\n    ],\n)\ndef test_foo(param1, param2): ...\n
        ","tags":["PT014"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as tests that rely on mutable global state may be affected by removing duplicate test cases.

        ","tags":["PT014"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/#references","title":"References","text":"
        • pytest documentation: How to parametrize fixtures and test functions
        ","tags":["PT014"]},{"location":"rules/pytest-erroneous-use-fixtures-on-fixture/","title":"pytest-erroneous-use-fixtures-on-fixture (PT025)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT025"]},{"location":"rules/pytest-erroneous-use-fixtures-on-fixture/#what-it-does","title":"What it does","text":"

        Checks for pytest.mark.usefixtures decorators applied to pytest fixtures.

        ","tags":["PT025"]},{"location":"rules/pytest-erroneous-use-fixtures-on-fixture/#why-is-this-bad","title":"Why is this bad?","text":"

        The pytest.mark.usefixtures decorator has no effect on pytest fixtures.

        ","tags":["PT025"]},{"location":"rules/pytest-erroneous-use-fixtures-on-fixture/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef a():\n    pass\n\n\n@pytest.mark.usefixtures(\"a\")\n@pytest.fixture()\ndef b(a):\n    pass\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef a():\n    pass\n\n\n@pytest.fixture()\ndef b(a):\n    pass\n
        ","tags":["PT025"]},{"location":"rules/pytest-erroneous-use-fixtures-on-fixture/#references","title":"References","text":"
        • pytest documentation: pytest.mark.usefixtures
        ","tags":["PT025"]},{"location":"rules/pytest-extraneous-scope-function/","title":"pytest-extraneous-scope-function (PT003)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT003"]},{"location":"rules/pytest-extraneous-scope-function/#what-it-does","title":"What it does","text":"

        Checks for pytest.fixture calls with scope=\"function\".

        ","tags":["PT003"]},{"location":"rules/pytest-extraneous-scope-function/#why-is-this-bad","title":"Why is this bad?","text":"

        scope=\"function\" can be omitted, as it is the default.

        ","tags":["PT003"]},{"location":"rules/pytest-extraneous-scope-function/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture(scope=\"function\")\ndef my_fixture(): ...\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef my_fixture(): ...\n
        ","tags":["PT003"]},{"location":"rules/pytest-extraneous-scope-function/#references","title":"References","text":"
        • pytest documentation: @pytest.fixture functions
        ","tags":["PT003"]},{"location":"rules/pytest-fail-without-message/","title":"pytest-fail-without-message (PT016)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT016"]},{"location":"rules/pytest-fail-without-message/#what-it-does","title":"What it does","text":"

        Checks for pytest.fail calls without a message.

        ","tags":["PT016"]},{"location":"rules/pytest-fail-without-message/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.fail calls without a message make it harder to understand and debug test failures.

        ","tags":["PT016"]},{"location":"rules/pytest-fail-without-message/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    pytest.fail()\n\n\ndef test_bar():\n    pytest.fail(\"\")\n\n\ndef test_baz():\n    pytest.fail(reason=\"\")\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    pytest.fail(\"...\")\n\n\ndef test_bar():\n    pytest.fail(reason=\"...\")\n
        ","tags":["PT016"]},{"location":"rules/pytest-fail-without-message/#references","title":"References","text":"
        • pytest documentation: pytest.fail
        ","tags":["PT016"]},{"location":"rules/pytest-fixture-finalizer-callback/","title":"pytest-fixture-finalizer-callback (PT021)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT021"]},{"location":"rules/pytest-fixture-finalizer-callback/#what-it-does","title":"What it does","text":"

        Checks for unnecessary request.addfinalizer usages in pytest fixtures.

        ","tags":["PT021"]},{"location":"rules/pytest-fixture-finalizer-callback/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest offers two ways to perform cleanup in fixture code. The first is sequential (via the yield statement), the second callback-based (via request.addfinalizer).

        The sequential approach is more readable and should be preferred, unless the fixture uses the \"factory as fixture\" pattern.

        ","tags":["PT021"]},{"location":"rules/pytest-fixture-finalizer-callback/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef my_fixture(request):\n    resource = acquire_resource()\n    request.addfinalizer(resource.release)\n    return resource\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef my_fixture():\n    resource = acquire_resource()\n    yield resource\n    resource.release()\n\n\n# \"factory-as-fixture\" pattern\n@pytest.fixture()\ndef my_factory(request):\n    def create_resource(arg):\n        resource = acquire_resource(arg)\n        request.addfinalizer(resource.release)\n        return resource\n\n    return create_resource\n
        ","tags":["PT021"]},{"location":"rules/pytest-fixture-finalizer-callback/#references","title":"References","text":"
        • pytest documentation: Adding finalizers directly
        • pytest documentation: Factories as fixtures
        ","tags":["PT021"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/","title":"pytest-fixture-incorrect-parentheses-style (PT001)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT001"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/#what-it-does","title":"What it does","text":"

        Checks for argument-free @pytest.fixture() decorators with or without parentheses, depending on the lint.flake8-pytest-style.fixture-parentheses setting.

        ","tags":["PT001"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/#why-is-this-bad","title":"Why is this bad?","text":"

        If a @pytest.fixture() doesn't take any arguments, the parentheses are optional.

        Either removing those unnecessary parentheses or requiring them for all fixtures is fine, but it's best to be consistent. The rule defaults to removing unnecessary parentheses, to match the documentation of the official pytest projects.

        ","tags":["PT001"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef my_fixture(): ...\n

        Use instead:

        import pytest\n\n\n@pytest.fixture\ndef my_fixture(): ...\n
        ","tags":["PT001"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/#options","title":"Options","text":"
        • lint.flake8-pytest-style.fixture-parentheses
        ","tags":["PT001"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/#references","title":"References","text":"
        • pytest documentation: API Reference: Fixtures
        ","tags":["PT001"]},{"location":"rules/pytest-fixture-param-without-value/","title":"pytest-fixture-param-without-value (PT019)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT019"]},{"location":"rules/pytest-fixture-param-without-value/#what-it-does","title":"What it does","text":"

        Checks for pytest test functions that should be decorated with @pytest.mark.usefixtures.

        ","tags":["PT019"]},{"location":"rules/pytest-fixture-param-without-value/#why-is-this-bad","title":"Why is this bad?","text":"

        In pytest, fixture injection is used to activate fixtures in a test function.

        Fixtures can be injected either by passing them as parameters to the test function, or by using the @pytest.mark.usefixtures decorator.

        If the test function depends on the fixture being activated, but does not use it in the test body or otherwise rely on its return value, prefer the @pytest.mark.usefixtures decorator, to make the dependency explicit and avoid the confusion caused by unused arguments.

        ","tags":["PT019"]},{"location":"rules/pytest-fixture-param-without-value/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture\ndef _patch_something(): ...\n\n\ndef test_foo(_patch_something): ...\n

        Use instead:

        import pytest\n\n\n@pytest.fixture\ndef _patch_something(): ...\n\n\n@pytest.mark.usefixtures(\"_patch_something\")\ndef test_foo(): ...\n
        ","tags":["PT019"]},{"location":"rules/pytest-fixture-param-without-value/#references","title":"References","text":"
        • pytest documentation: pytest.mark.usefixtures
        ","tags":["PT019"]},{"location":"rules/pytest-fixture-positional-args/","title":"pytest-fixture-positional-args (PT002)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT002"]},{"location":"rules/pytest-fixture-positional-args/#what-it-does","title":"What it does","text":"

        Checks for pytest.fixture calls with positional arguments.

        ","tags":["PT002"]},{"location":"rules/pytest-fixture-positional-args/#why-is-this-bad","title":"Why is this bad?","text":"

        For clarity and consistency, prefer using keyword arguments to specify fixture configuration.

        ","tags":["PT002"]},{"location":"rules/pytest-fixture-positional-args/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture(\"module\")\ndef my_fixture(): ...\n

        Use instead:

        import pytest\n\n\n@pytest.fixture(scope=\"module\")\ndef my_fixture(): ...\n
        ","tags":["PT002"]},{"location":"rules/pytest-fixture-positional-args/#references","title":"References","text":"
        • pytest documentation: @pytest.fixture functions
        ","tags":["PT002"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/","title":"pytest-incorrect-fixture-name-underscore (PT005)","text":"

        Derived from the flake8-pytest-style linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/#removal","title":"Removal","text":"

        This rule has been removed because marking fixtures that do not return a value with an underscore isn't a practice recommended by the pytest community.

        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/#what-it-does","title":"What it does","text":"

        Checks for pytest fixtures that return a value, but are named with a leading underscore.

        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/#why-is-this-bad","title":"Why is this bad?","text":"

        By convention, fixtures that don't return a value should be named with a leading underscore, while fixtures that do return a value should not.

        This rule ignores abstract fixtures.

        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef _some_object():\n    return SomeClass()\n\n\n@pytest.fixture()\ndef _some_object_with_cleanup():\n    obj = SomeClass()\n    yield obj\n    obj.cleanup()\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef some_object():\n    return SomeClass()\n\n\n@pytest.fixture()\ndef some_object_with_cleanup():\n    obj = SomeClass()\n    yield obj\n    obj.cleanup()\n
        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/#references","title":"References","text":"
        • pytest documentation: @pytest.fixture functions
        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/","title":"pytest-incorrect-mark-parentheses-style (PT023)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/#what-it-does","title":"What it does","text":"

        Checks for argument-free @pytest.mark.<marker>() decorators with or without parentheses, depending on the lint.flake8-pytest-style.mark-parentheses setting.

        The rule defaults to removing unnecessary parentheses, to match the documentation of the official pytest projects.

        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/#why-is-this-bad","title":"Why is this bad?","text":"

        If a @pytest.mark.<marker>() doesn't take any arguments, the parentheses are optional.

        Either removing those unnecessary parentheses or requiring them for all fixtures is fine, but it's best to be consistent.

        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.mark.foo\ndef test_something(): ...\n

        Use instead:

        import pytest\n\n\n@pytest.mark.foo()\ndef test_something(): ...\n
        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/#options","title":"Options","text":"
        • lint.flake8-pytest-style.mark-parentheses
        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/#references","title":"References","text":"
        • pytest documentation: Marks
        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-pytest-import/","title":"pytest-incorrect-pytest-import (PT013)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT013"]},{"location":"rules/pytest-incorrect-pytest-import/#what-it-does","title":"What it does","text":"

        Checks for incorrect import of pytest.

        ","tags":["PT013"]},{"location":"rules/pytest-incorrect-pytest-import/#why-is-this-bad","title":"Why is this bad?","text":"

        For consistency, pytest should be imported as import pytest and its members should be accessed in the form of pytest.xxx.yyy for consistency

        ","tags":["PT013"]},{"location":"rules/pytest-incorrect-pytest-import/#example","title":"Example","text":"
        import pytest as pt\nfrom pytest import fixture\n

        Use instead:

        import pytest\n
        ","tags":["PT013"]},{"location":"rules/pytest-missing-fixture-name-underscore/","title":"pytest-missing-fixture-name-underscore (PT004)","text":"

        Derived from the flake8-pytest-style linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["PT004"]},{"location":"rules/pytest-missing-fixture-name-underscore/#removal","title":"Removal","text":"

        This rule has been removed because marking fixtures that do not return a value with an underscore isn't a practice recommended by the pytest community.

        ","tags":["PT004"]},{"location":"rules/pytest-missing-fixture-name-underscore/#what-it-does","title":"What it does","text":"

        Checks for pytest fixtures that do not return a value, but are not named with a leading underscore.

        ","tags":["PT004"]},{"location":"rules/pytest-missing-fixture-name-underscore/#why-is-this-bad","title":"Why is this bad?","text":"

        By convention, fixtures that don't return a value should be named with a leading underscore, while fixtures that do return a value should not.

        This rule ignores abstract fixtures and generators.

        ","tags":["PT004"]},{"location":"rules/pytest-missing-fixture-name-underscore/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef patch_something(mocker):\n    mocker.patch(\"module.object\")\n\n\n@pytest.fixture()\ndef use_context():\n    with create_context():\n        yield\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef _patch_something(mocker):\n    mocker.patch(\"module.object\")\n\n\n@pytest.fixture()\ndef _use_context():\n    with create_context():\n        yield\n
        ","tags":["PT004"]},{"location":"rules/pytest-missing-fixture-name-underscore/#references","title":"References","text":"
        • pytest documentation: @pytest.fixture functions
        ","tags":["PT004"]},{"location":"rules/pytest-parameter-with-default-argument/","title":"pytest-parameter-with-default-argument (PT028)","text":"

        Derived from the flake8-pytest-style linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PT028"]},{"location":"rules/pytest-parameter-with-default-argument/#what-it-does","title":"What it does","text":"

        Checks for parameters of test functions with default arguments.

        ","tags":["PT028"]},{"location":"rules/pytest-parameter-with-default-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Such a parameter will always have the default value during the test regardless of whether a fixture with the same name is defined.

        ","tags":["PT028"]},{"location":"rules/pytest-parameter-with-default-argument/#example","title":"Example","text":"
        def test_foo(a=1): ...\n

        Use instead:

        def test_foo(a): ...\n
        ","tags":["PT028"]},{"location":"rules/pytest-parameter-with-default-argument/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as modifying a function signature can change the behavior of the code.

        ","tags":["PT028"]},{"location":"rules/pytest-parameter-with-default-argument/#references","title":"References","text":"
        • Original Pytest issue
        ","tags":["PT028"]},{"location":"rules/pytest-parametrize-names-wrong-type/","title":"pytest-parametrize-names-wrong-type (PT006)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-names-wrong-type/#what-it-does","title":"What it does","text":"

        Checks for the type of parameter names passed to pytest.mark.parametrize.

        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-names-wrong-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The argnames argument of pytest.mark.parametrize takes a string or a sequence of strings. For a single parameter, it's preferable to use a string. For multiple parameters, it's preferable to use the style configured via the lint.flake8-pytest-style.parametrize-names-type setting.

        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-names-wrong-type/#example","title":"Example","text":"
        import pytest\n\n\n# single parameter, always expecting string\n@pytest.mark.parametrize((\"param\",), [1, 2, 3])\ndef test_foo(param): ...\n\n\n# multiple parameters, expecting tuple\n@pytest.mark.parametrize([\"param1\", \"param2\"], [(1, 2), (3, 4)])\ndef test_bar(param1, param2): ...\n\n\n# multiple parameters, expecting tuple\n@pytest.mark.parametrize(\"param1,param2\", [(1, 2), (3, 4)])\ndef test_baz(param1, param2): ...\n

        Use instead:

        import pytest\n\n\n@pytest.mark.parametrize(\"param\", [1, 2, 3])\ndef test_foo(param): ...\n\n\n@pytest.mark.parametrize((\"param1\", \"param2\"), [(1, 2), (3, 4)])\ndef test_bar(param1, param2): ...\n
        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-names-wrong-type/#options","title":"Options","text":"
        • lint.flake8-pytest-style.parametrize-names-type
        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-names-wrong-type/#references","title":"References","text":"
        • pytest documentation: How to parametrize fixtures and test functions
        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-values-wrong-type/","title":"pytest-parametrize-values-wrong-type (PT007)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT007"]},{"location":"rules/pytest-parametrize-values-wrong-type/#what-it-does","title":"What it does","text":"

        Checks for the type of parameter values passed to pytest.mark.parametrize.

        ","tags":["PT007"]},{"location":"rules/pytest-parametrize-values-wrong-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The argvalues argument of pytest.mark.parametrize takes an iterator of parameter values, which can be provided as lists or tuples.

        To aid in readability, it's recommended to use a consistent style for the list of values rows, and, in the case of multiple parameters, for each row of values.

        The style for the list of values rows can be configured via the lint.flake8-pytest-style.parametrize-values-type setting, while the style for each row of values can be configured via the lint.flake8-pytest-style.parametrize-values-row-type setting.

        For example, lint.flake8-pytest-style.parametrize-values-type will lead to the following expectations:

        • tuple: @pytest.mark.parametrize(\"value\", (\"a\", \"b\", \"c\"))
        • list: @pytest.mark.parametrize(\"value\", [\"a\", \"b\", \"c\"])

        Similarly, lint.flake8-pytest-style.parametrize-values-row-type will lead to the following expectations:

        • tuple: @pytest.mark.parametrize((\"key\", \"value\"), [(\"a\", \"b\"), (\"c\", \"d\")])
        • list: @pytest.mark.parametrize((\"key\", \"value\"), [[\"a\", \"b\"], [\"c\", \"d\"]])
        ","tags":["PT007"]},{"location":"rules/pytest-parametrize-values-wrong-type/#example","title":"Example","text":"
        import pytest\n\n\n# expected list, got tuple\n@pytest.mark.parametrize(\"param\", (1, 2))\ndef test_foo(param): ...\n\n\n# expected top-level list, got tuple\n@pytest.mark.parametrize(\n    (\"param1\", \"param2\"),\n    (\n        (1, 2),\n        (3, 4),\n    ),\n)\ndef test_bar(param1, param2): ...\n\n\n# expected individual rows to be tuples, got lists\n@pytest.mark.parametrize(\n    (\"param1\", \"param2\"),\n    [\n        [1, 2],\n        [3, 4],\n    ],\n)\ndef test_baz(param1, param2): ...\n

        Use instead:

        import pytest\n\n\n@pytest.mark.parametrize(\"param\", [1, 2, 3])\ndef test_foo(param): ...\n\n\n@pytest.mark.parametrize((\"param1\", \"param2\"), [(1, 2), (3, 4)])\ndef test_bar(param1, param2): ...\n
        ","tags":["PT007"]},{"location":"rules/pytest-parametrize-values-wrong-type/#options","title":"Options","text":"
        • lint.flake8-pytest-style.parametrize-values-type
        • lint.flake8-pytest-style.parametrize-values-row-type
        ","tags":["PT007"]},{"location":"rules/pytest-parametrize-values-wrong-type/#references","title":"References","text":"
        • pytest documentation: How to parametrize fixtures and test functions
        ","tags":["PT007"]},{"location":"rules/pytest-patch-with-lambda/","title":"pytest-patch-with-lambda (PT008)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT008"]},{"location":"rules/pytest-patch-with-lambda/#what-it-does","title":"What it does","text":"

        Checks for mocked calls that use a dummy lambda function instead of return_value.

        ","tags":["PT008"]},{"location":"rules/pytest-patch-with-lambda/#why-is-this-bad","title":"Why is this bad?","text":"

        When patching calls, an explicit return_value better conveys the intent than a lambda function, assuming the lambda does not use the arguments passed to it.

        return_value is also robust to changes in the patched function's signature, and enables additional assertions to verify behavior. For example, return_value allows for verification of the number of calls or the arguments passed to the patched function via assert_called_once_with and related methods.

        ","tags":["PT008"]},{"location":"rules/pytest-patch-with-lambda/#example","title":"Example","text":"
        def test_foo(mocker):\n    mocker.patch(\"module.target\", lambda x, y: 7)\n

        Use instead:

        def test_foo(mocker):\n    mocker.patch(\"module.target\", return_value=7)\n\n    # If the lambda makes use of the arguments, no diagnostic is emitted.\n    mocker.patch(\"module.other_target\", lambda x, y: x)\n
        ","tags":["PT008"]},{"location":"rules/pytest-patch-with-lambda/#references","title":"References","text":"
        • Python documentation: unittest.mock.patch
        • PyPI: pytest-mock
        ","tags":["PT008"]},{"location":"rules/pytest-raises-ambiguous-pattern/","title":"pytest-raises-ambiguous-pattern (RUF043)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF043"]},{"location":"rules/pytest-raises-ambiguous-pattern/#what-it-does","title":"What it does","text":"

        Checks for non-raw literal string arguments passed to the match parameter of pytest.raises() where the string contains at least one unescaped regex metacharacter.

        ","tags":["RUF043"]},{"location":"rules/pytest-raises-ambiguous-pattern/#why-is-this-bad","title":"Why is this bad?","text":"

        The match argument is implicitly converted to a regex under the hood. It should be made explicit whether the string is meant to be a regex or a \"plain\" pattern by prefixing the string with the r suffix, escaping the metacharacter(s) in the string using backslashes, or wrapping the entire string in a call to re.escape().

        ","tags":["RUF043"]},{"location":"rules/pytest-raises-ambiguous-pattern/#example","title":"Example","text":"
        import pytest\n\n\nwith pytest.raises(Exception, match=\"A full sentence.\"):\n    do_thing_that_raises()\n

        Use instead:

        import pytest\n\n\nwith pytest.raises(Exception, match=r\"A full sentence.\"):\n    do_thing_that_raises()\n

        Alternatively:

        import pytest\nimport re\n\n\nwith pytest.raises(Exception, match=re.escape(\"A full sentence.\")):\n    do_thing_that_raises()\n

        or:

        import pytest\nimport re\n\n\nwith pytest.raises(Exception, \"A full sentence\\\\.\"):\n    do_thing_that_raises()\n
        ","tags":["RUF043"]},{"location":"rules/pytest-raises-ambiguous-pattern/#references","title":"References","text":"
        • Python documentation: re.escape
        • pytest documentation: pytest.raises
        ","tags":["RUF043"]},{"location":"rules/pytest-raises-too-broad/","title":"pytest-raises-too-broad (PT011)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT011"]},{"location":"rules/pytest-raises-too-broad/#what-it-does","title":"What it does","text":"

        Checks for pytest.raises calls without a match parameter.

        ","tags":["PT011"]},{"location":"rules/pytest-raises-too-broad/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.raises(Error) will catch any Error and may catch errors that are unrelated to the code under test. To avoid this, pytest.raises should be called with a match parameter. The exception names that require a match parameter can be configured via the lint.flake8-pytest-style.raises-require-match-for and lint.flake8-pytest-style.raises-extend-require-match-for settings.

        ","tags":["PT011"]},{"location":"rules/pytest-raises-too-broad/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    with pytest.raises(ValueError):\n        ...\n\n    # empty string is also an error\n    with pytest.raises(ValueError, match=\"\"):\n        ...\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    with pytest.raises(ValueError, match=\"expected message\"):\n        ...\n
        ","tags":["PT011"]},{"location":"rules/pytest-raises-too-broad/#options","title":"Options","text":"
        • lint.flake8-pytest-style.raises-require-match-for
        • lint.flake8-pytest-style.raises-extend-require-match-for
        ","tags":["PT011"]},{"location":"rules/pytest-raises-too-broad/#references","title":"References","text":"
        • pytest documentation: pytest.raises
        ","tags":["PT011"]},{"location":"rules/pytest-raises-with-multiple-statements/","title":"pytest-raises-with-multiple-statements (PT012)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT012"]},{"location":"rules/pytest-raises-with-multiple-statements/#what-it-does","title":"What it does","text":"

        Checks for pytest.raises context managers with multiple statements.

        This rule allows pytest.raises bodies to contain for loops with empty bodies (e.g., pass or ... statements), to test iterator behavior.

        ","tags":["PT012"]},{"location":"rules/pytest-raises-with-multiple-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        When a pytest.raises is used as a context manager and contains multiple statements, it can lead to the test passing when it actually should fail.

        A pytest.raises context manager should only contain a single simple statement that raises the expected exception.

        ","tags":["PT012"]},{"location":"rules/pytest-raises-with-multiple-statements/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    with pytest.raises(MyError):\n        setup()\n        func_to_test()  # not executed if `setup()` raises `MyError`\n        assert foo()  # not executed\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    setup()\n    with pytest.raises(MyError):\n        func_to_test()\n    assert foo()\n
        ","tags":["PT012"]},{"location":"rules/pytest-raises-with-multiple-statements/#references","title":"References","text":"
        • pytest documentation: pytest.raises
        ","tags":["PT012"]},{"location":"rules/pytest-raises-without-exception/","title":"pytest-raises-without-exception (PT010)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT010"]},{"location":"rules/pytest-raises-without-exception/#what-it-does","title":"What it does","text":"

        Checks for pytest.raises calls without an expected exception.

        ","tags":["PT010"]},{"location":"rules/pytest-raises-without-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.raises expects to receive an expected exception as its first argument. If omitted, the pytest.raises call will fail at runtime.

        ","tags":["PT010"]},{"location":"rules/pytest-raises-without-exception/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    with pytest.raises():\n        do_something()\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    with pytest.raises(SomeException):\n        do_something()\n
        ","tags":["PT010"]},{"location":"rules/pytest-raises-without-exception/#references","title":"References","text":"
        • pytest documentation: pytest.raises
        ","tags":["PT010"]},{"location":"rules/pytest-unittest-assertion/","title":"pytest-unittest-assertion (PT009)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT009"]},{"location":"rules/pytest-unittest-assertion/#what-it-does","title":"What it does","text":"

        Checks for uses of assertion methods from the unittest module.

        ","tags":["PT009"]},{"location":"rules/pytest-unittest-assertion/#why-is-this-bad","title":"Why is this bad?","text":"

        To make use of pytest's assertion rewriting, a regular assert statement is preferred over unittest's assertion methods.

        ","tags":["PT009"]},{"location":"rules/pytest-unittest-assertion/#example","title":"Example","text":"
        import unittest\n\n\nclass TestFoo(unittest.TestCase):\n    def test_foo(self):\n        self.assertEqual(a, b)\n

        Use instead:

        import unittest\n\n\nclass TestFoo(unittest.TestCase):\n    def test_foo(self):\n        assert a == b\n
        ","tags":["PT009"]},{"location":"rules/pytest-unittest-assertion/#references","title":"References","text":"
        • pytest documentation: Assertion introspection details
        ","tags":["PT009"]},{"location":"rules/pytest-unittest-raises-assertion/","title":"pytest-unittest-raises-assertion (PT027)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT027"]},{"location":"rules/pytest-unittest-raises-assertion/#what-it-does","title":"What it does","text":"

        Checks for uses of exception-related assertion methods from the unittest module.

        ","tags":["PT027"]},{"location":"rules/pytest-unittest-raises-assertion/#why-is-this-bad","title":"Why is this bad?","text":"

        To enforce the assertion style recommended by pytest, pytest.raises is preferred over the exception-related assertion methods in unittest, like assertRaises.

        ","tags":["PT027"]},{"location":"rules/pytest-unittest-raises-assertion/#example","title":"Example","text":"
        import unittest\n\n\nclass TestFoo(unittest.TestCase):\n    def test_foo(self):\n        with self.assertRaises(ValueError):\n            raise ValueError(\"foo\")\n

        Use instead:

        import unittest\nimport pytest\n\n\nclass TestFoo(unittest.TestCase):\n    def test_foo(self):\n        with pytest.raises(ValueError):\n            raise ValueError(\"foo\")\n
        ","tags":["PT027"]},{"location":"rules/pytest-unittest-raises-assertion/#references","title":"References","text":"
        • pytest documentation: Assertions about expected exceptions
        ","tags":["PT027"]},{"location":"rules/pytest-unnecessary-asyncio-mark-on-fixture/","title":"pytest-unnecessary-asyncio-mark-on-fixture (PT024)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT024"]},{"location":"rules/pytest-unnecessary-asyncio-mark-on-fixture/#what-it-does","title":"What it does","text":"

        Checks for unnecessary @pytest.mark.asyncio decorators applied to fixtures.

        ","tags":["PT024"]},{"location":"rules/pytest-unnecessary-asyncio-mark-on-fixture/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.mark.asyncio is unnecessary for fixtures.

        ","tags":["PT024"]},{"location":"rules/pytest-unnecessary-asyncio-mark-on-fixture/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.mark.asyncio()\n@pytest.fixture()\nasync def my_fixture():\n    return 0\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\nasync def my_fixture():\n    return 0\n
        ","tags":["PT024"]},{"location":"rules/pytest-unnecessary-asyncio-mark-on-fixture/#references","title":"References","text":"
        • PyPI: pytest-asyncio
        ","tags":["PT024"]},{"location":"rules/pytest-use-fixtures-without-parameters/","title":"pytest-use-fixtures-without-parameters (PT026)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT026"]},{"location":"rules/pytest-use-fixtures-without-parameters/#what-it-does","title":"What it does","text":"

        Checks for @pytest.mark.usefixtures() decorators that aren't passed any arguments.

        ","tags":["PT026"]},{"location":"rules/pytest-use-fixtures-without-parameters/#why-is-this-bad","title":"Why is this bad?","text":"

        A @pytest.mark.usefixtures() decorator that isn't passed any arguments is useless and should be removed.

        ","tags":["PT026"]},{"location":"rules/pytest-use-fixtures-without-parameters/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.mark.usefixtures()\ndef test_something(): ...\n

        Use instead:

        def test_something(): ...\n
        ","tags":["PT026"]},{"location":"rules/pytest-use-fixtures-without-parameters/#references","title":"References","text":"
        • pytest documentation: pytest.mark.usefixtures
        ","tags":["PT026"]},{"location":"rules/pytest-useless-yield-fixture/","title":"pytest-useless-yield-fixture (PT022)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT022"]},{"location":"rules/pytest-useless-yield-fixture/#what-it-does","title":"What it does","text":"

        Checks for unnecessary yield expressions in pytest fixtures.

        ","tags":["PT022"]},{"location":"rules/pytest-useless-yield-fixture/#why-is-this-bad","title":"Why is this bad?","text":"

        In pytest fixtures, the yield expression should only be used for fixtures that include teardown code, to clean up the fixture after the test function has finished executing.

        ","tags":["PT022"]},{"location":"rules/pytest-useless-yield-fixture/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef my_fixture():\n    resource = acquire_resource()\n    yield resource\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef my_fixture_with_teardown():\n    resource = acquire_resource()\n    yield resource\n    resource.release()\n\n\n@pytest.fixture()\ndef my_fixture_without_teardown():\n    resource = acquire_resource()\n    return resource\n
        ","tags":["PT022"]},{"location":"rules/pytest-useless-yield-fixture/#references","title":"References","text":"
        • pytest documentation: Teardown/Cleanup
        ","tags":["PT022"]},{"location":"rules/pytest-warns-too-broad/","title":"pytest-warns-too-broad (PT030)","text":"

        Derived from the flake8-pytest-style linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PT030"]},{"location":"rules/pytest-warns-too-broad/#what-it-does","title":"What it does","text":"

        Checks for pytest.warns calls without a match parameter.

        ","tags":["PT030"]},{"location":"rules/pytest-warns-too-broad/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.warns(Warning) will catch any Warning and may catch warnings that are unrelated to the code under test. To avoid this, pytest.warns should be called with a match parameter. The warning names that require a match parameter can be configured via the lint.flake8-pytest-style.warns-require-match-for and lint.flake8-pytest-style.warns-extend-require-match-for settings.

        ","tags":["PT030"]},{"location":"rules/pytest-warns-too-broad/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    with pytest.warns(RuntimeWarning):\n        ...\n\n    # empty string is also an error\n    with pytest.warns(RuntimeWarning, match=\"\"):\n        ...\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    with pytest.warns(RuntimeWarning, match=\"expected message\"):\n        ...\n
        ","tags":["PT030"]},{"location":"rules/pytest-warns-too-broad/#options","title":"Options","text":"
        • lint.flake8-pytest-style.warns-require-match-for
        • lint.flake8-pytest-style.warns-extend-require-match-for
        ","tags":["PT030"]},{"location":"rules/pytest-warns-too-broad/#references","title":"References","text":"
        • pytest documentation: pytest.warns
        ","tags":["PT030"]},{"location":"rules/pytest-warns-with-multiple-statements/","title":"pytest-warns-with-multiple-statements (PT031)","text":"

        Derived from the flake8-pytest-style linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PT031"]},{"location":"rules/pytest-warns-with-multiple-statements/#what-it-does","title":"What it does","text":"

        Checks for pytest.warns context managers with multiple statements.

        This rule allows pytest.warns bodies to contain for loops with empty bodies (e.g., pass or ... statements), to test iterator behavior.

        ","tags":["PT031"]},{"location":"rules/pytest-warns-with-multiple-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        When pytest.warns is used as a context manager and contains multiple statements, it can lead to the test passing when it should instead fail.

        A pytest.warns context manager should only contain a single simple statement that triggers the expected warning.

        ","tags":["PT031"]},{"location":"rules/pytest-warns-with-multiple-statements/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo_warns():\n    with pytest.warns(Warning):\n        setup()  # False negative if setup triggers a warning but foo does not.\n        foo()\n

        Use instead:

        import pytest\n\n\ndef test_foo_warns():\n    setup()\n    with pytest.warns(Warning):\n        foo()\n
        ","tags":["PT031"]},{"location":"rules/pytest-warns-with-multiple-statements/#references","title":"References","text":"
        • pytest documentation: pytest.warns
        ","tags":["PT031"]},{"location":"rules/pytest-warns-without-warning/","title":"pytest-warns-without-warning (PT029)","text":"

        Derived from the flake8-pytest-style linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PT029"]},{"location":"rules/pytest-warns-without-warning/#what-it-does","title":"What it does","text":"

        Checks for pytest.warns calls without an expected warning.

        ","tags":["PT029"]},{"location":"rules/pytest-warns-without-warning/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.warns expects to receive an expected warning as its first argument. If omitted, the pytest.warns call will fail at runtime.

        ","tags":["PT029"]},{"location":"rules/pytest-warns-without-warning/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    with pytest.warns():\n        do_something()\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    with pytest.warns(SomeWarning):\n        do_something()\n
        ","tags":["PT029"]},{"location":"rules/pytest-warns-without-warning/#references","title":"References","text":"
        • pytest documentation: pytest.warns
        ","tags":["PT029"]},{"location":"rules/quadratic-list-summation/","title":"quadratic-list-summation (RUF017)","text":"

        Fix is always available.

        ","tags":["RUF017"]},{"location":"rules/quadratic-list-summation/#what-it-does","title":"What it does","text":"

        Checks for the use of sum() to flatten lists of lists, which has quadratic complexity.

        ","tags":["RUF017"]},{"location":"rules/quadratic-list-summation/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of sum() to flatten lists of lists is quadratic in the number of lists, as sum() creates a new list for each element in the summation.

        Instead, consider using another method of flattening lists to avoid quadratic complexity. The following methods are all linear in the number of lists:

        • functools.reduce(operator.iadd, lists, [])
        • list(itertools.chain.from_iterable(lists))
        • [item for sublist in lists for item in sublist]

        When fixing relevant violations, Ruff defaults to the functools.reduce form, which outperforms the other methods in microbenchmarks.

        ","tags":["RUF017"]},{"location":"rules/quadratic-list-summation/#example","title":"Example","text":"
        lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\njoined = sum(lists, [])\n

        Use instead:

        import functools\nimport operator\n\n\nlists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\nfunctools.reduce(operator.iadd, lists, [])\n
        ","tags":["RUF017"]},{"location":"rules/quadratic-list-summation/#fix-safety","title":"Fix safety","text":"

        This fix is always marked as unsafe because sum uses the __add__ magic method while operator.iadd uses the __iadd__ magic method, and these behave differently on lists. The former requires the right summand to be a list, whereas the latter allows for any iterable. Therefore, the fix could inadvertently cause code that previously raised an error to silently succeed. Moreover, the fix could remove comments from the original code.

        ","tags":["RUF017"]},{"location":"rules/quadratic-list-summation/#references","title":"References","text":"
        • How Not to Flatten a List of Lists in Python
        • How do I make a flat list out of a list of lists?
        ","tags":["RUF017"]},{"location":"rules/quoted-annotation-in-stub/","title":"quoted-annotation-in-stub (PYI020)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI020"]},{"location":"rules/quoted-annotation-in-stub/#what-it-does","title":"What it does","text":"

        Checks for quoted type annotations in stub (.pyi) files, which should be avoided.

        ","tags":["PYI020"]},{"location":"rules/quoted-annotation-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files natively support forward references in all contexts, as stubs are never executed at runtime. (They should be thought of as \"data files\" for type checkers and IDEs.) As such, quotes are never required for type annotations in stub files, and should be omitted.

        ","tags":["PYI020"]},{"location":"rules/quoted-annotation-in-stub/#example","title":"Example","text":"
        def function() -> \"int\": ...\n

        Use instead:

        def function() -> int: ...\n
        ","tags":["PYI020"]},{"location":"rules/quoted-annotation-in-stub/#references","title":"References","text":"
        • Typing documentation - Writing and Maintaining Stub Files
        ","tags":["PYI020"]},{"location":"rules/quoted-annotation/","title":"quoted-annotation (UP037)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP037"]},{"location":"rules/quoted-annotation/#what-it-does","title":"What it does","text":"

        Checks for the presence of unnecessary quotes in type annotations.

        ","tags":["UP037"]},{"location":"rules/quoted-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, type annotations can be quoted to avoid forward references.

        However, if from __future__ import annotations is present, Python will always evaluate type annotations in a deferred manner, making the quotes unnecessary.

        Similarly, if the annotation is located in a typing-only context and won't be evaluated by Python at runtime, the quotes will also be considered unnecessary. For example, Python does not evaluate type annotations on assignments in function bodies.

        ","tags":["UP037"]},{"location":"rules/quoted-annotation/#example","title":"Example","text":"

        Given:

        from __future__ import annotations\n\n\ndef foo(bar: \"Bar\") -> \"Bar\": ...\n

        Use instead:

        from __future__ import annotations\n\n\ndef foo(bar: Bar) -> Bar: ...\n

        Given:

        def foo() -> None:\n    bar: \"Bar\"\n

        Use instead:

        def foo() -> None:\n    bar: Bar\n
        ","tags":["UP037"]},{"location":"rules/quoted-annotation/#see-also","title":"See also","text":"
        • quoted-annotation-in-stub: A rule that removes all quoted annotations from stub files
        • quoted-type-alias: A rule that removes unnecessary quotes from type aliases.
        ","tags":["UP037"]},{"location":"rules/quoted-annotation/#references","title":"References","text":"
        • PEP 563 \u2013 Postponed Evaluation of Annotations
        • Python documentation: __future__
        ","tags":["UP037"]},{"location":"rules/quoted-type-alias/","title":"quoted-type-alias (TC008)","text":"

        Derived from the flake8-type-checking linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#what-it-does","title":"What it does","text":"

        Checks for unnecessary quotes in PEP 613 explicit type aliases and PEP 695 type statements.

        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        Unnecessary string forward references can lead to additional overhead in runtime libraries making use of type hints. They can also have bad interactions with other runtime uses like PEP 604 type unions.

        PEP-613 type aliases are only flagged by the rule if Ruff can have high confidence that the quotes are unnecessary. Specifically, any PEP-613 type alias where the type expression on the right-hand side contains subscripts or attribute accesses will not be flagged. This is because type aliases can reference types that are, for example, generic in stub files but not at runtime. That can mean that a type checker expects the referenced type to be subscripted with type arguments despite the fact that doing so would fail at runtime if the type alias value was not quoted. Similarly, a type alias might need to reference a module-level attribute that exists in a stub file but not at runtime, meaning that the type alias value would need to be quoted to avoid a runtime error.

        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#example","title":"Example","text":"

        Given:

        OptInt: TypeAlias = \"int | None\"\n

        Use instead:

        OptInt: TypeAlias = int | None\n

        Given:

        type OptInt = \"int | None\"\n

        Use instead:

        type OptInt = int | None\n
        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the type annotation contains comments.

        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#see-also","title":"See also","text":"

        This rule only applies to type aliases in non-stub files. For removing quotes in other contexts or in stub files, see:

        • quoted-annotation-in-stub: A rule that removes all quoted annotations from stub files
        • quoted-annotation: A rule that removes unnecessary quotes from annotations in runtime files.
        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#references","title":"References","text":"
        • PEP 613 \u2013 Explicit Type Aliases
        • PEP 695: Generic Type Alias
        • PEP 604 \u2013 Allow writing union types as X | Y
        ","tags":["TC008"]},{"location":"rules/raise-literal/","title":"raise-literal (B016)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B016"]},{"location":"rules/raise-literal/#what-it-does","title":"What it does","text":"

        Checks for raise statements that raise a literal value.

        ","tags":["B016"]},{"location":"rules/raise-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        raise must be followed by an exception instance or an exception class, and exceptions must be instances of BaseException or a subclass thereof. Raising a literal will raise a TypeError at runtime.

        ","tags":["B016"]},{"location":"rules/raise-literal/#example","title":"Example","text":"
        raise \"foo\"\n

        Use instead:

        raise Exception(\"foo\")\n
        ","tags":["B016"]},{"location":"rules/raise-literal/#references","title":"References","text":"
        • Python documentation: raise statement
        ","tags":["B016"]},{"location":"rules/raise-not-implemented/","title":"raise-not-implemented (F901)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F901"]},{"location":"rules/raise-not-implemented/#what-it-does","title":"What it does","text":"

        Checks for raise statements that raise NotImplemented.

        ","tags":["F901"]},{"location":"rules/raise-not-implemented/#why-is-this-bad","title":"Why is this bad?","text":"

        NotImplemented is an exception used by binary special methods to indicate that an operation is not implemented with respect to a particular type.

        NotImplemented should not be raised directly. Instead, raise NotImplementedError, which is used to indicate that the method is abstract or not implemented in the derived class.

        ","tags":["F901"]},{"location":"rules/raise-not-implemented/#example","title":"Example","text":"
        class Foo:\n    def bar(self):\n        raise NotImplemented\n

        Use instead:

        class Foo:\n    def bar(self):\n        raise NotImplementedError\n
        ","tags":["F901"]},{"location":"rules/raise-not-implemented/#references","title":"References","text":"
        • Python documentation: NotImplemented
        • Python documentation: NotImplementedError
        ","tags":["F901"]},{"location":"rules/raise-vanilla-args/","title":"raise-vanilla-args (TRY003)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY003"]},{"location":"rules/raise-vanilla-args/#what-it-does","title":"What it does","text":"

        Checks for long exception messages that are not defined in the exception class itself.

        ","tags":["TRY003"]},{"location":"rules/raise-vanilla-args/#why-is-this-bad","title":"Why is this bad?","text":"

        By formatting an exception message at the raise site, the exception class becomes less reusable, and may now raise inconsistent messages depending on where it is raised.

        If the exception message is instead defined within the exception class, it will be consistent across all raise invocations.

        This rule is not enforced for some built-in exceptions that are commonly raised with a message and would be unusual to subclass, such as NotImplementedError.

        ","tags":["TRY003"]},{"location":"rules/raise-vanilla-args/#example","title":"Example","text":"
        class CantBeNegative(Exception):\n    pass\n\n\ndef foo(x):\n    if x < 0:\n        raise CantBeNegative(f\"{x} is negative\")\n

        Use instead:

        class CantBeNegative(Exception):\n    def __init__(self, number):\n        super().__init__(f\"{number} is negative\")\n\n\ndef foo(x):\n    if x < 0:\n        raise CantBeNegative(x)\n
        ","tags":["TRY003"]},{"location":"rules/raise-vanilla-class/","title":"raise-vanilla-class (TRY002)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY002"]},{"location":"rules/raise-vanilla-class/#what-it-does","title":"What it does","text":"

        Checks for code that raises Exception or BaseException directly.

        ","tags":["TRY002"]},{"location":"rules/raise-vanilla-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Handling such exceptions requires the use of except Exception or except BaseException. These will capture almost any raised exception, including failed assertions, division by zero, and more.

        Prefer to raise your own exception, or a more specific built-in exception, so that you can avoid over-capturing exceptions that you don't intend to handle.

        ","tags":["TRY002"]},{"location":"rules/raise-vanilla-class/#example","title":"Example","text":"
        def main_function():\n    if not cond:\n        raise Exception()\n\n\ndef consumer_func():\n    try:\n        do_step()\n        prepare()\n        main_function()\n    except Exception:\n        logger.error(\"Oops\")\n

        Use instead:

        def main_function():\n    if not cond:\n        raise CustomException()\n\n\ndef consumer_func():\n    try:\n        do_step()\n        prepare()\n        main_function()\n    except CustomException:\n        logger.error(\"Main function failed\")\n    except Exception:\n        logger.error(\"Oops\")\n
        ","tags":["TRY002"]},{"location":"rules/raise-within-try/","title":"raise-within-try (TRY301)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY301"]},{"location":"rules/raise-within-try/#what-it-does","title":"What it does","text":"

        Checks for raise statements within try blocks. The only raises caught are those that throw exceptions caught by the try statement itself.

        ","tags":["TRY301"]},{"location":"rules/raise-within-try/#why-is-this-bad","title":"Why is this bad?","text":"

        Raising and catching exceptions within the same try block is redundant, as the code can be refactored to avoid the try block entirely.

        Alternatively, the raise can be moved within an inner function, making the exception reusable across multiple call sites.

        ","tags":["TRY301"]},{"location":"rules/raise-within-try/#example","title":"Example","text":"
        def bar():\n    pass\n\n\ndef foo():\n    try:\n        a = bar()\n        if not a:\n            raise ValueError\n    except ValueError:\n        raise\n

        Use instead:

        def bar():\n    raise ValueError\n\n\ndef foo():\n    try:\n        a = bar()  # refactored `bar` to raise `ValueError`\n    except ValueError:\n        raise\n
        ","tags":["TRY301"]},{"location":"rules/raise-without-from-inside-except/","title":"raise-without-from-inside-except (B904)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B904"]},{"location":"rules/raise-without-from-inside-except/#what-it-does","title":"What it does","text":"

        Checks for raise statements in exception handlers that lack a from clause.

        ","tags":["B904"]},{"location":"rules/raise-without-from-inside-except/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, raise can be used with or without an exception from which the current exception is derived. This is known as exception chaining. When printing the stack trace, chained exceptions are displayed in such a way so as make it easier to trace the exception back to its root cause.

        When raising an exception from within an except clause, always include a from clause to facilitate exception chaining. If the exception is not chained, it will be difficult to trace the exception back to its root cause.

        ","tags":["B904"]},{"location":"rules/raise-without-from-inside-except/#example","title":"Example","text":"
        try:\n    ...\nexcept FileNotFoundError:\n    if ...:\n        raise RuntimeError(\"...\")\n    else:\n        raise UserWarning(\"...\")\n

        Use instead:

        try:\n    ...\nexcept FileNotFoundError as exc:\n    if ...:\n        raise RuntimeError(\"...\") from None\n    else:\n        raise UserWarning(\"...\") from exc\n
        ","tags":["B904"]},{"location":"rules/raise-without-from-inside-except/#references","title":"References","text":"
        • Python documentation: raise statement
        ","tags":["B904"]},{"location":"rules/raw-string-in-exception/","title":"raw-string-in-exception (EM101)","text":"

        Derived from the flake8-errmsg linter.

        Fix is sometimes available.

        ","tags":["EM101"]},{"location":"rules/raw-string-in-exception/#what-it-does","title":"What it does","text":"

        Checks for the use of string literals in exception constructors.

        ","tags":["EM101"]},{"location":"rules/raw-string-in-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Python includes the raise in the default traceback (and formatters like Rich and IPython do too).

        By using a string literal, the error message will be duplicated in the traceback, which can make the traceback less readable.

        ","tags":["EM101"]},{"location":"rules/raw-string-in-exception/#example","title":"Example","text":"

        Given:

        raise RuntimeError(\"'Some value' is incorrect\")\n

        Python will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 2, in <module>\n    raise RuntimeError(\"'Some value' is incorrect\")\nRuntimeError: 'Some value' is incorrect\n

        Instead, assign the string to a variable:

        msg = \"'Some value' is incorrect\"\nraise RuntimeError(msg)\n

        Which will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 3, in <module>\n    raise RuntimeError(msg)\nRuntimeError: 'Some value' is incorrect\n
        ","tags":["EM101"]},{"location":"rules/re-sub-positional-args/","title":"re-sub-positional-args (B034)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B034"]},{"location":"rules/re-sub-positional-args/#what-it-does","title":"What it does","text":"

        Checks for calls to re.sub, re.subn, and re.split that pass count, maxsplit, or flags as positional arguments.

        ","tags":["B034"]},{"location":"rules/re-sub-positional-args/#why-is-this-bad","title":"Why is this bad?","text":"

        Passing count, maxsplit, or flags as positional arguments to re.sub, re.subn, or re.split can lead to confusion, as most methods in the re module accept flags as the third positional argument, while re.sub, re.subn, and re.split have different signatures.

        Instead, pass count, maxsplit, and flags as keyword arguments.

        ","tags":["B034"]},{"location":"rules/re-sub-positional-args/#example","title":"Example","text":"
        import re\n\nre.split(\"pattern\", \"replacement\", 1)\n

        Use instead:

        import re\n\nre.split(\"pattern\", \"replacement\", maxsplit=1)\n
        ","tags":["B034"]},{"location":"rules/re-sub-positional-args/#references","title":"References","text":"
        • Python documentation: re.sub
        • Python documentation: re.subn
        • Python documentation: re.split
        ","tags":["B034"]},{"location":"rules/read-whole-file/","title":"read-whole-file (FURB101)","text":"

        Derived from the refurb linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB101"]},{"location":"rules/read-whole-file/#what-it-does","title":"What it does","text":"

        Checks for uses of open and read that can be replaced by pathlib methods, like Path.read_text and Path.read_bytes.

        ","tags":["FURB101"]},{"location":"rules/read-whole-file/#why-is-this-bad","title":"Why is this bad?","text":"

        When reading the entire contents of a file into a variable, it's simpler and more concise to use pathlib methods like Path.read_text and Path.read_bytes instead of open and read calls via with statements.

        ","tags":["FURB101"]},{"location":"rules/read-whole-file/#example","title":"Example","text":"
        with open(filename) as f:\n    contents = f.read()\n

        Use instead:

        from pathlib import Path\n\ncontents = Path(filename).read_text()\n
        ","tags":["FURB101"]},{"location":"rules/read-whole-file/#references","title":"References","text":"
        • Python documentation: Path.read_bytes
        • Python documentation: Path.read_text
        ","tags":["FURB101"]},{"location":"rules/readlines-in-for/","title":"readlines-in-for (FURB129)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB129"]},{"location":"rules/readlines-in-for/#what-it-does","title":"What it does","text":"

        Checks for uses of readlines() when iterating over a file line-by-line.

        ","tags":["FURB129"]},{"location":"rules/readlines-in-for/#why-is-this-bad","title":"Why is this bad?","text":"

        Rather than iterating over all lines in a file by calling readlines(), it's more convenient and performant to iterate over the file object directly.

        ","tags":["FURB129"]},{"location":"rules/readlines-in-for/#example","title":"Example","text":"
        with open(\"file.txt\") as fp:\n    for line in fp.readlines():\n        ...\n

        Use instead:

        with open(\"file.txt\") as fp:\n    for line in fp:\n        ...\n
        ","tags":["FURB129"]},{"location":"rules/readlines-in-for/#references","title":"References","text":"
        • Python documentation: io.IOBase.readlines
        ","tags":["FURB129"]},{"location":"rules/redeclared-assigned-name/","title":"redeclared-assigned-name (PLW0128)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0128"]},{"location":"rules/redeclared-assigned-name/#what-it-does","title":"What it does","text":"

        Checks for declared assignments to the same variable multiple times in the same assignment.

        ","tags":["PLW0128"]},{"location":"rules/redeclared-assigned-name/#why-is-this-bad","title":"Why is this bad?","text":"

        Assigning a variable multiple times in the same assignment is redundant, as the final assignment to the variable is what the value will be.

        ","tags":["PLW0128"]},{"location":"rules/redeclared-assigned-name/#example","title":"Example","text":"
        a, b, a = (1, 2, 3)\nprint(a)  # 3\n

        Use instead:

        # this is assuming you want to assign 3 to `a`\n_, b, a = (1, 2, 3)\nprint(a)  # 3\n
        ","tags":["PLW0128"]},{"location":"rules/redefined-argument-from-local/","title":"redefined-argument-from-local (PLR1704)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR1704"]},{"location":"rules/redefined-argument-from-local/#what-it-does","title":"What it does","text":"

        Checks for variables defined in for, try, with statements that redefine function parameters.

        ","tags":["PLR1704"]},{"location":"rules/redefined-argument-from-local/#why-is-this-bad","title":"Why is this bad?","text":"

        Redefined variables can cause unexpected behavior because of overridden function parameters. If nested functions are declared, an inner function's body can override an outer function's parameters.

        ","tags":["PLR1704"]},{"location":"rules/redefined-argument-from-local/#example","title":"Example","text":"
        def show(host_id=10.11):\n    for host_id, host in [[12.13, \"Venus\"], [14.15, \"Mars\"]]:\n        print(host_id, host)\n

        Use instead:

        def show(host_id=10.11):\n    for inner_host_id, host in [[12.13, \"Venus\"], [14.15, \"Mars\"]]:\n        print(host_id, inner_host_id, host)\n
        ","tags":["PLR1704"]},{"location":"rules/redefined-argument-from-local/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["PLR1704"]},{"location":"rules/redefined-argument-from-local/#references","title":"References","text":"
        • Pylint documentation
        ","tags":["PLR1704"]},{"location":"rules/redefined-loop-name/","title":"redefined-loop-name (PLW2901)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW2901"]},{"location":"rules/redefined-loop-name/#what-it-does","title":"What it does","text":"

        Checks for variables defined in for loops and with statements that get overwritten within the body, for example by another for loop or with statement or by direct assignment.

        ","tags":["PLW2901"]},{"location":"rules/redefined-loop-name/#why-is-this-bad","title":"Why is this bad?","text":"

        Redefinition of a loop variable inside the loop's body causes its value to differ from the original loop iteration for the remainder of the block, in a way that will likely cause bugs.

        In Python, unlike many other languages, for loops and with statements don't define their own scopes. Therefore, a nested loop that uses the same target variable name as an outer loop will reuse the same actual variable, and the value from the last iteration will \"leak out\" into the remainder of the enclosing loop.

        While this mistake is easy to spot in small examples, it can be hidden in larger blocks of code, where the definition and redefinition of the variable may not be visible at the same time.

        ","tags":["PLW2901"]},{"location":"rules/redefined-loop-name/#example","title":"Example","text":"
        for i in range(10):\n    i = 9\n    print(i)  # prints 9 every iteration\n\nfor i in range(10):\n    for i in range(10):  # original value overwritten\n        pass\n    print(i)  # also prints 9 every iteration\n\nwith path1.open() as f:\n    with path2.open() as f:\n        f = path2.open()\n    print(f.readline())  # prints a line from path2\n
        ","tags":["PLW2901"]},{"location":"rules/redefined-slots-in-subclass/","title":"redefined-slots-in-subclass (PLW0244)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW0244"]},{"location":"rules/redefined-slots-in-subclass/#what-it-does","title":"What it does","text":"

        Checks for a re-defined slot in a subclass.

        ","tags":["PLW0244"]},{"location":"rules/redefined-slots-in-subclass/#why-is-this-bad","title":"Why is this bad?","text":"

        If a class defines a slot also defined in a base class, the instance variable defined by the base class slot is inaccessible (except by retrieving its descriptor directly from the base class).

        ","tags":["PLW0244"]},{"location":"rules/redefined-slots-in-subclass/#example","title":"Example","text":"
        class Base:\n    __slots__ = (\"a\", \"b\")\n\n\nclass Subclass(Base):\n    __slots__ = (\"a\", \"d\")  # slot \"a\" redefined\n

        Use instead:

        class Base:\n    __slots__ = (\"a\", \"b\")\n\n\nclass Subclass(Base):\n    __slots__ = \"d\"\n
        ","tags":["PLW0244"]},{"location":"rules/redefined-while-unused/","title":"redefined-while-unused (F811)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F811"]},{"location":"rules/redefined-while-unused/#what-it-does","title":"What it does","text":"

        Checks for variable definitions that redefine (or \"shadow\") unused variables.

        ","tags":["F811"]},{"location":"rules/redefined-while-unused/#why-is-this-bad","title":"Why is this bad?","text":"

        Redefinitions of unused names are unnecessary and often indicative of a mistake.

        ","tags":["F811"]},{"location":"rules/redefined-while-unused/#example","title":"Example","text":"
        import foo\nimport bar\nimport foo  # Redefinition of unused `foo` from line 1\n

        Use instead:

        import foo\nimport bar\n
        ","tags":["F811"]},{"location":"rules/redirected-noqa/","title":"redirected-noqa (RUF101)","text":"

        Fix is always available.

        ","tags":["RUF101"]},{"location":"rules/redirected-noqa/#what-it-does","title":"What it does","text":"

        Checks for noqa directives that use redirected rule codes.

        ","tags":["RUF101"]},{"location":"rules/redirected-noqa/#why-is-this-bad","title":"Why is this bad?","text":"

        When one of Ruff's rule codes has been redirected, the implication is that the rule has been deprecated in favor of another rule or code. To keep your codebase consistent and up-to-date, prefer the canonical rule code over the deprecated code.

        ","tags":["RUF101"]},{"location":"rules/redirected-noqa/#example","title":"Example","text":"
        x = eval(command)  # noqa: PGH001\n

        Use instead:

        x = eval(command)  # noqa: S307\n
        ","tags":["RUF101"]},{"location":"rules/redundant-backslash/","title":"redundant-backslash (E502)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E502"]},{"location":"rules/redundant-backslash/#what-it-does","title":"What it does","text":"

        Checks for redundant backslashes between brackets.

        ","tags":["E502"]},{"location":"rules/redundant-backslash/#why-is-this-bad","title":"Why is this bad?","text":"

        Explicit line joins using a backslash are redundant between brackets.

        ","tags":["E502"]},{"location":"rules/redundant-backslash/#example","title":"Example","text":"
        x = (2 + \\\n    2)\n

        Use instead:

        x = (2 +\n    2)\n
        ","tags":["E502"]},{"location":"rules/redundant-bool-literal/","title":"redundant-bool-literal (RUF038)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF038"]},{"location":"rules/redundant-bool-literal/#what-it-does","title":"What it does","text":"

        Checks for Literal[True, False] type annotations.

        ","tags":["RUF038"]},{"location":"rules/redundant-bool-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        Literal[True, False] can be replaced with bool in type annotations, which has the same semantic meaning but is more concise and readable.

        bool type has exactly two constant instances: True and False. Static type checkers such as mypy treat Literal[True, False] as equivalent to bool in a type annotation.

        ","tags":["RUF038"]},{"location":"rules/redundant-bool-literal/#example","title":"Example","text":"
        from typing import Literal\n\nx: Literal[True, False]\ny: Literal[True, False, \"hello\", \"world\"]\n

        Use instead:

        from typing import Literal\n\nx: bool\ny: Literal[\"hello\", \"world\"] | bool\n
        ","tags":["RUF038"]},{"location":"rules/redundant-bool-literal/#fix-safety","title":"Fix safety","text":"

        The fix for this rule is marked as unsafe, as it may change the semantics of the code. Specifically:

        • Type checkers may not treat bool as equivalent when overloading boolean arguments with Literal[True] and Literal[False] (see, e.g., #14764 and #5421).
        • bool is not strictly equivalent to Literal[True, False], as bool is a subclass of int, and this rule may not apply if the type annotations are used in a numeric context.

        Further, the Literal slice may contain trailing-line comments which the fix would remove.

        ","tags":["RUF038"]},{"location":"rules/redundant-bool-literal/#references","title":"References","text":"
        • Typing documentation: Legal parameters for Literal at type check time
        • Python documentation: Boolean type - bool
        ","tags":["RUF038"]},{"location":"rules/redundant-final-literal/","title":"redundant-final-literal (PYI064)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI064"]},{"location":"rules/redundant-final-literal/#what-it-does","title":"What it does","text":"

        Checks for redundant Final[Literal[...]] annotations.

        ","tags":["PYI064"]},{"location":"rules/redundant-final-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        All constant variables annotated as Final are understood as implicitly having Literal types by a type checker. As such, a Final[Literal[...]] annotation can often be replaced with a bare Final, annotation, which will have the same meaning to the type checker while being more concise and more readable.

        ","tags":["PYI064"]},{"location":"rules/redundant-final-literal/#example","title":"Example","text":"
        from typing import Final, Literal\n\nx: Final[Literal[42]]\ny: Final[Literal[42]] = 42\n

        Use instead:

        from typing import Final, Literal\n\nx: Final = 42\ny: Final = 42\n
        ","tags":["PYI064"]},{"location":"rules/redundant-literal-union/","title":"redundant-literal-union (PYI051)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI051"]},{"location":"rules/redundant-literal-union/#what-it-does","title":"What it does","text":"

        Checks for redundant unions between a Literal and a builtin supertype of that Literal.

        ","tags":["PYI051"]},{"location":"rules/redundant-literal-union/#why-is-this-bad","title":"Why is this bad?","text":"

        Using a Literal type in a union with its builtin supertype is redundant, as the supertype will be strictly more general than the Literal type. For example, Literal[\"A\"] | str is equivalent to str, and Literal[1] | int is equivalent to int, as str and int are the supertypes of \"A\" and 1 respectively.

        ","tags":["PYI051"]},{"location":"rules/redundant-literal-union/#example","title":"Example","text":"
        from typing import Literal\n\nx: Literal[\"A\", b\"B\"] | str\n

        Use instead:

        from typing import Literal\n\nx: Literal[b\"B\"] | str\n
        ","tags":["PYI051"]},{"location":"rules/redundant-log-base/","title":"redundant-log-base (FURB163)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB163"]},{"location":"rules/redundant-log-base/#what-it-does","title":"What it does","text":"

        Checks for math.log calls with a redundant base.

        ","tags":["FURB163"]},{"location":"rules/redundant-log-base/#why-is-this-bad","title":"Why is this bad?","text":"

        The default base of math.log is e, so specifying it explicitly is redundant.

        Instead of passing 2 or 10 as the base, use math.log2 or math.log10 respectively, as these dedicated variants are typically more accurate than math.log.

        ","tags":["FURB163"]},{"location":"rules/redundant-log-base/#example","title":"Example","text":"
        import math\n\nmath.log(4, math.e)\nmath.log(4, 2)\nmath.log(4, 10)\n

        Use instead:

        import math\n\nmath.log(4)\nmath.log2(4)\nmath.log10(4)\n
        ","tags":["FURB163"]},{"location":"rules/redundant-log-base/#references","title":"References","text":"
        • Python documentation: math.log
        • Python documentation: math.log2
        • Python documentation: math.log10
        • Python documentation: math.e
        ","tags":["FURB163"]},{"location":"rules/redundant-none-literal/","title":"redundant-none-literal (PYI061)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PYI061"]},{"location":"rules/redundant-none-literal/#what-it-does","title":"What it does","text":"

        Checks for redundant Literal[None] annotations.

        ","tags":["PYI061"]},{"location":"rules/redundant-none-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        While Literal[None] is a valid type annotation, it is semantically equivalent to None. Prefer None over Literal[None] for both consistency and readability.

        ","tags":["PYI061"]},{"location":"rules/redundant-none-literal/#example","title":"Example","text":"
        from typing import Literal\n\nLiteral[None]\nLiteral[1, 2, 3, \"foo\", 5, None]\n

        Use instead:

        from typing import Literal\n\nNone\nLiteral[1, 2, 3, \"foo\", 5] | None\n
        ","tags":["PYI061"]},{"location":"rules/redundant-none-literal/#fix-safety-and-availability","title":"Fix safety and availability","text":"

        This rule's fix is marked as safe unless the literal contains comments.

        There is currently no fix available when applying the fix would lead to a TypeError from an expression of the form None | None or when we are unable to import the symbol typing.Optional and the Python version is 3.9 or below.

        ","tags":["PYI061"]},{"location":"rules/redundant-none-literal/#references","title":"References","text":"
        • Typing documentation: Legal parameters for Literal at type check time
        ","tags":["PYI061"]},{"location":"rules/redundant-numeric-union/","title":"redundant-numeric-union (PYI041)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI041"]},{"location":"rules/redundant-numeric-union/#what-it-does","title":"What it does","text":"

        Checks for parameter annotations that contain redundant unions between builtin numeric types (e.g., int | float).

        ","tags":["PYI041"]},{"location":"rules/redundant-numeric-union/#why-is-this-bad","title":"Why is this bad?","text":"

        The typing specification states:

        Python\u2019s numeric types complex, float and int are not subtypes of each other, but to support common use cases, the type system contains a straightforward shortcut: when an argument is annotated as having type float, an argument of type int is acceptable; similar, for an argument annotated as having type complex, arguments of type float or int are acceptable.

        As such, a union that includes both int and float is redundant in the specific context of a parameter annotation, as it is equivalent to a union that only includes float. For readability and clarity, unions should omit redundant elements.

        ","tags":["PYI041"]},{"location":"rules/redundant-numeric-union/#example","title":"Example","text":"
        def foo(x: float | int | str) -> None: ...\n

        Use instead:

        def foo(x: float | str) -> None: ...\n
        ","tags":["PYI041"]},{"location":"rules/redundant-numeric-union/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the type annotation contains comments.

        Note that while the fix may flatten nested unions into a single top-level union, the semantics of the annotation will remain unchanged.

        ","tags":["PYI041"]},{"location":"rules/redundant-numeric-union/#references","title":"References","text":"
        • Python documentation: The numeric tower
        • PEP 484: The numeric tower
        ","tags":["PYI041"]},{"location":"rules/redundant-open-modes/","title":"redundant-open-modes (UP015)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP015"]},{"location":"rules/redundant-open-modes/#what-it-does","title":"What it does","text":"

        Checks for redundant open mode arguments.

        ","tags":["UP015"]},{"location":"rules/redundant-open-modes/#why-is-this-bad","title":"Why is this bad?","text":"

        Redundant open mode arguments are unnecessary and should be removed to avoid confusion.

        ","tags":["UP015"]},{"location":"rules/redundant-open-modes/#example","title":"Example","text":"
        with open(\"foo.txt\", \"r\") as f:\n    ...\n

        Use instead:

        with open(\"foo.txt\") as f:\n    ...\n
        ","tags":["UP015"]},{"location":"rules/redundant-open-modes/#references","title":"References","text":"
        • Python documentation: open
        ","tags":["UP015"]},{"location":"rules/redundant-tuple-in-exception-handler/","title":"redundant-tuple-in-exception-handler (B013)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B013"]},{"location":"rules/redundant-tuple-in-exception-handler/#what-it-does","title":"What it does","text":"

        Checks for single-element tuples in exception handlers (e.g., except (ValueError,):).

        Note: Single-element tuples consisting of a starred expression are allowed.

        ","tags":["B013"]},{"location":"rules/redundant-tuple-in-exception-handler/#why-is-this-bad","title":"Why is this bad?","text":"

        A tuple with a single element can be more concisely and idiomatically expressed as a single value.

        ","tags":["B013"]},{"location":"rules/redundant-tuple-in-exception-handler/#example","title":"Example","text":"
        try:\n    ...\nexcept (ValueError,):\n    ...\n

        Use instead:

        try:\n    ...\nexcept ValueError:\n    ...\n
        ","tags":["B013"]},{"location":"rules/redundant-tuple-in-exception-handler/#references","title":"References","text":"
        • Python documentation: except clause
        ","tags":["B013"]},{"location":"rules/regex-flag-alias/","title":"regex-flag-alias (FURB167)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB167"]},{"location":"rules/regex-flag-alias/#what-it-does","title":"What it does","text":"

        Checks for the use of shorthand aliases for regular expression flags (e.g., re.I instead of re.IGNORECASE).

        ","tags":["FURB167"]},{"location":"rules/regex-flag-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        The regular expression module provides descriptive names for each flag, along with single-letter aliases. Prefer the descriptive names, as they are more readable and self-documenting.

        ","tags":["FURB167"]},{"location":"rules/regex-flag-alias/#example","title":"Example","text":"
        import re\n\nif re.match(\"^hello\", \"hello world\", re.I):\n    ...\n

        Use instead:

        import re\n\nif re.match(\"^hello\", \"hello world\", re.IGNORECASE):\n    ...\n
        ","tags":["FURB167"]},{"location":"rules/reimplemented-builtin/","title":"reimplemented-builtin (SIM110)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM110"]},{"location":"rules/reimplemented-builtin/#what-it-does","title":"What it does","text":"

        Checks for for loops that can be replaced with a builtin function, like any or all.

        ","tags":["SIM110"]},{"location":"rules/reimplemented-builtin/#why-is-this-bad","title":"Why is this bad?","text":"

        Using a builtin function is more concise and readable.

        ","tags":["SIM110"]},{"location":"rules/reimplemented-builtin/#example","title":"Example","text":"
        for item in iterable:\n    if predicate(item):\n        return True\nreturn False\n

        Use instead:

        return any(predicate(item) for item in iterable)\n
        ","tags":["SIM110"]},{"location":"rules/reimplemented-builtin/#references","title":"References","text":"
        • Python documentation: any
        • Python documentation: all
        ","tags":["SIM110"]},{"location":"rules/reimplemented-container-builtin/","title":"reimplemented-container-builtin (PIE807)","text":"

        Derived from the flake8-pie linter.

        Fix is sometimes available.

        ","tags":["PIE807"]},{"location":"rules/reimplemented-container-builtin/#what-it-does","title":"What it does","text":"

        Checks for lambdas that can be replaced with the list or dict builtins.

        ","tags":["PIE807"]},{"location":"rules/reimplemented-container-builtin/#why-is-this-bad","title":"Why is this bad?","text":"

        Using container builtins are more succinct and idiomatic than wrapping the literal in a lambda.

        ","tags":["PIE807"]},{"location":"rules/reimplemented-container-builtin/#example","title":"Example","text":"
        from dataclasses import dataclass, field\n\n\n@dataclass\nclass Foo:\n    bar: list[int] = field(default_factory=lambda: [])\n

        Use instead:

        from dataclasses import dataclass, field\n\n\n@dataclass\nclass Foo:\n    bar: list[int] = field(default_factory=list)\n    baz: dict[str, int] = field(default_factory=dict)\n
        ","tags":["PIE807"]},{"location":"rules/reimplemented-container-builtin/#references","title":"References","text":"
        • Python documentation: list
        ","tags":["PIE807"]},{"location":"rules/reimplemented-operator/","title":"reimplemented-operator (FURB118)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB118"]},{"location":"rules/reimplemented-operator/#what-it-does","title":"What it does","text":"

        Checks for lambda expressions and function definitions that can be replaced with a function from the operator module.

        ","tags":["FURB118"]},{"location":"rules/reimplemented-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        The operator module provides functions that implement the same functionality as the corresponding operators. For example, operator.add is often equivalent to lambda x, y: x + y. Using the functions from the operator module is more concise and communicates the intent of the code more clearly.

        ","tags":["FURB118"]},{"location":"rules/reimplemented-operator/#example","title":"Example","text":"
        import functools\n\nnums = [1, 2, 3]\ntotal = functools.reduce(lambda x, y: x + y, nums)\n

        Use instead:

        import functools\nimport operator\n\nnums = [1, 2, 3]\ntotal = functools.reduce(operator.add, nums)\n
        ","tags":["FURB118"]},{"location":"rules/reimplemented-operator/#fix-safety","title":"Fix safety","text":"

        The fix offered by this rule is always marked as unsafe. While the changes the fix would make would rarely break your code, there are two ways in which functions from the operator module differ from user-defined functions. It would be non-trivial for Ruff to detect whether or not these differences would matter in a specific situation where Ruff is emitting a diagnostic for this rule.

        The first difference is that operator functions cannot be called with keyword arguments, but most user-defined functions can. If an add function is defined as add = lambda x, y: x + y, replacing this function with operator.add will cause the later call to raise TypeError if the function is later called with keyword arguments, e.g. add(x=1, y=2).

        The second difference is that user-defined functions are descriptors, but this is not true of the functions defined in the operator module. Practically speaking, this means that defining a function in a class body (either by using a def statement or assigning a lambda function to a variable) is a valid way of defining an instance method on that class; monkeypatching a user-defined function onto a class after the class has been created also has the same effect. The same is not true of an operator function: assigning an operator function to a variable in a class body or monkeypatching one onto a class will not create a valid instance method. Ruff will refrain from emitting diagnostics for this rule on function definitions in class bodies; however, it does not currently have sophisticated enough type inference to avoid emitting this diagnostic if a user-defined function is being monkeypatched onto a class after the class has been constructed.

        ","tags":["FURB118"]},{"location":"rules/reimplemented-starmap/","title":"reimplemented-starmap (FURB140)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB140"]},{"location":"rules/reimplemented-starmap/#what-it-does","title":"What it does","text":"

        Checks for generator expressions, list and set comprehensions that can be replaced with itertools.starmap.

        ","tags":["FURB140"]},{"location":"rules/reimplemented-starmap/#why-is-this-bad","title":"Why is this bad?","text":"

        When unpacking values from iterators to pass them directly to a function, prefer itertools.starmap.

        Using itertools.starmap is more concise and readable. Furthermore, it is more efficient than generator expressions, and in some versions of Python, it is more efficient than comprehensions.

        ","tags":["FURB140"]},{"location":"rules/reimplemented-starmap/#known-problems","title":"Known problems","text":"

        Since Python 3.12, itertools.starmap is less efficient than comprehensions (#7771). This is due to PEP 709, which made comprehensions faster.

        ","tags":["FURB140"]},{"location":"rules/reimplemented-starmap/#example","title":"Example","text":"
        all(predicate(a, b) for a, b in some_iterable)\n

        Use instead:

        from itertools import starmap\n\n\nall(starmap(predicate, some_iterable))\n
        ","tags":["FURB140"]},{"location":"rules/reimplemented-starmap/#references","title":"References","text":"
        • Python documentation: itertools.starmap
        ","tags":["FURB140"]},{"location":"rules/relative-imports/","title":"relative-imports (TID252)","text":"

        Derived from the flake8-tidy-imports linter.

        Fix is sometimes available.

        ","tags":["TID252"]},{"location":"rules/relative-imports/#what-it-does","title":"What it does","text":"

        Checks for relative imports.

        ","tags":["TID252"]},{"location":"rules/relative-imports/#why-is-this-bad","title":"Why is this bad?","text":"

        Absolute imports, or relative imports from siblings, are recommended by PEP 8:

        Absolute imports are recommended, as they are usually more readable and tend to be better behaved...

        import mypkg.sibling\nfrom mypkg import sibling\nfrom mypkg.sibling import example\n

        However, explicit relative imports are an acceptable alternative to absolute imports, especially when dealing with complex package layouts where using absolute imports would be unnecessarily verbose:

        from . import sibling\nfrom .sibling import example\n
        ","tags":["TID252"]},{"location":"rules/relative-imports/#example","title":"Example","text":"
        from .. import foo\n

        Use instead:

        from mypkg import foo\n
        ","tags":["TID252"]},{"location":"rules/relative-imports/#options","title":"Options","text":"
        • lint.flake8-tidy-imports.ban-relative-imports
        ","tags":["TID252"]},{"location":"rules/repeated-append/","title":"repeated-append (FURB113)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB113"]},{"location":"rules/repeated-append/#what-it-does","title":"What it does","text":"

        Checks for consecutive calls to append.

        ","tags":["FURB113"]},{"location":"rules/repeated-append/#why-is-this-bad","title":"Why is this bad?","text":"

        Consecutive calls to append can be less efficient than batching them into a single extend. Each append resizes the list individually, whereas an extend can resize the list once for all elements.

        ","tags":["FURB113"]},{"location":"rules/repeated-append/#known-problems","title":"Known problems","text":"

        This rule is prone to false negatives due to type inference limitations, as it will only detect lists that are instantiated as literals or annotated with a type annotation.

        ","tags":["FURB113"]},{"location":"rules/repeated-append/#example","title":"Example","text":"
        nums = [1, 2, 3]\n\nnums.append(4)\nnums.append(5)\nnums.append(6)\n

        Use instead:

        nums = [1, 2, 3]\n\nnums.extend((4, 5, 6))\n
        ","tags":["FURB113"]},{"location":"rules/repeated-append/#references","title":"References","text":"
        • Python documentation: More on Lists
        ","tags":["FURB113"]},{"location":"rules/repeated-equality-comparison/","title":"repeated-equality-comparison (PLR1714)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLR1714"]},{"location":"rules/repeated-equality-comparison/#what-it-does","title":"What it does","text":"

        Checks for repeated equality comparisons that can be rewritten as a membership test.

        This rule will try to determine if the values are hashable and the fix will use a set if they are. If unable to determine, the fix will use a tuple and suggest the use of a set.

        ","tags":["PLR1714"]},{"location":"rules/repeated-equality-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        To check if a variable is equal to one of many values, it is common to write a series of equality comparisons (e.g., foo == \"bar\" or foo == \"baz\").

        Instead, prefer to combine the values into a collection and use the in operator to check for membership, which is more performant and succinct. If the items are hashable, use a set for efficiency; otherwise, use a tuple.

        ","tags":["PLR1714"]},{"location":"rules/repeated-equality-comparison/#example","title":"Example","text":"
        foo == \"bar\" or foo == \"baz\" or foo == \"qux\"\n

        Use instead:

        foo in {\"bar\", \"baz\", \"qux\"}\n
        ","tags":["PLR1714"]},{"location":"rules/repeated-equality-comparison/#references","title":"References","text":"
        • Python documentation: Comparisons
        • Python documentation: Membership test operations
        • Python documentation: set
        ","tags":["PLR1714"]},{"location":"rules/repeated-global/","title":"repeated-global (FURB154)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB154"]},{"location":"rules/repeated-global/#what-it-does","title":"What it does","text":"

        Checks for consecutive global (or nonlocal) statements.

        ","tags":["FURB154"]},{"location":"rules/repeated-global/#why-is-this-bad","title":"Why is this bad?","text":"

        The global and nonlocal keywords accepts multiple comma-separated names. Instead of using multiple global (or nonlocal) statements for separate variables, you can use a single statement to declare multiple variables at once.

        ","tags":["FURB154"]},{"location":"rules/repeated-global/#example","title":"Example","text":"
        def func():\n    global x\n    global y\n\n    print(x, y)\n

        Use instead:

        def func():\n    global x, y\n\n    print(x, y)\n
        ","tags":["FURB154"]},{"location":"rules/repeated-global/#references","title":"References","text":"
        • Python documentation: the global statement
        • Python documentation: the nonlocal statement
        ","tags":["FURB154"]},{"location":"rules/repeated-isinstance-calls/","title":"repeated-isinstance-calls (PLR1701)","text":"

        Derived from the Pylint linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        Fix is always available.

        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#removed","title":"Removed","text":"

        This rule is identical to SIM101 which should be used instead.

        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#what-it-does","title":"What it does","text":"

        Checks for repeated isinstance calls on the same object.

        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#why-is-this-bad","title":"Why is this bad?","text":"

        Repeated isinstance calls on the same object can be merged into a single call.

        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe on Python 3.10 and later, as combining multiple isinstance calls with a binary operator (|) will fail at runtime if any of the operands are themselves tuples.

        For example, given TYPES = (dict, list), then isinstance(None, TYPES | set | float) will raise a TypeError at runtime, while isinstance(None, set | float) will not.

        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#example","title":"Example","text":"
        def is_number(x):\n    return isinstance(x, int) or isinstance(x, float) or isinstance(x, complex)\n

        Use instead:

        def is_number(x):\n    return isinstance(x, (int, float, complex))\n

        Or, for Python 3.10 and later:

        def is_number(x):\n    return isinstance(x, int | float | complex)\n
        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#options","title":"Options","text":"
        • target-version
        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#references","title":"References","text":"
        • Python documentation: isinstance
        ","tags":["PLR1701"]},{"location":"rules/repeated-keyword-argument/","title":"repeated-keyword-argument (PLE1132)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1132"]},{"location":"rules/repeated-keyword-argument/#what-it-does","title":"What it does","text":"

        Checks for repeated keyword arguments in function calls.

        ","tags":["PLE1132"]},{"location":"rules/repeated-keyword-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Python does not allow repeated keyword arguments in function calls. If a function is called with the same keyword argument multiple times, the interpreter will raise an exception.

        ","tags":["PLE1132"]},{"location":"rules/repeated-keyword-argument/#example","title":"Example","text":"
        func(1, 2, c=3, **{\"c\": 4})\n
        ","tags":["PLE1132"]},{"location":"rules/repeated-keyword-argument/#references","title":"References","text":"
        • Python documentation: Argument
        ","tags":["PLE1132"]},{"location":"rules/replace-stdout-stderr/","title":"replace-stdout-stderr (UP022)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP022"]},{"location":"rules/replace-stdout-stderr/#what-it-does","title":"What it does","text":"

        Checks for uses of subprocess.run that send stdout and stderr to a pipe.

        ","tags":["UP022"]},{"location":"rules/replace-stdout-stderr/#why-is-this-bad","title":"Why is this bad?","text":"

        As of Python 3.7, subprocess.run has a capture_output keyword argument that can be set to True to capture stdout and stderr outputs. This is equivalent to setting stdout and stderr to subprocess.PIPE, but is more explicit and readable.

        ","tags":["UP022"]},{"location":"rules/replace-stdout-stderr/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.run([\"foo\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n

        Use instead:

        import subprocess\n\nsubprocess.run([\"foo\"], capture_output=True)\n
        ","tags":["UP022"]},{"location":"rules/replace-stdout-stderr/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because replacing stdout=subprocess.PIPE and stderr=subprocess.PIPE with capture_output=True may delete comments attached to the original arguments.

        ","tags":["UP022"]},{"location":"rules/replace-stdout-stderr/#references","title":"References","text":"
        • Python 3.7 release notes
        • Python documentation: subprocess.run
        ","tags":["UP022"]},{"location":"rules/replace-str-enum/","title":"replace-str-enum (UP042)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["UP042"]},{"location":"rules/replace-str-enum/#what-it-does","title":"What it does","text":"

        Checks for classes that inherit from both str and enum.Enum.

        ","tags":["UP042"]},{"location":"rules/replace-str-enum/#why-is-this-bad","title":"Why is this bad?","text":"

        Python 3.11 introduced enum.StrEnum, which is preferred over inheriting from both str and enum.Enum.

        ","tags":["UP042"]},{"location":"rules/replace-str-enum/#example","title":"Example","text":"
        import enum\n\n\nclass Foo(str, enum.Enum): ...\n

        Use instead:

        import enum\n\n\nclass Foo(enum.StrEnum): ...\n
        ","tags":["UP042"]},{"location":"rules/replace-str-enum/#fix-safety","title":"Fix safety","text":"

        Python 3.11 introduced a breaking change for enums that inherit from both str and enum.Enum. Consider the following enum:

        from enum import Enum\n\n\nclass Foo(str, Enum):\n    BAR = \"bar\"\n

        In Python 3.11, the formatted representation of Foo.BAR changed as follows:

        # Python 3.10\nf\"{Foo.BAR}\"  # > bar\n# Python 3.11\nf\"{Foo.BAR}\"  # > Foo.BAR\n

        Migrating from str and enum.Enum to enum.StrEnum will restore the previous behavior, such that:

        from enum import StrEnum\n\n\nclass Foo(StrEnum):\n    BAR = \"bar\"\n\n\nf\"{Foo.BAR}\"  # > bar\n

        As such, migrating to enum.StrEnum will introduce a behavior change for code that relies on the Python 3.11 behavior.

        ","tags":["UP042"]},{"location":"rules/replace-str-enum/#references","title":"References","text":"
        • enum.StrEnum
        ","tags":["UP042"]},{"location":"rules/replace-universal-newlines/","title":"replace-universal-newlines (UP021)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP021"]},{"location":"rules/replace-universal-newlines/#what-it-does","title":"What it does","text":"

        Checks for uses of subprocess.run that set the universal_newlines keyword argument.

        ","tags":["UP021"]},{"location":"rules/replace-universal-newlines/#why-is-this-bad","title":"Why is this bad?","text":"

        As of Python 3.7, the universal_newlines keyword argument has been renamed to text, and now exists for backwards compatibility. The universal_newlines keyword argument may be removed in a future version of Python. Prefer text, which is more explicit and readable.

        ","tags":["UP021"]},{"location":"rules/replace-universal-newlines/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.run([\"foo\"], universal_newlines=True)\n

        Use instead:

        import subprocess\n\nsubprocess.run([\"foo\"], text=True)\n
        ","tags":["UP021"]},{"location":"rules/replace-universal-newlines/#references","title":"References","text":"
        • Python 3.7 release notes
        • Python documentation: subprocess.run
        ","tags":["UP021"]},{"location":"rules/request-with-no-cert-validation/","title":"request-with-no-cert-validation (S501)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S501"]},{"location":"rules/request-with-no-cert-validation/#what-it-does","title":"What it does","text":"

        Checks for HTTPS requests that disable SSL certificate checks.

        ","tags":["S501"]},{"location":"rules/request-with-no-cert-validation/#why-is-this-bad","title":"Why is this bad?","text":"

        If SSL certificates are not verified, an attacker could perform a \"man in the middle\" attack by intercepting and modifying traffic between the client and server.

        ","tags":["S501"]},{"location":"rules/request-with-no-cert-validation/#example","title":"Example","text":"
        import requests\n\nrequests.get(\"https://www.example.com\", verify=False)\n

        Use instead:

        import requests\n\nrequests.get(\"https://www.example.com\")  # By default, `verify=True`.\n
        ","tags":["S501"]},{"location":"rules/request-with-no-cert-validation/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-295
        ","tags":["S501"]},{"location":"rules/request-without-timeout/","title":"request-without-timeout (S113)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S113"]},{"location":"rules/request-without-timeout/#what-it-does","title":"What it does","text":"

        Checks for uses of the Python requests or httpx module that omit the timeout parameter.

        ","tags":["S113"]},{"location":"rules/request-without-timeout/#why-is-this-bad","title":"Why is this bad?","text":"

        The timeout parameter is used to set the maximum time to wait for a response from the server. By omitting the timeout parameter, the program may hang indefinitely while awaiting a response.

        ","tags":["S113"]},{"location":"rules/request-without-timeout/#example","title":"Example","text":"
        import requests\n\nrequests.get(\"https://www.example.com/\")\n

        Use instead:

        import requests\n\nrequests.get(\"https://www.example.com/\", timeout=10)\n
        ","tags":["S113"]},{"location":"rules/request-without-timeout/#references","title":"References","text":"
        • Requests documentation: Timeouts
        • httpx documentation: Timeouts
        ","tags":["S113"]},{"location":"rules/reraise-no-cause/","title":"reraise-no-cause (TRY200)","text":"

        Derived from the tryceratops linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["TRY200"]},{"location":"rules/reraise-no-cause/#removed","title":"Removed","text":"

        This rule is identical to B904 which should be used instead.

        ","tags":["TRY200"]},{"location":"rules/reraise-no-cause/#what-it-does","title":"What it does","text":"

        Checks for exceptions that are re-raised without specifying the cause via the from keyword.

        ","tags":["TRY200"]},{"location":"rules/reraise-no-cause/#why-is-this-bad","title":"Why is this bad?","text":"

        The from keyword sets the __cause__ attribute of the exception, which stores the \"cause\" of the exception. The availability of an exception \"cause\" is useful for debugging.

        ","tags":["TRY200"]},{"location":"rules/reraise-no-cause/#example","title":"Example","text":"
        def reciprocal(n):\n    try:\n        return 1 / n\n    except ZeroDivisionError:\n        raise ValueError()\n

        Use instead:

        def reciprocal(n):\n    try:\n        return 1 / n\n    except ZeroDivisionError as exc:\n        raise ValueError() from exc\n
        ","tags":["TRY200"]},{"location":"rules/reraise-no-cause/#references","title":"References","text":"
        • Python documentation: Exception context
        ","tags":["TRY200"]},{"location":"rules/return-in-generator/","title":"return-in-generator (B901)","text":"

        Derived from the flake8-bugbear linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["B901"]},{"location":"rules/return-in-generator/#what-it-does","title":"What it does","text":"

        Checks for return {value} statements in functions that also contain yield or yield from statements.

        ","tags":["B901"]},{"location":"rules/return-in-generator/#why-is-this-bad","title":"Why is this bad?","text":"

        Using return {value} in a generator function was syntactically invalid in Python 2. In Python 3 return {value} can be used in a generator; however, the combination of yield and return can lead to confusing behavior, as the return statement will cause the generator to raise StopIteration with the value provided, rather than returning the value to the caller.

        For example, given:

        from collections.abc import Iterable\nfrom pathlib import Path\n\n\ndef get_file_paths(file_types: Iterable[str] | None = None) -> Iterable[Path]:\n    dir_path = Path(\".\")\n    if file_types is None:\n        return dir_path.glob(\"*\")\n\n    for file_type in file_types:\n        yield from dir_path.glob(f\"*.{file_type}\")\n

        Readers might assume that get_file_paths() would return an iterable of Path objects in the directory; in reality, though, list(get_file_paths()) evaluates to [], since the return statement causes the generator to raise StopIteration with the value dir_path.glob(\"*\"):

        >>> list(get_file_paths(file_types=[\"cfg\", \"toml\"]))\n[PosixPath('setup.cfg'), PosixPath('pyproject.toml')]\n>>> list(get_file_paths())\n[]\n

        For intentional uses of return in a generator, consider suppressing this diagnostic.

        ","tags":["B901"]},{"location":"rules/return-in-generator/#example","title":"Example","text":"
        from collections.abc import Iterable\nfrom pathlib import Path\n\n\ndef get_file_paths(file_types: Iterable[str] | None = None) -> Iterable[Path]:\n    dir_path = Path(\".\")\n    if file_types is None:\n        return dir_path.glob(\"*\")\n\n    for file_type in file_types:\n        yield from dir_path.glob(f\"*.{file_type}\")\n

        Use instead:

        from collections.abc import Iterable\nfrom pathlib import Path\n\n\ndef get_file_paths(file_types: Iterable[str] | None = None) -> Iterable[Path]:\n    dir_path = Path(\".\")\n    if file_types is None:\n        yield from dir_path.glob(\"*\")\n    else:\n        for file_type in file_types:\n            yield from dir_path.glob(f\"*.{file_type}\")\n
        ","tags":["B901"]},{"location":"rules/return-in-init/","title":"return-in-init (PLE0101)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0101"]},{"location":"rules/return-in-init/#what-it-does","title":"What it does","text":"

        Checks for __init__ methods that return values.

        ","tags":["PLE0101"]},{"location":"rules/return-in-init/#why-is-this-bad","title":"Why is this bad?","text":"

        The __init__ method is the constructor for a given Python class, responsible for initializing, rather than creating, new objects.

        The __init__ method has to return None. Returning any value from an __init__ method will result in a runtime error.

        ","tags":["PLE0101"]},{"location":"rules/return-in-init/#example","title":"Example","text":"
        class Example:\n    def __init__(self):\n        return []\n

        Use instead:

        class Example:\n    def __init__(self):\n        self.value = []\n
        ","tags":["PLE0101"]},{"location":"rules/return-in-init/#references","title":"References","text":"
        • CodeQL: py-explicit-return-in-init
        ","tags":["PLE0101"]},{"location":"rules/return-in-try-except-finally/","title":"return-in-try-except-finally (SIM107)","text":"

        Derived from the flake8-simplify linter.

        ","tags":["SIM107"]},{"location":"rules/return-in-try-except-finally/#what-it-does","title":"What it does","text":"

        Checks for return statements in try-except and finally blocks.

        ","tags":["SIM107"]},{"location":"rules/return-in-try-except-finally/#why-is-this-bad","title":"Why is this bad?","text":"

        The return statement in a finally block will always be executed, even if an exception is raised in the try or except block. This can lead to unexpected behavior.

        ","tags":["SIM107"]},{"location":"rules/return-in-try-except-finally/#example","title":"Example","text":"
        def squared(n):\n    try:\n        sqr = n**2\n        return sqr\n    except Exception:\n        return \"An exception occurred\"\n    finally:\n        return -1  # Always returns -1.\n

        Use instead:

        def squared(n):\n    try:\n        return_value = n**2\n    except Exception:\n        return_value = \"An exception occurred\"\n    finally:\n        return_value = -1\n    return return_value\n
        ","tags":["SIM107"]},{"location":"rules/return-in-try-except-finally/#references","title":"References","text":"
        • Python documentation: Defining Clean-up Actions
        ","tags":["SIM107"]},{"location":"rules/return-outside-function/","title":"return-outside-function (F706)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F706"]},{"location":"rules/return-outside-function/#what-it-does","title":"What it does","text":"

        Checks for return statements outside of functions.

        ","tags":["F706"]},{"location":"rules/return-outside-function/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of a return statement outside of a function will raise a SyntaxError.

        ","tags":["F706"]},{"location":"rules/return-outside-function/#example","title":"Example","text":"
        class Foo:\n    return 1\n
        ","tags":["F706"]},{"location":"rules/return-outside-function/#references","title":"References","text":"
        • Python documentation: return
        ","tags":["F706"]},{"location":"rules/reuse-of-groupby-generator/","title":"reuse-of-groupby-generator (B031)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B031"]},{"location":"rules/reuse-of-groupby-generator/#what-it-does","title":"What it does","text":"

        Checks for multiple usage of the generator returned from itertools.groupby().

        ","tags":["B031"]},{"location":"rules/reuse-of-groupby-generator/#why-is-this-bad","title":"Why is this bad?","text":"

        Using the generator more than once will do nothing on the second usage. If that data is needed later, it should be stored as a list.

        ","tags":["B031"]},{"location":"rules/reuse-of-groupby-generator/#example","title":"Example:","text":"
        import itertools\n\nfor name, group in itertools.groupby(data):\n    for _ in range(5):\n        do_something_with_the_group(group)\n

        Use instead:

        import itertools\n\nfor name, group in itertools.groupby(data):\n    values = list(group)\n    for _ in range(5):\n        do_something_with_the_group(values)\n
        ","tags":["B031"]},{"location":"rules/root-logger-call/","title":"root-logger-call (LOG015)","text":"

        Derived from the flake8-logging linter.

        ","tags":["LOG015"]},{"location":"rules/root-logger-call/#what-it-does","title":"What it does","text":"

        Checks for usages of the following logging top-level functions: debug, info, warn, warning, error, critical, log, exception.

        ","tags":["LOG015"]},{"location":"rules/root-logger-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Using the root logger causes the messages to have no source information, making them less useful for debugging.

        ","tags":["LOG015"]},{"location":"rules/root-logger-call/#example","title":"Example","text":"
        import logging\n\nlogging.info(\"Foobar\")\n

        Use instead:

        import logging\n\nlogger = logging.getLogger(__name__)\nlogger.info(\"Foobar\")\n
        ","tags":["LOG015"]},{"location":"rules/ruff-static-key-dict-comprehension/","title":"ruff-static-key-dict-comprehension (RUF011)","text":"

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["RUF011"]},{"location":"rules/ruff-static-key-dict-comprehension/#removed","title":"Removed","text":"

        This rule was implemented in flake8-bugbear and has been remapped to B035

        ","tags":["RUF011"]},{"location":"rules/ruff-static-key-dict-comprehension/#what-it-does","title":"What it does","text":"

        Checks for dictionary comprehensions that use a static key, like a string literal or a variable defined outside the comprehension.

        ","tags":["RUF011"]},{"location":"rules/ruff-static-key-dict-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        Using a static key (like a string literal) in a dictionary comprehension is usually a mistake, as it will result in a dictionary with only one key, despite the comprehension iterating over multiple values.

        ","tags":["RUF011"]},{"location":"rules/ruff-static-key-dict-comprehension/#example","title":"Example","text":"
        data = [\"some\", \"Data\"]\n{\"key\": value.upper() for value in data}\n

        Use instead:

        data = [\"some\", \"Data\"]\n{value: value.upper() for value in data}\n
        ","tags":["RUF011"]},{"location":"rules/ruff-unsafe-markup-use/","title":"ruff-unsafe-markup-use (RUF035)","text":"

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#removed","title":"Removed","text":"

        This rule was implemented in bandit and has been remapped to S704

        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#what-it-does","title":"What it does","text":"

        Checks for non-literal strings being passed to markupsafe.Markup.

        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#why-is-this-bad","title":"Why is this bad?","text":"

        markupsafe.Markup does not perform any escaping, so passing dynamic content, like f-strings, variables or interpolated strings will potentially lead to XSS vulnerabilities.

        Instead you should interpolate the Markup object.

        Using lint.flake8-bandit.extend-markup-names additional objects can be treated like Markup.

        This rule was originally inspired by flake8-markupsafe but doesn't carve out any exceptions for i18n related calls by default.

        You can use lint.flake8-bandit.allowed-markup-calls to specify exceptions.

        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#example","title":"Example","text":"

        Given:

        from markupsafe import Markup\n\ncontent = \"<script>alert('Hello, world!')</script>\"\nhtml = Markup(f\"<b>{content}</b>\")  # XSS\n

        Use instead:

        from markupsafe import Markup\n\ncontent = \"<script>alert('Hello, world!')</script>\"\nhtml = Markup(\"<b>{}</b>\").format(content)  # Safe\n

        Given:

        from markupsafe import Markup\n\nlines = [\n    Markup(\"<b>heading</b>\"),\n    \"<script>alert('XSS attempt')</script>\",\n]\nhtml = Markup(\"<br>\".join(lines))  # XSS\n

        Use instead:

        from markupsafe import Markup\n\nlines = [\n    Markup(\"<b>heading</b>\"),\n    \"<script>alert('XSS attempt')</script>\",\n]\nhtml = Markup(\"<br>\").join(lines)  # Safe\n
        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#options","title":"Options","text":"
        • lint.flake8-bandit.extend-markup-names
        • lint.flake8-bandit.allowed-markup-calls
        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#references","title":"References","text":"
        • MarkupSafe on PyPI
        • markupsafe.Markup API documentation
        ","tags":["RUF035"]},{"location":"rules/run-process-in-async-function/","title":"run-process-in-async-function (ASYNC221)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC221"]},{"location":"rules/run-process-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not run processes with blocking methods.

        ","tags":["ASYNC221"]},{"location":"rules/run-process-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a blocking call will block the entire event loop, preventing it from executing other tasks while waiting for the call to complete, negating the benefits of asynchronous programming.

        Instead of making a blocking call, use an equivalent asynchronous library or function, like trio.run_process() or anyio.run_process().

        ","tags":["ASYNC221"]},{"location":"rules/run-process-in-async-function/#example","title":"Example","text":"
        async def foo():\n    subprocess.run(cmd)\n

        Use instead:

        async def foo():\n    asyncio.create_subprocess_shell(cmd)\n
        ","tags":["ASYNC221"]},{"location":"rules/runtime-cast-value/","title":"runtime-cast-value (TC006)","text":"

        Derived from the flake8-type-checking linter.

        Fix is always available.

        ","tags":["TC006"]},{"location":"rules/runtime-cast-value/#what-it-does","title":"What it does","text":"

        Checks for unquoted type expressions in typing.cast() calls.

        ","tags":["TC006"]},{"location":"rules/runtime-cast-value/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule helps enforce a consistent style across your codebase.

        It's often necessary to quote the first argument passed to cast(), as type expressions can involve forward references, or references to symbols which are only imported in typing.TYPE_CHECKING blocks. This can lead to a visual inconsistency across different cast() calls, where some type expressions are quoted but others are not. By enabling this rule, you ensure that all type expressions passed to cast() are quoted, enforcing stylistic consistency across all of your cast() calls.

        In some cases where cast() is used in a hot loop, this rule may also help avoid overhead from repeatedly evaluating complex type expressions at runtime.

        ","tags":["TC006"]},{"location":"rules/runtime-cast-value/#example","title":"Example","text":"
        from typing import cast\n\nx = cast(dict[str, int], foo)\n

        Use instead:

        from typing import cast\n\nx = cast(\"dict[str, int]\", foo)\n
        ","tags":["TC006"]},{"location":"rules/runtime-cast-value/#fix-safety","title":"Fix safety","text":"

        This fix is safe as long as the type expression doesn't span multiple lines and includes comments on any of the lines apart from the last one.

        ","tags":["TC006"]},{"location":"rules/runtime-import-in-type-checking-block/","title":"runtime-import-in-type-checking-block (TC004)","text":"

        Derived from the flake8-type-checking linter.

        Fix is sometimes available.

        ","tags":["TC004"]},{"location":"rules/runtime-import-in-type-checking-block/#what-it-does","title":"What it does","text":"

        Checks for imports that are required at runtime but are only defined in type-checking blocks.

        ","tags":["TC004"]},{"location":"rules/runtime-import-in-type-checking-block/#why-is-this-bad","title":"Why is this bad?","text":"

        The type-checking block is not executed at runtime, so if the only definition of a symbol is in a type-checking block, it will not be available at runtime.

        If lint.flake8-type-checking.quote-annotations is set to true, annotations will be wrapped in quotes if doing so would enable the corresponding import to remain in the type-checking block.

        ","tags":["TC004"]},{"location":"rules/runtime-import-in-type-checking-block/#example","title":"Example","text":"
        from typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    import foo\n\n\ndef bar() -> None:\n    foo.bar()  # raises NameError: name 'foo' is not defined\n

        Use instead:

        import foo\n\n\ndef bar() -> None:\n    foo.bar()\n
        ","tags":["TC004"]},{"location":"rules/runtime-import-in-type-checking-block/#options","title":"Options","text":"
        • lint.flake8-type-checking.quote-annotations
        ","tags":["TC004"]},{"location":"rules/runtime-import-in-type-checking-block/#references","title":"References","text":"
        • PEP 563: Runtime annotation resolution and TYPE_CHECKING
        ","tags":["TC004"]},{"location":"rules/runtime-string-union/","title":"runtime-string-union (TC010)","text":"

        Derived from the flake8-type-checking linter.

        ","tags":["TC010"]},{"location":"rules/runtime-string-union/#what-it-does","title":"What it does","text":"

        Checks for the presence of string literals in X | Y-style union types.

        ","tags":["TC010"]},{"location":"rules/runtime-string-union/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 604 introduced a new syntax for union type annotations based on the | operator.

        While Python's type annotations can typically be wrapped in strings to avoid runtime evaluation, the use of a string member within an X | Y-style union type will cause a runtime error.

        Instead, remove the quotes, wrap the entire union in quotes, or use from __future__ import annotations to disable runtime evaluation of annotations entirely.

        ","tags":["TC010"]},{"location":"rules/runtime-string-union/#example","title":"Example","text":"
        var: str | \"int\"\n

        Use instead:

        var: str | int\n

        Or, extend the quotes to include the entire union:

        var: \"str | int\"\n
        ","tags":["TC010"]},{"location":"rules/runtime-string-union/#references","title":"References","text":"
        • PEP 563 - Postponed Evaluation of Annotations
        • PEP 604 \u2013 Allow writing union types as X | Y
        ","tags":["TC010"]},{"location":"rules/self-assigning-variable/","title":"self-assigning-variable (PLW0127)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0127"]},{"location":"rules/self-assigning-variable/#what-it-does","title":"What it does","text":"

        Checks for self-assignment of variables.

        ","tags":["PLW0127"]},{"location":"rules/self-assigning-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        Self-assignment of variables is redundant and likely a mistake.

        ","tags":["PLW0127"]},{"location":"rules/self-assigning-variable/#example","title":"Example","text":"
        country = \"Poland\"\ncountry = country\n

        Use instead:

        country = \"Poland\"\n
        ","tags":["PLW0127"]},{"location":"rules/self-or-cls-assignment/","title":"self-or-cls-assignment (PLW0642)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0642"]},{"location":"rules/self-or-cls-assignment/#what-it-does","title":"What it does","text":"

        Checks for assignment of self and cls in instance and class methods respectively.

        This check also applies to __new__ even though this is technically a static method.

        ","tags":["PLW0642"]},{"location":"rules/self-or-cls-assignment/#why-is-this-bad","title":"Why is this bad?","text":"

        The identifiers self and cls are conventional in Python for the first parameter of instance methods and class methods, respectively. Assigning new values to these variables can be confusing for others reading your code; using a different variable name can lead to clearer code.

        ","tags":["PLW0642"]},{"location":"rules/self-or-cls-assignment/#example","title":"Example","text":"
        class Version:\n    def add(self, other):\n        self = self + other\n        return self\n\n    @classmethod\n    def superclass(cls):\n        cls = cls.__mro__[-1]\n        return cls\n

        Use instead:

        class Version:\n    def add(self, other):\n        new_version = self + other\n        return new_version\n\n    @classmethod\n    def superclass(cls):\n        supercls = cls.__mro__[-1]\n        return supercls\n
        ","tags":["PLW0642"]},{"location":"rules/set-attr-with-constant/","title":"set-attr-with-constant (B010)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B010"]},{"location":"rules/set-attr-with-constant/#what-it-does","title":"What it does","text":"

        Checks for uses of setattr that take a constant attribute value as an argument (e.g., setattr(obj, \"foo\", 42)).

        ","tags":["B010"]},{"location":"rules/set-attr-with-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        setattr is used to set attributes dynamically. If the attribute is defined as a constant, it is no safer than a typical property access. When possible, prefer property access over setattr calls, as the former is more concise and idiomatic.

        ","tags":["B010"]},{"location":"rules/set-attr-with-constant/#example","title":"Example","text":"
        setattr(obj, \"foo\", 42)\n

        Use instead:

        obj.foo = 42\n
        ","tags":["B010"]},{"location":"rules/set-attr-with-constant/#references","title":"References","text":"
        • Python documentation: setattr
        ","tags":["B010"]},{"location":"rules/shallow-copy-environ/","title":"shallow-copy-environ (PLW1507)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLW1507"]},{"location":"rules/shallow-copy-environ/#what-it-does","title":"What it does","text":"

        Check for shallow os.environ copies.

        ","tags":["PLW1507"]},{"location":"rules/shallow-copy-environ/#why-is-this-bad","title":"Why is this bad?","text":"

        os.environ is not a dict object, but rather, a proxy object. As such, mutating a shallow copy of os.environ will also mutate the original object.

        See BPO 15373 for more information.

        ","tags":["PLW1507"]},{"location":"rules/shallow-copy-environ/#example","title":"Example","text":"
        import copy\nimport os\n\nenv = copy.copy(os.environ)\n

        Use instead:

        import os\n\nenv = os.environ.copy()\n
        ","tags":["PLW1507"]},{"location":"rules/shallow-copy-environ/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because replacing a shallow copy with a deep copy can lead to unintended side effects. If the program modifies the shallow copy at some point, changing it to a deep copy may prevent those modifications from affecting the original data, potentially altering the program's behavior.

        ","tags":["PLW1507"]},{"location":"rules/shallow-copy-environ/#references","title":"References","text":"
        • Python documentation: copy \u2014 Shallow and deep copy operations
        • Python documentation: os.environ
        ","tags":["PLW1507"]},{"location":"rules/shebang-leading-whitespace/","title":"shebang-leading-whitespace (EXE004)","text":"

        Derived from the flake8-executable linter.

        Fix is always available.

        ","tags":["EXE004"]},{"location":"rules/shebang-leading-whitespace/#what-it-does","title":"What it does","text":"

        Checks for whitespace before a shebang directive.

        ","tags":["EXE004"]},{"location":"rules/shebang-leading-whitespace/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a shebang (also known as a hashbang) is the first line of a script, which specifies the interpreter that should be used to run the script.

        The shebang's #! prefix must be the first two characters of a file. The presence of whitespace before the shebang will cause the shebang to be ignored, which is likely a mistake.

        ","tags":["EXE004"]},{"location":"rules/shebang-leading-whitespace/#example","title":"Example","text":"
         #!/usr/bin/env python3\n

        Use instead:

        #!/usr/bin/env python3\n
        ","tags":["EXE004"]},{"location":"rules/shebang-leading-whitespace/#references","title":"References","text":"
        • Python documentation: Executable Python Scripts
        ","tags":["EXE004"]},{"location":"rules/shebang-missing-executable-file/","title":"shebang-missing-executable-file (EXE002)","text":"

        Derived from the flake8-executable linter.

        ","tags":["EXE002"]},{"location":"rules/shebang-missing-executable-file/#what-it-does","title":"What it does","text":"

        Checks for executable .py files that do not have a shebang.

        ","tags":["EXE002"]},{"location":"rules/shebang-missing-executable-file/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a shebang (also known as a hashbang) is the first line of a script, which specifies the interpreter that should be used to run the script.

        If a .py file is executable, but does not have a shebang, it may be run with the wrong interpreter, or fail to run at all.

        If the file is meant to be executable, add a shebang, as in:

        #!/usr/bin/env python\n

        Otherwise, remove the executable bit from the file (e.g., chmod -x __main__.py or git update-index --chmod=-x __main__.py).

        A file is considered executable if it has the executable bit set (i.e., its permissions mode intersects with 0o111). As such, this rule is only available on Unix-like systems, and is not enforced on Windows or WSL.

        ","tags":["EXE002"]},{"location":"rules/shebang-missing-executable-file/#references","title":"References","text":"
        • Python documentation: Executable Python Scripts
        • Git documentation: git update-index --chmod
        ","tags":["EXE002"]},{"location":"rules/shebang-missing-python/","title":"shebang-missing-python (EXE003)","text":"

        Derived from the flake8-executable linter.

        ","tags":["EXE003"]},{"location":"rules/shebang-missing-python/#what-it-does","title":"What it does","text":"

        Checks for a shebang directive in .py files that does not contain python, pytest, or uv run.

        ","tags":["EXE003"]},{"location":"rules/shebang-missing-python/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a shebang (also known as a hashbang) is the first line of a script, which specifies the command that should be used to run the script.

        For Python scripts, if the shebang does not include a command that explicitly or implicitly specifies an interpreter, then the file will be executed with the default interpreter, which is likely a mistake.

        ","tags":["EXE003"]},{"location":"rules/shebang-missing-python/#example","title":"Example","text":"
        #!/usr/bin/env bash\n

        Use instead:

        #!/usr/bin/env python3\n
        ","tags":["EXE003"]},{"location":"rules/shebang-missing-python/#references","title":"References","text":"
        • Python documentation: Executable Python Scripts
        ","tags":["EXE003"]},{"location":"rules/shebang-not-executable/","title":"shebang-not-executable (EXE001)","text":"

        Derived from the flake8-executable linter.

        ","tags":["EXE001"]},{"location":"rules/shebang-not-executable/#what-it-does","title":"What it does","text":"

        Checks for a shebang directive in a file that is not executable.

        ","tags":["EXE001"]},{"location":"rules/shebang-not-executable/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a shebang (also known as a hashbang) is the first line of a script, which specifies the interpreter that should be used to run the script.

        The presence of a shebang suggests that a file is intended to be executable. If a file contains a shebang but is not executable, then the shebang is misleading, or the file is missing the executable bit.

        If the file is meant to be executable, add the executable bit to the file (e.g., chmod +x __main__.py or git update-index --chmod=+x __main__.py).

        Otherwise, remove the shebang.

        A file is considered executable if it has the executable bit set (i.e., its permissions mode intersects with 0o111). As such, this rule is only available on Unix-like systems, and is not enforced on Windows or WSL.

        ","tags":["EXE001"]},{"location":"rules/shebang-not-executable/#example","title":"Example","text":"
        #!/usr/bin/env python\n
        ","tags":["EXE001"]},{"location":"rules/shebang-not-executable/#references","title":"References","text":"
        • Python documentation: Executable Python Scripts
        • Git documentation: git update-index --chmod
        ","tags":["EXE001"]},{"location":"rules/shebang-not-first-line/","title":"shebang-not-first-line (EXE005)","text":"

        Derived from the flake8-executable linter.

        ","tags":["EXE005"]},{"location":"rules/shebang-not-first-line/#what-it-does","title":"What it does","text":"

        Checks for a shebang directive that is not at the beginning of the file.

        ","tags":["EXE005"]},{"location":"rules/shebang-not-first-line/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a shebang (also known as a hashbang) is the first line of a script, which specifies the interpreter that should be used to run the script.

        The shebang's #! prefix must be the first two characters of a file. If the shebang is not at the beginning of the file, it will be ignored, which is likely a mistake.

        ","tags":["EXE005"]},{"location":"rules/shebang-not-first-line/#example","title":"Example","text":"
        foo = 1\n#!/usr/bin/env python3\n

        Use instead:

        #!/usr/bin/env python3\nfoo = 1\n
        ","tags":["EXE005"]},{"location":"rules/shebang-not-first-line/#references","title":"References","text":"
        • Python documentation: Executable Python Scripts
        ","tags":["EXE005"]},{"location":"rules/signature-in-docstring/","title":"signature-in-docstring (D402)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D402"]},{"location":"rules/signature-in-docstring/#what-it-does","title":"What it does","text":"

        Checks for function docstrings that include the function's signature in the summary line.

        ","tags":["D402"]},{"location":"rules/signature-in-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends against including a function's signature in its docstring. Instead, consider using type annotations as a form of documentation for the function's parameters and return value.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the google and pep257 conventions, and disabled when using the numpy convention.

        ","tags":["D402"]},{"location":"rules/signature-in-docstring/#example","title":"Example","text":"
        def foo(a, b):\n    \"\"\"foo(a: int, b: int) -> list[int]\"\"\"\n

        Use instead:

        def foo(a: int, b: int) -> list[int]:\n    \"\"\"Return a list of a and b.\"\"\"\n
        ","tags":["D402"]},{"location":"rules/signature-in-docstring/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D402"]},{"location":"rules/signature-in-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D402"]},{"location":"rules/single-item-membership-test/","title":"single-item-membership-test (FURB171)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB171"]},{"location":"rules/single-item-membership-test/#what-it-does","title":"What it does","text":"

        Checks for membership tests against single-item containers.

        ","tags":["FURB171"]},{"location":"rules/single-item-membership-test/#why-is-this-bad","title":"Why is this bad?","text":"

        Performing a membership test against a container (like a list or set) with a single item is less readable and less efficient than comparing against the item directly.

        ","tags":["FURB171"]},{"location":"rules/single-item-membership-test/#example","title":"Example","text":"
        1 in [1]\n

        Use instead:

        1 == 1\n
        ","tags":["FURB171"]},{"location":"rules/single-item-membership-test/#fix-safety","title":"Fix safety","text":"

        When the right-hand side is a string, the fix is marked as unsafe. This is because c in \"a\" is true both when c is \"a\" and when c is the empty string, so the fix can change the behavior of your program in these cases.

        Additionally, if there are comments within the fix's range, it will also be marked as unsafe.

        ","tags":["FURB171"]},{"location":"rules/single-item-membership-test/#references","title":"References","text":"
        • Python documentation: Comparisons
        • Python documentation: Membership test operations
        ","tags":["FURB171"]},{"location":"rules/single-line-implicit-string-concatenation/","title":"single-line-implicit-string-concatenation (ISC001)","text":"

        Derived from the flake8-implicit-str-concat linter.

        Fix is sometimes available.

        ","tags":["ISC001"]},{"location":"rules/single-line-implicit-string-concatenation/#what-it-does","title":"What it does","text":"

        Checks for implicitly concatenated strings on a single line.

        ","tags":["ISC001"]},{"location":"rules/single-line-implicit-string-concatenation/#why-is-this-bad","title":"Why is this bad?","text":"

        While it is valid Python syntax to concatenate multiple string or byte literals implicitly (via whitespace delimiters), it is unnecessary and negatively affects code readability.

        In some cases, the implicit concatenation may also be unintentional, as code formatters are capable of introducing single-line implicit concatenations when collapsing long lines.

        ","tags":["ISC001"]},{"location":"rules/single-line-implicit-string-concatenation/#example","title":"Example","text":"
        z = \"The quick \" \"brown fox.\"\n

        Use instead:

        z = \"The quick brown fox.\"\n
        ","tags":["ISC001"]},{"location":"rules/single-string-slots/","title":"single-string-slots (PLC0205)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC0205"]},{"location":"rules/single-string-slots/#what-it-does","title":"What it does","text":"

        Checks for single strings assigned to __slots__.

        ","tags":["PLC0205"]},{"location":"rules/single-string-slots/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the __slots__ attribute allows you to explicitly define the attributes (instance variables) that a class can have. By default, Python uses a dictionary to store an object's attributes, which incurs some memory overhead. However, when __slots__ is defined, Python uses a more compact internal structure to store the object's attributes, resulting in memory savings.

        Any string iterable may be assigned to __slots__ (most commonly, a tuple of strings). If a string is assigned to __slots__, it is interpreted as a single attribute name, rather than an iterable of attribute names. This can cause confusion, as users that iterate over the __slots__ value may expect to iterate over a sequence of attributes, but would instead iterate over the characters of the string.

        To use a single string attribute in __slots__, wrap the string in an iterable container type, like a tuple.

        ","tags":["PLC0205"]},{"location":"rules/single-string-slots/#example","title":"Example","text":"
        class Person:\n    __slots__: str = \"name\"\n\n    def __init__(self, name: str) -> None:\n        self.name = name\n

        Use instead:

        class Person:\n    __slots__: tuple[str, ...] = (\"name\",)\n\n    def __init__(self, name: str) -> None:\n        self.name = name\n
        ","tags":["PLC0205"]},{"location":"rules/single-string-slots/#references","title":"References","text":"
        • Python documentation: __slots__
        ","tags":["PLC0205"]},{"location":"rules/singledispatch-method/","title":"singledispatch-method (PLE1519)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE1519"]},{"location":"rules/singledispatch-method/#what-it-does","title":"What it does","text":"

        Checks for methods decorated with @singledispatch.

        ","tags":["PLE1519"]},{"location":"rules/singledispatch-method/#why-is-this-bad","title":"Why is this bad?","text":"

        The @singledispatch decorator is intended for use with functions, not methods.

        Instead, use the @singledispatchmethod decorator, or migrate the method to a standalone function.

        ","tags":["PLE1519"]},{"location":"rules/singledispatch-method/#example","title":"Example","text":"
        from functools import singledispatch\n\n\nclass Class:\n    @singledispatch\n    def method(self, arg): ...\n

        Use instead:

        from functools import singledispatchmethod\n\n\nclass Class:\n    @singledispatchmethod\n    def method(self, arg): ...\n
        ","tags":["PLE1519"]},{"location":"rules/singledispatch-method/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as migrating from @singledispatch to @singledispatchmethod may change the behavior of the code.

        ","tags":["PLE1519"]},{"location":"rules/singledispatchmethod-function/","title":"singledispatchmethod-function (PLE1520)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE1520"]},{"location":"rules/singledispatchmethod-function/#what-it-does","title":"What it does","text":"

        Checks for non-method functions decorated with @singledispatchmethod.

        ","tags":["PLE1520"]},{"location":"rules/singledispatchmethod-function/#why-is-this-bad","title":"Why is this bad?","text":"

        The @singledispatchmethod decorator is intended for use with methods, not functions.

        Instead, use the @singledispatch decorator.

        ","tags":["PLE1520"]},{"location":"rules/singledispatchmethod-function/#example","title":"Example","text":"
        from functools import singledispatchmethod\n\n\n@singledispatchmethod\ndef func(arg): ...\n

        Use instead:

        from functools import singledispatch\n\n\n@singledispatch\ndef func(arg): ...\n
        ","tags":["PLE1520"]},{"location":"rules/singledispatchmethod-function/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as migrating from @singledispatchmethod to @singledispatch may change the behavior of the code.

        ","tags":["PLE1520"]},{"location":"rules/six-py3/","title":"six-py3 (YTT202)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT202"]},{"location":"rules/six-py3/#what-it-does","title":"What it does","text":"

        Checks for uses of six.PY3.

        ","tags":["YTT202"]},{"location":"rules/six-py3/#why-is-this-bad","title":"Why is this bad?","text":"

        six.PY3 will evaluate to False on Python 4 and greater. This is likely unintended, and may cause code intended to run on Python 2 to run on Python 4 too.

        Instead, use not six.PY2 to validate that the current Python major version is not equal to 2, to future-proof the code.

        ","tags":["YTT202"]},{"location":"rules/six-py3/#example","title":"Example","text":"
        import six\n\nsix.PY3  # `False` on Python 4.\n

        Use instead:

        import six\n\nnot six.PY2  # `True` on Python 4.\n
        ","tags":["YTT202"]},{"location":"rules/six-py3/#references","title":"References","text":"
        • PyPI: six
        • Six documentation: six.PY2
        • Six documentation: six.PY3
        ","tags":["YTT202"]},{"location":"rules/slice-copy/","title":"slice-copy (FURB145)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB145"]},{"location":"rules/slice-copy/#what-it-does","title":"What it does","text":"

        Checks for unbounded slice expressions to copy a list.

        ","tags":["FURB145"]},{"location":"rules/slice-copy/#why-is-this-bad","title":"Why is this bad?","text":"

        The list.copy method is more readable and consistent with copying other types.

        ","tags":["FURB145"]},{"location":"rules/slice-copy/#known-problems","title":"Known problems","text":"

        This rule is prone to false negatives due to type inference limitations, as it will only detect lists that are instantiated as literals or annotated with a type annotation.

        ","tags":["FURB145"]},{"location":"rules/slice-copy/#example","title":"Example","text":"
        a = [1, 2, 3]\nb = a[:]\n

        Use instead:

        a = [1, 2, 3]\nb = a.copy()\n
        ","tags":["FURB145"]},{"location":"rules/slice-copy/#references","title":"References","text":"
        • Python documentation: Mutable Sequence Types
        ","tags":["FURB145"]},{"location":"rules/slice-to-remove-prefix-or-suffix/","title":"slice-to-remove-prefix-or-suffix (FURB188)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB188"]},{"location":"rules/slice-to-remove-prefix-or-suffix/#what-it-does","title":"What it does","text":"

        Checks for code that could be written more idiomatically using str.removeprefix() or str.removesuffix().

        Specifically, the rule flags code that conditionally removes a prefix or suffix using a slice operation following an if test that uses str.startswith() or str.endswith().

        The rule is only applied if your project targets Python 3.9 or later.

        ","tags":["FURB188"]},{"location":"rules/slice-to-remove-prefix-or-suffix/#why-is-this-bad","title":"Why is this bad?","text":"

        The methods str.removeprefix() and str.removesuffix(), introduced in Python 3.9, have the same behavior while being more readable and efficient.

        ","tags":["FURB188"]},{"location":"rules/slice-to-remove-prefix-or-suffix/#example","title":"Example","text":"
        def example(filename: str, text: str):\n    filename = filename[:-4] if filename.endswith(\".txt\") else filename\n\n    if text.startswith(\"pre\"):\n        text = text[3:]\n

        Use instead:

        def example(filename: str, text: str):\n    filename = filename.removesuffix(\".txt\")\n    text = text.removeprefix(\"pre\")\n
        ","tags":["FURB188"]},{"location":"rules/snake-case-type-alias/","title":"snake-case-type-alias (PYI042)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI042"]},{"location":"rules/snake-case-type-alias/#what-it-does","title":"What it does","text":"

        Checks for type aliases that do not use the CamelCase naming convention.

        ","tags":["PYI042"]},{"location":"rules/snake-case-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        It's conventional to use the CamelCase naming convention for type aliases, to distinguish them from other variables.

        ","tags":["PYI042"]},{"location":"rules/snake-case-type-alias/#example","title":"Example","text":"
        type_alias_name: TypeAlias = int\n

        Use instead:

        TypeAliasName: TypeAlias = int\n
        ","tags":["PYI042"]},{"location":"rules/snmp-insecure-version/","title":"snmp-insecure-version (S508)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S508"]},{"location":"rules/snmp-insecure-version/#what-it-does","title":"What it does","text":"

        Checks for uses of SNMPv1 or SNMPv2.

        ","tags":["S508"]},{"location":"rules/snmp-insecure-version/#why-is-this-bad","title":"Why is this bad?","text":"

        The SNMPv1 and SNMPv2 protocols are considered insecure as they do not support encryption. Instead, prefer SNMPv3, which supports encryption.

        ","tags":["S508"]},{"location":"rules/snmp-insecure-version/#example","title":"Example","text":"
        from pysnmp.hlapi import CommunityData\n\nCommunityData(\"public\", mpModel=0)\n

        Use instead:

        from pysnmp.hlapi import CommunityData\n\nCommunityData(\"public\", mpModel=2)\n
        ","tags":["S508"]},{"location":"rules/snmp-insecure-version/#references","title":"References","text":"
        • Cybersecurity and Infrastructure Security Agency (CISA): Alert TA17-156A
        • Common Weakness Enumeration: CWE-319
        ","tags":["S508"]},{"location":"rules/snmp-weak-cryptography/","title":"snmp-weak-cryptography (S509)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S509"]},{"location":"rules/snmp-weak-cryptography/#what-it-does","title":"What it does","text":"

        Checks for uses of the SNMPv3 protocol without encryption.

        ","tags":["S509"]},{"location":"rules/snmp-weak-cryptography/#why-is-this-bad","title":"Why is this bad?","text":"

        Unencrypted SNMPv3 communication can be intercepted and read by unauthorized parties. Instead, enable encryption when using SNMPv3.

        ","tags":["S509"]},{"location":"rules/snmp-weak-cryptography/#example","title":"Example","text":"
        from pysnmp.hlapi import UsmUserData\n\nUsmUserData(\"user\")\n

        Use instead:

        from pysnmp.hlapi import UsmUserData\n\nUsmUserData(\"user\", \"authkey\", \"privkey\")\n
        ","tags":["S509"]},{"location":"rules/snmp-weak-cryptography/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-319
        ","tags":["S509"]},{"location":"rules/sorted-min-max/","title":"sorted-min-max (FURB192)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB192"]},{"location":"rules/sorted-min-max/#what-it-does","title":"What it does","text":"

        Checks for uses of sorted() to retrieve the minimum or maximum value in a sequence.

        ","tags":["FURB192"]},{"location":"rules/sorted-min-max/#why-is-this-bad","title":"Why is this bad?","text":"

        Using sorted() to compute the minimum or maximum value in a sequence is inefficient and less readable than using min() or max() directly.

        ","tags":["FURB192"]},{"location":"rules/sorted-min-max/#example","title":"Example","text":"
        nums = [3, 1, 4, 1, 5]\nlowest = sorted(nums)[0]\nhighest = sorted(nums)[-1]\nhighest = sorted(nums, reverse=True)[0]\n

        Use instead:

        nums = [3, 1, 4, 1, 5]\nlowest = min(nums)\nhighest = max(nums)\n
        ","tags":["FURB192"]},{"location":"rules/sorted-min-max/#fix-safety","title":"Fix safety","text":"

        In some cases, migrating to min or max can lead to a change in behavior, notably when breaking ties.

        As an example, sorted(data, key=itemgetter(0), reverse=True)[0] will return the last \"minimum\" element in the list, if there are multiple elements with the same key. However, min(data, key=itemgetter(0)) will return the first \"minimum\" element in the list in the same scenario.

        As such, this rule's fix is marked as unsafe when the reverse keyword is used.

        ","tags":["FURB192"]},{"location":"rules/sorted-min-max/#references","title":"References","text":"
        • Python documentation: min
        • Python documentation: max
        ","tags":["FURB192"]},{"location":"rules/split-static-string/","title":"split-static-string (SIM905)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM905"]},{"location":"rules/split-static-string/#what-it-does","title":"What it does","text":"

        Checks for static str.split calls that can be replaced with list literals.

        ","tags":["SIM905"]},{"location":"rules/split-static-string/#why-is-this-bad","title":"Why is this bad?","text":"

        List literals are more readable and do not require the overhead of calling str.split.

        ","tags":["SIM905"]},{"location":"rules/split-static-string/#example","title":"Example","text":"
        \"a,b,c,d\".split(\",\")\n

        Use instead:

        [\"a\", \"b\", \"c\", \"d\"]\n
        ","tags":["SIM905"]},{"location":"rules/split-static-string/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for implicit string concatenations with comments interleaved between segments, as comments may be removed.

        For example, the fix would be marked as unsafe in the following case:

        (\n    \"a\"  # comment\n    \",\"  # comment\n    \"b\"  # comment\n).split(\",\")\n

        as this is converted to [\"a\", \"b\"] without any of the comments.

        ","tags":["SIM905"]},{"location":"rules/split-static-string/#references","title":"References","text":"
        • Python documentation: str.split
        ","tags":["SIM905"]},{"location":"rules/ssh-no-host-key-verification/","title":"ssh-no-host-key-verification (S507)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S507"]},{"location":"rules/ssh-no-host-key-verification/#what-it-does","title":"What it does","text":"

        Checks for uses of policies disabling SSH verification in Paramiko.

        ","tags":["S507"]},{"location":"rules/ssh-no-host-key-verification/#why-is-this-bad","title":"Why is this bad?","text":"

        By default, Paramiko checks the identity of the remote host when establishing an SSH connection. Disabling the verification might lead to the client connecting to a malicious host, without the client knowing.

        ","tags":["S507"]},{"location":"rules/ssh-no-host-key-verification/#example","title":"Example","text":"
        from paramiko import client\n\nssh_client = client.SSHClient()\nssh_client.set_missing_host_key_policy(client.AutoAddPolicy)\n

        Use instead:

        from paramiko import client\n\nssh_client = client.SSHClient()\nssh_client.set_missing_host_key_policy(client.RejectPolicy)\n
        ","tags":["S507"]},{"location":"rules/ssh-no-host-key-verification/#references","title":"References","text":"
        • Paramiko documentation: set_missing_host_key_policy
        ","tags":["S507"]},{"location":"rules/ssl-insecure-version/","title":"ssl-insecure-version (S502)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S502"]},{"location":"rules/ssl-insecure-version/#what-it-does","title":"What it does","text":"

        Checks for function calls with parameters that indicate the use of insecure SSL and TLS protocol versions.

        ","tags":["S502"]},{"location":"rules/ssl-insecure-version/#why-is-this-bad","title":"Why is this bad?","text":"

        Several highly publicized exploitable flaws have been discovered in all versions of SSL and early versions of TLS. The following versions are considered insecure, and should be avoided:

        • SSL v2
        • SSL v3
        • TLS v1
        • TLS v1.1

        This method supports detection on the Python's built-in ssl module and the pyOpenSSL module.

        ","tags":["S502"]},{"location":"rules/ssl-insecure-version/#example","title":"Example","text":"
        import ssl\n\nssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1)\n

        Use instead:

        import ssl\n\nssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1_2)\n
        ","tags":["S502"]},{"location":"rules/ssl-with-bad-defaults/","title":"ssl-with-bad-defaults (S503)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S503"]},{"location":"rules/ssl-with-bad-defaults/#what-it-does","title":"What it does","text":"

        Checks for function definitions with default arguments set to insecure SSL and TLS protocol versions.

        ","tags":["S503"]},{"location":"rules/ssl-with-bad-defaults/#why-is-this-bad","title":"Why is this bad?","text":"

        Several highly publicized exploitable flaws have been discovered in all versions of SSL and early versions of TLS. The following versions are considered insecure, and should be avoided:

        • SSL v2
        • SSL v3
        • TLS v1
        • TLS v1.1
        ","tags":["S503"]},{"location":"rules/ssl-with-bad-defaults/#example","title":"Example","text":"
        import ssl\n\n\ndef func(version=ssl.PROTOCOL_TLSv1): ...\n

        Use instead:

        import ssl\n\n\ndef func(version=ssl.PROTOCOL_TLSv1_2): ...\n
        ","tags":["S503"]},{"location":"rules/ssl-with-no-version/","title":"ssl-with-no-version (S504)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S504"]},{"location":"rules/ssl-with-no-version/#what-it-does","title":"What it does","text":"

        Checks for calls to ssl.wrap_socket() without an ssl_version.

        ","tags":["S504"]},{"location":"rules/ssl-with-no-version/#why-is-this-bad","title":"Why is this bad?","text":"

        This method is known to provide a default value that maximizes compatibility, but permits use of insecure protocols.

        ","tags":["S504"]},{"location":"rules/ssl-with-no-version/#example","title":"Example","text":"
        import ssl\n\nssl.wrap_socket()\n

        Use instead:

        import ssl\n\nssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1_2)\n
        ","tags":["S504"]},{"location":"rules/star-arg-unpacking-after-keyword-arg/","title":"star-arg-unpacking-after-keyword-arg (B026)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B026"]},{"location":"rules/star-arg-unpacking-after-keyword-arg/#what-it-does","title":"What it does","text":"

        Checks for function calls that use star-argument unpacking after providing a keyword argument

        ","tags":["B026"]},{"location":"rules/star-arg-unpacking-after-keyword-arg/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, you can use star-argument unpacking to pass a list or tuple of arguments to a function.

        Providing a star-argument after a keyword argument can lead to confusing behavior, and is only supported for backwards compatibility.

        ","tags":["B026"]},{"location":"rules/star-arg-unpacking-after-keyword-arg/#example","title":"Example","text":"
        def foo(x, y, z):\n    return x, y, z\n\n\nfoo(1, 2, 3)  # (1, 2, 3)\nfoo(1, *[2, 3])  # (1, 2, 3)\n# foo(x=1, *[2, 3])  # TypeError\n# foo(y=2, *[1, 3])  # TypeError\nfoo(z=3, *[1, 2])  # (1, 2, 3)  # No error, but confusing!\n

        Use instead:

        def foo(x, y, z):\n    return x, y, z\n\n\nfoo(1, 2, 3)  # (1, 2, 3)\nfoo(x=1, y=2, z=3)  # (1, 2, 3)\nfoo(*[1, 2, 3])  # (1, 2, 3)\nfoo(*[1, 2], 3)  # (1, 2, 3)\n
        ","tags":["B026"]},{"location":"rules/star-arg-unpacking-after-keyword-arg/#references","title":"References","text":"
        • Python documentation: Calls
        • Disallow iterable argument unpacking after a keyword argument?
        ","tags":["B026"]},{"location":"rules/starmap-zip/","title":"starmap-zip (RUF058)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF058"]},{"location":"rules/starmap-zip/#what-it-does","title":"What it does","text":"

        Checks for itertools.starmap calls where the second argument is a zip call.

        ","tags":["RUF058"]},{"location":"rules/starmap-zip/#why-is-this-bad","title":"Why is this bad?","text":"

        zip-ping iterables only to unpack them later from within starmap is unnecessary. For such cases, map() should be used instead.

        ","tags":["RUF058"]},{"location":"rules/starmap-zip/#example","title":"Example","text":"
        from itertools import starmap\n\n\nstarmap(func, zip(a, b))\nstarmap(func, zip(a, b, strict=True))\n

        Use instead:

        map(func, a, b)\nmap(func, a, b, strict=True)  # 3.14+\n
        ","tags":["RUF058"]},{"location":"rules/starmap-zip/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe if the starmap or zip expressions contain comments that would be deleted by applying the fix. Otherwise, the fix can be applied safely.

        ","tags":["RUF058"]},{"location":"rules/starmap-zip/#fix-availability","title":"Fix availability","text":"

        This rule will emit a diagnostic but not suggest a fix if map has been shadowed from its builtin binding.

        ","tags":["RUF058"]},{"location":"rules/start-process-with-a-shell/","title":"start-process-with-a-shell (S605)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S605"]},{"location":"rules/start-process-with-a-shell/#what-it-does","title":"What it does","text":"

        Checks for calls that start a process with a shell, providing guidance on whether the usage is safe or not.

        ","tags":["S605"]},{"location":"rules/start-process-with-a-shell/#why-is-this-bad","title":"Why is this bad?","text":"

        Starting a process with a shell can introduce security risks, such as code injection vulnerabilities. It's important to be aware of whether the usage of the shell is safe or not.

        This rule triggers on functions like os.system, popen, etc., which start processes with a shell. It evaluates whether the provided command is a literal string or an expression. If the command is a literal string, it's considered safe. If the command is an expression, it's considered (potentially) unsafe.

        ","tags":["S605"]},{"location":"rules/start-process-with-a-shell/#example","title":"Example","text":"
        import os\n\n# Safe usage (literal string)\ncommand = \"ls -l\"\nos.system(command)\n\n# Potentially unsafe usage (expression)\ncmd = get_user_input()\nos.system(cmd)\n
        ","tags":["S605"]},{"location":"rules/start-process-with-a-shell/#note","title":"Note","text":"

        The subprocess module provides more powerful facilities for spawning new processes and retrieving their results, and using that module is preferable to using os.system or similar functions. Consider replacing such usages with subprocess.call or related functions.

        ","tags":["S605"]},{"location":"rules/start-process-with-a-shell/#references","title":"References","text":"
        • Python documentation: subprocess
        ","tags":["S605"]},{"location":"rules/start-process-with-no-shell/","title":"start-process-with-no-shell (S606)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S606"]},{"location":"rules/start-process-with-no-shell/#what-it-does","title":"What it does","text":"

        Checks for functions that start a process without a shell.

        ","tags":["S606"]},{"location":"rules/start-process-with-no-shell/#why-is-this-bad","title":"Why is this bad?","text":"

        Invoking any kind of external executable via a function call can pose security risks if arbitrary variables are passed to the executable, or if the input is otherwise unsanitised or unvalidated.

        This rule specifically flags functions in the os module that spawn subprocesses without the use of a shell. Note that these typically pose a much smaller security risk than subprocesses that are started with a shell, which are flagged by start-process-with-a-shell (S605). This gives you the option of enabling one rule while disabling the other if you decide that the security risk from these functions is acceptable for your use case.

        ","tags":["S606"]},{"location":"rules/start-process-with-no-shell/#example","title":"Example","text":"
        import os\n\n\ndef insecure_function(arbitrary_user_input: str):\n    os.spawnlp(os.P_NOWAIT, \"/bin/mycmd\", \"mycmd\", arbitrary_user_input)\n
        ","tags":["S606"]},{"location":"rules/start-process-with-partial-path/","title":"start-process-with-partial-path (S607)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S607"]},{"location":"rules/start-process-with-partial-path/#what-it-does","title":"What it does","text":"

        Checks for the starting of a process with a partial executable path.

        ","tags":["S607"]},{"location":"rules/start-process-with-partial-path/#why-is-this-bad","title":"Why is this bad?","text":"

        Starting a process with a partial executable path can allow attackers to execute an arbitrary executable by adjusting the PATH environment variable. Consider using a full path to the executable instead.

        ","tags":["S607"]},{"location":"rules/start-process-with-partial-path/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.Popen([\"ruff\", \"check\", \"file.py\"])\n

        Use instead:

        import subprocess\n\nsubprocess.Popen([\"/usr/bin/ruff\", \"check\", \"file.py\"])\n
        ","tags":["S607"]},{"location":"rules/start-process-with-partial-path/#references","title":"References","text":"
        • Python documentation: subprocess.Popen()
        • Common Weakness Enumeration: CWE-426
        ","tags":["S607"]},{"location":"rules/static-join-to-f-string/","title":"static-join-to-f-string (FLY002)","text":"

        Derived from the flynt linter.

        Fix is always available.

        ","tags":["FLY002"]},{"location":"rules/static-join-to-f-string/#what-it-does","title":"What it does","text":"

        Checks for str.join calls that can be replaced with f-strings.

        ","tags":["FLY002"]},{"location":"rules/static-join-to-f-string/#why-is-this-bad","title":"Why is this bad?","text":"

        f-strings are more readable and generally preferred over str.join calls.

        ","tags":["FLY002"]},{"location":"rules/static-join-to-f-string/#example","title":"Example","text":"
        \" \".join((foo, bar))\n

        Use instead:

        f\"{foo} {bar}\"\n
        ","tags":["FLY002"]},{"location":"rules/static-join-to-f-string/#fix-safety","title":"Fix safety","text":"

        The fix is always marked unsafe because the evaluation of the f-string expressions will default to calling the __format__ method of each object, whereas str.join expects each object to be an instance of str and uses the corresponding string. Therefore it is possible for the values of the resulting strings to differ, or for one expression to raise an exception while the other does not.

        ","tags":["FLY002"]},{"location":"rules/static-join-to-f-string/#references","title":"References","text":"
        • Python documentation: f-strings
        ","tags":["FLY002"]},{"location":"rules/static-key-dict-comprehension/","title":"static-key-dict-comprehension (B035)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B035"]},{"location":"rules/static-key-dict-comprehension/#what-it-does","title":"What it does","text":"

        Checks for dictionary comprehensions that use a static key, like a string literal or a variable defined outside the comprehension.

        ","tags":["B035"]},{"location":"rules/static-key-dict-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        Using a static key (like a string literal) in a dictionary comprehension is usually a mistake, as it will result in a dictionary with only one key, despite the comprehension iterating over multiple values.

        ","tags":["B035"]},{"location":"rules/static-key-dict-comprehension/#example","title":"Example","text":"
        data = [\"some\", \"Data\"]\n{\"key\": value.upper() for value in data}\n

        Use instead:

        data = [\"some\", \"Data\"]\n{value: value.upper() for value in data}\n
        ","tags":["B035"]},{"location":"rules/stdlib-module-shadowing/","title":"stdlib-module-shadowing (A005)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A005"]},{"location":"rules/stdlib-module-shadowing/#what-it-does","title":"What it does","text":"

        Checks for modules that use the same names as Python standard-library modules.

        ","tags":["A005"]},{"location":"rules/stdlib-module-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a standard-library module name for the name of a module increases the difficulty of reading and maintaining the code, and can cause non-obvious errors. Readers may mistake the first-party module for the standard-library module and vice versa.

        Standard-library modules can be marked as exceptions to this rule via the lint.flake8-builtins.allowed-modules configuration option.

        By default, the module path relative to the project root or src directories is considered, so a top-level logging.py or logging/__init__.py will clash with the builtin logging module, but utils/logging.py, for example, will not. With the lint.flake8-builtins.strict-checking option set to true, only the last component of the module name is considered, so logging.py, utils/logging.py, and utils/logging/__init__.py will all trigger the rule.

        This rule is not applied to stub files, as the name of a stub module is out of the control of the author of the stub file. Instead, a stub should aim to faithfully emulate the runtime module it is stubbing.

        As of Python 3.13, errors from modules that use the same name as standard-library modules now display a custom message.

        ","tags":["A005"]},{"location":"rules/stdlib-module-shadowing/#example","title":"Example","text":"
        $ touch random.py\n$ python3 -c 'from random import choice'\nTraceback (most recent call last):\n  File \"<string>\", line 1, in <module>\n    from random import choice\nImportError: cannot import name 'choice' from 'random' (consider renaming '/random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)\n
        ","tags":["A005"]},{"location":"rules/stdlib-module-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.allowed-modules
        • lint.flake8-builtins.strict-checking
        ","tags":["A005"]},{"location":"rules/str-or-repr-defined-in-stub/","title":"str-or-repr-defined-in-stub (PYI029)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI029"]},{"location":"rules/str-or-repr-defined-in-stub/#what-it-does","title":"What it does","text":"

        Checks for redundant definitions of __str__ or __repr__ in stubs.

        ","tags":["PYI029"]},{"location":"rules/str-or-repr-defined-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Defining __str__ or __repr__ in a stub is almost always redundant, as the signatures are almost always identical to those of the default equivalent, object.__str__ and object.__repr__, respectively.

        ","tags":["PYI029"]},{"location":"rules/str-or-repr-defined-in-stub/#example","title":"Example","text":"
        class Foo:\n    def __repr__(self) -> str: ...\n
        ","tags":["PYI029"]},{"location":"rules/string-dot-format-extra-named-arguments/","title":"string-dot-format-extra-named-arguments (F522)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F522"]},{"location":"rules/string-dot-format-extra-named-arguments/#what-it-does","title":"What it does","text":"

        Checks for str.format calls with unused keyword arguments.

        ","tags":["F522"]},{"location":"rules/string-dot-format-extra-named-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused keyword arguments are redundant, and often indicative of a mistake. They should be removed.

        ","tags":["F522"]},{"location":"rules/string-dot-format-extra-named-arguments/#example","title":"Example","text":"
        \"Hello, {name}\".format(greeting=\"Hello\", name=\"World\")\n

        Use instead:

        \"Hello, {name}\".format(name=\"World\")\n
        ","tags":["F522"]},{"location":"rules/string-dot-format-extra-named-arguments/#references","title":"References","text":"
        • Python documentation: str.format
        ","tags":["F522"]},{"location":"rules/string-dot-format-extra-positional-arguments/","title":"string-dot-format-extra-positional-arguments (F523)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F523"]},{"location":"rules/string-dot-format-extra-positional-arguments/#what-it-does","title":"What it does","text":"

        Checks for str.format calls with unused positional arguments.

        ","tags":["F523"]},{"location":"rules/string-dot-format-extra-positional-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused positional arguments are redundant, and often indicative of a mistake. They should be removed.

        ","tags":["F523"]},{"location":"rules/string-dot-format-extra-positional-arguments/#example","title":"Example","text":"
        \"Hello, {0}\".format(\"world\", \"!\")\n

        Use instead:

        \"Hello, {0}\".format(\"world\")\n
        ","tags":["F523"]},{"location":"rules/string-dot-format-extra-positional-arguments/#references","title":"References","text":"
        • Python documentation: str.format
        ","tags":["F523"]},{"location":"rules/string-dot-format-invalid-format/","title":"string-dot-format-invalid-format (F521)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F521"]},{"location":"rules/string-dot-format-invalid-format/#what-it-does","title":"What it does","text":"

        Checks for str.format calls with invalid format strings.

        ","tags":["F521"]},{"location":"rules/string-dot-format-invalid-format/#why-is-this-bad","title":"Why is this bad?","text":"

        Invalid format strings will raise a ValueError.

        ","tags":["F521"]},{"location":"rules/string-dot-format-invalid-format/#example","title":"Example","text":"
        \"{\".format(foo)\n

        Use instead:

        \"{}\".format(foo)\n
        ","tags":["F521"]},{"location":"rules/string-dot-format-invalid-format/#references","title":"References","text":"
        • Python documentation: str.format
        ","tags":["F521"]},{"location":"rules/string-dot-format-missing-arguments/","title":"string-dot-format-missing-arguments (F524)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F524"]},{"location":"rules/string-dot-format-missing-arguments/#what-it-does","title":"What it does","text":"

        Checks for str.format calls with placeholders that are missing arguments.

        ","tags":["F524"]},{"location":"rules/string-dot-format-missing-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        In str.format calls, omitting arguments for placeholders will raise a KeyError at runtime.

        ","tags":["F524"]},{"location":"rules/string-dot-format-missing-arguments/#example","title":"Example","text":"
        \"{greeting}, {name}\".format(name=\"World\")\n

        Use instead:

        \"{greeting}, {name}\".format(greeting=\"Hello\", name=\"World\")\n
        ","tags":["F524"]},{"location":"rules/string-dot-format-missing-arguments/#references","title":"References","text":"
        • Python documentation: str.format
        ","tags":["F524"]},{"location":"rules/string-dot-format-mixing-automatic/","title":"string-dot-format-mixing-automatic (F525)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F525"]},{"location":"rules/string-dot-format-mixing-automatic/#what-it-does","title":"What it does","text":"

        Checks for str.format calls that mix automatic and manual numbering.

        ","tags":["F525"]},{"location":"rules/string-dot-format-mixing-automatic/#why-is-this-bad","title":"Why is this bad?","text":"

        In str.format calls, mixing automatic and manual numbering will raise a ValueError at runtime.

        ","tags":["F525"]},{"location":"rules/string-dot-format-mixing-automatic/#example","title":"Example","text":"
        \"{0}, {}\".format(\"Hello\", \"World\")\n

        Use instead:

        \"{0}, {1}\".format(\"Hello\", \"World\")\n

        Or:

        \"{}, {}\".format(\"Hello\", \"World\")\n
        ","tags":["F525"]},{"location":"rules/string-dot-format-mixing-automatic/#references","title":"References","text":"
        • Python documentation: str.format
        ","tags":["F525"]},{"location":"rules/string-or-bytes-too-long/","title":"string-or-bytes-too-long (PYI053)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI053"]},{"location":"rules/string-or-bytes-too-long/#what-it-does","title":"What it does","text":"

        Checks for the use of string and bytes literals longer than 50 characters in stub (.pyi) files.

        ","tags":["PYI053"]},{"location":"rules/string-or-bytes-too-long/#why-is-this-bad","title":"Why is this bad?","text":"

        If a function or variable has a default value where the string or bytes representation is greater than 50 characters long, it is likely to be an implementation detail or a constant that varies depending on the system you're running on.

        Although IDEs may find them useful, default values are ignored by type checkers, the primary consumers of stub files. Replace very long constants with ellipses (...) to simplify the stub.

        ","tags":["PYI053"]},{"location":"rules/string-or-bytes-too-long/#example","title":"Example","text":"
        def foo(arg: str = \"51 character stringgggggggggggggggggggggggggggggggg\") -> None: ...\n

        Use instead:

        def foo(arg: str = ...) -> None: ...\n
        ","tags":["PYI053"]},{"location":"rules/strip-with-multi-characters/","title":"strip-with-multi-characters (B005)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B005"]},{"location":"rules/strip-with-multi-characters/#what-it-does","title":"What it does","text":"

        Checks for uses of multi-character strings in .strip(), .lstrip(), and .rstrip() calls.

        ","tags":["B005"]},{"location":"rules/strip-with-multi-characters/#why-is-this-bad","title":"Why is this bad?","text":"

        All characters in the call to .strip(), .lstrip(), or .rstrip() are removed from the leading and trailing ends of the string. If the string contains multiple characters, the reader may be misled into thinking that a prefix or suffix is being removed, rather than a set of characters.

        In Python 3.9 and later, you can use str.removeprefix and str.removesuffix to remove an exact prefix or suffix from a string, respectively, which should be preferred when possible.

        ","tags":["B005"]},{"location":"rules/strip-with-multi-characters/#known-problems","title":"Known problems","text":"

        As a heuristic, this rule only flags multi-character strings that contain duplicate characters. This allows usages like .strip(\"xyz\"), which removes all occurrences of the characters x, y, and z from the leading and trailing ends of the string, but not .strip(\"foo\").

        The use of unique, multi-character strings may be intentional and consistent with the intent of .strip(), .lstrip(), or .rstrip(), while the use of duplicate-character strings is very likely to be a mistake.

        ","tags":["B005"]},{"location":"rules/strip-with-multi-characters/#example","title":"Example","text":"
        \"text.txt\".strip(\".txt\")  # \"e\"\n

        Use instead:

        \"text.txt\".removesuffix(\".txt\")  # \"text\"\n
        ","tags":["B005"]},{"location":"rules/strip-with-multi-characters/#references","title":"References","text":"
        • Python documentation: str.strip
        ","tags":["B005"]},{"location":"rules/stub-body-multiple-statements/","title":"stub-body-multiple-statements (PYI048)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI048"]},{"location":"rules/stub-body-multiple-statements/#what-it-does","title":"What it does","text":"

        Checks for functions in stub (.pyi) files that contain multiple statements.

        ","tags":["PYI048"]},{"location":"rules/stub-body-multiple-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files are never executed, and are only intended to define type hints. As such, functions in stub files should not contain functional code, and should instead contain only a single statement (e.g., ...).

        ","tags":["PYI048"]},{"location":"rules/stub-body-multiple-statements/#example","title":"Example","text":"
        def function():\n    x = 1\n    y = 2\n    return x + y\n

        Use instead:

        def function(): ...\n
        ","tags":["PYI048"]},{"location":"rules/subclass-builtin/","title":"subclass-builtin (FURB189)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB189"]},{"location":"rules/subclass-builtin/#what-it-does","title":"What it does","text":"

        Checks for subclasses of dict, list or str.

        ","tags":["FURB189"]},{"location":"rules/subclass-builtin/#why-is-this-bad","title":"Why is this bad?","text":"

        Built-in types don't consistently use their own dunder methods. For example, dict.__init__ and dict.update() bypass __setitem__, making inheritance unreliable.

        Use the UserDict, UserList, and UserString objects from the collections module instead.

        ","tags":["FURB189"]},{"location":"rules/subclass-builtin/#example","title":"Example","text":"
        class UppercaseDict(dict):\n    def __setitem__(self, key, value):\n        super().__setitem__(key.upper(), value)\n\n\nd = UppercaseDict({\"a\": 1, \"b\": 2})  # Bypasses __setitem__\nprint(d)  # {'a': 1, 'b': 2}\n

        Use instead:

        from collections import UserDict\n\n\nclass UppercaseDict(UserDict):\n    def __setitem__(self, key, value):\n        super().__setitem__(key.upper(), value)\n\n\nd = UppercaseDict({\"a\": 1, \"b\": 2})  # Uses __setitem__\nprint(d)  # {'A': 1, 'B': 2}\n
        ","tags":["FURB189"]},{"location":"rules/subclass-builtin/#fix-safety","title":"Fix safety","text":"

        This fix is marked as unsafe because isinstance() checks for dict, list, and str types will fail when using the corresponding User class. If you need to pass custom dict or list objects to code you don't control, ignore this check. If you do control the code, consider using the following type checks instead:

        • dict -> collections.abc.MutableMapping
        • list -> collections.abc.MutableSequence
        • str -> No such conversion exists
        ","tags":["FURB189"]},{"location":"rules/subclass-builtin/#references","title":"References","text":"
        • Python documentation: collections
        ","tags":["FURB189"]},{"location":"rules/subprocess-popen-preexec-fn/","title":"subprocess-popen-preexec-fn (PLW1509)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW1509"]},{"location":"rules/subprocess-popen-preexec-fn/#what-it-does","title":"What it does","text":"

        Checks for uses of subprocess.Popen with a preexec_fn argument.

        ","tags":["PLW1509"]},{"location":"rules/subprocess-popen-preexec-fn/#why-is-this-bad","title":"Why is this bad?","text":"

        The preexec_fn argument is unsafe within threads as it can lead to deadlocks. Furthermore, preexec_fn is targeted for deprecation.

        Instead, consider using task-specific arguments such as env, start_new_session, and process_group. These are not prone to deadlocks and are more explicit.

        ","tags":["PLW1509"]},{"location":"rules/subprocess-popen-preexec-fn/#example","title":"Example","text":"
        import os, subprocess\n\nsubprocess.Popen(foo, preexec_fn=os.setsid)\nsubprocess.Popen(bar, preexec_fn=os.setpgid(0, 0))\n

        Use instead:

        import subprocess\n\nsubprocess.Popen(foo, start_new_session=True)\nsubprocess.Popen(bar, process_group=0)  # Introduced in Python 3.11\n
        ","tags":["PLW1509"]},{"location":"rules/subprocess-popen-preexec-fn/#references","title":"References","text":"
        • Python documentation: subprocess.Popen
        • Why preexec_fn in subprocess.Popen may lead to deadlock?
        ","tags":["PLW1509"]},{"location":"rules/subprocess-popen-with-shell-equals-true/","title":"subprocess-popen-with-shell-equals-true (S602)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S602"]},{"location":"rules/subprocess-popen-with-shell-equals-true/#what-it-does","title":"What it does","text":"

        Check for method calls that initiate a subprocess with a shell.

        ","tags":["S602"]},{"location":"rules/subprocess-popen-with-shell-equals-true/#why-is-this-bad","title":"Why is this bad?","text":"

        Starting a subprocess with a shell can allow attackers to execute arbitrary shell commands. Consider starting the process without a shell call and sanitize the input to mitigate the risk of shell injection.

        ","tags":["S602"]},{"location":"rules/subprocess-popen-with-shell-equals-true/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.run(\"ls -l\", shell=True)\n

        Use instead:

        import subprocess\n\nsubprocess.run([\"ls\", \"-l\"])\n
        ","tags":["S602"]},{"location":"rules/subprocess-popen-with-shell-equals-true/#references","title":"References","text":"
        • Python documentation: subprocess \u2014 Subprocess management
        • Common Weakness Enumeration: CWE-78
        ","tags":["S602"]},{"location":"rules/subprocess-run-without-check/","title":"subprocess-run-without-check (PLW1510)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLW1510"]},{"location":"rules/subprocess-run-without-check/#what-it-does","title":"What it does","text":"

        Checks for uses of subprocess.run without an explicit check argument.

        ","tags":["PLW1510"]},{"location":"rules/subprocess-run-without-check/#why-is-this-bad","title":"Why is this bad?","text":"

        By default, subprocess.run does not check the return code of the process it runs. This can lead to silent failures.

        Instead, consider using check=True to raise an exception if the process fails, or set check=False explicitly to mark the behavior as intentional.

        ","tags":["PLW1510"]},{"location":"rules/subprocess-run-without-check/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.run([\"ls\", \"nonexistent\"])  # No exception raised.\n

        Use instead:

        import subprocess\n\nsubprocess.run([\"ls\", \"nonexistent\"], check=True)  # Raises exception.\n

        Or:

        import subprocess\n\nsubprocess.run([\"ls\", \"nonexistent\"], check=False)  # Explicitly no check.\n
        ","tags":["PLW1510"]},{"location":"rules/subprocess-run-without-check/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for function calls that contain **kwargs, as adding a check keyword argument to such a call may lead to a duplicate keyword argument error.

        ","tags":["PLW1510"]},{"location":"rules/subprocess-run-without-check/#references","title":"References","text":"
        • Python documentation: subprocess.run
        ","tags":["PLW1510"]},{"location":"rules/subprocess-without-shell-equals-true/","title":"subprocess-without-shell-equals-true (S603)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S603"]},{"location":"rules/subprocess-without-shell-equals-true/#what-it-does","title":"What it does","text":"

        Check for method calls that initiate a subprocess without a shell.

        ","tags":["S603"]},{"location":"rules/subprocess-without-shell-equals-true/#why-is-this-bad","title":"Why is this bad?","text":"

        Starting a subprocess without a shell can prevent attackers from executing arbitrary shell commands; however, it is still error-prone. Consider validating the input.

        ","tags":["S603"]},{"location":"rules/subprocess-without-shell-equals-true/#known-problems","title":"Known problems","text":"

        Prone to false positives as it is difficult to determine whether the passed arguments have been validated (#4045).

        ","tags":["S603"]},{"location":"rules/subprocess-without-shell-equals-true/#example","title":"Example","text":"
        import subprocess\n\ncmd = input(\"Enter a command: \").split()\nsubprocess.run(cmd)\n
        ","tags":["S603"]},{"location":"rules/subprocess-without-shell-equals-true/#references","title":"References","text":"
        • Python documentation: subprocess \u2014 Subprocess management
        ","tags":["S603"]},{"location":"rules/super-call-with-parameters/","title":"super-call-with-parameters (UP008)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP008"]},{"location":"rules/super-call-with-parameters/#what-it-does","title":"What it does","text":"

        Checks for super calls that pass redundant arguments.

        ","tags":["UP008"]},{"location":"rules/super-call-with-parameters/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3, super can be invoked without any arguments when: (1) the first argument is __class__, and (2) the second argument is equivalent to the first argument of the enclosing method.

        When possible, omit the arguments to super to make the code more concise and maintainable.

        ","tags":["UP008"]},{"location":"rules/super-call-with-parameters/#example","title":"Example","text":"
        class A:\n    def foo(self):\n        pass\n\n\nclass B(A):\n    def bar(self):\n        super(B, self).foo()\n

        Use instead:

        class A:\n    def foo(self):\n        pass\n\n\nclass B(A):\n    def bar(self):\n        super().foo()\n
        ","tags":["UP008"]},{"location":"rules/super-call-with-parameters/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because removing the arguments from a call may delete comments that are attached to the arguments.

        ","tags":["UP008"]},{"location":"rules/super-call-with-parameters/#references","title":"References","text":"
        • Python documentation: super
        • super/MRO, Python's most misunderstood feature.
        ","tags":["UP008"]},{"location":"rules/super-without-brackets/","title":"super-without-brackets (PLW0245)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLW0245"]},{"location":"rules/super-without-brackets/#what-it-does","title":"What it does","text":"

        Detects attempts to use super without parentheses.

        ","tags":["PLW0245"]},{"location":"rules/super-without-brackets/#why-is-this-bad","title":"Why is this bad?","text":"

        The super() callable can be used inside method definitions to create a proxy object that delegates attribute access to a superclass of the current class. Attempting to access attributes on super itself, however, instead of the object returned by a call to super(), will raise AttributeError.

        ","tags":["PLW0245"]},{"location":"rules/super-without-brackets/#example","title":"Example","text":"
        class Animal:\n    @staticmethod\n    def speak():\n        return \"This animal says something.\"\n\n\nclass Dog(Animal):\n    @staticmethod\n    def speak():\n        original_speak = super.speak()  # ERROR: `super.speak()`\n        return f\"{original_speak} But as a dog, it barks!\"\n

        Use instead:

        class Animal:\n    @staticmethod\n    def speak():\n        return \"This animal says something.\"\n\n\nclass Dog(Animal):\n    @staticmethod\n    def speak():\n        original_speak = super().speak()  # Correct: `super().speak()`\n        return f\"{original_speak} But as a dog, it barks!\"\n
        ","tags":["PLW0245"]},{"location":"rules/superfluous-else-break/","title":"superfluous-else-break (RET508)","text":"

        Derived from the flake8-return linter.

        Fix is sometimes available.

        ","tags":["RET508"]},{"location":"rules/superfluous-else-break/#what-it-does","title":"What it does","text":"

        Checks for else statements with a break statement in the preceding if block.

        ","tags":["RET508"]},{"location":"rules/superfluous-else-break/#why-is-this-bad","title":"Why is this bad?","text":"

        The else statement is not needed, as the break statement will always break out of the loop. Removing the else will reduce nesting and make the code more readable.

        ","tags":["RET508"]},{"location":"rules/superfluous-else-break/#example","title":"Example","text":"
        def foo(bar, baz):\n    for i in bar:\n        if i > baz:\n            break\n        else:\n            x = 0\n

        Use instead:

        def foo(bar, baz):\n    for i in bar:\n        if i > baz:\n            break\n        x = 0\n
        ","tags":["RET508"]},{"location":"rules/superfluous-else-continue/","title":"superfluous-else-continue (RET507)","text":"

        Derived from the flake8-return linter.

        Fix is sometimes available.

        ","tags":["RET507"]},{"location":"rules/superfluous-else-continue/#what-it-does","title":"What it does","text":"

        Checks for else statements with a continue statement in the preceding if block.

        ","tags":["RET507"]},{"location":"rules/superfluous-else-continue/#why-is-this-bad","title":"Why is this bad?","text":"

        The else statement is not needed, as the continue statement will always continue onto the next iteration of a loop. Removing the else will reduce nesting and make the code more readable.

        ","tags":["RET507"]},{"location":"rules/superfluous-else-continue/#example","title":"Example","text":"
        def foo(bar, baz):\n    for i in bar:\n        if i < baz:\n            continue\n        else:\n            x = 0\n

        Use instead:

        def foo(bar, baz):\n    for i in bar:\n        if i < baz:\n            continue\n        x = 0\n
        ","tags":["RET507"]},{"location":"rules/superfluous-else-raise/","title":"superfluous-else-raise (RET506)","text":"

        Derived from the flake8-return linter.

        Fix is sometimes available.

        ","tags":["RET506"]},{"location":"rules/superfluous-else-raise/#what-it-does","title":"What it does","text":"

        Checks for else statements with a raise statement in the preceding if block.

        ","tags":["RET506"]},{"location":"rules/superfluous-else-raise/#why-is-this-bad","title":"Why is this bad?","text":"

        The else statement is not needed as the raise statement will always break out of the current scope. Removing the else will reduce nesting and make the code more readable.

        ","tags":["RET506"]},{"location":"rules/superfluous-else-raise/#example","title":"Example","text":"
        def foo(bar, baz):\n    if bar == \"Specific Error\":\n        raise Exception(bar)\n    else:\n        raise Exception(baz)\n

        Use instead:

        def foo(bar, baz):\n    if bar == \"Specific Error\":\n        raise Exception(bar)\n    raise Exception(baz)\n
        ","tags":["RET506"]},{"location":"rules/superfluous-else-return/","title":"superfluous-else-return (RET505)","text":"

        Derived from the flake8-return linter.

        Fix is sometimes available.

        ","tags":["RET505"]},{"location":"rules/superfluous-else-return/#what-it-does","title":"What it does","text":"

        Checks for else statements with a return statement in the preceding if block.

        ","tags":["RET505"]},{"location":"rules/superfluous-else-return/#why-is-this-bad","title":"Why is this bad?","text":"

        The else statement is not needed as the return statement will always break out of the enclosing function. Removing the else will reduce nesting and make the code more readable.

        ","tags":["RET505"]},{"location":"rules/superfluous-else-return/#example","title":"Example","text":"
        def foo(bar, baz):\n    if bar:\n        return 1\n    else:\n        return baz\n

        Use instead:

        def foo(bar, baz):\n    if bar:\n        return 1\n    return baz\n
        ","tags":["RET505"]},{"location":"rules/suppressible-exception/","title":"suppressible-exception (SIM105)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM105"]},{"location":"rules/suppressible-exception/#what-it-does","title":"What it does","text":"

        Checks for try-except-pass blocks that can be replaced with the contextlib.suppress context manager.

        ","tags":["SIM105"]},{"location":"rules/suppressible-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Using contextlib.suppress is more concise and directly communicates the intent of the code: to suppress a given exception.

        Note that contextlib.suppress is slower than using try-except-pass directly. For performance-critical code, consider retaining the try-except-pass pattern.

        ","tags":["SIM105"]},{"location":"rules/suppressible-exception/#example","title":"Example","text":"
        try:\n    1 / 0\nexcept ZeroDivisionError:\n    pass\n

        Use instead:

        import contextlib\n\nwith contextlib.suppress(ZeroDivisionError):\n    1 / 0\n
        ","tags":["SIM105"]},{"location":"rules/suppressible-exception/#references","title":"References","text":"
        • Python documentation: contextlib.suppress
        • Python documentation: try statement
        • a simpler try/except (and why maybe shouldn't)
        ","tags":["SIM105"]},{"location":"rules/surrounding-whitespace/","title":"surrounding-whitespace (D210)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D210"]},{"location":"rules/surrounding-whitespace/#what-it-does","title":"What it does","text":"

        Checks for surrounding whitespace in docstrings.

        ","tags":["D210"]},{"location":"rules/surrounding-whitespace/#why-is-this-bad","title":"Why is this bad?","text":"

        Remove surrounding whitespace from the docstring, for consistency.

        ","tags":["D210"]},{"location":"rules/surrounding-whitespace/#example","title":"Example","text":"
        def factorial(n: int) -> int:\n    \"\"\" Return the factorial of n. \"\"\"\n

        Use instead:

        def factorial(n: int) -> int:\n    \"\"\"Return the factorial of n.\"\"\"\n
        ","tags":["D210"]},{"location":"rules/surrounding-whitespace/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D210"]},{"location":"rules/suspicious-eval-usage/","title":"suspicious-eval-usage (S307)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S307"]},{"location":"rules/suspicious-eval-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of the builtin eval() function.

        ","tags":["S307"]},{"location":"rules/suspicious-eval-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        The eval() function is insecure as it enables arbitrary code execution.

        If you need to evaluate an expression from a string, consider using ast.literal_eval() instead, which will raise an exception if the expression is not a valid Python literal.

        In preview, this rule will also flag references to eval.

        ","tags":["S307"]},{"location":"rules/suspicious-eval-usage/#example","title":"Example","text":"
        x = eval(input(\"Enter a number: \"))\n

        Use instead:

        from ast import literal_eval\n\nx = literal_eval(input(\"Enter a number: \"))\n
        ","tags":["S307"]},{"location":"rules/suspicious-eval-usage/#references","title":"References","text":"
        • Python documentation: eval
        • Python documentation: literal_eval
        • Eval really is dangerous by Ned Batchelder
        ","tags":["S307"]},{"location":"rules/suspicious-ftp-lib-usage/","title":"suspicious-ftp-lib-usage (S321)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S321"]},{"location":"rules/suspicious-ftp-lib-usage/#what-it-does","title":"What it does","text":"

        Checks for the use of FTP-related functions.

        ","tags":["S321"]},{"location":"rules/suspicious-ftp-lib-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        FTP is considered insecure as it does not encrypt data sent over the connection and is thus vulnerable to numerous attacks.

        Instead, consider using FTPS (which secures FTP using SSL/TLS) or SFTP.

        In preview, this rule will also flag references to FTP-related functions.

        ","tags":["S321"]},{"location":"rules/suspicious-ftp-lib-usage/#references","title":"References","text":"
        • Python documentation: ftplib \u2014 FTP protocol client
        ","tags":["S321"]},{"location":"rules/suspicious-ftplib-import/","title":"suspicious-ftplib-import (S402)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S402"]},{"location":"rules/suspicious-ftplib-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the ftplib module.

        ","tags":["S402"]},{"location":"rules/suspicious-ftplib-import/#why-is-this-bad","title":"Why is this bad?","text":"

        FTP is considered insecure. Instead, use SSH, SFTP, SCP, or another encrypted protocol.

        ","tags":["S402"]},{"location":"rules/suspicious-ftplib-import/#example","title":"Example","text":"
        import ftplib\n
        ","tags":["S402"]},{"location":"rules/suspicious-ftplib-import/#references","title":"References","text":"
        • Python documentation: ftplib - FTP protocol client
        ","tags":["S402"]},{"location":"rules/suspicious-httpoxy-import/","title":"suspicious-httpoxy-import (S412)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S412"]},{"location":"rules/suspicious-httpoxy-import/#what-it-does","title":"What it does","text":"

        Checks for imports of wsgiref.handlers.CGIHandler and twisted.web.twcgi.CGIScript.

        ","tags":["S412"]},{"location":"rules/suspicious-httpoxy-import/#why-is-this-bad","title":"Why is this bad?","text":"

        httpoxy is a set of vulnerabilities that affect application code running in CGI or CGI-like environments. The use of CGI for web applications should be avoided to prevent this class of attack.

        ","tags":["S412"]},{"location":"rules/suspicious-httpoxy-import/#example","title":"Example","text":"
        import wsgiref.handlers.CGIHandler\n
        ","tags":["S412"]},{"location":"rules/suspicious-httpoxy-import/#references","title":"References","text":"
        • httpoxy website
        ","tags":["S412"]},{"location":"rules/suspicious-insecure-cipher-mode-usage/","title":"suspicious-insecure-cipher-mode-usage (S305)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S305"]},{"location":"rules/suspicious-insecure-cipher-mode-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of weak or broken cryptographic cipher modes.

        ","tags":["S305"]},{"location":"rules/suspicious-insecure-cipher-mode-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Weak or broken cryptographic ciphers may be susceptible to attacks that allow an attacker to decrypt ciphertext without knowing the key or otherwise compromise the security of the cipher, such as forgeries.

        Use strong, modern cryptographic ciphers instead of weak or broken ones.

        In preview, this rule will also flag references to insecure cipher modes.

        ","tags":["S305"]},{"location":"rules/suspicious-insecure-cipher-mode-usage/#example","title":"Example","text":"
        from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes\n\nalgorithm = algorithms.ARC4(key)\ncipher = Cipher(algorithm, mode=modes.ECB(iv))\nencryptor = cipher.encryptor()\n

        Use instead:

        from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes\n\nalgorithm = algorithms.ARC4(key)\ncipher = Cipher(algorithm, mode=modes.CTR(iv))\nencryptor = cipher.encryptor()\n
        ","tags":["S305"]},{"location":"rules/suspicious-insecure-cipher-mode-usage/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-327
        ","tags":["S305"]},{"location":"rules/suspicious-insecure-cipher-usage/","title":"suspicious-insecure-cipher-usage (S304)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S304"]},{"location":"rules/suspicious-insecure-cipher-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of weak or broken cryptographic ciphers.

        ","tags":["S304"]},{"location":"rules/suspicious-insecure-cipher-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Weak or broken cryptographic ciphers may be susceptible to attacks that allow an attacker to decrypt ciphertext without knowing the key or otherwise compromise the security of the cipher, such as forgeries.

        Use strong, modern cryptographic ciphers instead of weak or broken ones.

        In preview, this rule will also flag references to insecure ciphers.

        ","tags":["S304"]},{"location":"rules/suspicious-insecure-cipher-usage/#example","title":"Example","text":"
        from cryptography.hazmat.primitives.ciphers import Cipher, algorithms\n\nalgorithm = algorithms.ARC4(key)\ncipher = Cipher(algorithm, mode=None)\nencryptor = cipher.encryptor()\n

        Use instead:

        from cryptography.fernet import Fernet\n\nfernet = Fernet(key)\n
        ","tags":["S304"]},{"location":"rules/suspicious-insecure-cipher-usage/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-327
        ","tags":["S304"]},{"location":"rules/suspicious-insecure-hash-usage/","title":"suspicious-insecure-hash-usage (S303)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S303"]},{"location":"rules/suspicious-insecure-hash-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of weak or broken cryptographic hash functions.

        ","tags":["S303"]},{"location":"rules/suspicious-insecure-hash-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Weak or broken cryptographic hash functions may be susceptible to collision attacks (where two different inputs produce the same hash) or pre-image attacks (where an attacker can find an input that produces a given hash). This can lead to security vulnerabilities in applications that rely on these hash functions.

        Avoid using weak or broken cryptographic hash functions in security contexts. Instead, use a known secure hash function such as SHA-256.

        In preview, this rule will also flag references to insecure hash functions.

        ","tags":["S303"]},{"location":"rules/suspicious-insecure-hash-usage/#example","title":"Example","text":"
        from cryptography.hazmat.primitives import hashes\n\ndigest = hashes.Hash(hashes.MD5())\ndigest.update(b\"Hello, world!\")\ndigest.finalize()\n

        Use instead:

        from cryptography.hazmat.primitives import hashes\n\ndigest = hashes.Hash(hashes.SHA256())\ndigest.update(b\"Hello, world!\")\ndigest.finalize()\n
        ","tags":["S303"]},{"location":"rules/suspicious-insecure-hash-usage/#references","title":"References","text":"
        • Python documentation: hashlib \u2014 Secure hashes and message digests
        • Common Weakness Enumeration: CWE-327
        • Common Weakness Enumeration: CWE-328
        • Common Weakness Enumeration: CWE-916
        ","tags":["S303"]},{"location":"rules/suspicious-lxml-import/","title":"suspicious-lxml-import (S410)","text":"

        Derived from the flake8-bandit linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["S410"]},{"location":"rules/suspicious-lxml-import/#removed","title":"Removed","text":"

        This rule was removed as the lxml library has been modified to address known vulnerabilities and unsafe defaults. As such, the defusedxml library is no longer necessary, defusedxml has deprecated its lxml module.

        ","tags":["S410"]},{"location":"rules/suspicious-lxml-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the lxml module.

        ","tags":["S410"]},{"location":"rules/suspicious-lxml-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from the lxml module to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package.

        ","tags":["S410"]},{"location":"rules/suspicious-lxml-import/#example","title":"Example","text":"
        import lxml\n
        ","tags":["S410"]},{"location":"rules/suspicious-mark-safe-usage/","title":"suspicious-mark-safe-usage (S308)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S308"]},{"location":"rules/suspicious-mark-safe-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of calls to django.utils.safestring.mark_safe.

        ","tags":["S308"]},{"location":"rules/suspicious-mark-safe-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Cross-site scripting (XSS) vulnerabilities allow attackers to execute arbitrary JavaScript. To guard against XSS attacks, Django templates assumes that data is unsafe and automatically escapes malicious strings before rending them.

        django.utils.safestring.mark_safe marks a string as safe for use in HTML templates, bypassing XSS protection. Its usage can be dangerous if the contents of the string are dynamically generated, because it may allow cross-site scripting attacks if the string is not properly escaped.

        For dynamically generated strings, consider utilizing django.utils.html.format_html.

        In preview, this rule will also flag references to django.utils.safestring.mark_safe.

        ","tags":["S308"]},{"location":"rules/suspicious-mark-safe-usage/#example","title":"Example","text":"
        from django.utils.safestring import mark_safe\n\n\ndef render_username(username):\n    return mark_safe(f\"<i>{username}</i>\")  # Dangerous if username is user-provided.\n

        Use instead:

        from django.utils.html import format_html\n\n\ndef render_username(username):\n    return django.utils.html.format_html(\"<i>{}</i>\", username)  # username is escaped.\n
        ","tags":["S308"]},{"location":"rules/suspicious-mark-safe-usage/#references","title":"References","text":"
        • Django documentation: mark_safe
        • Django documentation: Cross Site Scripting (XSS) protection
        • Common Weakness Enumeration: CWE-80
        ","tags":["S308"]},{"location":"rules/suspicious-marshal-usage/","title":"suspicious-marshal-usage (S302)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S302"]},{"location":"rules/suspicious-marshal-usage/#what-it-does","title":"What it does","text":"

        Checks for calls to marshal functions.

        ","tags":["S302"]},{"location":"rules/suspicious-marshal-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Deserializing untrusted data with marshal is insecure, as it can allow for the creation of arbitrary objects, which can then be used to achieve arbitrary code execution and otherwise unexpected behavior.

        Avoid deserializing untrusted data with marshal. Instead, consider safer formats, such as JSON.

        If you must deserialize untrusted data with marshal, consider signing the data with a secret key and verifying the signature before deserializing the payload. This will prevent an attacker from injecting arbitrary objects into the serialized data.

        In preview, this rule will also flag references to marshal functions.

        ","tags":["S302"]},{"location":"rules/suspicious-marshal-usage/#example","title":"Example","text":"
        import marshal\n\nwith open(\"foo.marshal\", \"rb\") as file:\n    foo = marshal.load(file)\n

        Use instead:

        import json\n\nwith open(\"foo.json\", \"rb\") as file:\n    foo = json.load(file)\n
        ","tags":["S302"]},{"location":"rules/suspicious-marshal-usage/#references","title":"References","text":"
        • Python documentation: marshal \u2014 Internal Python object serialization
        • Common Weakness Enumeration: CWE-502
        ","tags":["S302"]},{"location":"rules/suspicious-mktemp-usage/","title":"suspicious-mktemp-usage (S306)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S306"]},{"location":"rules/suspicious-mktemp-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of tempfile.mktemp.

        ","tags":["S306"]},{"location":"rules/suspicious-mktemp-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        tempfile.mktemp returns a pathname of a file that does not exist at the time the call is made; then, the caller is responsible for creating the file and subsequently using it. This is insecure because another process could create a file with the same name between the time the function returns and the time the caller creates the file.

        tempfile.mktemp is deprecated in favor of tempfile.mkstemp which creates the file when it is called. Consider using tempfile.mkstemp instead, either directly or via a context manager such as tempfile.TemporaryFile.

        In preview, this rule will also flag references to tempfile.mktemp.

        ","tags":["S306"]},{"location":"rules/suspicious-mktemp-usage/#example","title":"Example","text":"
        import tempfile\n\ntmp_file = tempfile.mktemp()\nwith open(tmp_file, \"w\") as file:\n    file.write(\"Hello, world!\")\n

        Use instead:

        import tempfile\n\nwith tempfile.TemporaryFile() as file:\n    file.write(\"Hello, world!\")\n
        ","tags":["S306"]},{"location":"rules/suspicious-mktemp-usage/#references","title":"References","text":"
        • Python documentation:mktemp
        ","tags":["S306"]},{"location":"rules/suspicious-non-cryptographic-random-usage/","title":"suspicious-non-cryptographic-random-usage (S311)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S311"]},{"location":"rules/suspicious-non-cryptographic-random-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of cryptographically weak pseudo-random number generators.

        ","tags":["S311"]},{"location":"rules/suspicious-non-cryptographic-random-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Cryptographically weak pseudo-random number generators are insecure, as they are easily predictable. This can allow an attacker to guess the generated numbers and compromise the security of the system.

        Instead, use a cryptographically secure pseudo-random number generator (such as using the secrets module) when generating random numbers for security purposes.

        In preview, this rule will also flag references to these generators.

        ","tags":["S311"]},{"location":"rules/suspicious-non-cryptographic-random-usage/#example","title":"Example","text":"
        import random\n\nrandom.randrange(10)\n

        Use instead:

        import secrets\n\nsecrets.randbelow(10)\n
        ","tags":["S311"]},{"location":"rules/suspicious-non-cryptographic-random-usage/#references","title":"References","text":"
        • Python documentation: random \u2014 Generate pseudo-random numbers
        ","tags":["S311"]},{"location":"rules/suspicious-pickle-import/","title":"suspicious-pickle-import (S403)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S403"]},{"location":"rules/suspicious-pickle-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the pickle, cPickle, dill, and shelve modules.

        ","tags":["S403"]},{"location":"rules/suspicious-pickle-import/#why-is-this-bad","title":"Why is this bad?","text":"

        It is possible to construct malicious pickle data which will execute arbitrary code during unpickling. Consider possible security implications associated with these modules.

        ","tags":["S403"]},{"location":"rules/suspicious-pickle-import/#example","title":"Example","text":"
        import pickle\n
        ","tags":["S403"]},{"location":"rules/suspicious-pickle-import/#references","title":"References","text":"
        • Python documentation: pickle \u2014 Python object serialization
        ","tags":["S403"]},{"location":"rules/suspicious-pickle-usage/","title":"suspicious-pickle-usage (S301)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S301"]},{"location":"rules/suspicious-pickle-usage/#what-it-does","title":"What it does","text":"

        Checks for calls to pickle functions or modules that wrap them.

        ","tags":["S301"]},{"location":"rules/suspicious-pickle-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Deserializing untrusted data with pickle and other deserialization modules is insecure as it can allow for the creation of arbitrary objects, which can then be used to achieve arbitrary code execution and otherwise unexpected behavior.

        Avoid deserializing untrusted data with pickle and other deserialization modules. Instead, consider safer formats, such as JSON.

        If you must deserialize untrusted data with pickle, consider signing the data with a secret key and verifying the signature before deserializing the payload, This will prevent an attacker from injecting arbitrary objects into the serialized data.

        In preview, this rule will also flag references to pickle functions.

        ","tags":["S301"]},{"location":"rules/suspicious-pickle-usage/#example","title":"Example","text":"
        import pickle\n\nwith open(\"foo.pickle\", \"rb\") as file:\n    foo = pickle.load(file)\n

        Use instead:

        import json\n\nwith open(\"foo.json\", \"rb\") as file:\n    foo = json.load(file)\n
        ","tags":["S301"]},{"location":"rules/suspicious-pickle-usage/#references","title":"References","text":"
        • Python documentation: pickle \u2014 Python object serialization
        • Common Weakness Enumeration: CWE-502
        ","tags":["S301"]},{"location":"rules/suspicious-pycrypto-import/","title":"suspicious-pycrypto-import (S413)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S413"]},{"location":"rules/suspicious-pycrypto-import/#what-it-does","title":"What it does","text":"

        Checks for imports of several unsafe cryptography modules.

        ","tags":["S413"]},{"location":"rules/suspicious-pycrypto-import/#why-is-this-bad","title":"Why is this bad?","text":"

        The pycrypto library is known to have a publicly disclosed buffer overflow vulnerability. It is no longer actively maintained and has been deprecated in favor of the pyca/cryptography library.

        ","tags":["S413"]},{"location":"rules/suspicious-pycrypto-import/#example","title":"Example","text":"
        import Crypto.Random\n
        ","tags":["S413"]},{"location":"rules/suspicious-pycrypto-import/#references","title":"References","text":"
        • Buffer Overflow Issue
        ","tags":["S413"]},{"location":"rules/suspicious-pyghmi-import/","title":"suspicious-pyghmi-import (S415)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S415"]},{"location":"rules/suspicious-pyghmi-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the pyghmi module.

        ","tags":["S415"]},{"location":"rules/suspicious-pyghmi-import/#why-is-this-bad","title":"Why is this bad?","text":"

        pyghmi is an IPMI-related module, but IPMI is considered insecure. Instead, use an encrypted protocol.

        ","tags":["S415"]},{"location":"rules/suspicious-pyghmi-import/#example","title":"Example","text":"
        import pyghmi\n
        ","tags":["S415"]},{"location":"rules/suspicious-pyghmi-import/#references","title":"References","text":"
        • Buffer Overflow Issue
        ","tags":["S415"]},{"location":"rules/suspicious-subprocess-import/","title":"suspicious-subprocess-import (S404)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S404"]},{"location":"rules/suspicious-subprocess-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the subprocess module.

        ","tags":["S404"]},{"location":"rules/suspicious-subprocess-import/#why-is-this-bad","title":"Why is this bad?","text":"

        It is possible to inject malicious commands into subprocess calls. Consider possible security implications associated with this module.

        ","tags":["S404"]},{"location":"rules/suspicious-subprocess-import/#example","title":"Example","text":"
        import subprocess\n
        ","tags":["S404"]},{"location":"rules/suspicious-telnet-usage/","title":"suspicious-telnet-usage (S312)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S312"]},{"location":"rules/suspicious-telnet-usage/#what-it-does","title":"What it does","text":"

        Checks for the use of Telnet-related functions.

        ","tags":["S312"]},{"location":"rules/suspicious-telnet-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Telnet is considered insecure because it does not encrypt data sent over the connection and is vulnerable to numerous attacks.

        Instead, consider using a more secure protocol such as SSH.

        In preview, this rule will also flag references to Telnet-related functions.

        ","tags":["S312"]},{"location":"rules/suspicious-telnet-usage/#references","title":"References","text":"
        • Python documentation: telnetlib \u2014 Telnet client
        ","tags":["S312"]},{"location":"rules/suspicious-telnetlib-import/","title":"suspicious-telnetlib-import (S401)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S401"]},{"location":"rules/suspicious-telnetlib-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the telnetlib module.

        ","tags":["S401"]},{"location":"rules/suspicious-telnetlib-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Telnet is considered insecure. It is deprecated since version 3.11, and was removed in version 3.13. Instead, use SSH or another encrypted protocol.

        ","tags":["S401"]},{"location":"rules/suspicious-telnetlib-import/#example","title":"Example","text":"
        import telnetlib\n
        ","tags":["S401"]},{"location":"rules/suspicious-telnetlib-import/#references","title":"References","text":"
        • Python documentation: telnetlib - Telnet client
        • PEP 594: telnetlib
        ","tags":["S401"]},{"location":"rules/suspicious-unverified-context-usage/","title":"suspicious-unverified-context-usage (S323)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S323"]},{"location":"rules/suspicious-unverified-context-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of ssl._create_unverified_context.

        ","tags":["S323"]},{"location":"rules/suspicious-unverified-context-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 476 enabled certificate and hostname validation by default in Python standard library HTTP clients. Previously, Python did not validate certificates by default, which could allow an attacker to perform a \"man in the middle\" attack by intercepting and modifying traffic between client and server.

        To support legacy environments, ssl._create_unverified_context reverts to the previous behavior that does perform verification. Otherwise, use ssl.create_default_context to create a secure context.

        In preview, this rule will also flag references to ssl._create_unverified_context.

        ","tags":["S323"]},{"location":"rules/suspicious-unverified-context-usage/#example","title":"Example","text":"
        import ssl\n\ncontext = ssl._create_unverified_context()\n

        Use instead:

        import ssl\n\ncontext = ssl.create_default_context()\n
        ","tags":["S323"]},{"location":"rules/suspicious-unverified-context-usage/#references","title":"References","text":"
        • PEP 476 \u2013 Enabling certificate verification by default for stdlib http clients: Opting out
        • Python documentation: ssl \u2014 TLS/SSL wrapper for socket objects
        ","tags":["S323"]},{"location":"rules/suspicious-url-open-usage/","title":"suspicious-url-open-usage (S310)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S310"]},{"location":"rules/suspicious-url-open-usage/#what-it-does","title":"What it does","text":"

        Checks for instances where URL open functions are used with unexpected schemes.

        ","tags":["S310"]},{"location":"rules/suspicious-url-open-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Some URL open functions allow the use of file: or custom schemes (for use instead of http: or https:). An attacker may be able to use these schemes to access or modify unauthorized resources, and cause unexpected behavior.

        To mitigate this risk, audit all uses of URL open functions and ensure that only permitted schemes are used (e.g., allowing http: and https:, and disallowing file: and ftp:).

        In preview, this rule will also flag references to URL open functions.

        ","tags":["S310"]},{"location":"rules/suspicious-url-open-usage/#example","title":"Example","text":"
        from urllib.request import urlopen\n\nurl = input(\"Enter a URL: \")\n\nwith urlopen(url) as response:\n    ...\n

        Use instead:

        from urllib.request import urlopen\n\nurl = input(\"Enter a URL: \")\n\nif not url.startswith((\"http:\", \"https:\")):\n    raise ValueError(\"URL must start with 'http:' or 'https:'\")\n\nwith urlopen(url) as response:\n    ...\n
        ","tags":["S310"]},{"location":"rules/suspicious-url-open-usage/#references","title":"References","text":"
        • Python documentation: urlopen
        ","tags":["S310"]},{"location":"rules/suspicious-xml-element-tree-usage/","title":"suspicious-xml-element-tree-usage (S314)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S314"]},{"location":"rules/suspicious-xml-element-tree-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S314"]},{"location":"rules/suspicious-xml-element-tree-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S314"]},{"location":"rules/suspicious-xml-element-tree-usage/#example","title":"Example","text":"
        from xml.etree.ElementTree import parse\n\ntree = parse(\"untrusted.xml\")  # Vulnerable to XML attacks.\n

        Use instead:

        from defusedxml.ElementTree import parse\n\ntree = parse(\"untrusted.xml\")\n
        ","tags":["S314"]},{"location":"rules/suspicious-xml-element-tree-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S314"]},{"location":"rules/suspicious-xml-etree-import/","title":"suspicious-xml-etree-import (S405)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S405"]},{"location":"rules/suspicious-xml-etree-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xml.etree.cElementTree and xml.etree.ElementTree modules

        ","tags":["S405"]},{"location":"rules/suspicious-xml-etree-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from these modules to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called before parsing XML data.

        ","tags":["S405"]},{"location":"rules/suspicious-xml-etree-import/#example","title":"Example","text":"
        import xml.etree.cElementTree\n
        ","tags":["S405"]},{"location":"rules/suspicious-xml-expat-builder-usage/","title":"suspicious-xml-expat-builder-usage (S316)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S316"]},{"location":"rules/suspicious-xml-expat-builder-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S316"]},{"location":"rules/suspicious-xml-expat-builder-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S316"]},{"location":"rules/suspicious-xml-expat-builder-usage/#example","title":"Example","text":"
        from xml.dom.expatbuilder import parse\n\nparse(\"untrusted.xml\")\n

        Use instead:

        from defusedxml.expatbuilder import parse\n\ntree = parse(\"untrusted.xml\")\n
        ","tags":["S316"]},{"location":"rules/suspicious-xml-expat-builder-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S316"]},{"location":"rules/suspicious-xml-expat-import/","title":"suspicious-xml-expat-import (S407)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S407"]},{"location":"rules/suspicious-xml-expat-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xml.dom.expatbuilder module.

        ","tags":["S407"]},{"location":"rules/suspicious-xml-expat-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from these modules to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called before parsing XML data.

        ","tags":["S407"]},{"location":"rules/suspicious-xml-expat-import/#example","title":"Example","text":"
        import xml.dom.expatbuilder\n
        ","tags":["S407"]},{"location":"rules/suspicious-xml-expat-reader-usage/","title":"suspicious-xml-expat-reader-usage (S315)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S315"]},{"location":"rules/suspicious-xml-expat-reader-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S315"]},{"location":"rules/suspicious-xml-expat-reader-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S315"]},{"location":"rules/suspicious-xml-expat-reader-usage/#example","title":"Example","text":"
        from xml.sax.expatreader import create_parser\n\nparser = create_parser()\n

        Use instead:

        from defusedxml.sax import create_parser\n\nparser = create_parser()\n
        ","tags":["S315"]},{"location":"rules/suspicious-xml-expat-reader-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S315"]},{"location":"rules/suspicious-xml-mini-dom-usage/","title":"suspicious-xml-mini-dom-usage (S318)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S318"]},{"location":"rules/suspicious-xml-mini-dom-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S318"]},{"location":"rules/suspicious-xml-mini-dom-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S318"]},{"location":"rules/suspicious-xml-mini-dom-usage/#example","title":"Example","text":"
        from xml.dom.minidom import parse\n\ncontent = parse(\"untrusted.xml\")\n

        Use instead:

        from defusedxml.minidom import parse\n\ncontent = parse(\"untrusted.xml\")\n
        ","tags":["S318"]},{"location":"rules/suspicious-xml-mini-dom-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S318"]},{"location":"rules/suspicious-xml-minidom-import/","title":"suspicious-xml-minidom-import (S408)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S408"]},{"location":"rules/suspicious-xml-minidom-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xml.dom.minidom module.

        ","tags":["S408"]},{"location":"rules/suspicious-xml-minidom-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from these modules to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called before parsing XML data.

        ","tags":["S408"]},{"location":"rules/suspicious-xml-minidom-import/#example","title":"Example","text":"
        import xml.dom.minidom\n
        ","tags":["S408"]},{"location":"rules/suspicious-xml-pull-dom-usage/","title":"suspicious-xml-pull-dom-usage (S319)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S319"]},{"location":"rules/suspicious-xml-pull-dom-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S319"]},{"location":"rules/suspicious-xml-pull-dom-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S319"]},{"location":"rules/suspicious-xml-pull-dom-usage/#example","title":"Example","text":"
        from xml.dom.pulldom import parse\n\ncontent = parse(\"untrusted.xml\")\n

        Use instead:

        from defusedxml.pulldom import parse\n\ncontent = parse(\"untrusted.xml\")\n
        ","tags":["S319"]},{"location":"rules/suspicious-xml-pull-dom-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S319"]},{"location":"rules/suspicious-xml-pulldom-import/","title":"suspicious-xml-pulldom-import (S409)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S409"]},{"location":"rules/suspicious-xml-pulldom-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xml.dom.pulldom module.

        ","tags":["S409"]},{"location":"rules/suspicious-xml-pulldom-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from these modules to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called before parsing XML data.

        ","tags":["S409"]},{"location":"rules/suspicious-xml-pulldom-import/#example","title":"Example","text":"
        import xml.dom.pulldom\n
        ","tags":["S409"]},{"location":"rules/suspicious-xml-sax-import/","title":"suspicious-xml-sax-import (S406)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S406"]},{"location":"rules/suspicious-xml-sax-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xml.sax module.

        ","tags":["S406"]},{"location":"rules/suspicious-xml-sax-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from these modules to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called before parsing XML data.

        ","tags":["S406"]},{"location":"rules/suspicious-xml-sax-import/#example","title":"Example","text":"
        import xml.sax\n
        ","tags":["S406"]},{"location":"rules/suspicious-xml-sax-usage/","title":"suspicious-xml-sax-usage (S317)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S317"]},{"location":"rules/suspicious-xml-sax-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S317"]},{"location":"rules/suspicious-xml-sax-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S317"]},{"location":"rules/suspicious-xml-sax-usage/#example","title":"Example","text":"
        from xml.sax import make_parser\n\nmake_parser()\n

        Use instead:

        from defusedxml.sax import make_parser\n\nmake_parser()\n
        ","tags":["S317"]},{"location":"rules/suspicious-xml-sax-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S317"]},{"location":"rules/suspicious-xmlc-element-tree-usage/","title":"suspicious-xmlc-element-tree-usage (S313)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S313"]},{"location":"rules/suspicious-xmlc-element-tree-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S313"]},{"location":"rules/suspicious-xmlc-element-tree-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S313"]},{"location":"rules/suspicious-xmlc-element-tree-usage/#example","title":"Example","text":"
        from xml.etree.cElementTree import parse\n\ntree = parse(\"untrusted.xml\")  # Vulnerable to XML attacks.\n

        Use instead:

        from defusedxml.cElementTree import parse\n\ntree = parse(\"untrusted.xml\")\n
        ","tags":["S313"]},{"location":"rules/suspicious-xmlc-element-tree-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S313"]},{"location":"rules/suspicious-xmle-tree-usage/","title":"suspicious-xmle-tree-usage (S320)","text":"

        Derived from the flake8-bandit linter.

        Warning: This rule is deprecated and will be removed in a future release.

        ","tags":["S320"]},{"location":"rules/suspicious-xmle-tree-usage/#deprecation","title":"Deprecation","text":"

        This rule was deprecated as the lxml library has been modified to address known vulnerabilities and unsafe defaults. As such, the defusedxml library is no longer necessary, defusedxml has deprecated its lxml module.

        ","tags":["S320"]},{"location":"rules/suspicious-xmle-tree-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S320"]},{"location":"rules/suspicious-xmle-tree-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S320"]},{"location":"rules/suspicious-xmle-tree-usage/#example","title":"Example","text":"
        from lxml import etree\n\ncontent = etree.parse(\"untrusted.xml\")\n
        ","tags":["S320"]},{"location":"rules/suspicious-xmle-tree-usage/#references","title":"References","text":"
        • PyPI: lxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S320"]},{"location":"rules/suspicious-xmlrpc-import/","title":"suspicious-xmlrpc-import (S411)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S411"]},{"location":"rules/suspicious-xmlrpc-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xmlrpc module.

        ","tags":["S411"]},{"location":"rules/suspicious-xmlrpc-import/#why-is-this-bad","title":"Why is this bad?","text":"

        XMLRPC is a particularly dangerous XML module, as it is also concerned with communicating data over a network. Use the defused.xmlrpc.monkey_patch() function to monkey-patch the xmlrpclib module and mitigate remote XML attacks.

        ","tags":["S411"]},{"location":"rules/suspicious-xmlrpc-import/#example","title":"Example","text":"
        import xmlrpc\n
        ","tags":["S411"]},{"location":"rules/syntax-error/","title":"syntax-error (E999)","text":"

        Derived from the pycodestyle linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["E999"]},{"location":"rules/syntax-error/#removed","title":"Removed","text":"

        This rule has been removed. Syntax errors will always be shown regardless of whether this rule is selected or not.

        ","tags":["E999"]},{"location":"rules/syntax-error/#what-it-does","title":"What it does","text":"

        Checks for code that contains syntax errors.

        ","tags":["E999"]},{"location":"rules/syntax-error/#why-is-this-bad","title":"Why is this bad?","text":"

        Code with syntax errors cannot be executed. Such errors are likely a mistake.

        ","tags":["E999"]},{"location":"rules/syntax-error/#example","title":"Example","text":"
        x =\n

        Use instead:

        x = 1\n
        ","tags":["E999"]},{"location":"rules/syntax-error/#references","title":"References","text":"
        • Python documentation: Syntax Errors
        ","tags":["E999"]},{"location":"rules/sys-exit-alias/","title":"sys-exit-alias (PLR1722)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLR1722"]},{"location":"rules/sys-exit-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of the exit() and quit().

        ","tags":["PLR1722"]},{"location":"rules/sys-exit-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        exit and quit come from the site module, which is typically imported automatically during startup. However, it is not guaranteed to be imported, and so using these functions may result in a NameError at runtime. Generally, these constants are intended to be used in an interactive interpreter, and not in programs.

        Prefer sys.exit(), as the sys module is guaranteed to exist in all contexts.

        ","tags":["PLR1722"]},{"location":"rules/sys-exit-alias/#fix-safety","title":"Fix safety","text":"

        This fix is always unsafe. When replacing exit or quit with sys.exit, the behavior can change in the following ways:

        1. If the code runs in an environment where the site module is not imported (e.g., with python -S), the original code would raise a NameError, while the fixed code would execute normally.

        2. site.exit and sys.exit handle tuple arguments differently. site.exit treats tuples as regular objects and always returns exit code 1, while sys.exit interprets tuple contents to determine the exit code: an empty tuple () results in exit code 0, and a single-element tuple like (2,) uses that element's value (2) as the exit code.

        ","tags":["PLR1722"]},{"location":"rules/sys-exit-alias/#example","title":"Example","text":"
        if __name__ == \"__main__\":\n    exit()\n

        Use instead:

        import sys\n\nif __name__ == \"__main__\":\n    sys.exit()\n
        ","tags":["PLR1722"]},{"location":"rules/sys-exit-alias/#references","title":"References","text":"
        • Python documentation: Constants added by the site module
        ","tags":["PLR1722"]},{"location":"rules/sys-version-cmp-str10/","title":"sys-version-cmp-str10 (YTT302)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT302"]},{"location":"rules/sys-version-cmp-str10/#what-it-does","title":"What it does","text":"

        Checks for comparisons that test sys.version against string literals, such that the comparison would fail if the major version number were ever incremented to Python 10 or higher.

        ","tags":["YTT302"]},{"location":"rules/sys-version-cmp-str10/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing sys.version to a string is error-prone and may cause subtle bugs, as the comparison will be performed lexicographically, not semantically.

        Instead, use sys.version_info to access the current major and minor version numbers as a tuple, which can be compared to other tuples without issue.

        ","tags":["YTT302"]},{"location":"rules/sys-version-cmp-str10/#example","title":"Example","text":"
        import sys\n\nsys.version >= \"3\"  # `False` on Python 10.\n

        Use instead:

        import sys\n\nsys.version_info >= (3,)  # `True` on Python 10.\n
        ","tags":["YTT302"]},{"location":"rules/sys-version-cmp-str10/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT302"]},{"location":"rules/sys-version-cmp-str3/","title":"sys-version-cmp-str3 (YTT103)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT103"]},{"location":"rules/sys-version-cmp-str3/#what-it-does","title":"What it does","text":"

        Checks for comparisons that test sys.version against string literals, such that the comparison will evaluate to False on Python 3.10 or later.

        ","tags":["YTT103"]},{"location":"rules/sys-version-cmp-str3/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing sys.version to a string is error-prone and may cause subtle bugs, as the comparison will be performed lexicographically, not semantically. For example, sys.version > \"3.9\" will evaluate to False when using Python 3.10, as \"3.10\" is lexicographically \"less\" than \"3.9\".

        Instead, use sys.version_info to access the current major and minor version numbers as a tuple, which can be compared to other tuples without issue.

        ","tags":["YTT103"]},{"location":"rules/sys-version-cmp-str3/#example","title":"Example","text":"
        import sys\n\nsys.version > \"3.9\"  # `False` on Python 3.10.\n

        Use instead:

        import sys\n\nsys.version_info > (3, 9)  # `True` on Python 3.10.\n
        ","tags":["YTT103"]},{"location":"rules/sys-version-cmp-str3/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT103"]},{"location":"rules/sys-version-info-minor-cmp-int/","title":"sys-version-info-minor-cmp-int (YTT204)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT204"]},{"location":"rules/sys-version-info-minor-cmp-int/#what-it-does","title":"What it does","text":"

        Checks for comparisons that test sys.version_info.minor against an integer.

        ","tags":["YTT204"]},{"location":"rules/sys-version-info-minor-cmp-int/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparisons based on the current minor version number alone can cause subtle bugs and would likely lead to unintended effects if the Python major version number were ever incremented (e.g., to Python 4).

        Instead, compare sys.version_info to a tuple, including the major and minor version numbers, to future-proof the code.

        ","tags":["YTT204"]},{"location":"rules/sys-version-info-minor-cmp-int/#example","title":"Example","text":"
        import sys\n\nif sys.version_info.minor < 7:\n    print(\"Python 3.6 or earlier.\")  # This will be printed on Python 4.0.\n

        Use instead:

        import sys\n\nif sys.version_info < (3, 7):\n    print(\"Python 3.6 or earlier.\")\n
        ","tags":["YTT204"]},{"location":"rules/sys-version-info-minor-cmp-int/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT204"]},{"location":"rules/sys-version-info0-eq3/","title":"sys-version-info0-eq3 (YTT201)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT201"]},{"location":"rules/sys-version-info0-eq3/#what-it-does","title":"What it does","text":"

        Checks for equality comparisons against the major version returned by sys.version_info (e.g., sys.version_info[0] == 3).

        ","tags":["YTT201"]},{"location":"rules/sys-version-info0-eq3/#why-is-this-bad","title":"Why is this bad?","text":"

        Using sys.version_info[0] == 3 to verify that the major version is Python 3 or greater will fail if the major version number is ever incremented (e.g., to Python 4). This is likely unintended, as code that uses this comparison is likely intended to be run on Python 2, but would now run on Python 4 too.

        Instead, use >= to check if the major version number is 3 or greater, to future-proof the code.

        ","tags":["YTT201"]},{"location":"rules/sys-version-info0-eq3/#example","title":"Example","text":"
        import sys\n\nif sys.version_info[0] == 3:\n    ...\nelse:\n    print(\"Python 2\")  # This will be printed on Python 4.\n

        Use instead:

        import sys\n\nif sys.version_info >= (3,):\n    ...\nelse:\n    print(\"Python 2\")  # This will not be printed on Python 4.\n
        ","tags":["YTT201"]},{"location":"rules/sys-version-info0-eq3/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT201"]},{"location":"rules/sys-version-info1-cmp-int/","title":"sys-version-info1-cmp-int (YTT203)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT203"]},{"location":"rules/sys-version-info1-cmp-int/#what-it-does","title":"What it does","text":"

        Checks for comparisons that test sys.version_info[1] against an integer.

        ","tags":["YTT203"]},{"location":"rules/sys-version-info1-cmp-int/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparisons based on the current minor version number alone can cause subtle bugs and would likely lead to unintended effects if the Python major version number were ever incremented (e.g., to Python 4).

        Instead, compare sys.version_info to a tuple, including the major and minor version numbers, to future-proof the code.

        ","tags":["YTT203"]},{"location":"rules/sys-version-info1-cmp-int/#example","title":"Example","text":"
        import sys\n\nif sys.version_info[1] < 7:\n    print(\"Python 3.6 or earlier.\")  # This will be printed on Python 4.0.\n

        Use instead:

        import sys\n\nif sys.version_info < (3, 7):\n    print(\"Python 3.6 or earlier.\")\n
        ","tags":["YTT203"]},{"location":"rules/sys-version-info1-cmp-int/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT203"]},{"location":"rules/sys-version-slice1/","title":"sys-version-slice1 (YTT303)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT303"]},{"location":"rules/sys-version-slice1/#what-it-does","title":"What it does","text":"

        Checks for uses of sys.version[:1].

        ","tags":["YTT303"]},{"location":"rules/sys-version-slice1/#why-is-this-bad","title":"Why is this bad?","text":"

        If the major version number consists of more than one digit, this will select the first digit of the major version number only (e.g., \"10.0\" would evaluate to \"1\"). This is likely unintended, and can lead to subtle bugs in future versions of Python if the version string is used to test against a specific major version number.

        Instead, use sys.version_info.major to access the current major version number.

        ","tags":["YTT303"]},{"location":"rules/sys-version-slice1/#example","title":"Example","text":"
        import sys\n\nsys.version[:1]  # If using Python 10, this evaluates to \"1\".\n

        Use instead:

        import sys\n\nf\"{sys.version_info.major}\"  # If using Python 10, this evaluates to \"10\".\n
        ","tags":["YTT303"]},{"location":"rules/sys-version-slice1/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT303"]},{"location":"rules/sys-version-slice3/","title":"sys-version-slice3 (YTT101)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT101"]},{"location":"rules/sys-version-slice3/#what-it-does","title":"What it does","text":"

        Checks for uses of sys.version[:3].

        ","tags":["YTT101"]},{"location":"rules/sys-version-slice3/#why-is-this-bad","title":"Why is this bad?","text":"

        If the current major or minor version consists of multiple digits, sys.version[:3] will truncate the version number (e.g., \"3.10\" would become \"3.1\"). This is likely unintended, and can lead to subtle bugs if the version string is used to test against a specific Python version.

        Instead, use sys.version_info to access the current major and minor version numbers as a tuple, which can be compared to other tuples without issue.

        ","tags":["YTT101"]},{"location":"rules/sys-version-slice3/#example","title":"Example","text":"
        import sys\n\nsys.version[:3]  # Evaluates to \"3.1\" on Python 3.10.\n

        Use instead:

        import sys\n\nsys.version_info[:2]  # Evaluates to (3, 10) on Python 3.10.\n
        ","tags":["YTT101"]},{"location":"rules/sys-version-slice3/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT101"]},{"location":"rules/sys-version0/","title":"sys-version0 (YTT301)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT301"]},{"location":"rules/sys-version0/#what-it-does","title":"What it does","text":"

        Checks for uses of sys.version[0].

        ","tags":["YTT301"]},{"location":"rules/sys-version0/#why-is-this-bad","title":"Why is this bad?","text":"

        If the current major or minor version consists of multiple digits, sys.version[0] will select the first digit of the major version number only (e.g., \"10.2\" would evaluate to \"1\"). This is likely unintended, and can lead to subtle bugs if the version string is used to test against a major version number.

        Instead, use sys.version_info.major to access the current major version number.

        ","tags":["YTT301"]},{"location":"rules/sys-version0/#example","title":"Example","text":"
        import sys\n\nsys.version[0]  # If using Python 10, this evaluates to \"1\".\n

        Use instead:

        import sys\n\nf\"{sys.version_info.major}\"  # If using Python 10, this evaluates to \"10\".\n
        ","tags":["YTT301"]},{"location":"rules/sys-version0/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT301"]},{"location":"rules/sys-version2/","title":"sys-version2 (YTT102)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT102"]},{"location":"rules/sys-version2/#what-it-does","title":"What it does","text":"

        Checks for uses of sys.version[2].

        ","tags":["YTT102"]},{"location":"rules/sys-version2/#why-is-this-bad","title":"Why is this bad?","text":"

        If the current major or minor version consists of multiple digits, sys.version[2] will select the first digit of the minor number only (e.g., \"3.10\" would evaluate to \"1\"). This is likely unintended, and can lead to subtle bugs if the version is used to test against a minor version number.

        Instead, use sys.version_info.minor to access the current minor version number.

        ","tags":["YTT102"]},{"location":"rules/sys-version2/#example","title":"Example","text":"
        import sys\n\nsys.version[2]  # Evaluates to \"1\" on Python 3.10.\n

        Use instead:

        import sys\n\nf\"{sys.version_info.minor}\"  # Evaluates to \"10\" on Python 3.10.\n
        ","tags":["YTT102"]},{"location":"rules/sys-version2/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT102"]},{"location":"rules/t-suffixed-type-alias/","title":"t-suffixed-type-alias (PYI043)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI043"]},{"location":"rules/t-suffixed-type-alias/#what-it-does","title":"What it does","text":"

        Checks for private type alias definitions suffixed with 'T'.

        ","tags":["PYI043"]},{"location":"rules/t-suffixed-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        It's conventional to use the 'T' suffix for type variables; the use of such a suffix implies that the object is a TypeVar.

        Adding the 'T' suffix to a non-TypeVar, it can be misleading and should be avoided.

        ","tags":["PYI043"]},{"location":"rules/t-suffixed-type-alias/#example","title":"Example","text":"
        from typing import TypeAlias\n\n_MyTypeT: TypeAlias = int\n

        Use instead:

        from typing import TypeAlias\n\n_MyType: TypeAlias = int\n
        ","tags":["PYI043"]},{"location":"rules/t-suffixed-type-alias/#references","title":"References","text":"
        • PEP 484: Type Aliases
        ","tags":["PYI043"]},{"location":"rules/tab-after-comma/","title":"tab-after-comma (E242)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E242"]},{"location":"rules/tab-after-comma/#what-it-does","title":"What it does","text":"

        Checks for extraneous tabs after a comma.

        ","tags":["E242"]},{"location":"rules/tab-after-comma/#why-is-this-bad","title":"Why is this bad?","text":"

        Commas should be followed by one space, never tabs.

        ","tags":["E242"]},{"location":"rules/tab-after-comma/#example","title":"Example","text":"
        a = 4,\\t5\n

        Use instead:

        a = 4, 5\n
        ","tags":["E242"]},{"location":"rules/tab-after-keyword/","title":"tab-after-keyword (E273)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E273"]},{"location":"rules/tab-after-keyword/#what-it-does","title":"What it does","text":"

        Checks for extraneous tabs after keywords.

        ","tags":["E273"]},{"location":"rules/tab-after-keyword/#why-is-this-bad","title":"Why is this bad?","text":"","tags":["E273"]},{"location":"rules/tab-after-keyword/#example","title":"Example","text":"
        True and\\tFalse\n

        Use instead:

        True and False\n
        ","tags":["E273"]},{"location":"rules/tab-after-operator/","title":"tab-after-operator (E224)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E224"]},{"location":"rules/tab-after-operator/#what-it-does","title":"What it does","text":"

        Checks for extraneous tabs after an operator.

        ","tags":["E224"]},{"location":"rules/tab-after-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, operators should be surrounded by at most a single space on either side.

        ","tags":["E224"]},{"location":"rules/tab-after-operator/#example","title":"Example","text":"
        a = 4 +\\t5\n

        Use instead:

        a = 4 + 5\n
        ","tags":["E224"]},{"location":"rules/tab-before-keyword/","title":"tab-before-keyword (E274)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E274"]},{"location":"rules/tab-before-keyword/#what-it-does","title":"What it does","text":"

        Checks for extraneous tabs before keywords.

        ","tags":["E274"]},{"location":"rules/tab-before-keyword/#why-is-this-bad","title":"Why is this bad?","text":"","tags":["E274"]},{"location":"rules/tab-before-keyword/#example","title":"Example","text":"
        True\\tand False\n

        Use instead:

        True and False\n
        ","tags":["E274"]},{"location":"rules/tab-before-operator/","title":"tab-before-operator (E223)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E223"]},{"location":"rules/tab-before-operator/#what-it-does","title":"What it does","text":"

        Checks for extraneous tabs before an operator.

        ","tags":["E223"]},{"location":"rules/tab-before-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, operators should be surrounded by at most a single space on either side.

        ","tags":["E223"]},{"location":"rules/tab-before-operator/#example","title":"Example","text":"
        a = 4\\t+ 5\n

        Use instead:

        a = 4 + 5\n
        ","tags":["E223"]},{"location":"rules/tab-indentation/","title":"tab-indentation (W191)","text":"

        Derived from the pycodestyle linter.

        ","tags":["W191"]},{"location":"rules/tab-indentation/#what-it-does","title":"What it does","text":"

        Checks for indentation that uses tabs.

        ","tags":["W191"]},{"location":"rules/tab-indentation/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, spaces are preferred over tabs (unless used to remain consistent with code that is already indented with tabs).

        ","tags":["W191"]},{"location":"rules/tab-indentation/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        The rule is also incompatible with the formatter when using format.indent-style=\"tab\".

        ","tags":["W191"]},{"location":"rules/tarfile-unsafe-members/","title":"tarfile-unsafe-members (S202)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S202"]},{"location":"rules/tarfile-unsafe-members/#what-it-does","title":"What it does","text":"

        Checks for uses of tarfile.extractall.

        ","tags":["S202"]},{"location":"rules/tarfile-unsafe-members/#why-is-this-bad","title":"Why is this bad?","text":"

        Extracting archives from untrusted sources without prior inspection is a security risk, as maliciously crafted archives may contain files that will be written outside of the target directory. For example, the archive could include files with absolute paths (e.g., /etc/passwd), or relative paths with parent directory references (e.g., ../etc/passwd).

        On Python 3.12 and later, use filter='data' to prevent the most dangerous security issues (see: PEP 706). On earlier versions, set the members argument to a trusted subset of the archive's members.

        ","tags":["S202"]},{"location":"rules/tarfile-unsafe-members/#example","title":"Example","text":"
        import tarfile\nimport tempfile\n\ntar = tarfile.open(filename)\ntar.extractall(path=tempfile.mkdtemp())\ntar.close()\n
        ","tags":["S202"]},{"location":"rules/tarfile-unsafe-members/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-22
        • Python documentation: TarFile.extractall
        • Python documentation: Extraction filters
        ","tags":["S202"]},{"location":"rules/timeout-error-alias/","title":"timeout-error-alias (UP041)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP041"]},{"location":"rules/timeout-error-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of exceptions that alias TimeoutError.

        ","tags":["UP041"]},{"location":"rules/timeout-error-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        TimeoutError is the builtin error type used for exceptions when a system function timed out at the system level.

        In Python 3.10, socket.timeout was aliased to TimeoutError. In Python 3.11, asyncio.TimeoutError was aliased to TimeoutError.

        These aliases remain in place for compatibility with older versions of Python, but may be removed in future versions.

        Prefer using TimeoutError directly, as it is more idiomatic and future-proof.

        ","tags":["UP041"]},{"location":"rules/timeout-error-alias/#example","title":"Example","text":"
        raise asyncio.TimeoutError\n

        Use instead:

        raise TimeoutError\n
        ","tags":["UP041"]},{"location":"rules/timeout-error-alias/#references","title":"References","text":"
        • Python documentation: TimeoutError
        ","tags":["UP041"]},{"location":"rules/too-few-spaces-before-inline-comment/","title":"too-few-spaces-before-inline-comment (E261)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E261"]},{"location":"rules/too-few-spaces-before-inline-comment/#what-it-does","title":"What it does","text":"

        Checks if inline comments are separated by at least two spaces.

        ","tags":["E261"]},{"location":"rules/too-few-spaces-before-inline-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        An inline comment is a comment on the same line as a statement.

        Per PEP 8, inline comments should be separated by at least two spaces from the preceding statement.

        ","tags":["E261"]},{"location":"rules/too-few-spaces-before-inline-comment/#example","title":"Example","text":"
        x = x + 1 # Increment x\n

        Use instead:

        x = x + 1  # Increment x\nx = x + 1    # Increment x\n
        ","tags":["E261"]},{"location":"rules/too-many-arguments/","title":"too-many-arguments (PLR0913)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0913"]},{"location":"rules/too-many-arguments/#what-it-does","title":"What it does","text":"

        Checks for function definitions that include too many arguments.

        By default, this rule allows up to five arguments, as configured by the lint.pylint.max-args option.

        ","tags":["PLR0913"]},{"location":"rules/too-many-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions with many arguments are harder to understand, maintain, and call. Consider refactoring functions with many arguments into smaller functions with fewer arguments, or using objects to group related arguments.

        ","tags":["PLR0913"]},{"location":"rules/too-many-arguments/#example","title":"Example","text":"
        def calculate_position(x_pos, y_pos, z_pos, x_vel, y_vel, z_vel, time):\n    new_x = x_pos + x_vel * time\n    new_y = y_pos + y_vel * time\n    new_z = z_pos + z_vel * time\n    return new_x, new_y, new_z\n

        Use instead:

        from typing import NamedTuple\n\n\nclass Vector(NamedTuple):\n    x: float\n    y: float\n    z: float\n\n\ndef calculate_position(pos: Vector, vel: Vector, time: float) -> Vector:\n    return Vector(*(p + v * time for p, v in zip(pos, vel)))\n
        ","tags":["PLR0913"]},{"location":"rules/too-many-arguments/#options","title":"Options","text":"
        • lint.pylint.max-args
        ","tags":["PLR0913"]},{"location":"rules/too-many-blank-lines/","title":"too-many-blank-lines (E303)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#what-it-does","title":"What it does","text":"

        Checks for extraneous blank lines.

        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends using blank lines as follows:

        • No more than two blank lines between top-level statements.
        • No more than one blank line between non-top-level statements.
        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#example","title":"Example","text":"
        def func1():\n    pass\n\n\n\ndef func2():\n    pass\n

        Use instead:

        def func1():\n    pass\n\n\ndef func2():\n    pass\n
        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#typing-stub-files-pyi","title":"Typing stub files (.pyi)","text":"

        The rule allows at most one blank line in typing stub files in accordance to the typing style guide recommendation.

        Note: The rule respects the following isort settings when determining the maximum number of blank lines allowed between two statements:

        • lint.isort.lines-after-imports: For top-level statements directly following an import statement.
        • lint.isort.lines-between-types: For import statements directly following a from ... import ... statement or vice versa.
        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#options","title":"Options","text":"
        • lint.isort.lines-after-imports
        • lint.isort.lines-between-types
        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        • Typing Style Guide
        ","tags":["E303"]},{"location":"rules/too-many-boolean-expressions/","title":"too-many-boolean-expressions (PLR0916)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0916"]},{"location":"rules/too-many-boolean-expressions/#what-it-does","title":"What it does","text":"

        Checks for too many Boolean expressions in an if statement.

        By default, this rule allows up to 5 expressions. This can be configured using the lint.pylint.max-bool-expr option.

        ","tags":["PLR0916"]},{"location":"rules/too-many-boolean-expressions/#why-is-this-bad","title":"Why is this bad?","text":"

        if statements with many Boolean expressions are harder to understand and maintain. Consider assigning the result of the Boolean expression, or any of its sub-expressions, to a variable.

        ","tags":["PLR0916"]},{"location":"rules/too-many-boolean-expressions/#example","title":"Example","text":"
        if a and b and c and d and e and f and g and h:\n    ...\n
        ","tags":["PLR0916"]},{"location":"rules/too-many-boolean-expressions/#options","title":"Options","text":"
        • lint.pylint.max-bool-expr
        ","tags":["PLR0916"]},{"location":"rules/too-many-branches/","title":"too-many-branches (PLR0912)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0912"]},{"location":"rules/too-many-branches/#what-it-does","title":"What it does","text":"

        Checks for functions or methods with too many branches, including (nested) if, elif, and else branches, for loops, try-except clauses, and match and case statements.

        By default, this rule allows up to 12 branches. This can be configured using the lint.pylint.max-branches option.

        ","tags":["PLR0912"]},{"location":"rules/too-many-branches/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions or methods with many branches are harder to understand and maintain than functions or methods with fewer branches.

        ","tags":["PLR0912"]},{"location":"rules/too-many-branches/#example","title":"Example","text":"

        Given:

        def capital(country):\n    if country == \"Australia\":\n        return \"Canberra\"\n    elif country == \"Brazil\":\n        return \"Brasilia\"\n    elif country == \"Canada\":\n        return \"Ottawa\"\n    elif country == \"England\":\n        return \"London\"\n    elif country == \"France\":\n        return \"Paris\"\n    elif country == \"Germany\":\n        return \"Berlin\"\n    elif country == \"Poland\":\n        return \"Warsaw\"\n    elif country == \"Romania\":\n        return \"Bucharest\"\n    elif country == \"Spain\":\n        return \"Madrid\"\n    elif country == \"Thailand\":\n        return \"Bangkok\"\n    elif country == \"Turkey\":\n        return \"Ankara\"\n    elif country == \"United States\":\n        return \"Washington\"\n    else:\n        return \"Unknown\"  # 13th branch\n

        Use instead:

        def capital(country):\n    capitals = {\n        \"Australia\": \"Canberra\",\n        \"Brazil\": \"Brasilia\",\n        \"Canada\": \"Ottawa\",\n        \"England\": \"London\",\n        \"France\": \"Paris\",\n        \"Germany\": \"Berlin\",\n        \"Poland\": \"Warsaw\",\n        \"Romania\": \"Bucharest\",\n        \"Spain\": \"Madrid\",\n        \"Thailand\": \"Bangkok\",\n        \"Turkey\": \"Ankara\",\n        \"United States\": \"Washington\",\n    }\n    city = capitals.get(country, \"Unknown\")\n    return city\n

        Given:

        def grades_to_average_number(grades):\n    numbers = []\n    for grade in grades:  # 1st branch\n        if len(grade) not in {1, 2}:\n            raise ValueError(f\"Invalid grade: {grade}\")\n\n        if len(grade) == 2 and grade[1] not in {\"+\", \"-\"}:\n            raise ValueError(f\"Invalid grade: {grade}\")\n\n        letter = grade[0]\n\n        if letter in {\"F\", \"E\"}:\n            number = 0.0\n        elif letter == \"D\":\n            number = 1.0\n        elif letter == \"C\":\n            number = 2.0\n        elif letter == \"B\":\n            number = 3.0\n        elif letter == \"A\":\n            number = 4.0\n        else:\n            raise ValueError(f\"Invalid grade: {grade}\")\n\n        modifier = 0.0\n        if letter != \"F\" and grade[-1] == \"+\":\n            modifier = 0.3\n        elif letter != \"F\" and grade[-1] == \"-\":\n            modifier = -0.3\n\n        numbers.append(max(0.0, min(number + modifier, 4.0)))\n\n    try:\n        return sum(numbers) / len(numbers)\n    except ZeroDivisionError:  # 13th branch\n        return 0\n

        Use instead:

        def grades_to_average_number(grades):\n    grade_values = {\"F\": 0.0, \"E\": 0.0, \"D\": 1.0, \"C\": 2.0, \"B\": 3.0, \"A\": 4.0}\n    modifier_values = {\"+\": 0.3, \"-\": -0.3}\n\n    numbers = []\n    for grade in grades:\n        if len(grade) not in {1, 2}:\n            raise ValueError(f\"Invalid grade: {grade}\")\n\n        letter = grade[0]\n        if letter not in grade_values:\n            raise ValueError(f\"Invalid grade: {grade}\")\n        number = grade_values[letter]\n\n        if len(grade) == 2 and grade[1] not in modifier_values:\n            raise ValueError(f\"Invalid grade: {grade}\")\n        modifier = modifier_values.get(grade[-1], 0.0)\n\n        if letter == \"F\":\n            numbers.append(0.0)\n        else:\n            numbers.append(max(0.0, min(number + modifier, 4.0)))\n\n    try:\n        return sum(numbers) / len(numbers)\n    except ZeroDivisionError:\n        return 0\n
        ","tags":["PLR0912"]},{"location":"rules/too-many-branches/#options","title":"Options","text":"
        • lint.pylint.max-branches
        ","tags":["PLR0912"]},{"location":"rules/too-many-locals/","title":"too-many-locals (PLR0914)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0914"]},{"location":"rules/too-many-locals/#what-it-does","title":"What it does","text":"

        Checks for functions that include too many local variables.

        By default, this rule allows up to fifteen locals, as configured by the lint.pylint.max-locals option.

        ","tags":["PLR0914"]},{"location":"rules/too-many-locals/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions with many local variables are harder to understand and maintain.

        Consider refactoring functions with many local variables into smaller functions with fewer assignments.

        ","tags":["PLR0914"]},{"location":"rules/too-many-locals/#options","title":"Options","text":"
        • lint.pylint.max-locals
        ","tags":["PLR0914"]},{"location":"rules/too-many-nested-blocks/","title":"too-many-nested-blocks (PLR1702)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR1702"]},{"location":"rules/too-many-nested-blocks/#what-it-does","title":"What it does","text":"

        Checks for functions or methods with too many nested blocks.

        By default, this rule allows up to five nested blocks. This can be configured using the lint.pylint.max-nested-blocks option.

        ","tags":["PLR1702"]},{"location":"rules/too-many-nested-blocks/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions or methods with too many nested blocks are harder to understand and maintain.

        ","tags":["PLR1702"]},{"location":"rules/too-many-nested-blocks/#options","title":"Options","text":"
        • lint.pylint.max-nested-blocks
        ","tags":["PLR1702"]},{"location":"rules/too-many-newlines-at-end-of-file/","title":"too-many-newlines-at-end-of-file (W391)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["W391"]},{"location":"rules/too-many-newlines-at-end-of-file/#what-it-does","title":"What it does","text":"

        Checks for files with multiple trailing blank lines.

        In the case of notebooks, this check is applied to each cell separately.

        ","tags":["W391"]},{"location":"rules/too-many-newlines-at-end-of-file/#why-is-this-bad","title":"Why is this bad?","text":"

        Trailing blank lines in a file are superfluous.

        However, the last line of the file should end with a newline.

        ","tags":["W391"]},{"location":"rules/too-many-newlines-at-end-of-file/#example","title":"Example","text":"
        spam(1)\\n\\n\\n\n

        Use instead:

        spam(1)\\n\n
        ","tags":["W391"]},{"location":"rules/too-many-positional-arguments/","title":"too-many-positional-arguments (PLR0917)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0917"]},{"location":"rules/too-many-positional-arguments/#what-it-does","title":"What it does","text":"

        Checks for function definitions that include too many positional arguments.

        By default, this rule allows up to five arguments, as configured by the lint.pylint.max-positional-args option.

        ","tags":["PLR0917"]},{"location":"rules/too-many-positional-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions with many arguments are harder to understand, maintain, and call. This is especially true for functions with many positional arguments, as providing arguments positionally is more error-prone and less clear to readers than providing arguments by name.

        Consider refactoring functions with many arguments into smaller functions with fewer arguments, using objects to group related arguments, or migrating to keyword-only arguments.

        ","tags":["PLR0917"]},{"location":"rules/too-many-positional-arguments/#example","title":"Example","text":"
        def plot(x, y, z, color, mark, add_trendline): ...\n\n\nplot(1, 2, 3, \"r\", \"*\", True)\n

        Use instead:

        def plot(x, y, z, *, color, mark, add_trendline): ...\n\n\nplot(1, 2, 3, color=\"r\", mark=\"*\", add_trendline=True)\n
        ","tags":["PLR0917"]},{"location":"rules/too-many-positional-arguments/#options","title":"Options","text":"
        • lint.pylint.max-positional-args
        ","tags":["PLR0917"]},{"location":"rules/too-many-public-methods/","title":"too-many-public-methods (PLR0904)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0904"]},{"location":"rules/too-many-public-methods/#what-it-does","title":"What it does","text":"

        Checks for classes with too many public methods

        By default, this rule allows up to 20 public methods, as configured by the lint.pylint.max-public-methods option.

        ","tags":["PLR0904"]},{"location":"rules/too-many-public-methods/#why-is-this-bad","title":"Why is this bad?","text":"

        Classes with many public methods are harder to understand and maintain.

        Instead, consider refactoring the class into separate classes.

        ","tags":["PLR0904"]},{"location":"rules/too-many-public-methods/#example","title":"Example","text":"

        Assuming that lint.pylint.max-public-methods is set to 5:

        class Linter:\n    def __init__(self):\n        pass\n\n    def pylint(self):\n        pass\n\n    def pylint_settings(self):\n        pass\n\n    def flake8(self):\n        pass\n\n    def flake8_settings(self):\n        pass\n\n    def pydocstyle(self):\n        pass\n\n    def pydocstyle_settings(self):\n        pass\n

        Use instead:

        class Linter:\n    def __init__(self):\n        self.pylint = Pylint()\n        self.flake8 = Flake8()\n        self.pydocstyle = Pydocstyle()\n\n    def lint(self):\n        pass\n\n\nclass Pylint:\n    def lint(self):\n        pass\n\n    def settings(self):\n        pass\n\n\nclass Flake8:\n    def lint(self):\n        pass\n\n    def settings(self):\n        pass\n\n\nclass Pydocstyle:\n    def lint(self):\n        pass\n\n    def settings(self):\n        pass\n
        ","tags":["PLR0904"]},{"location":"rules/too-many-public-methods/#options","title":"Options","text":"
        • lint.pylint.max-public-methods
        ","tags":["PLR0904"]},{"location":"rules/too-many-return-statements/","title":"too-many-return-statements (PLR0911)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0911"]},{"location":"rules/too-many-return-statements/#what-it-does","title":"What it does","text":"

        Checks for functions or methods with too many return statements.

        By default, this rule allows up to six return statements, as configured by the lint.pylint.max-returns option.

        ","tags":["PLR0911"]},{"location":"rules/too-many-return-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions or methods with many return statements are harder to understand and maintain, and often indicative of complex logic.

        ","tags":["PLR0911"]},{"location":"rules/too-many-return-statements/#example","title":"Example","text":"
        def capital(country: str) -> str | None:\n    if country == \"England\":\n        return \"London\"\n    elif country == \"France\":\n        return \"Paris\"\n    elif country == \"Poland\":\n        return \"Warsaw\"\n    elif country == \"Romania\":\n        return \"Bucharest\"\n    elif country == \"Spain\":\n        return \"Madrid\"\n    elif country == \"Thailand\":\n        return \"Bangkok\"\n    else:\n        return None\n

        Use instead:

        def capital(country: str) -> str | None:\n    capitals = {\n        \"England\": \"London\",\n        \"France\": \"Paris\",\n        \"Poland\": \"Warsaw\",\n        \"Romania\": \"Bucharest\",\n        \"Spain\": \"Madrid\",\n        \"Thailand\": \"Bangkok\",\n    }\n    return capitals.get(country)\n
        ","tags":["PLR0911"]},{"location":"rules/too-many-return-statements/#options","title":"Options","text":"
        • lint.pylint.max-returns
        ","tags":["PLR0911"]},{"location":"rules/too-many-statements/","title":"too-many-statements (PLR0915)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0915"]},{"location":"rules/too-many-statements/#what-it-does","title":"What it does","text":"

        Checks for functions or methods with too many statements.

        By default, this rule allows up to 50 statements, as configured by the lint.pylint.max-statements option.

        ","tags":["PLR0915"]},{"location":"rules/too-many-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions or methods with many statements are harder to understand and maintain.

        Instead, consider refactoring the function or method into smaller functions or methods, or identifying generalizable patterns and replacing them with generic logic or abstractions.

        ","tags":["PLR0915"]},{"location":"rules/too-many-statements/#example","title":"Example","text":"
        def is_even(number: int) -> bool:\n    if number == 0:\n        return True\n    elif number == 1:\n        return False\n    elif number == 2:\n        return True\n    elif number == 3:\n        return False\n    elif number == 4:\n        return True\n    elif number == 5:\n        return False\n    else:\n        ...\n

        Use instead:

        def is_even(number: int) -> bool:\n    return number % 2 == 0\n
        ","tags":["PLR0915"]},{"location":"rules/too-many-statements/#options","title":"Options","text":"
        • lint.pylint.max-statements
        ","tags":["PLR0915"]},{"location":"rules/trailing-comma-on-bare-tuple/","title":"trailing-comma-on-bare-tuple (COM818)","text":"

        Derived from the flake8-commas linter.

        ","tags":["COM818"]},{"location":"rules/trailing-comma-on-bare-tuple/#what-it-does","title":"What it does","text":"

        Checks for the presence of trailing commas on bare (i.e., unparenthesized) tuples.

        ","tags":["COM818"]},{"location":"rules/trailing-comma-on-bare-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        The presence of a misplaced comma will cause Python to interpret the value as a tuple, which can lead to unexpected behaviour.

        ","tags":["COM818"]},{"location":"rules/trailing-comma-on-bare-tuple/#example","title":"Example","text":"
        import json\n\n\nfoo = json.dumps({\"bar\": 1}),\n

        Use instead:

        import json\n\n\nfoo = json.dumps({\"bar\": 1})\n

        In the event that a tuple is intended, then use instead:

        import json\n\n\nfoo = (json.dumps({\"bar\": 1}),)\n
        ","tags":["COM818"]},{"location":"rules/trailing-whitespace/","title":"trailing-whitespace (W291)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["W291"]},{"location":"rules/trailing-whitespace/#what-it-does","title":"What it does","text":"

        Checks for superfluous trailing whitespace.

        ","tags":["W291"]},{"location":"rules/trailing-whitespace/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"avoid trailing whitespace anywhere. Because it\u2019s usually invisible, it can be confusing\"

        ","tags":["W291"]},{"location":"rules/trailing-whitespace/#example","title":"Example","text":"
        spam(1) \\n#\n

        Use instead:

        spam(1)\\n#\n
        ","tags":["W291"]},{"location":"rules/trio-sync-call/","title":"trio-sync-call (ASYNC105)","text":"

        Derived from the flake8-async linter.

        Fix is sometimes available.

        ","tags":["ASYNC105"]},{"location":"rules/trio-sync-call/#what-it-does","title":"What it does","text":"

        Checks for calls to trio functions that are not immediately awaited.

        ","tags":["ASYNC105"]},{"location":"rules/trio-sync-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Many of the functions exposed by trio are asynchronous, and must be awaited to take effect. Calling a trio function without an await can lead to RuntimeWarning diagnostics and unexpected behaviour.

        ","tags":["ASYNC105"]},{"location":"rules/trio-sync-call/#example","title":"Example","text":"
        async def double_sleep(x):\n    trio.sleep(2 * x)\n

        Use instead:

        async def double_sleep(x):\n    await trio.sleep(2 * x)\n
        ","tags":["ASYNC105"]},{"location":"rules/trio-sync-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as adding an await to a function call changes its semantics and runtime behavior.

        ","tags":["ASYNC105"]},{"location":"rules/triple-single-quotes/","title":"triple-single-quotes (D300)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D300"]},{"location":"rules/triple-single-quotes/#what-it-does","title":"What it does","text":"

        Checks for docstrings that use '''triple single quotes''' instead of \"\"\"triple double quotes\"\"\".

        ","tags":["D300"]},{"location":"rules/triple-single-quotes/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends the use of \"\"\"triple double quotes\"\"\" for docstrings, to ensure consistency.

        ","tags":["D300"]},{"location":"rules/triple-single-quotes/#example","title":"Example","text":"
        def kos_root():\n    '''Return the pathname of the KOS root directory.'''\n

        Use instead:

        def kos_root():\n    \"\"\"Return the pathname of the KOS root directory.\"\"\"\n
        ","tags":["D300"]},{"location":"rules/triple-single-quotes/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent quotes, making the rule redundant.

        ","tags":["D300"]},{"location":"rules/triple-single-quotes/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D300"]},{"location":"rules/true-false-comparison/","title":"true-false-comparison (E712)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["E712"]},{"location":"rules/true-false-comparison/#what-it-does","title":"What it does","text":"

        Checks for equality comparisons to boolean literals.

        ","tags":["E712"]},{"location":"rules/true-false-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends against using the equality operators == and != to compare values to True or False.

        Instead, use if cond: or if not cond: to check for truth values.

        If you intend to check if a value is the boolean literal True or False, consider using is or is not to check for identity instead.

        ","tags":["E712"]},{"location":"rules/true-false-comparison/#example","title":"Example","text":"
        if foo == True:\n    ...\n\nif bar == False:\n    ...\n

        Use instead:

        if foo:\n    ...\n\nif not bar:\n    ...\n
        ","tags":["E712"]},{"location":"rules/true-false-comparison/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may alter runtime behavior when used with libraries that override the ==/__eq__ or !=/__ne__ operators. In these cases, is/is not may not be equivalent to ==/!=. For more information, see this issue.

        ","tags":["E712"]},{"location":"rules/try-consider-else/","title":"try-consider-else (TRY300)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY300"]},{"location":"rules/try-consider-else/#what-it-does","title":"What it does","text":"

        Checks for return statements in try blocks.

        ","tags":["TRY300"]},{"location":"rules/try-consider-else/#why-is-this-bad","title":"Why is this bad?","text":"

        The try-except statement has an else clause for code that should run only if no exceptions were raised. Returns in try blocks may exhibit confusing or unwanted behavior, such as being overridden by control flow in except and finally blocks, or unintentionally suppressing an exception.

        ","tags":["TRY300"]},{"location":"rules/try-consider-else/#example","title":"Example","text":"
        import logging\n\n\ndef reciprocal(n):\n    try:\n        rec = 1 / n\n        print(f\"reciprocal of {n} is {rec}\")\n        return rec\n    except ZeroDivisionError:\n        logging.exception(\"Exception occurred\")\n

        Use instead:

        import logging\n\n\ndef reciprocal(n):\n    try:\n        rec = 1 / n\n    except ZeroDivisionError:\n        logging.exception(\"Exception occurred\")\n    else:\n        print(f\"reciprocal of {n} is {rec}\")\n        return rec\n
        ","tags":["TRY300"]},{"location":"rules/try-consider-else/#references","title":"References","text":"
        • Python documentation: Errors and Exceptions
        ","tags":["TRY300"]},{"location":"rules/try-except-continue/","title":"try-except-continue (S112)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S112"]},{"location":"rules/try-except-continue/#what-it-does","title":"What it does","text":"

        Checks for uses of the try-except-continue pattern.

        ","tags":["S112"]},{"location":"rules/try-except-continue/#why-is-this-bad","title":"Why is this bad?","text":"

        The try-except-continue pattern suppresses all exceptions. Suppressing exceptions may hide errors that could otherwise reveal unexpected behavior, security vulnerabilities, or malicious activity. Instead, consider logging the exception.

        ","tags":["S112"]},{"location":"rules/try-except-continue/#example","title":"Example","text":"
        import logging\n\nwhile predicate:\n    try:\n        ...\n    except Exception:\n        continue\n

        Use instead:

        import logging\n\nwhile predicate:\n    try:\n        ...\n    except Exception as exc:\n        logging.exception(\"Error occurred\")\n
        ","tags":["S112"]},{"location":"rules/try-except-continue/#options","title":"Options","text":"
        • lint.flake8-bandit.check-typed-exception
        ","tags":["S112"]},{"location":"rules/try-except-continue/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-703
        • Python documentation: logging
        ","tags":["S112"]},{"location":"rules/try-except-in-loop/","title":"try-except-in-loop (PERF203)","text":"

        Derived from the Perflint linter.

        ","tags":["PERF203"]},{"location":"rules/try-except-in-loop/#what-it-does","title":"What it does","text":"

        Checks for uses of except handling via try-except within for and while loops.

        ","tags":["PERF203"]},{"location":"rules/try-except-in-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        Exception handling via try-except blocks incurs some performance overhead, regardless of whether an exception is raised.

        To optimize your code, two techniques are possible:

        1. Refactor your code to put the entire loop into the try-except block, rather than wrapping each iteration in a separate try-except block.
        2. Use \"Look Before You Leap\" idioms that attempt to avoid exceptions being raised in the first place, avoiding the need to use try-except blocks in the first place.

        This rule is only enforced for Python versions prior to 3.11, which introduced \"zero-cost\" exception handling. However, note that even on Python 3.11 and newer, refactoring your code to avoid exception handling in tight loops can provide a significant speedup in some cases, as zero-cost exception handling is only zero-cost in the \"happy path\" where no exception is raised in the try-except block.

        As with all perflint rules, this is only intended as a micro-optimization. In many cases, it will have a negligible impact on performance.

        ","tags":["PERF203"]},{"location":"rules/try-except-in-loop/#example","title":"Example","text":"
        string_numbers: list[str] = [\"1\", \"2\", \"three\", \"4\", \"5\"]\n\n# `try`/`except` that could be moved out of the loop:\nint_numbers: list[int] = []\nfor num in string_numbers:\n    try:\n        int_numbers.append(int(num))\n    except ValueError as e:\n        print(f\"Couldn't convert to integer: {e}\")\n        break\n\n# `try`/`except` used when \"look before you leap\" idioms could be used:\nnumber_names: dict[int, str] = {1: \"one\", 3: \"three\", 4: \"four\"}\nfor number in range(5):\n    try:\n        name = number_names[number]\n    except KeyError:\n        continue\n    else:\n        print(f\"The name of {number} is {name}\")\n

        Use instead:

        string_numbers: list[str] = [\"1\", \"2\", \"three\", \"4\", \"5\"]\n\nint_numbers: list[int] = []\ntry:\n    for num in string_numbers:\n        int_numbers.append(int(num))\nexcept ValueError as e:\n    print(f\"Couldn't convert to integer: {e}\")\n\nnumber_names: dict[int, str] = {1: \"one\", 3: \"three\", 4: \"four\"}\nfor number in range(5):\n    name = number_names.get(number)\n    if name is not None:\n        print(f\"The name of {number} is {name}\")\n
        ","tags":["PERF203"]},{"location":"rules/try-except-in-loop/#options","title":"Options","text":"
        • target-version
        ","tags":["PERF203"]},{"location":"rules/try-except-pass/","title":"try-except-pass (S110)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S110"]},{"location":"rules/try-except-pass/#what-it-does","title":"What it does","text":"

        Checks for uses of the try-except-pass pattern.

        ","tags":["S110"]},{"location":"rules/try-except-pass/#why-is-this-bad","title":"Why is this bad?","text":"

        The try-except-pass pattern suppresses all exceptions. Suppressing exceptions may hide errors that could otherwise reveal unexpected behavior, security vulnerabilities, or malicious activity. Instead, consider logging the exception.

        ","tags":["S110"]},{"location":"rules/try-except-pass/#example","title":"Example","text":"
        try:\n    ...\nexcept Exception:\n    pass\n

        Use instead:

        import logging\n\ntry:\n    ...\nexcept Exception as exc:\n    logging.exception(\"Exception occurred\")\n
        ","tags":["S110"]},{"location":"rules/try-except-pass/#options","title":"Options","text":"
        • lint.flake8-bandit.check-typed-exception
        ","tags":["S110"]},{"location":"rules/try-except-pass/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-703
        • Python documentation: logging
        ","tags":["S110"]},{"location":"rules/type-alias-without-annotation/","title":"type-alias-without-annotation (PYI026)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI026"]},{"location":"rules/type-alias-without-annotation/#what-it-does","title":"What it does","text":"

        Checks for type alias definitions that are not annotated with typing.TypeAlias.

        ","tags":["PYI026"]},{"location":"rules/type-alias-without-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a type alias is defined by assigning a type to a variable (e.g., Vector = list[float]).

        It's best to annotate type aliases with the typing.TypeAlias type to make it clear that the statement is a type alias declaration, as opposed to a normal variable assignment.

        ","tags":["PYI026"]},{"location":"rules/type-alias-without-annotation/#example","title":"Example","text":"
        Vector = list[float]\n

        Use instead:

        from typing import TypeAlias\n\nVector: TypeAlias = list[float]\n
        ","tags":["PYI026"]},{"location":"rules/type-alias-without-annotation/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for Python versions before 3.10, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["PYI026"]},{"location":"rules/type-alias-without-annotation/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["PYI026"]},{"location":"rules/type-bivariance/","title":"type-bivariance (PLC0131)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC0131"]},{"location":"rules/type-bivariance/#what-it-does","title":"What it does","text":"

        Checks for TypeVar and ParamSpec definitions in which the type is both covariant and contravariant.

        ","tags":["PLC0131"]},{"location":"rules/type-bivariance/#why-is-this-bad","title":"Why is this bad?","text":"

        By default, Python's generic types are invariant, but can be marked as either covariant or contravariant via the covariant and contravariant keyword arguments. While the API does allow you to mark a type as both covariant and contravariant, this is not supported by the type system, and should be avoided.

        Instead, change the variance of the type to be either covariant, contravariant, or invariant. If you want to describe both covariance and contravariance, consider using two separate type parameters.

        For context: an \"invariant\" generic type only accepts values that exactly match the type parameter; for example, list[Dog] accepts only list[Dog], not list[Animal] (superclass) or list[Bulldog] (subclass). This is the default behavior for Python's generic types.

        A \"covariant\" generic type accepts subclasses of the type parameter; for example, Sequence[Animal] accepts Sequence[Dog]. A \"contravariant\" generic type accepts superclasses of the type parameter; for example, Callable[Dog] accepts Callable[Animal].

        ","tags":["PLC0131"]},{"location":"rules/type-bivariance/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"T\", covariant=True, contravariant=True)\n

        Use instead:

        from typing import TypeVar\n\nT_co = TypeVar(\"T_co\", covariant=True)\nT_contra = TypeVar(\"T_contra\", contravariant=True)\n
        ","tags":["PLC0131"]},{"location":"rules/type-bivariance/#references","title":"References","text":"
        • Python documentation: typing \u2014 Support for type hints
        • PEP 483 \u2013 The Theory of Type Hints: Covariance and Contravariance
        • PEP 484 \u2013 Type Hints: Covariance and contravariance
        ","tags":["PLC0131"]},{"location":"rules/type-check-without-type-error/","title":"type-check-without-type-error (TRY004)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY004"]},{"location":"rules/type-check-without-type-error/#what-it-does","title":"What it does","text":"

        Checks for type checks that do not raise TypeError.

        ","tags":["TRY004"]},{"location":"rules/type-check-without-type-error/#why-is-this-bad","title":"Why is this bad?","text":"

        The Python documentation states that TypeError should be raised upon encountering an inappropriate type.

        ","tags":["TRY004"]},{"location":"rules/type-check-without-type-error/#example","title":"Example","text":"
        def foo(n: int):\n    if isinstance(n, int):\n        pass\n    else:\n        raise ValueError(\"n must be an integer\")\n

        Use instead:

        def foo(n: int):\n    if isinstance(n, int):\n        pass\n    else:\n        raise TypeError(\"n must be an integer\")\n
        ","tags":["TRY004"]},{"location":"rules/type-check-without-type-error/#references","title":"References","text":"
        • Python documentation: TypeError
        ","tags":["TRY004"]},{"location":"rules/type-comment-in-stub/","title":"type-comment-in-stub (PYI033)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI033"]},{"location":"rules/type-comment-in-stub/#what-it-does","title":"What it does","text":"

        Checks for the use of type comments (e.g., x = 1 # type: int) in stub files.

        ","tags":["PYI033"]},{"location":"rules/type-comment-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub (.pyi) files should use type annotations directly, rather than type comments, even if they're intended to support Python 2, since stub files are not executed at runtime. The one exception is # type: ignore.

        ","tags":["PYI033"]},{"location":"rules/type-comment-in-stub/#example","title":"Example","text":"
        x = 1  # type: int\n

        Use instead:

        x: int = 1\n
        ","tags":["PYI033"]},{"location":"rules/type-comparison/","title":"type-comparison (E721)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E721"]},{"location":"rules/type-comparison/#what-it-does","title":"What it does","text":"

        Checks for object type comparisons using == and other comparison operators.

        ","tags":["E721"]},{"location":"rules/type-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Unlike a direct type comparison, isinstance will also check if an object is an instance of a class or a subclass thereof.

        If you want to check for an exact type match, use is or is not.

        ","tags":["E721"]},{"location":"rules/type-comparison/#known-problems","title":"Known problems","text":"

        When using libraries that override the == (__eq__) operator (such as NumPy, Pandas, and SQLAlchemy), this rule may produce false positives, as converting from == to is or is not will change the behavior of the code.

        For example, the following operations are not equivalent:

        import numpy as np\n\nnp.array([True, False]) == False\n# array([False,  True])\n\nnp.array([True, False]) is False\n# False\n
        ","tags":["E721"]},{"location":"rules/type-comparison/#example","title":"Example","text":"
        if type(obj) == type(1):\n    pass\n\nif type(obj) == int:\n    pass\n

        Use instead:

        if isinstance(obj, int):\n    pass\n
        ","tags":["E721"]},{"location":"rules/type-name-incorrect-variance/","title":"type-name-incorrect-variance (PLC0105)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC0105"]},{"location":"rules/type-name-incorrect-variance/#what-it-does","title":"What it does","text":"

        Checks for type names that do not match the variance of their associated type parameter.

        ","tags":["PLC0105"]},{"location":"rules/type-name-incorrect-variance/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 484 recommends the use of the _co and _contra suffixes for covariant and contravariant type parameters, respectively (while invariant type parameters should not have any such suffix).

        ","tags":["PLC0105"]},{"location":"rules/type-name-incorrect-variance/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"T\", covariant=True)\nU = TypeVar(\"U\", contravariant=True)\nV_co = TypeVar(\"V_co\")\n

        Use instead:

        from typing import TypeVar\n\nT_co = TypeVar(\"T_co\", covariant=True)\nU_contra = TypeVar(\"U_contra\", contravariant=True)\nV = TypeVar(\"V\")\n
        ","tags":["PLC0105"]},{"location":"rules/type-name-incorrect-variance/#references","title":"References","text":"
        • Python documentation: typing \u2014 Support for type hints
        • PEP 483 \u2013 The Theory of Type Hints: Covariance and Contravariance
        • PEP 484 \u2013 Type Hints: Covariance and contravariance
        ","tags":["PLC0105"]},{"location":"rules/type-none-comparison/","title":"type-none-comparison (FURB169)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB169"]},{"location":"rules/type-none-comparison/#what-it-does","title":"What it does","text":"

        Checks for uses of type that compare the type of an object to the type of None.

        ","tags":["FURB169"]},{"location":"rules/type-none-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        There is only ever one instance of None, so it is more efficient and readable to use the is operator to check if an object is None.

        ","tags":["FURB169"]},{"location":"rules/type-none-comparison/#example","title":"Example","text":"
        type(obj) is type(None)\n

        Use instead:

        obj is None\n
        ","tags":["FURB169"]},{"location":"rules/type-none-comparison/#fix-safety","title":"Fix safety","text":"

        If the fix might remove comments, it will be marked as unsafe.

        ","tags":["FURB169"]},{"location":"rules/type-none-comparison/#references","title":"References","text":"
        • Python documentation: isinstance
        • Python documentation: None
        • Python documentation: type
        • Python documentation: Identity comparisons
        ","tags":["FURB169"]},{"location":"rules/type-of-primitive/","title":"type-of-primitive (UP003)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP003"]},{"location":"rules/type-of-primitive/#what-it-does","title":"What it does","text":"

        Checks for uses of type that take a primitive as an argument.

        ","tags":["UP003"]},{"location":"rules/type-of-primitive/#why-is-this-bad","title":"Why is this bad?","text":"

        type() returns the type of a given object. A type of a primitive can always be known in advance and accessed directly, which is more concise and explicit than using type().

        ","tags":["UP003"]},{"location":"rules/type-of-primitive/#example","title":"Example","text":"
        type(1)\n

        Use instead:

        int\n
        ","tags":["UP003"]},{"location":"rules/type-of-primitive/#references","title":"References","text":"
        • Python documentation: type()
        • Python documentation: Built-in types
        ","tags":["UP003"]},{"location":"rules/type-param-name-mismatch/","title":"type-param-name-mismatch (PLC0132)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC0132"]},{"location":"rules/type-param-name-mismatch/#what-it-does","title":"What it does","text":"

        Checks for TypeVar, TypeVarTuple, ParamSpec, and NewType definitions in which the name of the type parameter does not match the name of the variable to which it is assigned.

        ","tags":["PLC0132"]},{"location":"rules/type-param-name-mismatch/#why-is-this-bad","title":"Why is this bad?","text":"

        When defining a TypeVar or a related type parameter, Python allows you to provide a name for the type parameter. According to PEP 484, the name provided to the TypeVar constructor must be equal to the name of the variable to which it is assigned.

        ","tags":["PLC0132"]},{"location":"rules/type-param-name-mismatch/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"U\")\n

        Use instead:

        from typing import TypeVar\n\nT = TypeVar(\"T\")\n
        ","tags":["PLC0132"]},{"location":"rules/type-param-name-mismatch/#references","title":"References","text":"
        • Python documentation: typing \u2014 Support for type hints
        • PEP 484 \u2013 Type Hints: Generics
        ","tags":["PLC0132"]},{"location":"rules/typed-argument-default-in-stub/","title":"typed-argument-default-in-stub (PYI011)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI011"]},{"location":"rules/typed-argument-default-in-stub/#what-it-does","title":"What it does","text":"

        Checks for typed function arguments in stubs with complex default values.

        ","tags":["PYI011"]},{"location":"rules/typed-argument-default-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub (.pyi) files exist as \"data files\" for static analysis tools, and are not evaluated at runtime. While simple default values may be useful for some tools that consume stubs, such as IDEs, they are ignored by type checkers.

        Instead of including and reproducing a complex value, use ... to indicate that the assignment has a default value, but that the value is \"complex\" or varies according to the current platform or Python version. For the purposes of this rule, any default value counts as \"complex\" unless it is a literal int, float, complex, bytes, str, bool, None, ..., or a simple container literal.

        ","tags":["PYI011"]},{"location":"rules/typed-argument-default-in-stub/#example","title":"Example","text":"
        def foo(arg: list[int] = list(range(10_000))) -> None: ...\n

        Use instead:

        def foo(arg: list[int] = ...) -> None: ...\n
        ","tags":["PYI011"]},{"location":"rules/typed-argument-default-in-stub/#references","title":"References","text":"
        • flake8-pyi
        ","tags":["PYI011"]},{"location":"rules/typing-only-first-party-import/","title":"typing-only-first-party-import (TC001)","text":"

        Derived from the flake8-type-checking linter.

        Fix is sometimes available.

        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#what-it-does","title":"What it does","text":"

        Checks for first-party imports that are only used for type annotations, but aren't defined in a type-checking block.

        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused imports add a performance overhead at runtime, and risk creating import cycles. If an import is only used in typing-only contexts, it can instead be imported conditionally under an if TYPE_CHECKING: block to minimize runtime overhead.

        If lint.flake8-type-checking.quote-annotations is set to true, annotations will be wrapped in quotes if doing so would enable the corresponding import to be moved into an if TYPE_CHECKING: block.

        If a class requires that type annotations be available at runtime (as is the case for Pydantic, SQLAlchemy, and other libraries), consider using the lint.flake8-type-checking.runtime-evaluated-base-classes and lint.flake8-type-checking.runtime-evaluated-decorators settings to mark them as such.

        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#example","title":"Example","text":"
        from __future__ import annotations\n\nimport local_module\n\n\ndef func(sized: local_module.Container) -> int:\n    return len(sized)\n

        Use instead:

        from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    import local_module\n\n\ndef func(sized: local_module.Container) -> int:\n    return len(sized)\n
        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#preview","title":"Preview","text":"

        When preview is enabled, the criterion for determining whether an import is first-party is stricter, which could affect whether this lint is triggered vs TC001. See this FAQ section for more details.

        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#options","title":"Options","text":"
        • lint.flake8-type-checking.quote-annotations
        • lint.flake8-type-checking.runtime-evaluated-base-classes
        • lint.flake8-type-checking.runtime-evaluated-decorators
        • lint.flake8-type-checking.strict
        • lint.typing-modules
        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#references","title":"References","text":"
        • PEP 563: Runtime annotation resolution and TYPE_CHECKING
        ","tags":["TC001"]},{"location":"rules/typing-only-standard-library-import/","title":"typing-only-standard-library-import (TC003)","text":"

        Derived from the flake8-type-checking linter.

        Fix is sometimes available.

        ","tags":["TC003"]},{"location":"rules/typing-only-standard-library-import/#what-it-does","title":"What it does","text":"

        Checks for standard library imports that are only used for type annotations, but aren't defined in a type-checking block.

        ","tags":["TC003"]},{"location":"rules/typing-only-standard-library-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused imports add a performance overhead at runtime, and risk creating import cycles. If an import is only used in typing-only contexts, it can instead be imported conditionally under an if TYPE_CHECKING: block to minimize runtime overhead.

        If lint.flake8-type-checking.quote-annotations is set to true, annotations will be wrapped in quotes if doing so would enable the corresponding import to be moved into an if TYPE_CHECKING: block.

        If a class requires that type annotations be available at runtime (as is the case for Pydantic, SQLAlchemy, and other libraries), consider using the lint.flake8-type-checking.runtime-evaluated-base-classes and lint.flake8-type-checking.runtime-evaluated-decorators settings to mark them as such.

        ","tags":["TC003"]},{"location":"rules/typing-only-standard-library-import/#example","title":"Example","text":"
        from __future__ import annotations\n\nfrom pathlib import Path\n\n\ndef func(path: Path) -> str:\n    return str(path)\n

        Use instead:

        from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from pathlib import Path\n\n\ndef func(path: Path) -> str:\n    return str(path)\n
        ","tags":["TC003"]},{"location":"rules/typing-only-standard-library-import/#options","title":"Options","text":"
        • lint.flake8-type-checking.quote-annotations
        • lint.flake8-type-checking.runtime-evaluated-base-classes
        • lint.flake8-type-checking.runtime-evaluated-decorators
        • lint.flake8-type-checking.strict
        • lint.typing-modules
        ","tags":["TC003"]},{"location":"rules/typing-only-standard-library-import/#references","title":"References","text":"
        • PEP 563: Runtime annotation resolution and TYPE_CHECKING
        ","tags":["TC003"]},{"location":"rules/typing-only-third-party-import/","title":"typing-only-third-party-import (TC002)","text":"

        Derived from the flake8-type-checking linter.

        Fix is sometimes available.

        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#what-it-does","title":"What it does","text":"

        Checks for third-party imports that are only used for type annotations, but aren't defined in a type-checking block.

        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused imports add a performance overhead at runtime, and risk creating import cycles. If an import is only used in typing-only contexts, it can instead be imported conditionally under an if TYPE_CHECKING: block to minimize runtime overhead.

        If lint.flake8-type-checking.quote-annotations is set to true, annotations will be wrapped in quotes if doing so would enable the corresponding import to be moved into an if TYPE_CHECKING: block.

        If a class requires that type annotations be available at runtime (as is the case for Pydantic, SQLAlchemy, and other libraries), consider using the lint.flake8-type-checking.runtime-evaluated-base-classes and lint.flake8-type-checking.runtime-evaluated-decorators settings to mark them as such.

        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#example","title":"Example","text":"
        from __future__ import annotations\n\nimport pandas as pd\n\n\ndef func(df: pd.DataFrame) -> int:\n    return len(df)\n

        Use instead:

        from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    import pandas as pd\n\n\ndef func(df: pd.DataFrame) -> int:\n    return len(df)\n
        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#preview","title":"Preview","text":"

        When preview is enabled, the criterion for determining whether an import is first-party is stricter, which could affect whether this lint is triggered vs TC001. See this FAQ section for more details.

        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#options","title":"Options","text":"
        • lint.flake8-type-checking.quote-annotations
        • lint.flake8-type-checking.runtime-evaluated-base-classes
        • lint.flake8-type-checking.runtime-evaluated-decorators
        • lint.flake8-type-checking.strict
        • lint.typing-modules
        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#references","title":"References","text":"
        • PEP 563: Runtime annotation resolution and TYPE_CHECKING
        ","tags":["TC002"]},{"location":"rules/typing-text-str-alias/","title":"typing-text-str-alias (UP019)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP019"]},{"location":"rules/typing-text-str-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of typing.Text.

        ","tags":["UP019"]},{"location":"rules/typing-text-str-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        typing.Text is an alias for str, and only exists for Python 2 compatibility. As of Python 3.11, typing.Text is deprecated. Use str instead.

        ","tags":["UP019"]},{"location":"rules/typing-text-str-alias/#example","title":"Example","text":"
        from typing import Text\n\nfoo: Text = \"bar\"\n

        Use instead:

        foo: str = \"bar\"\n
        ","tags":["UP019"]},{"location":"rules/typing-text-str-alias/#references","title":"References","text":"
        • Python documentation: typing.Text
        ","tags":["UP019"]},{"location":"rules/unaliased-collections-abc-set-import/","title":"unaliased-collections-abc-set-import (PYI025)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI025"]},{"location":"rules/unaliased-collections-abc-set-import/#what-it-does","title":"What it does","text":"

        Checks for from collections.abc import Set imports that do not alias Set to AbstractSet.

        ","tags":["PYI025"]},{"location":"rules/unaliased-collections-abc-set-import/#why-is-this-bad","title":"Why is this bad?","text":"

        The Set type in collections.abc is an abstract base class for set-like types. It is easily confused with, and not equivalent to, the set builtin.

        To avoid confusion, Set should be aliased to AbstractSet when imported. This makes it clear that the imported type is an abstract base class, and not the set builtin.

        ","tags":["PYI025"]},{"location":"rules/unaliased-collections-abc-set-import/#example","title":"Example","text":"
        from collections.abc import Set\n

        Use instead:

        from collections.abc import Set as AbstractSet\n
        ","tags":["PYI025"]},{"location":"rules/unaliased-collections-abc-set-import/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for Set imports defined at the top-level of a .py module. Top-level symbols are implicitly exported by the module, and so renaming a top-level symbol may break downstream modules that import it.

        The same is not true for .pyi files, where imported symbols are only re-exported if they are included in __all__, use a \"redundant\" import foo as foo alias, or are imported via a * import. As such, the fix is marked as safe in more cases for .pyi files.

        ","tags":["PYI025"]},{"location":"rules/unannotated-assignment-in-stub/","title":"unannotated-assignment-in-stub (PYI052)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI052"]},{"location":"rules/unannotated-assignment-in-stub/#what-it-does","title":"What it does","text":"

        Checks for unannotated assignments in stub (.pyi) files.

        ","tags":["PYI052"]},{"location":"rules/unannotated-assignment-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files exist to provide type hints, and are never executed. As such, all assignments in stub files should be annotated with a type.

        ","tags":["PYI052"]},{"location":"rules/unary-prefix-increment-decrement/","title":"unary-prefix-increment-decrement (B002)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B002"]},{"location":"rules/unary-prefix-increment-decrement/#what-it-does","title":"What it does","text":"

        Checks for the attempted use of the unary prefix increment (++) or decrement operator (--).

        ","tags":["B002"]},{"location":"rules/unary-prefix-increment-decrement/#why-is-this-bad","title":"Why is this bad?","text":"

        Python does not support the unary prefix increment or decrement operator. Writing ++n is equivalent to +(+(n)) and writing --n is equivalent to -(-(n)). In both cases, it is equivalent to n.

        ","tags":["B002"]},{"location":"rules/unary-prefix-increment-decrement/#example","title":"Example","text":"
        ++x\n--y\n

        Use instead:

        x += 1\ny -= 1\n
        ","tags":["B002"]},{"location":"rules/unary-prefix-increment-decrement/#references","title":"References","text":"
        • Python documentation: Unary arithmetic and bitwise operations
        • Python documentation: Augmented assignment statements
        ","tags":["B002"]},{"location":"rules/unassigned-special-variable-in-stub/","title":"unassigned-special-variable-in-stub (PYI035)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI035"]},{"location":"rules/unassigned-special-variable-in-stub/#what-it-does","title":"What it does","text":"

        Checks that __all__, __match_args__, and __slots__ variables are assigned to values when defined in stub files.

        ","tags":["PYI035"]},{"location":"rules/unassigned-special-variable-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Special variables like __all__ have the same semantics in stub files as they do in Python modules, and so should be consistent with their runtime counterparts.

        ","tags":["PYI035"]},{"location":"rules/unassigned-special-variable-in-stub/#example","title":"Example","text":"
        __all__: list[str]\n

        Use instead:

        __all__: list[str] = [\"foo\", \"bar\"]\n
        ","tags":["PYI035"]},{"location":"rules/uncapitalized-environment-variables/","title":"uncapitalized-environment-variables (SIM112)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM112"]},{"location":"rules/uncapitalized-environment-variables/#what-it-does","title":"What it does","text":"

        Check for environment variables that are not capitalized.

        ","tags":["SIM112"]},{"location":"rules/uncapitalized-environment-variables/#why-is-this-bad","title":"Why is this bad?","text":"

        By convention, environment variables should be capitalized.

        On Windows, environment variables are case-insensitive and are converted to uppercase, so using lowercase environment variables can lead to subtle bugs.

        ","tags":["SIM112"]},{"location":"rules/uncapitalized-environment-variables/#example","title":"Example","text":"
        import os\n\nos.environ[\"foo\"]\n

        Use instead:

        import os\n\nos.environ[\"FOO\"]\n
        ","tags":["SIM112"]},{"location":"rules/uncapitalized-environment-variables/#fix-safety","title":"Fix safety","text":"

        This fix is always marked as unsafe because automatically capitalizing environment variable names can change program behavior in environments where the variable names are case-sensitive, such as most Unix-like systems.

        ","tags":["SIM112"]},{"location":"rules/uncapitalized-environment-variables/#references","title":"References","text":"
        • Python documentation: os.environ
        ","tags":["SIM112"]},{"location":"rules/unconventional-import-alias/","title":"unconventional-import-alias (ICN001)","text":"

        Derived from the flake8-import-conventions linter.

        Fix is sometimes available.

        ","tags":["ICN001"]},{"location":"rules/unconventional-import-alias/#what-it-does","title":"What it does","text":"

        Checks for imports that are typically imported using a common convention, like import pandas as pd, and enforces that convention.

        ","tags":["ICN001"]},{"location":"rules/unconventional-import-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use a common convention for imports to make your code more readable and idiomatic.

        For example, import pandas as pd is a common convention for importing the pandas library, and users typically expect Pandas to be aliased as pd.

        ","tags":["ICN001"]},{"location":"rules/unconventional-import-alias/#example","title":"Example","text":"
        import pandas\n

        Use instead:

        import pandas as pd\n
        ","tags":["ICN001"]},{"location":"rules/unconventional-import-alias/#options","title":"Options","text":"
        • lint.flake8-import-conventions.aliases
        • lint.flake8-import-conventions.extend-aliases
        ","tags":["ICN001"]},{"location":"rules/undefined-export/","title":"undefined-export (F822)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F822"]},{"location":"rules/undefined-export/#what-it-does","title":"What it does","text":"

        Checks for undefined names in __all__.

        ","tags":["F822"]},{"location":"rules/undefined-export/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the __all__ variable is used to define the names that are exported when a module is imported as a wildcard (e.g., from foo import *). The names in __all__ must be defined in the module, but are included as strings.

        Including an undefined name in __all__ is likely to raise NameError at runtime, when the module is imported.

        In preview, this rule will flag undefined names in __init__.py file, even if those names implicitly refer to other modules in the package. Users that rely on implicit exports should disable this rule in __init__.py files via lint.per-file-ignores.

        ","tags":["F822"]},{"location":"rules/undefined-export/#example","title":"Example","text":"
        from foo import bar\n\n\n__all__ = [\"bar\", \"baz\"]  # undefined name `baz` in `__all__`\n

        Use instead:

        from foo import bar, baz\n\n\n__all__ = [\"bar\", \"baz\"]\n
        ","tags":["F822"]},{"location":"rules/undefined-export/#references","title":"References","text":"
        • Python documentation: __all__
        ","tags":["F822"]},{"location":"rules/undefined-local-with-import-star-usage/","title":"undefined-local-with-import-star-usage (F405)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F405"]},{"location":"rules/undefined-local-with-import-star-usage/#what-it-does","title":"What it does","text":"

        Checks for names that might be undefined, but may also be defined in a wildcard import.

        ","tags":["F405"]},{"location":"rules/undefined-local-with-import-star-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Wildcard imports (e.g., from module import *) make it hard to determine which symbols are available in the current namespace. If a module contains a wildcard import, and a name in the current namespace has not been explicitly defined or imported, then it's unclear whether the name is undefined or was imported by the wildcard import.

        If the name is defined in via a wildcard import, that member should be imported explicitly to avoid confusion.

        If the name is not defined in a wildcard import, it should be defined or imported.

        ","tags":["F405"]},{"location":"rules/undefined-local-with-import-star-usage/#example","title":"Example","text":"
        from math import *\n\n\ndef area(radius):\n    return pi * radius**2\n

        Use instead:

        from math import pi\n\n\ndef area(radius):\n    return pi * radius**2\n
        ","tags":["F405"]},{"location":"rules/undefined-local-with-import-star/","title":"undefined-local-with-import-star (F403)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F403"]},{"location":"rules/undefined-local-with-import-star/#what-it-does","title":"What it does","text":"

        Checks for the use of wildcard imports.

        ","tags":["F403"]},{"location":"rules/undefined-local-with-import-star/#why-is-this-bad","title":"Why is this bad?","text":"

        Wildcard imports (e.g., from module import *) make it hard to determine which symbols are available in the current namespace, and from which module they were imported. They're also discouraged by PEP 8.

        ","tags":["F403"]},{"location":"rules/undefined-local-with-import-star/#example","title":"Example","text":"
        from math import *\n\n\ndef area(radius):\n    return pi * radius**2\n

        Use instead:

        from math import pi\n\n\ndef area(radius):\n    return pi * radius**2\n
        ","tags":["F403"]},{"location":"rules/undefined-local-with-nested-import-star-usage/","title":"undefined-local-with-nested-import-star-usage (F406)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F406"]},{"location":"rules/undefined-local-with-nested-import-star-usage/#what-it-does","title":"What it does","text":"

        Check for the use of wildcard imports outside of the module namespace.

        ","tags":["F406"]},{"location":"rules/undefined-local-with-nested-import-star-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of wildcard imports outside of the module namespace (e.g., within functions) can lead to confusion, as the import can shadow local variables.

        Though wildcard imports are discouraged by PEP 8, when necessary, they should be placed in the module namespace (i.e., at the top-level of a module).

        ","tags":["F406"]},{"location":"rules/undefined-local-with-nested-import-star-usage/#example","title":"Example","text":"
        def foo():\n    from math import *\n

        Use instead:

        from math import *\n\n\ndef foo(): ...\n
        ","tags":["F406"]},{"location":"rules/undefined-local/","title":"undefined-local (F823)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F823"]},{"location":"rules/undefined-local/#what-it-does","title":"What it does","text":"

        Checks for undefined local variables.

        ","tags":["F823"]},{"location":"rules/undefined-local/#why-is-this-bad","title":"Why is this bad?","text":"

        Referencing a local variable before it has been assigned will raise an UnboundLocalError at runtime.

        ","tags":["F823"]},{"location":"rules/undefined-local/#example","title":"Example","text":"
        x = 1\n\n\ndef foo():\n    x += 1\n

        Use instead:

        x = 1\n\n\ndef foo():\n    global x\n    x += 1\n
        ","tags":["F823"]},{"location":"rules/undefined-name/","title":"undefined-name (F821)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F821"]},{"location":"rules/undefined-name/#what-it-does","title":"What it does","text":"

        Checks for uses of undefined names.

        ","tags":["F821"]},{"location":"rules/undefined-name/#why-is-this-bad","title":"Why is this bad?","text":"

        An undefined name is likely to raise NameError at runtime.

        ","tags":["F821"]},{"location":"rules/undefined-name/#example","title":"Example","text":"
        def double():\n    return n * 2  # raises `NameError` if `n` is undefined when `double` is called\n

        Use instead:

        def double(n):\n    return n * 2\n
        ","tags":["F821"]},{"location":"rules/undefined-name/#options","title":"Options","text":"
        • target-version: Can be used to configure which symbols Ruff will understand as being available in the builtins namespace.
        ","tags":["F821"]},{"location":"rules/undefined-name/#references","title":"References","text":"
        • Python documentation: Naming and binding
        ","tags":["F821"]},{"location":"rules/under-indentation/","title":"under-indentation (D207)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D207"]},{"location":"rules/under-indentation/#what-it-does","title":"What it does","text":"

        Checks for under-indented docstrings.

        ","tags":["D207"]},{"location":"rules/under-indentation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that docstrings be indented to the same level as their opening quotes. Avoid under-indenting docstrings, for consistency.

        ","tags":["D207"]},{"location":"rules/under-indentation/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\nSort the list in ascending order and return a copy of the result using the bubble sort\nalgorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D207"]},{"location":"rules/under-indentation/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        ","tags":["D207"]},{"location":"rules/under-indentation/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D207"]},{"location":"rules/undocumented-magic-method/","title":"undocumented-magic-method (D105)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D105"]},{"location":"rules/undocumented-magic-method/#what-it-does","title":"What it does","text":"

        Checks for undocumented magic method definitions.

        ","tags":["D105"]},{"location":"rules/undocumented-magic-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Magic methods (methods with names that start and end with double underscores) are used to implement operator overloading and other special behavior. Such methods should be documented via docstrings to outline their behavior.

        Generally, magic method docstrings should describe the method's behavior, arguments, side effects, exceptions, return values, and any other information that may be relevant to the user.

        If the codebase adheres to a standard format for method docstrings, follow that format for consistency.

        ","tags":["D105"]},{"location":"rules/undocumented-magic-method/#example","title":"Example","text":"
        class Cat(Animal):\n    def __str__(self) -> str:\n        return f\"Cat: {self.name}\"\n\n\ncat = Cat(\"Dusty\")\nprint(cat)  # \"Cat: Dusty\"\n

        Use instead:

        class Cat(Animal):\n    def __str__(self) -> str:\n        \"\"\"Return a string representation of the cat.\"\"\"\n        return f\"Cat: {self.name}\"\n\n\ncat = Cat(\"Dusty\")\nprint(cat)  # \"Cat: Dusty\"\n
        ","tags":["D105"]},{"location":"rules/undocumented-magic-method/#options","title":"Options","text":"
        • lint.pydocstyle.ignore-decorators
        ","tags":["D105"]},{"location":"rules/undocumented-magic-method/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Python Docstrings
        ","tags":["D105"]},{"location":"rules/undocumented-param/","title":"undocumented-param (D417)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D417"]},{"location":"rules/undocumented-param/#what-it-does","title":"What it does","text":"

        Checks for function docstrings that do not include documentation for all parameters in the function.

        ","tags":["D417"]},{"location":"rules/undocumented-param/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule helps prevent you from leaving Google-style docstrings unfinished or incomplete. Multiline Google-style docstrings should describe all parameters for the function they are documenting.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. Function docstrings often include a section for function arguments; this rule is concerned with that section only. Note that this rule only checks docstrings with an arguments (e.g. Args) section.

        This rule is enabled when using the google convention, and disabled when using the pep257 and numpy conventions.

        ","tags":["D417"]},{"location":"rules/undocumented-param/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D417"]},{"location":"rules/undocumented-param/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        • lint.pydocstyle.ignore-var-parameters
        ","tags":["D417"]},{"location":"rules/undocumented-param/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • Google Python Style Guide - Docstrings
        ","tags":["D417"]},{"location":"rules/undocumented-public-class/","title":"undocumented-public-class (D101)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D101"]},{"location":"rules/undocumented-public-class/#what-it-does","title":"What it does","text":"

        Checks for undocumented public class definitions.

        ","tags":["D101"]},{"location":"rules/undocumented-public-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Public classes should be documented via docstrings to outline their purpose and behavior.

        Generally, a class docstring should describe the class's purpose and list its public attributes and methods.

        If the codebase adheres to a standard format for class docstrings, follow that format for consistency.

        ","tags":["D101"]},{"location":"rules/undocumented-public-class/#example","title":"Example","text":"
        class Player:\n    def __init__(self, name: str, points: int = 0) -> None:\n        self.name: str = name\n        self.points: int = points\n\n    def add_points(self, points: int) -> None:\n        self.points += points\n

        Use instead (in the NumPy docstring format):

        class Player:\n    \"\"\"A player in the game.\n\n    Attributes\n    ----------\n    name : str\n        The name of the player.\n    points : int\n        The number of points the player has.\n\n    Methods\n    -------\n    add_points(points: int) -> None\n        Add points to the player's score.\n    \"\"\"\n\n    def __init__(self, name: str, points: int = 0) -> None:\n        self.name: str = name\n        self.points: int = points\n\n    def add_points(self, points: int) -> None:\n        self.points += points\n

        Or (in the Google docstring format):

        class Player:\n    \"\"\"A player in the game.\n\n    Attributes:\n        name: The name of the player.\n        points: The number of points the player has.\n    \"\"\"\n\n    def __init__(self, name: str, points: int = 0) -> None:\n        self.name: str = name\n        self.points: int = points\n\n    def add_points(self, points: int) -> None:\n        self.points += points\n
        ","tags":["D101"]},{"location":"rules/undocumented-public-class/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D101"]},{"location":"rules/undocumented-public-function/","title":"undocumented-public-function (D103)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D103"]},{"location":"rules/undocumented-public-function/#what-it-does","title":"What it does","text":"

        Checks for undocumented public function definitions.

        ","tags":["D103"]},{"location":"rules/undocumented-public-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Public functions should be documented via docstrings to outline their purpose and behavior.

        Generally, a function docstring should describe the function's behavior, arguments, side effects, exceptions, return values, and any other information that may be relevant to the user.

        If the codebase adheres to a standard format for function docstrings, follow that format for consistency.

        ","tags":["D103"]},{"location":"rules/undocumented-public-function/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead (using the NumPy docstring format):

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Or, using the Google docstring format:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D103"]},{"location":"rules/undocumented-public-function/#options","title":"Options","text":"
        • lint.pydocstyle.ignore-decorators
        ","tags":["D103"]},{"location":"rules/undocumented-public-function/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Python Docstrings
        ","tags":["D103"]},{"location":"rules/undocumented-public-init/","title":"undocumented-public-init (D107)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D107"]},{"location":"rules/undocumented-public-init/#what-it-does","title":"What it does","text":"

        Checks for public __init__ method definitions that are missing docstrings.

        ","tags":["D107"]},{"location":"rules/undocumented-public-init/#why-is-this-bad","title":"Why is this bad?","text":"

        Public __init__ methods are used to initialize objects. __init__ methods should be documented via docstrings to describe the method's behavior, arguments, side effects, exceptions, and any other information that may be relevant to the user.

        If the codebase adheres to a standard format for __init__ method docstrings, follow that format for consistency.

        ","tags":["D107"]},{"location":"rules/undocumented-public-init/#example","title":"Example","text":"
        class City:\n    def __init__(self, name: str, population: int) -> None:\n        self.name: str = name\n        self.population: int = population\n

        Use instead:

        class City:\n    def __init__(self, name: str, population: int) -> None:\n        \"\"\"Initialize a city with a name and population.\"\"\"\n        self.name: str = name\n        self.population: int = population\n
        ","tags":["D107"]},{"location":"rules/undocumented-public-init/#options","title":"Options","text":"
        • lint.pydocstyle.ignore-decorators
        ","tags":["D107"]},{"location":"rules/undocumented-public-init/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Python Docstrings
        ","tags":["D107"]},{"location":"rules/undocumented-public-method/","title":"undocumented-public-method (D102)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D102"]},{"location":"rules/undocumented-public-method/#what-it-does","title":"What it does","text":"

        Checks for undocumented public method definitions.

        ","tags":["D102"]},{"location":"rules/undocumented-public-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Public methods should be documented via docstrings to outline their purpose and behavior.

        Generally, a method docstring should describe the method's behavior, arguments, side effects, exceptions, return values, and any other information that may be relevant to the user.

        If the codebase adheres to a standard format for method docstrings, follow that format for consistency.

        ","tags":["D102"]},{"location":"rules/undocumented-public-method/#example","title":"Example","text":"
        class Cat(Animal):\n    def greet(self, happy: bool = True):\n        if happy:\n            print(\"Meow!\")\n        else:\n            raise ValueError(\"Tried to greet an unhappy cat.\")\n

        Use instead (in the NumPy docstring format):

        class Cat(Animal):\n    def greet(self, happy: bool = True):\n        \"\"\"Print a greeting from the cat.\n\n        Parameters\n        ----------\n        happy : bool, optional\n            Whether the cat is happy, is True by default.\n\n        Raises\n        ------\n        ValueError\n            If the cat is not happy.\n        \"\"\"\n        if happy:\n            print(\"Meow!\")\n        else:\n            raise ValueError(\"Tried to greet an unhappy cat.\")\n

        Or (in the Google docstring format):

        class Cat(Animal):\n    def greet(self, happy: bool = True):\n        \"\"\"Print a greeting from the cat.\n\n        Args:\n            happy: Whether the cat is happy, is True by default.\n\n        Raises:\n            ValueError: If the cat is not happy.\n        \"\"\"\n        if happy:\n            print(\"Meow!\")\n        else:\n            raise ValueError(\"Tried to greet an unhappy cat.\")\n
        ","tags":["D102"]},{"location":"rules/undocumented-public-method/#options","title":"Options","text":"
        • lint.pydocstyle.ignore-decorators
        ","tags":["D102"]},{"location":"rules/undocumented-public-method/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D102"]},{"location":"rules/undocumented-public-module/","title":"undocumented-public-module (D100)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D100"]},{"location":"rules/undocumented-public-module/#what-it-does","title":"What it does","text":"

        Checks for undocumented public module definitions.

        ","tags":["D100"]},{"location":"rules/undocumented-public-module/#why-is-this-bad","title":"Why is this bad?","text":"

        Public modules should be documented via docstrings to outline their purpose and contents.

        Generally, module docstrings should describe the purpose of the module and list the classes, exceptions, functions, and other objects that are exported by the module, alongside a one-line summary of each.

        If the module is a script, the docstring should be usable as its \"usage\" message.

        If the codebase adheres to a standard format for module docstrings, follow that format for consistency.

        ","tags":["D100"]},{"location":"rules/undocumented-public-module/#example","title":"Example","text":"
        class FasterThanLightError(ZeroDivisionError): ...\n\n\ndef calculate_speed(distance: float, time: float) -> float: ...\n

        Use instead:

        \"\"\"Utility functions and classes for calculating speed.\n\nThis module provides:\n- FasterThanLightError: exception when FTL speed is calculated;\n- calculate_speed: calculate speed given distance and time.\n\"\"\"\n\n\nclass FasterThanLightError(ZeroDivisionError): ...\n\n\ndef calculate_speed(distance: float, time: float) -> float: ...\n
        ","tags":["D100"]},{"location":"rules/undocumented-public-module/#notebook-behavior","title":"Notebook behavior","text":"

        This rule is ignored for Jupyter Notebooks.

        ","tags":["D100"]},{"location":"rules/undocumented-public-module/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D100"]},{"location":"rules/undocumented-public-nested-class/","title":"undocumented-public-nested-class (D106)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D106"]},{"location":"rules/undocumented-public-nested-class/#what-it-does","title":"What it does","text":"

        Checks for undocumented public class definitions, for nested classes.

        ","tags":["D106"]},{"location":"rules/undocumented-public-nested-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Public classes should be documented via docstrings to outline their purpose and behavior.

        Nested classes do not inherit the docstring of their enclosing class, so they should have their own docstrings.

        If the codebase adheres to a standard format for class docstrings, follow that format for consistency.

        ","tags":["D106"]},{"location":"rules/undocumented-public-nested-class/#example","title":"Example","text":"
        class Foo:\n    \"\"\"Class Foo.\"\"\"\n\n    class Bar: ...\n\n\nbar = Foo.Bar()\nbar.__doc__  # None\n

        Use instead:

        class Foo:\n    \"\"\"Class Foo.\"\"\"\n\n    class Bar:\n        \"\"\"Class Bar.\"\"\"\n\n\nbar = Foo.Bar()\nbar.__doc__  # \"Class Bar.\"\n
        ","tags":["D106"]},{"location":"rules/undocumented-public-nested-class/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Python Docstrings
        ","tags":["D106"]},{"location":"rules/undocumented-public-package/","title":"undocumented-public-package (D104)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D104"]},{"location":"rules/undocumented-public-package/#what-it-does","title":"What it does","text":"

        Checks for undocumented public package definitions.

        ","tags":["D104"]},{"location":"rules/undocumented-public-package/#why-is-this-bad","title":"Why is this bad?","text":"

        Public packages should be documented via docstrings to outline their purpose and contents.

        Generally, package docstrings should list the modules and subpackages that are exported by the package.

        If the codebase adheres to a standard format for package docstrings, follow that format for consistency.

        ","tags":["D104"]},{"location":"rules/undocumented-public-package/#example","title":"Example","text":"
        __all__ = [\"Player\", \"Game\"]\n

        Use instead:

        \"\"\"Game and player management package.\n\nThis package provides classes for managing players and games.\n\"\"\"\n\n__all__ = [\"player\", \"game\"]\n
        ","tags":["D104"]},{"location":"rules/undocumented-public-package/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Python Docstrings
        ","tags":["D104"]},{"location":"rules/undocumented-warn/","title":"undocumented-warn (LOG009)","text":"

        Derived from the flake8-logging linter.

        Fix is sometimes available.

        ","tags":["LOG009"]},{"location":"rules/undocumented-warn/#what-it-does","title":"What it does","text":"

        Checks for uses of logging.WARN.

        ","tags":["LOG009"]},{"location":"rules/undocumented-warn/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging.WARN constant is an undocumented alias for logging.WARNING.

        Although it\u2019s not explicitly deprecated, logging.WARN is not mentioned in the logging documentation. Prefer logging.WARNING instead.

        ","tags":["LOG009"]},{"location":"rules/undocumented-warn/#example","title":"Example","text":"
        import logging\n\n\nlogging.basicConfig(level=logging.WARN)\n

        Use instead:

        import logging\n\n\nlogging.basicConfig(level=logging.WARNING)\n
        ","tags":["LOG009"]},{"location":"rules/unexpected-indentation-comment/","title":"unexpected-indentation-comment (E116)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E116"]},{"location":"rules/unexpected-indentation-comment/#what-it-does","title":"What it does","text":"

        Checks for unexpected indentation of comment.

        ","tags":["E116"]},{"location":"rules/unexpected-indentation-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Comments should match the indentation of the containing code block.

        ","tags":["E116"]},{"location":"rules/unexpected-indentation-comment/#example","title":"Example","text":"
        a = 1\n    # b = 2\n

        Use instead:

        a = 1\n# b = 2\n
        ","tags":["E116"]},{"location":"rules/unexpected-indentation/","title":"unexpected-indentation (E113)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E113"]},{"location":"rules/unexpected-indentation/#what-it-does","title":"What it does","text":"

        Checks for unexpected indentation.

        ","tags":["E113"]},{"location":"rules/unexpected-indentation/#why-is-this-bad","title":"Why is this bad?","text":"

        Indentation outside of a code block is not valid Python syntax.

        ","tags":["E113"]},{"location":"rules/unexpected-indentation/#example","title":"Example","text":"
        a = 1\n    b = 2\n

        Use instead:

        a = 1\nb = 2\n
        ","tags":["E113"]},{"location":"rules/unexpected-spaces-around-keyword-parameter-equals/","title":"unexpected-spaces-around-keyword-parameter-equals (E251)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E251"]},{"location":"rules/unexpected-spaces-around-keyword-parameter-equals/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace around the equals sign in an unannotated function keyword parameter.

        ","tags":["E251"]},{"location":"rules/unexpected-spaces-around-keyword-parameter-equals/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, there should be no spaces around the equals sign in a keyword parameter, if it is unannotated:

        Don\u2019t use spaces around the = sign when used to indicate a keyword argument, or when used to indicate a default value for an unannotated function parameter.

        ","tags":["E251"]},{"location":"rules/unexpected-spaces-around-keyword-parameter-equals/#example","title":"Example","text":"
        def add(a = 0) -> int:\n    return a + 1\n

        Use instead:

        def add(a=0) -> int:\n    return a + 1\n
        ","tags":["E251"]},{"location":"rules/unexpected-special-method-signature/","title":"unexpected-special-method-signature (PLE0302)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0302"]},{"location":"rules/unexpected-special-method-signature/#what-it-does","title":"What it does","text":"

        Checks for \"special\" methods that have an unexpected method signature.

        ","tags":["PLE0302"]},{"location":"rules/unexpected-special-method-signature/#why-is-this-bad","title":"Why is this bad?","text":"

        \"Special\" methods, like __len__, are expected to adhere to a specific, standard function signature. Implementing a \"special\" method using a non-standard function signature can lead to unexpected and surprising behavior for users of a given class.

        ","tags":["PLE0302"]},{"location":"rules/unexpected-special-method-signature/#example","title":"Example","text":"
        class Bookshelf:\n    def __init__(self):\n        self._books = [\"Foo\", \"Bar\", \"Baz\"]\n\n    def __len__(self, index):  # __len__ does not except an index parameter\n        return len(self._books)\n\n    def __getitem__(self, index):\n        return self._books[index]\n

        Use instead:

        class Bookshelf:\n    def __init__(self):\n        self._books = [\"Foo\", \"Bar\", \"Baz\"]\n\n    def __len__(self):\n        return len(self._books)\n\n    def __getitem__(self, index):\n        return self._books[index]\n
        ","tags":["PLE0302"]},{"location":"rules/unexpected-special-method-signature/#references","title":"References","text":"
        • Python documentation: Data model
        ","tags":["PLE0302"]},{"location":"rules/unicode-kind-prefix/","title":"unicode-kind-prefix (UP025)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP025"]},{"location":"rules/unicode-kind-prefix/#what-it-does","title":"What it does","text":"

        Checks for uses of the Unicode kind prefix (u) in strings.

        ","tags":["UP025"]},{"location":"rules/unicode-kind-prefix/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3, all strings are Unicode by default. The Unicode kind prefix is unnecessary and should be removed to avoid confusion.

        ","tags":["UP025"]},{"location":"rules/unicode-kind-prefix/#example","title":"Example","text":"
        u\"foo\"\n

        Use instead:

        \"foo\"\n
        ","tags":["UP025"]},{"location":"rules/unicode-kind-prefix/#references","title":"References","text":"
        • Python documentation: Unicode HOWTO
        ","tags":["UP025"]},{"location":"rules/unintentional-type-annotation/","title":"unintentional-type-annotation (B032)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B032"]},{"location":"rules/unintentional-type-annotation/#what-it-does","title":"What it does","text":"

        Checks for the unintentional use of type annotations.

        ","tags":["B032"]},{"location":"rules/unintentional-type-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of a colon (:) in lieu of an assignment (=) can be syntactically valid, but is almost certainly a mistake when used in a subscript or attribute assignment.

        ","tags":["B032"]},{"location":"rules/unintentional-type-annotation/#example","title":"Example","text":"
        a[\"b\"]: 1\n

        Use instead:

        a[\"b\"] = 1\n
        ","tags":["B032"]},{"location":"rules/unix-command-wildcard-injection/","title":"unix-command-wildcard-injection (S609)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S609"]},{"location":"rules/unix-command-wildcard-injection/#what-it-does","title":"What it does","text":"

        Checks for possible wildcard injections in calls to subprocess.Popen().

        ","tags":["S609"]},{"location":"rules/unix-command-wildcard-injection/#why-is-this-bad","title":"Why is this bad?","text":"

        Wildcard injections can lead to unexpected behavior if unintended files are matched by the wildcard. Consider using a more specific path instead.

        ","tags":["S609"]},{"location":"rules/unix-command-wildcard-injection/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.Popen([\"chmod\", \"777\", \"*.py\"])\n

        Use instead:

        import subprocess\n\nsubprocess.Popen([\"chmod\", \"777\", \"main.py\"])\n
        ","tags":["S609"]},{"location":"rules/unix-command-wildcard-injection/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-78
        ","tags":["S609"]},{"location":"rules/unnecessary-assign/","title":"unnecessary-assign (RET504)","text":"

        Derived from the flake8-return linter.

        Fix is always available.

        ","tags":["RET504"]},{"location":"rules/unnecessary-assign/#what-it-does","title":"What it does","text":"

        Checks for variable assignments that immediately precede a return of the assigned variable.

        ","tags":["RET504"]},{"location":"rules/unnecessary-assign/#why-is-this-bad","title":"Why is this bad?","text":"

        The variable assignment is not necessary, as the value can be returned directly.

        ","tags":["RET504"]},{"location":"rules/unnecessary-assign/#example","title":"Example","text":"
        def foo():\n    bar = 1\n    return bar\n

        Use instead:

        def foo():\n    return 1\n
        ","tags":["RET504"]},{"location":"rules/unnecessary-builtin-import/","title":"unnecessary-builtin-import (UP029)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP029"]},{"location":"rules/unnecessary-builtin-import/#what-it-does","title":"What it does","text":"

        Checks for unnecessary imports of builtins.

        ","tags":["UP029"]},{"location":"rules/unnecessary-builtin-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Builtins are always available. Importing them is unnecessary and should be removed to avoid confusion.

        ","tags":["UP029"]},{"location":"rules/unnecessary-builtin-import/#example","title":"Example","text":"
        from builtins import str\n\nstr(1)\n

        Use instead:

        str(1)\n
        ","tags":["UP029"]},{"location":"rules/unnecessary-builtin-import/#references","title":"References","text":"
        • Python documentation: The Python Standard Library
        ","tags":["UP029"]},{"location":"rules/unnecessary-call-around-sorted/","title":"unnecessary-call-around-sorted (C413)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C413"]},{"location":"rules/unnecessary-call-around-sorted/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list() or reversed() calls around sorted() calls.

        ","tags":["C413"]},{"location":"rules/unnecessary-call-around-sorted/#why-is-this-bad","title":"Why is this bad?","text":"

        It is unnecessary to use list() around sorted(), as the latter already returns a list.

        It is also unnecessary to use reversed() around sorted(), as the latter has a reverse argument that can be used in lieu of an additional reversed() call.

        In both cases, it's clearer and more efficient to avoid the redundant call.

        ","tags":["C413"]},{"location":"rules/unnecessary-call-around-sorted/#example","title":"Example","text":"
        reversed(sorted(iterable))\n

        Use instead:

        sorted(iterable, reverse=True)\n
        ","tags":["C413"]},{"location":"rules/unnecessary-call-around-sorted/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as reversed() and reverse=True will yield different results in the event of custom sort keys or equality functions. Specifically, reversed() will reverse the order of the collection, while sorted() with reverse=True will perform a stable reverse sort, which will preserve the order of elements that compare as equal.

        ","tags":["C413"]},{"location":"rules/unnecessary-cast-to-int/","title":"unnecessary-cast-to-int (RUF046)","text":"

        Fix is always available.

        ","tags":["RUF046"]},{"location":"rules/unnecessary-cast-to-int/#what-it-does","title":"What it does","text":"

        Checks for int conversions of values that are already integers.

        ","tags":["RUF046"]},{"location":"rules/unnecessary-cast-to-int/#why-is-this-bad","title":"Why is this bad?","text":"

        Such a conversion is unnecessary.

        ","tags":["RUF046"]},{"location":"rules/unnecessary-cast-to-int/#known-problems","title":"Known problems","text":"

        This rule may produce false positives for round, math.ceil, math.floor, and math.trunc calls when values override the __round__, __ceil__, __floor__, or __trunc__ operators such that they don't return an integer.

        ","tags":["RUF046"]},{"location":"rules/unnecessary-cast-to-int/#example","title":"Example","text":"
        int(len([]))\nint(round(foo, None))\n

        Use instead:

        len([])\nround(foo)\n
        ","tags":["RUF046"]},{"location":"rules/unnecessary-cast-to-int/#fix-safety","title":"Fix safety","text":"

        The fix for round, math.ceil, math.floor, and math.truncate is unsafe because removing the int conversion can change the semantics for values overriding the __round__, __ceil__, __floor__, or __trunc__ dunder methods such that they don't return an integer.

        ","tags":["RUF046"]},{"location":"rules/unnecessary-class-parentheses/","title":"unnecessary-class-parentheses (UP039)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP039"]},{"location":"rules/unnecessary-class-parentheses/#what-it-does","title":"What it does","text":"

        Checks for class definitions that include unnecessary parentheses after the class name.

        ","tags":["UP039"]},{"location":"rules/unnecessary-class-parentheses/#why-is-this-bad","title":"Why is this bad?","text":"

        If a class definition doesn't have any bases, the parentheses are unnecessary.

        ","tags":["UP039"]},{"location":"rules/unnecessary-class-parentheses/#example","title":"Example","text":"
        class Foo():\n    ...\n

        Use instead:

        class Foo:\n    ...\n
        ","tags":["UP039"]},{"location":"rules/unnecessary-collection-call/","title":"unnecessary-collection-call (C408)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C408"]},{"location":"rules/unnecessary-collection-call/#what-it-does","title":"What it does","text":"

        Checks for unnecessary dict(), list() or tuple() calls that can be rewritten as empty literals.

        ","tags":["C408"]},{"location":"rules/unnecessary-collection-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to call, e.g., dict() as opposed to using an empty literal ({}). The former is slower because the name dict must be looked up in the global scope in case it has been rebound.

        ","tags":["C408"]},{"location":"rules/unnecessary-collection-call/#example","title":"Example","text":"
        dict()\ndict(a=1, b=2)\nlist()\ntuple()\n

        Use instead:

        {}\n{\"a\": 1, \"b\": 2}\n[]\n()\n
        ","tags":["C408"]},{"location":"rules/unnecessary-collection-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C408"]},{"location":"rules/unnecessary-collection-call/#options","title":"Options","text":"
        • lint.flake8-comprehensions.allow-dict-calls-with-keyword-arguments
        ","tags":["C408"]},{"location":"rules/unnecessary-comprehension-in-call/","title":"unnecessary-comprehension-in-call (C419)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is sometimes available.

        ","tags":["C419"]},{"location":"rules/unnecessary-comprehension-in-call/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list or set comprehensions passed to builtin functions that take an iterable.

        Set comprehensions are only a violation in the case where the builtin function does not care about duplication of elements in the passed iterable.

        ","tags":["C419"]},{"location":"rules/unnecessary-comprehension-in-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Many builtin functions (this rule currently covers any and all in stable, along with min, max, and sum in preview) accept any iterable, including a generator. Constructing a temporary list via list comprehension is unnecessary and wastes memory for large iterables.

        any and all can also short-circuit iteration, saving a lot of time. The unnecessary comprehension forces a full iteration of the input iterable, giving up the benefits of short-circuiting. For example, compare the performance of all with a list comprehension against that of a generator in a case where an early short-circuit is possible (almost 40x faster):

        In [1]: %timeit all([i for i in range(1000)])\n8.14 \u00b5s \u00b1 25.4 ns per loop (mean \u00b1 std. dev. of 7 runs, 100,000 loops each)\n\nIn [2]: %timeit all(i for i in range(1000))\n212 ns \u00b1 0.892 ns per loop (mean \u00b1 std. dev. of 7 runs, 1,000,000 loops each)\n

        This performance improvement is due to short-circuiting. If the entire iterable has to be traversed, the comprehension version may even be a bit faster: list allocation overhead is not necessarily greater than generator overhead.

        Applying this rule simplifies the code and will usually save memory, but in the absence of short-circuiting it may not improve performance. (It may even slightly regress performance, though the difference will usually be small.)

        ","tags":["C419"]},{"location":"rules/unnecessary-comprehension-in-call/#example","title":"Example","text":"
        any([x.id for x in bar])\nall([x.id for x in bar])\nsum([x.val for x in bar])\nmin([x.val for x in bar])\nmax([x.val for x in bar])\n

        Use instead:

        any(x.id for x in bar)\nall(x.id for x in bar)\nsum(x.val for x in bar)\nmin(x.val for x in bar)\nmax(x.val for x in bar)\n
        ","tags":["C419"]},{"location":"rules/unnecessary-comprehension-in-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it can change the behavior of the code if the iteration has side effects (due to laziness and short-circuiting). The fix may also drop comments when rewriting some comprehensions.

        ","tags":["C419"]},{"location":"rules/unnecessary-comprehension/","title":"unnecessary-comprehension (C416)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C416"]},{"location":"rules/unnecessary-comprehension/#what-it-does","title":"What it does","text":"

        Checks for unnecessary dict, list, and set comprehension.

        ","tags":["C416"]},{"location":"rules/unnecessary-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a dict/list/set comprehension to build a data structure if the elements are unchanged. Wrap the iterable with dict(), list(), or set() instead.

        ","tags":["C416"]},{"location":"rules/unnecessary-comprehension/#example","title":"Example","text":"
        {a: b for a, b in iterable}\n[x for x in iterable]\n{x for x in iterable}\n

        Use instead:

        dict(iterable)\nlist(iterable)\nset(iterable)\n
        ","tags":["C416"]},{"location":"rules/unnecessary-comprehension/#known-problems","title":"Known problems","text":"

        This rule may produce false positives for dictionary comprehensions that iterate over a mapping. The dict constructor behaves differently depending on if it receives a sequence (e.g., a list) or a mapping (e.g., a dict). When a comprehension iterates over the keys of a mapping, replacing it with a dict() constructor call will give a different result.

        For example:

        >>> d1 = {(1, 2): 3, (4, 5): 6}\n>>> {x: y for x, y in d1}  # Iterates over the keys of a mapping\n{1: 2, 4: 5}\n>>> dict(d1)               # Ruff's incorrect suggested fix\n(1, 2): 3, (4, 5): 6}\n>>> dict(d1.keys())        # Correct fix\n{1: 2, 4: 5}\n

        When the comprehension iterates over a sequence, Ruff's suggested fix is correct. However, Ruff cannot consistently infer if the iterable type is a sequence or a mapping and cannot suggest the correct fix for mappings.

        ","tags":["C416"]},{"location":"rules/unnecessary-comprehension/#fix-safety","title":"Fix safety","text":"

        Due to the known problem with dictionary comprehensions, this fix is marked as unsafe.

        Additionally, this fix may drop comments when rewriting the comprehension.

        ","tags":["C416"]},{"location":"rules/unnecessary-default-type-args/","title":"unnecessary-default-type-args (UP043)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#what-it-does","title":"What it does","text":"

        Checks for unnecessary default type arguments for Generator and AsyncGenerator on Python 3.13+.

        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#why-is-this-bad","title":"Why is this bad?","text":"

        Python 3.13 introduced the ability for type parameters to specify default values. Following this change, several standard-library classes were updated to add default values for some of their type parameters. For example, Generator[int] is now equivalent to Generator[int, None, None], as the second and third type parameters of Generator now default to None.

        Omitting type arguments that match the default values can make the code more concise and easier to read.

        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#example","title":"Example","text":"
        from collections.abc import Generator, AsyncGenerator\n\n\ndef sync_gen() -> Generator[int, None, None]:\n    yield 42\n\n\nasync def async_gen() -> AsyncGenerator[int, None]:\n    yield 42\n

        Use instead:

        from collections.abc import Generator, AsyncGenerator\n\n\ndef sync_gen() -> Generator[int]:\n    yield 42\n\n\nasync def async_gen() -> AsyncGenerator[int]:\n    yield 42\n
        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the type annotation contains comments.

        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#options","title":"Options","text":"
        • target-version
        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#references","title":"References","text":"
        • PEP 696 \u2013 Type Defaults for Type Parameters
        • Annotating generators and coroutines
        • Python documentation: typing.Generator
        • Python documentation: typing.AsyncGenerator
        ","tags":["UP043"]},{"location":"rules/unnecessary-dict-comprehension-for-iterable/","title":"unnecessary-dict-comprehension-for-iterable (C420)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is sometimes available.

        ","tags":["C420"]},{"location":"rules/unnecessary-dict-comprehension-for-iterable/#what-it-does","title":"What it does","text":"

        Checks for unnecessary dict comprehension when creating a dictionary from an iterable.

        ","tags":["C420"]},{"location":"rules/unnecessary-dict-comprehension-for-iterable/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a dict comprehension to build a dictionary from an iterable when the value is static.

        Prefer dict.fromkeys(iterable) over {value: None for value in iterable}, as dict.fromkeys is more readable and efficient.

        ","tags":["C420"]},{"location":"rules/unnecessary-dict-comprehension-for-iterable/#example","title":"Example","text":"
        {a: None for a in iterable}\n{a: 1 for a in iterable}\n

        Use instead:

        dict.fromkeys(iterable)\ndict.fromkeys(iterable, 1)\n
        ","tags":["C420"]},{"location":"rules/unnecessary-dict-comprehension-for-iterable/#references","title":"References","text":"
        • Python documentation: dict.fromkeys
        ","tags":["C420"]},{"location":"rules/unnecessary-dict-index-lookup/","title":"unnecessary-dict-index-lookup (PLR1733)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR1733"]},{"location":"rules/unnecessary-dict-index-lookup/#what-it-does","title":"What it does","text":"

        Checks for key-based dict accesses during .items() iterations.

        ","tags":["PLR1733"]},{"location":"rules/unnecessary-dict-index-lookup/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over a dict via .items(), the current value is already available alongside its key. Using the key to look up the value is unnecessary.

        ","tags":["PLR1733"]},{"location":"rules/unnecessary-dict-index-lookup/#example","title":"Example","text":"
        FRUITS = {\"apple\": 1, \"orange\": 10, \"berry\": 22}\n\nfor fruit_name, fruit_count in FRUITS.items():\n    print(FRUITS[fruit_name])\n

        Use instead:

        FRUITS = {\"apple\": 1, \"orange\": 10, \"berry\": 22}\n\nfor fruit_name, fruit_count in FRUITS.items():\n    print(fruit_count)\n
        ","tags":["PLR1733"]},{"location":"rules/unnecessary-dict-kwargs/","title":"unnecessary-dict-kwargs (PIE804)","text":"

        Derived from the flake8-pie linter.

        Fix is sometimes available.

        ","tags":["PIE804"]},{"location":"rules/unnecessary-dict-kwargs/#what-it-does","title":"What it does","text":"

        Checks for unnecessary dict kwargs.

        ","tags":["PIE804"]},{"location":"rules/unnecessary-dict-kwargs/#why-is-this-bad","title":"Why is this bad?","text":"

        If the dict keys are valid identifiers, they can be passed as keyword arguments directly.

        ","tags":["PIE804"]},{"location":"rules/unnecessary-dict-kwargs/#example","title":"Example","text":"
        def foo(bar):\n    return bar + 1\n\n\nprint(foo(**{\"bar\": 2}))  # prints 3\n

        Use instead:

        def foo(bar):\n    return bar + 1\n\n\nprint(foo(bar=2))  # prints 3\n
        ","tags":["PIE804"]},{"location":"rules/unnecessary-dict-kwargs/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for dictionaries with comments interleaved between the items, as comments may be removed.

        For example, the fix would be marked as unsafe in the following case:

        foo(\n    **{\n        # comment\n        \"x\": 1.0,\n        # comment\n        \"y\": 2.0,\n    }\n)\n

        as this is converted to foo(x=1.0, y=2.0) without any of the comments.

        ","tags":["PIE804"]},{"location":"rules/unnecessary-dict-kwargs/#references","title":"References","text":"
        • Python documentation: Dictionary displays
        • Python documentation: Calls
        ","tags":["PIE804"]},{"location":"rules/unnecessary-direct-lambda-call/","title":"unnecessary-direct-lambda-call (PLC3002)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC3002"]},{"location":"rules/unnecessary-direct-lambda-call/#what-it-does","title":"What it does","text":"

        Checks for unnecessary direct calls to lambda expressions.

        ","tags":["PLC3002"]},{"location":"rules/unnecessary-direct-lambda-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling a lambda expression directly is unnecessary. The expression can be executed inline instead to improve readability.

        ","tags":["PLC3002"]},{"location":"rules/unnecessary-direct-lambda-call/#example","title":"Example","text":"
        area = (lambda r: 3.14 * r**2)(radius)\n

        Use instead:

        area = 3.14 * radius**2\n
        ","tags":["PLC3002"]},{"location":"rules/unnecessary-direct-lambda-call/#references","title":"References","text":"
        • Python documentation: Lambdas
        ","tags":["PLC3002"]},{"location":"rules/unnecessary-double-cast-or-process/","title":"unnecessary-double-cast-or-process (C414)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C414"]},{"location":"rules/unnecessary-double-cast-or-process/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list(), reversed(), set(), sorted(), and tuple() call within list(), set(), sorted(), and tuple() calls.

        ","tags":["C414"]},{"location":"rules/unnecessary-double-cast-or-process/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to double-cast or double-process iterables by wrapping the listed functions within an additional list(), set(), sorted(), or tuple() call. Doing so is redundant and can be confusing for readers.

        ","tags":["C414"]},{"location":"rules/unnecessary-double-cast-or-process/#example","title":"Example","text":"
        list(tuple(iterable))\n

        Use instead:

        list(iterable)\n

        This rule applies to a variety of functions, including list(), reversed(), set(), sorted(), and tuple(). For example:

        • Instead of list(list(iterable)), use list(iterable).
        • Instead of list(tuple(iterable)), use list(iterable).
        • Instead of tuple(list(iterable)), use tuple(iterable).
        • Instead of tuple(tuple(iterable)), use tuple(iterable).
        • Instead of set(set(iterable)), use set(iterable).
        • Instead of set(list(iterable)), use set(iterable).
        • Instead of set(tuple(iterable)), use set(iterable).
        • Instead of set(sorted(iterable)), use set(iterable).
        • Instead of set(reversed(iterable)), use set(iterable).
        • Instead of sorted(list(iterable)), use sorted(iterable).
        • Instead of sorted(tuple(iterable)), use sorted(iterable).
        • Instead of sorted(sorted(iterable)), use sorted(iterable).
        • Instead of sorted(reversed(iterable)), use sorted(iterable).
        ","tags":["C414"]},{"location":"rules/unnecessary-double-cast-or-process/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C414"]},{"location":"rules/unnecessary-dunder-call/","title":"unnecessary-dunder-call (PLC2801)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLC2801"]},{"location":"rules/unnecessary-dunder-call/#what-it-does","title":"What it does","text":"

        Checks for explicit use of dunder methods, like __str__ and __add__.

        ","tags":["PLC2801"]},{"location":"rules/unnecessary-dunder-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Dunder names are not meant to be called explicitly and, in most cases, can be replaced with builtins or operators.

        ","tags":["PLC2801"]},{"location":"rules/unnecessary-dunder-call/#fix-safety","title":"Fix safety","text":"

        This fix is always unsafe. When replacing dunder method calls with operators or builtins, the behavior can change in the following ways:

        1. Types may implement only a subset of related dunder methods. Calling a missing dunder method directly returns NotImplemented, but using the equivalent operator raises a TypeError.

          class C: pass\nc = C()\nc.__gt__(1)  # before fix: NotImplemented\nc > 1        # after fix: raises TypeError\n
        2. Instance-assigned dunder methods are ignored by operators and builtins.

          class C: pass\nc = C()\nc.__bool__ = lambda: False\nc.__bool__() # before fix: False\nbool(c)      # after fix: True\n
        3. Even with built-in types, behavior can differ.

          (1).__gt__(1.0)  # before fix: NotImplemented\n1 > 1.0          # after fix: False\n
        ","tags":["PLC2801"]},{"location":"rules/unnecessary-dunder-call/#example","title":"Example","text":"
        three = (3.0).__str__()\ntwelve = \"1\".__add__(\"2\")\n\n\ndef is_greater_than_two(x: int) -> bool:\n    return x.__gt__(2)\n

        Use instead:

        three = str(3.0)\ntwelve = \"1\" + \"2\"\n\n\ndef is_greater_than_two(x: int) -> bool:\n    return x > 2\n
        ","tags":["PLC2801"]},{"location":"rules/unnecessary-empty-iterable-within-deque-call/","title":"unnecessary-empty-iterable-within-deque-call (RUF037)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF037"]},{"location":"rules/unnecessary-empty-iterable-within-deque-call/#what-it-does","title":"What it does","text":"

        Checks for usages of collections.deque that have an empty iterable as the first argument.

        ","tags":["RUF037"]},{"location":"rules/unnecessary-empty-iterable-within-deque-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use an empty literal as a deque's iterable, since this is already the default behavior.

        ","tags":["RUF037"]},{"location":"rules/unnecessary-empty-iterable-within-deque-call/#example","title":"Example","text":"
        from collections import deque\n\nqueue = deque(set())\nqueue = deque([], 10)\n

        Use instead:

        from collections import deque\n\nqueue = deque()\nqueue = deque(maxlen=10)\n
        ","tags":["RUF037"]},{"location":"rules/unnecessary-empty-iterable-within-deque-call/#references","title":"References","text":"
        • Python documentation: collections.deque
        ","tags":["RUF037"]},{"location":"rules/unnecessary-encode-utf8/","title":"unnecessary-encode-utf8 (UP012)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP012"]},{"location":"rules/unnecessary-encode-utf8/#what-it-does","title":"What it does","text":"

        Checks for unnecessary calls to encode as UTF-8.

        ","tags":["UP012"]},{"location":"rules/unnecessary-encode-utf8/#why-is-this-bad","title":"Why is this bad?","text":"

        UTF-8 is the default encoding in Python, so there is no need to call encode when UTF-8 is the desired encoding. Instead, use a bytes literal.

        ","tags":["UP012"]},{"location":"rules/unnecessary-encode-utf8/#example","title":"Example","text":"
        \"foo\".encode(\"utf-8\")\n

        Use instead:

        b\"foo\"\n
        ","tags":["UP012"]},{"location":"rules/unnecessary-encode-utf8/#references","title":"References","text":"
        • Python documentation: str.encode
        ","tags":["UP012"]},{"location":"rules/unnecessary-enumerate/","title":"unnecessary-enumerate (FURB148)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB148"]},{"location":"rules/unnecessary-enumerate/#what-it-does","title":"What it does","text":"

        Checks for uses of enumerate that discard either the index or the value when iterating over a sequence.

        ","tags":["FURB148"]},{"location":"rules/unnecessary-enumerate/#why-is-this-bad","title":"Why is this bad?","text":"

        The built-in enumerate function is useful when you need both the index and value of a sequence.

        If you only need the index or values of a sequence, you should iterate over range(len(...)) or the sequence itself, respectively, instead. This is more efficient and communicates the intent of the code more clearly.

        ","tags":["FURB148"]},{"location":"rules/unnecessary-enumerate/#known-problems","title":"Known problems","text":"

        This rule is prone to false negatives due to type inference limitations; namely, it will only suggest a fix using the len builtin function if the sequence passed to enumerate is an instantiated as a list, set, dict, or tuple literal, or annotated as such with a type annotation.

        The len builtin function is not defined for all object types (such as generators), and so refactoring to use len over enumerate is not always safe.

        ","tags":["FURB148"]},{"location":"rules/unnecessary-enumerate/#example","title":"Example","text":"
        for index, _ in enumerate(sequence):\n    print(index)\n\nfor _, value in enumerate(sequence):\n    print(value)\n

        Use instead:

        for index in range(len(sequence)):\n    print(index)\n\nfor value in sequence:\n    print(value)\n
        ","tags":["FURB148"]},{"location":"rules/unnecessary-enumerate/#references","title":"References","text":"
        • Python documentation: enumerate
        • Python documentation: range
        • Python documentation: len
        ","tags":["FURB148"]},{"location":"rules/unnecessary-escaped-quote/","title":"unnecessary-escaped-quote (Q004)","text":"

        Derived from the flake8-quotes linter.

        Fix is always available.

        ","tags":["Q004"]},{"location":"rules/unnecessary-escaped-quote/#what-it-does","title":"What it does","text":"

        Checks for strings that include unnecessarily escaped quotes.

        ","tags":["Q004"]},{"location":"rules/unnecessary-escaped-quote/#why-is-this-bad","title":"Why is this bad?","text":"

        If a string contains an escaped quote that doesn't match the quote character used for the string, it's unnecessary and can be removed.

        ","tags":["Q004"]},{"location":"rules/unnecessary-escaped-quote/#example","title":"Example","text":"
        foo = \"bar\\'s\"\n

        Use instead:

        foo = \"bar's\"\n
        ","tags":["Q004"]},{"location":"rules/unnecessary-escaped-quote/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter automatically removes unnecessary escapes, making the rule redundant.

        ","tags":["Q004"]},{"location":"rules/unnecessary-from-float/","title":"unnecessary-from-float (FURB164)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB164"]},{"location":"rules/unnecessary-from-float/#what-it-does","title":"What it does","text":"

        Checks for unnecessary from_float and from_decimal usages to construct Decimal and Fraction instances.

        ","tags":["FURB164"]},{"location":"rules/unnecessary-from-float/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3.2, the Fraction and Decimal classes can be constructed by passing float or decimal instances to the constructor directly. As such, the use of from_float and from_decimal methods is unnecessary, and should be avoided in favor of the more concise constructor syntax.

        ","tags":["FURB164"]},{"location":"rules/unnecessary-from-float/#example","title":"Example","text":"
        Decimal.from_float(4.2)\nDecimal.from_float(float(\"inf\"))\nFraction.from_float(4.2)\nFraction.from_decimal(Decimal(\"4.2\"))\n

        Use instead:

        Decimal(4.2)\nDecimal(\"inf\")\nFraction(4.2)\nFraction(Decimal(4.2))\n
        ","tags":["FURB164"]},{"location":"rules/unnecessary-from-float/#references","title":"References","text":"
        • Python documentation: decimal
        • Python documentation: fractions
        ","tags":["FURB164"]},{"location":"rules/unnecessary-future-import/","title":"unnecessary-future-import (UP010)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP010"]},{"location":"rules/unnecessary-future-import/#what-it-does","title":"What it does","text":"

        Checks for unnecessary __future__ imports.

        ","tags":["UP010"]},{"location":"rules/unnecessary-future-import/#why-is-this-bad","title":"Why is this bad?","text":"

        The __future__ module is used to enable features that are not yet available in the current Python version. If a feature is already available in the minimum supported Python version, importing it from __future__ is unnecessary and should be removed to avoid confusion.

        ","tags":["UP010"]},{"location":"rules/unnecessary-future-import/#example","title":"Example","text":"
        from __future__ import print_function\n\nprint(\"Hello, world!\")\n

        Use instead:

        print(\"Hello, world!\")\n
        ","tags":["UP010"]},{"location":"rules/unnecessary-future-import/#options","title":"Options","text":"
        • target-version
        ","tags":["UP010"]},{"location":"rules/unnecessary-future-import/#references","title":"References","text":"
        • Python documentation: __future__ \u2014 Future statement definitions
        ","tags":["UP010"]},{"location":"rules/unnecessary-generator-dict/","title":"unnecessary-generator-dict (C402)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C402"]},{"location":"rules/unnecessary-generator-dict/#what-it-does","title":"What it does","text":"

        Checks for unnecessary generators that can be rewritten as dict comprehensions.

        ","tags":["C402"]},{"location":"rules/unnecessary-generator-dict/#why-is-this-bad","title":"Why is this bad?","text":"

        It is unnecessary to use dict() around a generator expression, since there are equivalent comprehensions for these types. Using a comprehension is clearer and more idiomatic.

        ","tags":["C402"]},{"location":"rules/unnecessary-generator-dict/#example","title":"Example","text":"
        dict((x, f(x)) for x in foo)\n

        Use instead:

        {x: f(x) for x in foo}\n
        ","tags":["C402"]},{"location":"rules/unnecessary-generator-dict/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C402"]},{"location":"rules/unnecessary-generator-list/","title":"unnecessary-generator-list (C400)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C400"]},{"location":"rules/unnecessary-generator-list/#what-it-does","title":"What it does","text":"

        Checks for unnecessary generators that can be rewritten as list comprehensions (or with list() directly).

        ","tags":["C400"]},{"location":"rules/unnecessary-generator-list/#why-is-this-bad","title":"Why is this bad?","text":"

        It is unnecessary to use list() around a generator expression, since there are equivalent comprehensions for these types. Using a comprehension is clearer and more idiomatic.

        Further, if the comprehension can be removed entirely, as in the case of list(x for x in foo), it's better to use list(foo) directly, since it's even more direct.

        ","tags":["C400"]},{"location":"rules/unnecessary-generator-list/#example","title":"Example","text":"
        list(f(x) for x in foo)\nlist(x for x in foo)\nlist((x for x in foo))\n

        Use instead:

        [f(x) for x in foo]\nlist(foo)\nlist(foo)\n
        ","tags":["C400"]},{"location":"rules/unnecessary-generator-list/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C400"]},{"location":"rules/unnecessary-generator-set/","title":"unnecessary-generator-set (C401)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C401"]},{"location":"rules/unnecessary-generator-set/#what-it-does","title":"What it does","text":"

        Checks for unnecessary generators that can be rewritten as set comprehensions (or with set() directly).

        ","tags":["C401"]},{"location":"rules/unnecessary-generator-set/#why-is-this-bad","title":"Why is this bad?","text":"

        It is unnecessary to use set around a generator expression, since there are equivalent comprehensions for these types. Using a comprehension is clearer and more idiomatic.

        Further, if the comprehension can be removed entirely, as in the case of set(x for x in foo), it's better to use set(foo) directly, since it's even more direct.

        ","tags":["C401"]},{"location":"rules/unnecessary-generator-set/#example","title":"Example","text":"
        set(f(x) for x in foo)\nset(x for x in foo)\nset((x for x in foo))\n

        Use instead:

        {f(x) for x in foo}\nset(foo)\nset(foo)\n
        ","tags":["C401"]},{"location":"rules/unnecessary-generator-set/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C401"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/","title":"unnecessary-iterable-allocation-for-first-element (RUF015)","text":"

        Fix is always available.

        ","tags":["RUF015"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/#what-it-does","title":"What it does","text":"

        Checks the following constructs, all of which can be replaced by next(iter(...)):

        • list(...)[0]
        • tuple(...)[0]
        • list(i for i in ...)[0]
        • [i for i in ...][0]
        • list(...).pop(0)
        ","tags":["RUF015"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling e.g. list(...) will create a new list of the entire collection, which can be very expensive for large collections. If you only need the first element of the collection, you can use next(...) or next(iter(...) to lazily fetch the first element. The same is true for the other constructs.

        ","tags":["RUF015"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/#example","title":"Example","text":"
        head = list(x)[0]\nhead = [x * x for x in range(10)][0]\n

        Use instead:

        head = next(iter(x))\nhead = next(x * x for x in range(10))\n
        ","tags":["RUF015"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as migrating from (e.g.) list(...)[0] to next(iter(...)) can change the behavior of your program in two ways:

        1. First, all above-mentioned constructs will eagerly evaluate the entire collection, while next(iter(...)) will only evaluate the first element. As such, any side effects that occur during iteration will be delayed.
        2. Second, accessing members of a collection via square bracket notation [0] of the pop() function will raise IndexError if the collection is empty, while next(iter(...)) will raise StopIteration.
        ","tags":["RUF015"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/#references","title":"References","text":"
        • Iterators and Iterables in Python: Run Efficient Iterations
        ","tags":["RUF015"]},{"location":"rules/unnecessary-key-check/","title":"unnecessary-key-check (RUF019)","text":"

        Fix is always available.

        ","tags":["RUF019"]},{"location":"rules/unnecessary-key-check/#what-it-does","title":"What it does","text":"

        Checks for unnecessary key checks prior to accessing a dictionary.

        ","tags":["RUF019"]},{"location":"rules/unnecessary-key-check/#why-is-this-bad","title":"Why is this bad?","text":"

        When working with dictionaries, the get can be used to access a value without having to check if the dictionary contains the relevant key, returning None if the key is not present.

        ","tags":["RUF019"]},{"location":"rules/unnecessary-key-check/#example","title":"Example","text":"
        if \"key\" in dct and dct[\"key\"]:\n    ...\n

        Use instead:

        if dct.get(\"key\"):\n    ...\n
        ","tags":["RUF019"]},{"location":"rules/unnecessary-lambda/","title":"unnecessary-lambda (PLW0108)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW0108"]},{"location":"rules/unnecessary-lambda/#what-it-does","title":"What it does","text":"

        Checks for lambda definitions that consist of a single function call with the same arguments as the lambda itself.

        ","tags":["PLW0108"]},{"location":"rules/unnecessary-lambda/#why-is-this-bad","title":"Why is this bad?","text":"

        When a lambda is used to wrap a function call, and merely propagates the lambda arguments to that function, it can typically be replaced with the function itself, removing a level of indirection.

        ","tags":["PLW0108"]},{"location":"rules/unnecessary-lambda/#example","title":"Example","text":"
        df.apply(lambda x: str(x))\n

        Use instead:

        df.apply(str)\n
        ","tags":["PLW0108"]},{"location":"rules/unnecessary-lambda/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for two primary reasons.

        First, the lambda body itself could contain an effect.

        For example, replacing lambda x, y: (func()(x, y)) with func() would lead to a change in behavior, as func() would be evaluated eagerly when defining the lambda, rather than when the lambda is called.

        However, even when the lambda body itself is pure, the lambda may change the argument names, which can lead to a change in behavior when callers pass arguments by name.

        For example, replacing foo = lambda x, y: func(x, y) with foo = func, where func is defined as def func(a, b): return a + b, would be a breaking change for callers that execute the lambda by passing arguments by name, as in: foo(x=1, y=2). Since func does not define the arguments x and y, unlike the lambda, the call would raise a TypeError.

        ","tags":["PLW0108"]},{"location":"rules/unnecessary-list-call/","title":"unnecessary-list-call (C411)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C411"]},{"location":"rules/unnecessary-list-call/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list() calls around list comprehensions.

        ","tags":["C411"]},{"location":"rules/unnecessary-list-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It is redundant to use a list() call around a list comprehension.

        ","tags":["C411"]},{"location":"rules/unnecessary-list-call/#example","title":"Example","text":"
        list([f(x) for x in foo])\n

        Use instead

        [f(x) for x in foo]\n
        ","tags":["C411"]},{"location":"rules/unnecessary-list-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C411"]},{"location":"rules/unnecessary-list-cast/","title":"unnecessary-list-cast (PERF101)","text":"

        Derived from the Perflint linter.

        Fix is always available.

        ","tags":["PERF101"]},{"location":"rules/unnecessary-list-cast/#what-it-does","title":"What it does","text":"

        Checks for explicit casts to list on for-loop iterables.

        ","tags":["PERF101"]},{"location":"rules/unnecessary-list-cast/#why-is-this-bad","title":"Why is this bad?","text":"

        Using a list() call to eagerly iterate over an already-iterable type (like a tuple, list, or set) is inefficient, as it forces Python to create a new list unnecessarily.

        Removing the list() call will not change the behavior of the code, but may improve performance.

        Note that, as with all perflint rules, this is only intended as a micro-optimization, and will have a negligible impact on performance in most cases.

        ","tags":["PERF101"]},{"location":"rules/unnecessary-list-cast/#example","title":"Example","text":"
        items = (1, 2, 3)\nfor i in list(items):\n    print(i)\n

        Use instead:

        items = (1, 2, 3)\nfor i in items:\n    print(i)\n
        ","tags":["PERF101"]},{"location":"rules/unnecessary-list-comprehension-dict/","title":"unnecessary-list-comprehension-dict (C404)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C404"]},{"location":"rules/unnecessary-list-comprehension-dict/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list comprehensions.

        ","tags":["C404"]},{"location":"rules/unnecessary-list-comprehension-dict/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list comprehension inside a call to dict(), since there is an equivalent comprehension for this type.

        ","tags":["C404"]},{"location":"rules/unnecessary-list-comprehension-dict/#example","title":"Example","text":"
        dict([(x, f(x)) for x in foo])\n

        Use instead:

        {x: f(x) for x in foo}\n
        ","tags":["C404"]},{"location":"rules/unnecessary-list-comprehension-dict/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C404"]},{"location":"rules/unnecessary-list-comprehension-set/","title":"unnecessary-list-comprehension-set (C403)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C403"]},{"location":"rules/unnecessary-list-comprehension-set/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list comprehensions.

        ","tags":["C403"]},{"location":"rules/unnecessary-list-comprehension-set/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list comprehension inside a call to set(), since there is an equivalent comprehension for this type.

        ","tags":["C403"]},{"location":"rules/unnecessary-list-comprehension-set/#example","title":"Example","text":"
        set([f(x) for x in foo])\n

        Use instead:

        {f(x) for x in foo}\n
        ","tags":["C403"]},{"location":"rules/unnecessary-list-comprehension-set/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C403"]},{"location":"rules/unnecessary-list-index-lookup/","title":"unnecessary-list-index-lookup (PLR1736)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLR1736"]},{"location":"rules/unnecessary-list-index-lookup/#what-it-does","title":"What it does","text":"

        Checks for index-based list accesses during enumerate iterations.

        ","tags":["PLR1736"]},{"location":"rules/unnecessary-list-index-lookup/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over a list with enumerate, the current item is already available alongside its index. Using the index to look up the item is unnecessary.

        ","tags":["PLR1736"]},{"location":"rules/unnecessary-list-index-lookup/#example","title":"Example","text":"
        letters = [\"a\", \"b\", \"c\"]\n\nfor index, letter in enumerate(letters):\n    print(letters[index])\n

        Use instead:

        letters = [\"a\", \"b\", \"c\"]\n\nfor index, letter in enumerate(letters):\n    print(letter)\n
        ","tags":["PLR1736"]},{"location":"rules/unnecessary-literal-dict/","title":"unnecessary-literal-dict (C406)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C406"]},{"location":"rules/unnecessary-literal-dict/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list or tuple literals.

        ","tags":["C406"]},{"location":"rules/unnecessary-literal-dict/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list or tuple literal within a call to dict(). It can be rewritten as a dict literal ({}).

        ","tags":["C406"]},{"location":"rules/unnecessary-literal-dict/#example","title":"Example","text":"
        dict([(1, 2), (3, 4)])\ndict(((1, 2), (3, 4)))\ndict([])\n

        Use instead:

        {1: 2, 3: 4}\n{1: 2, 3: 4}\n{}\n
        ","tags":["C406"]},{"location":"rules/unnecessary-literal-dict/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C406"]},{"location":"rules/unnecessary-literal-set/","title":"unnecessary-literal-set (C405)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C405"]},{"location":"rules/unnecessary-literal-set/#what-it-does","title":"What it does","text":"

        Checks for set() calls that take unnecessary list or tuple literals as arguments.

        ","tags":["C405"]},{"location":"rules/unnecessary-literal-set/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list or tuple literal within a call to set(). Instead, the expression can be rewritten as a set literal.

        ","tags":["C405"]},{"location":"rules/unnecessary-literal-set/#example","title":"Example","text":"
        set([1, 2])\nset((1, 2))\nset([])\n

        Use instead:

        {1, 2}\n{1, 2}\nset()\n
        ","tags":["C405"]},{"location":"rules/unnecessary-literal-set/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C405"]},{"location":"rules/unnecessary-literal-union/","title":"unnecessary-literal-union (PYI030)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-union/#what-it-does","title":"What it does","text":"

        Checks for the presence of multiple literal types in a union.

        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-union/#why-is-this-bad","title":"Why is this bad?","text":"

        Literal[\"foo\", 42] has identical semantics to Literal[\"foo\"] | Literal[42], but is clearer and more concise.

        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-union/#example","title":"Example","text":"
        from typing import Literal\n\nfield: Literal[1] | Literal[2] | str\n

        Use instead:

        from typing import Literal\n\nfield: Literal[1, 2] | str\n
        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-union/#fix-safety","title":"Fix safety","text":"

        This fix is marked unsafe if it would delete any comments within the replacement range.

        An example to illustrate where comments are preserved and where they are not:

        from typing import Literal\n\nfield: (\n    # deleted comment\n    Literal[\"a\", \"b\"]  # deleted comment\n    # deleted comment\n    | Literal[\"c\", \"d\"]  # preserved comment\n)\n
        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-union/#references","title":"References","text":"
        • Python documentation: typing.Literal
        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-within-dict-call/","title":"unnecessary-literal-within-dict-call (C418)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C418"]},{"location":"rules/unnecessary-literal-within-dict-call/#what-it-does","title":"What it does","text":"

        Checks for dict() calls that take unnecessary dict literals or dict comprehensions as arguments.

        ","tags":["C418"]},{"location":"rules/unnecessary-literal-within-dict-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to wrap a dict literal or comprehension within a dict() call, since the literal or comprehension syntax already returns a dictionary.

        ","tags":["C418"]},{"location":"rules/unnecessary-literal-within-dict-call/#example","title":"Example","text":"
        dict({})\ndict({\"a\": 1})\n

        Use instead:

        {}\n{\"a\": 1}\n
        ","tags":["C418"]},{"location":"rules/unnecessary-literal-within-dict-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C418"]},{"location":"rules/unnecessary-literal-within-list-call/","title":"unnecessary-literal-within-list-call (C410)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C410"]},{"location":"rules/unnecessary-literal-within-list-call/#what-it-does","title":"What it does","text":"

        Checks for list() calls that take unnecessary list or tuple literals as arguments.

        ","tags":["C410"]},{"location":"rules/unnecessary-literal-within-list-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list or tuple literal within a list() call, since there is a literal syntax for these types.

        If a list literal is passed in, then the outer call to list() should be removed. Otherwise, if a tuple literal is passed in, then it should be rewritten as a list literal.

        ","tags":["C410"]},{"location":"rules/unnecessary-literal-within-list-call/#example","title":"Example","text":"
        list([1, 2])\nlist((1, 2))\n

        Use instead:

        [1, 2]\n[1, 2]\n
        ","tags":["C410"]},{"location":"rules/unnecessary-literal-within-list-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C410"]},{"location":"rules/unnecessary-literal-within-tuple-call/","title":"unnecessary-literal-within-tuple-call (C409)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C409"]},{"location":"rules/unnecessary-literal-within-tuple-call/#what-it-does","title":"What it does","text":"

        Checks for tuple calls that take unnecessary list or tuple literals as arguments. In preview, this also includes unnecessary list comprehensions within tuple calls.

        ","tags":["C409"]},{"location":"rules/unnecessary-literal-within-tuple-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list or tuple literal within a tuple() call, since there is a literal syntax for these types.

        If a list literal was passed, then it should be rewritten as a tuple literal. Otherwise, if a tuple literal was passed, then the outer call to tuple() should be removed.

        In preview, this rule also checks for list comprehensions within tuple() calls. If a list comprehension is found, it should be rewritten as a generator expression.

        ","tags":["C409"]},{"location":"rules/unnecessary-literal-within-tuple-call/#example","title":"Example","text":"
        tuple([1, 2])\ntuple((1, 2))\ntuple([x for x in range(10)])\n

        Use instead:

        (1, 2)\n(1, 2)\ntuple(x for x in range(10))\n
        ","tags":["C409"]},{"location":"rules/unnecessary-literal-within-tuple-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C409"]},{"location":"rules/unnecessary-map/","title":"unnecessary-map (C417)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is sometimes available.

        ","tags":["C417"]},{"location":"rules/unnecessary-map/#what-it-does","title":"What it does","text":"

        Checks for unnecessary map() calls with lambda functions.

        ","tags":["C417"]},{"location":"rules/unnecessary-map/#why-is-this-bad","title":"Why is this bad?","text":"

        Using map(func, iterable) when func is a lambda is slower than using a generator expression or a comprehension, as the latter approach avoids the function call overhead, in addition to being more readable.

        This rule also applies to map() calls within list(), set(), and dict() calls. For example:

        • Instead of list(map(lambda num: num * 2, nums)), use [num * 2 for num in nums].
        • Instead of set(map(lambda num: num % 2 == 0, nums)), use {num % 2 == 0 for num in nums}.
        • Instead of dict(map(lambda v: (v, v ** 2), values)), use {v: v ** 2 for v in values}.
        ","tags":["C417"]},{"location":"rules/unnecessary-map/#example","title":"Example","text":"
        map(lambda x: x + 1, iterable)\n

        Use instead:

        (x + 1 for x in iterable)\n
        ","tags":["C417"]},{"location":"rules/unnecessary-map/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C417"]},{"location":"rules/unnecessary-multiline-docstring/","title":"unnecessary-multiline-docstring (D200)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D200"]},{"location":"rules/unnecessary-multiline-docstring/#what-it-does","title":"What it does","text":"

        Checks for single-line docstrings that are broken across multiple lines.

        ","tags":["D200"]},{"location":"rules/unnecessary-multiline-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that docstrings that can fit on one line should be formatted on a single line, for consistency and readability.

        ","tags":["D200"]},{"location":"rules/unnecessary-multiline-docstring/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"\n    Return the mean of the given values.\n    \"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D200"]},{"location":"rules/unnecessary-multiline-docstring/#fix-safety","title":"Fix safety","text":"

        The fix is marked as unsafe because it could affect tools that parse docstrings, documentation generators, or custom introspection utilities that rely on specific docstring formatting.

        ","tags":["D200"]},{"location":"rules/unnecessary-multiline-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        ","tags":["D200"]},{"location":"rules/unnecessary-nested-literal/","title":"unnecessary-nested-literal (RUF041)","text":"

        Fix is sometimes available.

        ","tags":["RUF041"]},{"location":"rules/unnecessary-nested-literal/#what-it-does","title":"What it does","text":"

        Checks for unnecessary nested Literal.

        ","tags":["RUF041"]},{"location":"rules/unnecessary-nested-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefer using a single Literal, which is equivalent and more concise.

        Parameterization of literals by other literals is supported as an ergonomic feature as proposed in [PEP 586], to enable patterns such as:

        ReadOnlyMode         = Literal[\"r\", \"r+\"]\nWriteAndTruncateMode = Literal[\"w\", \"w+\", \"wt\", \"w+t\"]\nWriteNoTruncateMode  = Literal[\"r+\", \"r+t\"]\nAppendMode           = Literal[\"a\", \"a+\", \"at\", \"a+t\"]\n\nAllModes = Literal[ReadOnlyMode, WriteAndTruncateMode,\n                  WriteNoTruncateMode, AppendMode]\n

        As a consequence, type checkers also support nesting of literals which is less readable than a flat Literal:

        AllModes = Literal[Literal[\"r\", \"r+\"], Literal[\"w\", \"w+\", \"wt\", \"w+t\"],\n                  Literal[\"r+\", \"r+t\"], Literal[\"a\", \"a+\", \"at\", \"a+t\"]]\n
        ","tags":["RUF041"]},{"location":"rules/unnecessary-nested-literal/#example","title":"Example","text":"
        AllModes = Literal[\n    Literal[\"r\", \"r+\"],\n    Literal[\"w\", \"w+\", \"wt\", \"w+t\"],\n    Literal[\"r+\", \"r+t\"],\n    Literal[\"a\", \"a+\", \"at\", \"a+t\"],\n]\n

        Use instead:

        AllModes = Literal[\n    \"r\", \"r+\", \"w\", \"w+\", \"wt\", \"w+t\", \"r+\", \"r+t\", \"a\", \"a+\", \"at\", \"a+t\"\n]\n

        or assign the literal to a variable as in the first example.

        ","tags":["RUF041"]},{"location":"rules/unnecessary-nested-literal/#fix-safety","title":"Fix safety","text":"

        The fix for this rule is marked as unsafe when the Literal slice is split across multiple lines and some of the lines have trailing comments.

        ","tags":["RUF041"]},{"location":"rules/unnecessary-nested-literal/#references","title":"References","text":"
        • Typing documentation: Legal parameters for Literal at type check time

        PEP 586

        ","tags":["RUF041"]},{"location":"rules/unnecessary-paren-on-raise-exception/","title":"unnecessary-paren-on-raise-exception (RSE102)","text":"

        Derived from the flake8-raise linter.

        Fix is always available.

        ","tags":["RSE102"]},{"location":"rules/unnecessary-paren-on-raise-exception/#what-it-does","title":"What it does","text":"

        Checks for unnecessary parentheses on raised exceptions.

        ","tags":["RSE102"]},{"location":"rules/unnecessary-paren-on-raise-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        If an exception is raised without any arguments, parentheses are not required, as the raise statement accepts either an exception instance or an exception class (which is then implicitly instantiated).

        Removing the parentheses makes the code more concise.

        ","tags":["RSE102"]},{"location":"rules/unnecessary-paren-on-raise-exception/#known-problems","title":"Known problems","text":"

        Parentheses can only be omitted if the exception is a class, as opposed to a function call. This rule isn't always capable of distinguishing between the two.

        For example, if you import a function module.get_exception from another module, and module.get_exception returns an exception object, this rule will incorrectly mark the parentheses in raise module.get_exception() as unnecessary.

        ","tags":["RSE102"]},{"location":"rules/unnecessary-paren-on-raise-exception/#example","title":"Example","text":"
        raise TypeError()\n

        Use instead:

        raise TypeError\n
        ","tags":["RSE102"]},{"location":"rules/unnecessary-paren-on-raise-exception/#references","title":"References","text":"
        • Python documentation: The raise statement
        ","tags":["RSE102"]},{"location":"rules/unnecessary-placeholder/","title":"unnecessary-placeholder (PIE790)","text":"

        Derived from the flake8-pie linter.

        Fix is always available.

        ","tags":["PIE790"]},{"location":"rules/unnecessary-placeholder/#what-it-does","title":"What it does","text":"

        Checks for unnecessary pass statements and ellipsis (...) literals in functions, classes, and other blocks.

        ","tags":["PIE790"]},{"location":"rules/unnecessary-placeholder/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the pass statement and ellipsis (...) literal serve as placeholders, allowing for syntactically correct empty code blocks. The primary purpose of these nodes is to avoid syntax errors in situations where a statement or expression is syntactically required, but no code needs to be executed.

        If a pass or ellipsis is present in a code block that includes at least one other statement (even, e.g., a docstring), it is unnecessary and should be removed.

        ","tags":["PIE790"]},{"location":"rules/unnecessary-placeholder/#example","title":"Example","text":"
        def func():\n    \"\"\"Placeholder docstring.\"\"\"\n    pass\n

        Use instead:

        def func():\n    \"\"\"Placeholder docstring.\"\"\"\n

        Or, given:

        def func():\n    \"\"\"Placeholder docstring.\"\"\"\n    ...\n

        Use instead:

        def func():\n    \"\"\"Placeholder docstring.\"\"\"\n
        ","tags":["PIE790"]},{"location":"rules/unnecessary-placeholder/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe in the rare case that the pass or ellipsis is followed by a string literal, since removal of the placeholder would convert the subsequent string literal into a docstring.

        ","tags":["PIE790"]},{"location":"rules/unnecessary-placeholder/#references","title":"References","text":"
        • Python documentation: The pass statement
        ","tags":["PIE790"]},{"location":"rules/unnecessary-range-start/","title":"unnecessary-range-start (PIE808)","text":"

        Derived from the flake8-pie linter.

        Fix is always available.

        ","tags":["PIE808"]},{"location":"rules/unnecessary-range-start/#what-it-does","title":"What it does","text":"

        Checks for range calls with an unnecessary start argument.

        ","tags":["PIE808"]},{"location":"rules/unnecessary-range-start/#why-is-this-bad","title":"Why is this bad?","text":"

        range(0, x) is equivalent to range(x), as 0 is the default value for the start argument. Omitting the start argument makes the code more concise and idiomatic.

        ","tags":["PIE808"]},{"location":"rules/unnecessary-range-start/#example","title":"Example","text":"
        range(0, 3)\n

        Use instead:

        range(3)\n
        ","tags":["PIE808"]},{"location":"rules/unnecessary-range-start/#references","title":"References","text":"
        • Python documentation: range
        ","tags":["PIE808"]},{"location":"rules/unnecessary-regular-expression/","title":"unnecessary-regular-expression (RUF055)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#what-it-does","title":"What it does","text":"

        Checks for uses of the re module that can be replaced with builtin str methods.

        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#why-is-this-bad","title":"Why is this bad?","text":"

        Performing checks on strings directly can make the code simpler, may require less escaping, and will often be faster.

        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#example","title":"Example","text":"
        re.sub(\"abc\", \"\", s)\n

        Use instead:

        s.replace(\"abc\", \"\")\n
        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#details","title":"Details","text":"

        The rule reports the following calls when the first argument to the call is a plain string literal, and no additional flags are passed:

        • re.sub
        • re.match
        • re.search
        • re.fullmatch
        • re.split

        For re.sub, the repl (replacement) argument must also be a string literal, not a function. For re.match, re.search, and re.fullmatch, the return value must also be used only for its truth value.

        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe if the affected expression contains comments. Otherwise, the fix can be applied safely.

        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#references","title":"References","text":"
        • Python Regular Expression HOWTO: Common Problems - Use String Methods
        ","tags":["RUF055"]},{"location":"rules/unnecessary-return-none/","title":"unnecessary-return-none (RET501)","text":"

        Derived from the flake8-return linter.

        Fix is always available.

        ","tags":["RET501"]},{"location":"rules/unnecessary-return-none/#what-it-does","title":"What it does","text":"

        Checks for the presence of a return None statement when None is the only possible return value.

        ","tags":["RET501"]},{"location":"rules/unnecessary-return-none/#why-is-this-bad","title":"Why is this bad?","text":"

        Python implicitly assumes return None if an explicit return value is omitted. Therefore, explicitly returning None is redundant and should be avoided when it is the only possible return value across all code paths in a given function.

        ","tags":["RET501"]},{"location":"rules/unnecessary-return-none/#example","title":"Example","text":"
        def foo(bar):\n    if not bar:\n        return\n    return None\n

        Use instead:

        def foo(bar):\n    if not bar:\n        return\n    return\n
        ","tags":["RET501"]},{"location":"rules/unnecessary-round/","title":"unnecessary-round (RUF057)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF057"]},{"location":"rules/unnecessary-round/#what-it-does","title":"What it does","text":"

        Checks for round() calls that have no effect on the input.

        ","tags":["RUF057"]},{"location":"rules/unnecessary-round/#why-is-this-bad","title":"Why is this bad?","text":"

        Rounding a value that's already an integer is unnecessary. It's clearer to use the value directly.

        ","tags":["RUF057"]},{"location":"rules/unnecessary-round/#example","title":"Example","text":"
        a = round(1, 0)\n

        Use instead:

        a = 1\n
        ","tags":["RUF057"]},{"location":"rules/unnecessary-round/#fix-safety","title":"Fix safety","text":"

        The fix is marked unsafe if it is not possible to guarantee that the first argument of round() is of type int, or if the fix deletes comments.

        ","tags":["RUF057"]},{"location":"rules/unnecessary-spread/","title":"unnecessary-spread (PIE800)","text":"

        Derived from the flake8-pie linter.

        Fix is sometimes available.

        ","tags":["PIE800"]},{"location":"rules/unnecessary-spread/#what-it-does","title":"What it does","text":"

        Checks for unnecessary dictionary unpacking operators (**).

        ","tags":["PIE800"]},{"location":"rules/unnecessary-spread/#why-is-this-bad","title":"Why is this bad?","text":"

        Unpacking a dictionary into another dictionary is redundant. The unpacking operator can be removed, making the code more readable.

        ","tags":["PIE800"]},{"location":"rules/unnecessary-spread/#example","title":"Example","text":"
        foo = {\"A\": 1, \"B\": 2}\nbar = {**foo, **{\"C\": 3}}\n

        Use instead:

        foo = {\"A\": 1, \"B\": 2}\nbar = {**foo, \"C\": 3}\n
        ","tags":["PIE800"]},{"location":"rules/unnecessary-spread/#references","title":"References","text":"
        • Python documentation: Dictionary displays
        ","tags":["PIE800"]},{"location":"rules/unnecessary-subscript-reversal/","title":"unnecessary-subscript-reversal (C415)","text":"

        Derived from the flake8-comprehensions linter.

        ","tags":["C415"]},{"location":"rules/unnecessary-subscript-reversal/#what-it-does","title":"What it does","text":"

        Checks for unnecessary subscript reversal of iterable.

        ","tags":["C415"]},{"location":"rules/unnecessary-subscript-reversal/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to reverse the order of an iterable when passing it into reversed(), set() or sorted() functions as they will change the order of the elements again.

        ","tags":["C415"]},{"location":"rules/unnecessary-subscript-reversal/#example","title":"Example","text":"
        sorted(iterable[::-1])\nset(iterable[::-1])\nreversed(iterable[::-1])\n

        Use instead:

        sorted(iterable)\nset(iterable)\niterable\n
        ","tags":["C415"]},{"location":"rules/unnecessary-type-union/","title":"unnecessary-type-union (PYI055)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI055"]},{"location":"rules/unnecessary-type-union/#what-it-does","title":"What it does","text":"

        Checks for the presence of multiple types in a union.

        ","tags":["PYI055"]},{"location":"rules/unnecessary-type-union/#why-is-this-bad","title":"Why is this bad?","text":"

        type[T | S] has identical semantics to type[T] | type[S] in a type annotation, but is cleaner and more concise.

        ","tags":["PYI055"]},{"location":"rules/unnecessary-type-union/#example","title":"Example","text":"
        field: type[int] | type[float] | str\n

        Use instead:

        field: type[int | float] | str\n
        ","tags":["PYI055"]},{"location":"rules/unnecessary-type-union/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the type annotation contains comments.

        Note that while the fix may flatten nested unions into a single top-level union, the semantics of the annotation will remain unchanged.

        ","tags":["PYI055"]},{"location":"rules/unpacked-list-comprehension/","title":"unpacked-list-comprehension (UP027)","text":"

        Derived from the pyupgrade linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["UP027"]},{"location":"rules/unpacked-list-comprehension/#removed","title":"Removed","text":"

        There's no evidence that generators are meaningfully faster than list comprehensions when combined with unpacking.

        ","tags":["UP027"]},{"location":"rules/unpacked-list-comprehension/#what-it-does","title":"What it does","text":"

        Checks for list comprehensions that are immediately unpacked.

        ","tags":["UP027"]},{"location":"rules/unpacked-list-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        There is no reason to use a list comprehension if the result is immediately unpacked. Instead, use a generator expression, which avoids allocating an intermediary list.

        ","tags":["UP027"]},{"location":"rules/unpacked-list-comprehension/#example","title":"Example","text":"
        a, b, c = [foo(x) for x in items]\n

        Use instead:

        a, b, c = (foo(x) for x in items)\n
        ","tags":["UP027"]},{"location":"rules/unpacked-list-comprehension/#references","title":"References","text":"
        • Python documentation: Generator expressions
        • Python documentation: List comprehensions
        ","tags":["UP027"]},{"location":"rules/unprefixed-type-param/","title":"unprefixed-type-param (PYI001)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI001"]},{"location":"rules/unprefixed-type-param/#what-it-does","title":"What it does","text":"

        Checks that type TypeVars, ParamSpecs, and TypeVarTuples in stubs have names prefixed with _.

        ","tags":["PYI001"]},{"location":"rules/unprefixed-type-param/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefixing type parameters with _ avoids accidentally exposing names internal to the stub.

        ","tags":["PYI001"]},{"location":"rules/unprefixed-type-param/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"T\")\n

        Use instead:

        from typing import TypeVar\n\n_T = TypeVar(\"_T\")\n
        ","tags":["PYI001"]},{"location":"rules/unquoted-type-alias/","title":"unquoted-type-alias (TC007)","text":"

        Derived from the flake8-type-checking linter.

        Fix is sometimes available.

        ","tags":["TC007"]},{"location":"rules/unquoted-type-alias/#what-it-does","title":"What it does","text":"

        Checks if PEP 613 explicit type aliases contain references to symbols that are not available at runtime.

        ","tags":["TC007"]},{"location":"rules/unquoted-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        Referencing type-checking only symbols results in a NameError at runtime.

        ","tags":["TC007"]},{"location":"rules/unquoted-type-alias/#example","title":"Example","text":"
        from typing import TYPE_CHECKING, TypeAlias\n\nif TYPE_CHECKING:\n    from foo import Foo\nOptFoo: TypeAlias = Foo | None\n

        Use instead:

        from typing import TYPE_CHECKING, TypeAlias\n\nif TYPE_CHECKING:\n    from foo import Foo\nOptFoo: TypeAlias = \"Foo | None\"\n
        ","tags":["TC007"]},{"location":"rules/unquoted-type-alias/#fix-safety","title":"Fix safety","text":"

        This rule's fix is currently always marked as unsafe, since runtime typing libraries may try to access/resolve the type alias in a way that we can't statically determine during analysis and relies on the type alias not containing any forward references.

        ","tags":["TC007"]},{"location":"rules/unquoted-type-alias/#references","title":"References","text":"
        • PEP 613 \u2013 Explicit Type Aliases
        ","tags":["TC007"]},{"location":"rules/unraw-re-pattern/","title":"unraw-re-pattern (RUF039)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF039"]},{"location":"rules/unraw-re-pattern/#what-it-does","title":"What it does","text":"

        Reports the following re and regex calls when their first arguments are not raw strings:

        • For regex and re: compile, findall, finditer, fullmatch, match, search, split, sub, subn.
        • regex-specific: splititer, subf, subfn, template.
        ","tags":["RUF039"]},{"location":"rules/unraw-re-pattern/#why-is-this-bad","title":"Why is this bad?","text":"

        Regular expressions should be written using raw strings to avoid double escaping.

        ","tags":["RUF039"]},{"location":"rules/unraw-re-pattern/#example","title":"Example","text":"
        re.compile(\"foo\\\\bar\")\n

        Use instead:

        re.compile(r\"foo\\bar\")\n
        ","tags":["RUF039"]},{"location":"rules/unrecognized-platform-check/","title":"unrecognized-platform-check (PYI007)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI007"]},{"location":"rules/unrecognized-platform-check/#what-it-does","title":"What it does","text":"

        Check for unrecognized sys.platform checks. Platform checks should be simple string comparisons.

        Note: this rule is only enabled in .pyi stub files.

        ","tags":["PYI007"]},{"location":"rules/unrecognized-platform-check/#why-is-this-bad","title":"Why is this bad?","text":"

        Some sys.platform checks are too complex for type checkers to understand, and thus result in incorrect inferences by these tools. sys.platform checks should be simple string comparisons, like if sys.platform == \"linux\".

        ","tags":["PYI007"]},{"location":"rules/unrecognized-platform-check/#example","title":"Example","text":"
        if sys.platform.startswith(\"linux\"):\n    # Linux specific definitions\n    ...\nelse:\n    # Posix specific definitions\n    ...\n

        Instead, use a simple string comparison, such as == or !=:

        if sys.platform == \"linux\":\n    # Linux specific definitions\n    ...\nelse:\n    # Posix specific definitions\n    ...\n
        ","tags":["PYI007"]},{"location":"rules/unrecognized-platform-check/#references","title":"References","text":"
        • Typing documentation: Version and Platform checking
        ","tags":["PYI007"]},{"location":"rules/unrecognized-platform-name/","title":"unrecognized-platform-name (PYI008)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI008"]},{"location":"rules/unrecognized-platform-name/#what-it-does","title":"What it does","text":"

        Check for unrecognized platform names in sys.platform checks.

        Note: this rule is only enabled in .pyi stub files.

        ","tags":["PYI008"]},{"location":"rules/unrecognized-platform-name/#why-is-this-bad","title":"Why is this bad?","text":"

        If a sys.platform check compares to a platform name outside of a small set of known platforms (e.g. \"linux\", \"win32\", etc.), it's likely a typo or a platform name that is not recognized by type checkers.

        The list of known platforms is: \"linux\", \"win32\", \"cygwin\", \"darwin\".

        ","tags":["PYI008"]},{"location":"rules/unrecognized-platform-name/#example","title":"Example","text":"
        if sys.platform == \"linus\": ...\n

        Use instead:

        if sys.platform == \"linux\": ...\n
        ","tags":["PYI008"]},{"location":"rules/unrecognized-platform-name/#references","title":"References","text":"
        • Typing documentation: Version and Platform checking
        ","tags":["PYI008"]},{"location":"rules/unrecognized-version-info-check/","title":"unrecognized-version-info-check (PYI003)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI003"]},{"location":"rules/unrecognized-version-info-check/#what-it-does","title":"What it does","text":"

        Checks for problematic sys.version_info-related conditions in stubs.

        ","tags":["PYI003"]},{"location":"rules/unrecognized-version-info-check/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files support simple conditionals to test for differences in Python versions using sys.version_info. However, there are a number of common mistakes involving sys.version_info comparisons that should be avoided. For example, comparing against a string can lead to unexpected behavior.

        ","tags":["PYI003"]},{"location":"rules/unrecognized-version-info-check/#example","title":"Example","text":"
        import sys\n\nif sys.version_info[0] == \"2\": ...\n

        Use instead:

        import sys\n\nif sys.version_info[0] == 2: ...\n
        ","tags":["PYI003"]},{"location":"rules/unrecognized-version-info-check/#references","title":"References","text":"
        • Typing documentation: Version and Platform checking
        ","tags":["PYI003"]},{"location":"rules/unreliable-callable-check/","title":"unreliable-callable-check (B004)","text":"

        Derived from the flake8-bugbear linter.

        Fix is sometimes available.

        ","tags":["B004"]},{"location":"rules/unreliable-callable-check/#what-it-does","title":"What it does","text":"

        Checks for uses of hasattr to test if an object is callable (e.g., hasattr(obj, \"__call__\")).

        ","tags":["B004"]},{"location":"rules/unreliable-callable-check/#why-is-this-bad","title":"Why is this bad?","text":"

        Using hasattr is an unreliable mechanism for testing if an object is callable. If obj implements a custom __getattr__, or if its __call__ is itself not callable, you may get misleading results.

        Instead, use callable(obj) to test if obj is callable.

        ","tags":["B004"]},{"location":"rules/unreliable-callable-check/#example","title":"Example","text":"
        hasattr(obj, \"__call__\")\n

        Use instead:

        callable(obj)\n
        ","tags":["B004"]},{"location":"rules/unreliable-callable-check/#references","title":"References","text":"
        • Python documentation: callable
        • Python documentation: hasattr
        • Python documentation: __getattr__
        • Python documentation: __call__
        ","tags":["B004"]},{"location":"rules/unsafe-markup-use/","title":"unsafe-markup-use (S704)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S704"]},{"location":"rules/unsafe-markup-use/#what-it-does","title":"What it does","text":"

        Checks for non-literal strings being passed to markupsafe.Markup.

        ","tags":["S704"]},{"location":"rules/unsafe-markup-use/#why-is-this-bad","title":"Why is this bad?","text":"

        [markupsafe.Markup][markupsafe.Markup] does not perform any escaping, so passing dynamic content, like f-strings, variables or interpolated strings will potentially lead to XSS vulnerabilities.

        Instead you should interpolate the Markup object.

        Using lint.flake8-bandit.extend-markup-names additional objects can be treated like Markup.

        This rule was originally inspired by flake8-markupsafe but doesn't carve out any exceptions for i18n related calls by default.

        You can use lint.flake8-bandit.allowed-markup-calls to specify exceptions.

        ","tags":["S704"]},{"location":"rules/unsafe-markup-use/#example","title":"Example","text":"

        Given:

        from markupsafe import Markup\n\ncontent = \"<script>alert('Hello, world!')</script>\"\nhtml = Markup(f\"<b>{content}</b>\")  # XSS\n

        Use instead:

        from markupsafe import Markup\n\ncontent = \"<script>alert('Hello, world!')</script>\"\nhtml = Markup(\"<b>{}</b>\").format(content)  # Safe\n

        Given:

        from markupsafe import Markup\n\nlines = [\n    Markup(\"<b>heading</b>\"),\n    \"<script>alert('XSS attempt')</script>\",\n]\nhtml = Markup(\"<br>\".join(lines))  # XSS\n

        Use instead:

        from markupsafe import Markup\n\nlines = [\n    Markup(\"<b>heading</b>\"),\n    \"<script>alert('XSS attempt')</script>\",\n]\nhtml = Markup(\"<br>\").join(lines)  # Safe\n
        ","tags":["S704"]},{"location":"rules/unsafe-markup-use/#options","title":"Options","text":"
        • lint.flake8-bandit.extend-markup-names
        • lint.flake8-bandit.allowed-markup-calls
        ","tags":["S704"]},{"location":"rules/unsafe-markup-use/#references","title":"References","text":"
        • MarkupSafe on PyPI
        • markupsafe.Markup API documentation
        ","tags":["S704"]},{"location":"rules/unsafe-yaml-load/","title":"unsafe-yaml-load (S506)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S506"]},{"location":"rules/unsafe-yaml-load/#what-it-does","title":"What it does","text":"

        Checks for uses of the yaml.load function.

        ","tags":["S506"]},{"location":"rules/unsafe-yaml-load/#why-is-this-bad","title":"Why is this bad?","text":"

        Running the yaml.load function over untrusted YAML files is insecure, as yaml.load allows for the creation of arbitrary Python objects, which can then be used to execute arbitrary code.

        Instead, consider using yaml.safe_load, which allows for the creation of simple Python objects like integers and lists, but prohibits the creation of more complex objects like functions and classes.

        ","tags":["S506"]},{"location":"rules/unsafe-yaml-load/#example","title":"Example","text":"
        import yaml\n\nyaml.load(untrusted_yaml)\n

        Use instead:

        import yaml\n\nyaml.safe_load(untrusted_yaml)\n
        ","tags":["S506"]},{"location":"rules/unsafe-yaml-load/#references","title":"References","text":"
        • PyYAML documentation: Loading YAML
        • Common Weakness Enumeration: CWE-20
        ","tags":["S506"]},{"location":"rules/unsorted-dunder-all/","title":"unsorted-dunder-all (RUF022)","text":"

        Fix is sometimes available.

        ","tags":["RUF022"]},{"location":"rules/unsorted-dunder-all/#what-it-does","title":"What it does","text":"

        Checks for __all__ definitions that are not ordered according to an \"isort-style\" sort.

        An isort-style sort orders items first according to their casing: SCREAMING_SNAKE_CASE names (conventionally used for global constants) come first, followed by CamelCase names (conventionally used for classes), followed by anything else. Within each category, a natural sort is used to order the elements.

        ","tags":["RUF022"]},{"location":"rules/unsorted-dunder-all/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use a common convention for __all__ to make your code more readable and idiomatic.

        ","tags":["RUF022"]},{"location":"rules/unsorted-dunder-all/#example","title":"Example","text":"
        import sys\n\n__all__ = [\n    \"b\",\n    \"c\",\n    \"a\",\n]\n\nif sys.platform == \"win32\":\n    __all__ += [\"z\", \"y\"]\n

        Use instead:

        import sys\n\n__all__ = [\n    \"a\",\n    \"b\",\n    \"c\",\n]\n\nif sys.platform == \"win32\":\n    __all__ += [\"y\", \"z\"]\n
        ","tags":["RUF022"]},{"location":"rules/unsorted-dunder-all/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe if there are any comments that take up a whole line by themselves inside the __all__ definition, for example:

        __all__ = [\n    # eggy things\n    \"duck_eggs\",\n    \"chicken_eggs\",\n    # hammy things\n    \"country_ham\",\n    \"parma_ham\",\n]\n

        This is a common pattern used to delimit categories within a module's API, but it would be out of the scope of this rule to attempt to maintain these categories when alphabetically sorting the items of __all__.

        The fix is also marked as unsafe if there are more than two __all__ items on a single line and that line also has a trailing comment, since here it is impossible to accurately gauge which item the comment should be moved with when sorting __all__:

        __all__ = [\n    \"a\", \"c\", \"e\",  # a comment\n    \"b\", \"d\", \"f\",  # a second  comment\n]\n

        Other than this, the rule's fix is marked as always being safe, in that it should very rarely alter the semantics of any Python code. However, note that (although it's rare) the value of __all__ could be read by code elsewhere that depends on the exact iteration order of the items in __all__, in which case this rule's fix could theoretically cause breakage.

        ","tags":["RUF022"]},{"location":"rules/unsorted-dunder-slots/","title":"unsorted-dunder-slots (RUF023)","text":"

        Fix is sometimes available.

        ","tags":["RUF023"]},{"location":"rules/unsorted-dunder-slots/#what-it-does","title":"What it does","text":"

        Checks for __slots__ definitions that are not ordered according to a natural sort.

        ","tags":["RUF023"]},{"location":"rules/unsorted-dunder-slots/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use a common convention for this special variable to make your code more readable and idiomatic.

        ","tags":["RUF023"]},{"location":"rules/unsorted-dunder-slots/#example","title":"Example","text":"
        class Dog:\n    __slots__ = \"name\", \"breed\"\n

        Use instead:

        class Dog:\n    __slots__ = \"breed\", \"name\"\n
        ","tags":["RUF023"]},{"location":"rules/unsorted-dunder-slots/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe in three situations.

        Firstly, the fix is unsafe if there are any comments that take up a whole line by themselves inside the __slots__ definition, for example:

        class Foo:\n    __slots__ = [\n        # eggy things\n        \"duck_eggs\",\n        \"chicken_eggs\",\n        # hammy things\n        \"country_ham\",\n        \"parma_ham\",\n    ]\n

        This is a common pattern used to delimit categories within a class's slots, but it would be out of the scope of this rule to attempt to maintain these categories when applying a natural sort to the items of __slots__.

        Secondly, the fix is also marked as unsafe if there are more than two __slots__ items on a single line and that line also has a trailing comment, since here it is impossible to accurately gauge which item the comment should be moved with when sorting __slots__:

        class Bar:\n    __slots__ = [\n        \"a\", \"c\", \"e\",  # a comment\n        \"b\", \"d\", \"f\",  # a second  comment\n    ]\n

        Lastly, this rule's fix is marked as unsafe whenever Ruff can detect that code elsewhere in the same file reads the __slots__ variable in some way and the __slots__ variable is not assigned to a set. This is because the order of the items in __slots__ may have semantic significance if the __slots__ of a class is being iterated over, or being assigned to another value.

        In the vast majority of other cases, this rule's fix is unlikely to cause breakage; as such, Ruff will otherwise mark this rule's fix as safe. However, note that (although it's rare) the value of __slots__ could still be read by code outside of the module in which the __slots__ definition occurs, in which case this rule's fix could theoretically cause breakage.

        ","tags":["RUF023"]},{"location":"rules/unsorted-imports/","title":"unsorted-imports (I001)","text":"

        Derived from the isort linter.

        Fix is sometimes available.

        ","tags":["I001"]},{"location":"rules/unsorted-imports/#what-it-does","title":"What it does","text":"

        De-duplicates, groups, and sorts imports based on the provided isort settings.

        ","tags":["I001"]},{"location":"rules/unsorted-imports/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use a common convention for imports to make your code more readable and idiomatic.

        ","tags":["I001"]},{"location":"rules/unsorted-imports/#example","title":"Example","text":"
        import pandas\nimport numpy as np\n

        Use instead:

        import numpy as np\nimport pandas\n
        ","tags":["I001"]},{"location":"rules/unsorted-imports/#preview","title":"Preview","text":"

        When preview mode is enabled, Ruff applies a stricter criterion for determining whether an import should be classified as first-party. Specifically, for an import of the form import foo.bar.baz, Ruff will check that foo/bar, relative to a user-specified src directory, contains either the directory baz or else a file with the name baz.py or baz.pyi.

        ","tags":["I001"]},{"location":"rules/unspecified-encoding/","title":"unspecified-encoding (PLW1514)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW1514"]},{"location":"rules/unspecified-encoding/#what-it-does","title":"What it does","text":"

        Checks for uses of open and related calls without an explicit encoding argument.

        ","tags":["PLW1514"]},{"location":"rules/unspecified-encoding/#why-is-this-bad","title":"Why is this bad?","text":"

        Using open in text mode without an explicit encoding can lead to non-portable code, with differing behavior across platforms. While readers may assume that UTF-8 is the default encoding, in reality, the default is locale-specific.

        Instead, consider using the encoding parameter to enforce a specific encoding. PEP 597 recommends the use of encoding=\"utf-8\" as a default, and suggests that it may become the default in future versions of Python.

        If a locale-specific encoding is intended, use encoding=\"locale\" on Python 3.10 and later, or locale.getpreferredencoding() on earlier versions, to make the encoding explicit.

        ","tags":["PLW1514"]},{"location":"rules/unspecified-encoding/#fix-safety","title":"Fix safety","text":"

        This fix is always unsafe and may change the program's behavior. It forces encoding=\"utf-8\" as the default, regardless of the platform\u2019s actual default encoding, which may cause UnicodeDecodeError on non-UTF-8 systems.

        with open(\"test.txt\") as f:\n    print(f.read()) # before fix (on UTF-8 systems): \u4f60\u597d\uff0c\u4e16\u754c\uff01\nwith open(\"test.txt\", encoding=\"utf-8\") as f:\n    print(f.read()) # after fix (on Windows): UnicodeDecodeError\n
        ","tags":["PLW1514"]},{"location":"rules/unspecified-encoding/#example","title":"Example","text":"
        open(\"file.txt\")\n

        Use instead:

        open(\"file.txt\", encoding=\"utf-8\")\n
        ","tags":["PLW1514"]},{"location":"rules/unspecified-encoding/#references","title":"References","text":"
        • Python documentation: open
        ","tags":["PLW1514"]},{"location":"rules/unsupported-method-call-on-all/","title":"unsupported-method-call-on-all (PYI056)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI056"]},{"location":"rules/unsupported-method-call-on-all/#what-it-does","title":"What it does","text":"

        Checks that append, extend and remove methods are not called on __all__.

        ","tags":["PYI056"]},{"location":"rules/unsupported-method-call-on-all/#why-is-this-bad","title":"Why is this bad?","text":"

        Different type checkers have varying levels of support for calling these methods on __all__. Instead, use the += operator to add items to __all__, which is known to be supported by all major type checkers.

        ","tags":["PYI056"]},{"location":"rules/unsupported-method-call-on-all/#example","title":"Example","text":"
        import sys\n\n__all__ = [\"A\", \"B\"]\n\nif sys.version_info >= (3, 10):\n    __all__.append(\"C\")\n\nif sys.version_info >= (3, 11):\n    __all__.remove(\"B\")\n

        Use instead:

        import sys\n\n__all__ = [\"A\"]\n\nif sys.version_info < (3, 11):\n    __all__ += [\"B\"]\n\nif sys.version_info >= (3, 10):\n    __all__ += [\"C\"]\n
        ","tags":["PYI056"]},{"location":"rules/unused-annotation/","title":"unused-annotation (F842)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F842"]},{"location":"rules/unused-annotation/#what-it-does","title":"What it does","text":"

        Checks for local variables that are annotated but never used.

        ","tags":["F842"]},{"location":"rules/unused-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        Annotations are used to provide type hints to static type checkers. If a variable is annotated but never used, the annotation is unnecessary.

        ","tags":["F842"]},{"location":"rules/unused-annotation/#example","title":"Example","text":"
        def foo():\n    bar: int\n
        ","tags":["F842"]},{"location":"rules/unused-annotation/#references","title":"References","text":"
        • PEP 484 \u2013 Type Hints
        ","tags":["F842"]},{"location":"rules/unused-async/","title":"unused-async (RUF029)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF029"]},{"location":"rules/unused-async/#what-it-does","title":"What it does","text":"

        Checks for functions declared async that do not await or otherwise use features requiring the function to be declared async.

        ","tags":["RUF029"]},{"location":"rules/unused-async/#why-is-this-bad","title":"Why is this bad?","text":"

        Declaring a function async when it's not is usually a mistake, and will artificially limit the contexts where that function may be called. In some cases, labeling a function async is semantically meaningful (e.g. with the trio library).

        ","tags":["RUF029"]},{"location":"rules/unused-async/#example","title":"Example","text":"
        async def foo():\n    bar()\n

        Use instead:

        def foo():\n    bar()\n
        ","tags":["RUF029"]},{"location":"rules/unused-class-method-argument/","title":"unused-class-method-argument (ARG003)","text":"

        Derived from the flake8-unused-arguments linter.

        ","tags":["ARG003"]},{"location":"rules/unused-class-method-argument/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused arguments in class method definitions.

        ","tags":["ARG003"]},{"location":"rules/unused-class-method-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An argument that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["ARG003"]},{"location":"rules/unused-class-method-argument/#example","title":"Example","text":"
        class Class:\n    @classmethod\n    def foo(cls, arg1, arg2):\n        print(arg1)\n

        Use instead:

        class Class:\n    @classmethod\n    def foo(cls, arg1):\n        print(arg1)\n
        ","tags":["ARG003"]},{"location":"rules/unused-class-method-argument/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["ARG003"]},{"location":"rules/unused-function-argument/","title":"unused-function-argument (ARG001)","text":"

        Derived from the flake8-unused-arguments linter.

        ","tags":["ARG001"]},{"location":"rules/unused-function-argument/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused arguments in function definitions.

        ","tags":["ARG001"]},{"location":"rules/unused-function-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An argument that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["ARG001"]},{"location":"rules/unused-function-argument/#example","title":"Example","text":"
        def foo(bar, baz):\n    return bar * 2\n

        Use instead:

        def foo(bar):\n    return bar * 2\n
        ","tags":["ARG001"]},{"location":"rules/unused-function-argument/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["ARG001"]},{"location":"rules/unused-import/","title":"unused-import (F401)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F401"]},{"location":"rules/unused-import/#what-it-does","title":"What it does","text":"

        Checks for unused imports.

        ","tags":["F401"]},{"location":"rules/unused-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused imports add a performance overhead at runtime, and risk creating import cycles. They also increase the cognitive load of reading the code.

        If an import statement is used to check for the availability or existence of a module, consider using importlib.util.find_spec instead.

        If an import statement is used to re-export a symbol as part of a module's public interface, consider using a \"redundant\" import alias, which instructs Ruff (and other tools) to respect the re-export, and avoid marking it as unused, as in:

        from module import member as member\n

        Alternatively, you can use __all__ to declare a symbol as part of the module's interface, as in:

        # __init__.py\nimport some_module\n\n__all__ = [\"some_module\"]\n
        ","tags":["F401"]},{"location":"rules/unused-import/#fix-safety","title":"Fix safety","text":"

        Fixes to remove unused imports are safe, except in __init__.py files.

        Applying fixes to __init__.py files is currently in preview. The fix offered depends on the type of the unused import. Ruff will suggest a safe fix to export first-party imports with either a redundant alias or, if already present in the file, an __all__ entry. If multiple __all__ declarations are present, Ruff will not offer a fix. Ruff will suggest an unsafe fix to remove third-party and standard library imports -- the fix is unsafe because the module's interface changes.

        ","tags":["F401"]},{"location":"rules/unused-import/#example","title":"Example","text":"
        import numpy as np  # unused import\n\n\ndef area(radius):\n    return 3.14 * radius**2\n

        Use instead:

        def area(radius):\n    return 3.14 * radius**2\n

        To check the availability of a module, use importlib.util.find_spec:

        from importlib.util import find_spec\n\nif find_spec(\"numpy\") is not None:\n    print(\"numpy is installed\")\nelse:\n    print(\"numpy is not installed\")\n
        ","tags":["F401"]},{"location":"rules/unused-import/#preview","title":"Preview","text":"

        When preview is enabled, the criterion for determining whether an import is first-party is stricter, which could affect the suggested fix. See this FAQ section for more details.

        ","tags":["F401"]},{"location":"rules/unused-import/#options","title":"Options","text":"
        • lint.ignore-init-module-imports
        • lint.pyflakes.allowed-unused-imports
        ","tags":["F401"]},{"location":"rules/unused-import/#references","title":"References","text":"
        • Python documentation: import
        • Python documentation: importlib.util.find_spec
        • Typing documentation: interface conventions
        ","tags":["F401"]},{"location":"rules/unused-lambda-argument/","title":"unused-lambda-argument (ARG005)","text":"

        Derived from the flake8-unused-arguments linter.

        ","tags":["ARG005"]},{"location":"rules/unused-lambda-argument/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused arguments in lambda expression definitions.

        ","tags":["ARG005"]},{"location":"rules/unused-lambda-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An argument that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["ARG005"]},{"location":"rules/unused-lambda-argument/#example","title":"Example","text":"
        my_list = [1, 2, 3, 4, 5]\nsquares = map(lambda x, y: x**2, my_list)\n

        Use instead:

        my_list = [1, 2, 3, 4, 5]\nsquares = map(lambda x: x**2, my_list)\n
        ","tags":["ARG005"]},{"location":"rules/unused-lambda-argument/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["ARG005"]},{"location":"rules/unused-loop-control-variable/","title":"unused-loop-control-variable (B007)","text":"

        Derived from the flake8-bugbear linter.

        Fix is sometimes available.

        ","tags":["B007"]},{"location":"rules/unused-loop-control-variable/#what-it-does","title":"What it does","text":"

        Checks for unused variables in loops (e.g., for and while statements).

        ","tags":["B007"]},{"location":"rules/unused-loop-control-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        Defining a variable in a loop statement that is never used can confuse readers.

        If the variable is intended to be unused (e.g., to facilitate destructuring of a tuple or other object), prefix it with an underscore to indicate the intent. Otherwise, remove the variable entirely.

        ","tags":["B007"]},{"location":"rules/unused-loop-control-variable/#example","title":"Example","text":"
        for i, j in foo:\n    bar(i)\n

        Use instead:

        for i, _j in foo:\n    bar(i)\n
        ","tags":["B007"]},{"location":"rules/unused-loop-control-variable/#references","title":"References","text":"
        • PEP 8: Naming Conventions
        ","tags":["B007"]},{"location":"rules/unused-method-argument/","title":"unused-method-argument (ARG002)","text":"

        Derived from the flake8-unused-arguments linter.

        ","tags":["ARG002"]},{"location":"rules/unused-method-argument/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused arguments in instance method definitions.

        ","tags":["ARG002"]},{"location":"rules/unused-method-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An argument that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["ARG002"]},{"location":"rules/unused-method-argument/#example","title":"Example","text":"
        class Class:\n    def foo(self, arg1, arg2):\n        print(arg1)\n

        Use instead:

        class Class:\n    def foo(self, arg1):\n        print(arg1)\n
        ","tags":["ARG002"]},{"location":"rules/unused-method-argument/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["ARG002"]},{"location":"rules/unused-noqa/","title":"unused-noqa (RUF100)","text":"

        Fix is always available.

        ","tags":["RUF100"]},{"location":"rules/unused-noqa/#what-it-does","title":"What it does","text":"

        Checks for noqa directives that are no longer applicable.

        ","tags":["RUF100"]},{"location":"rules/unused-noqa/#why-is-this-bad","title":"Why is this bad?","text":"

        A noqa directive that no longer matches any diagnostic violations is likely included by mistake, and should be removed to avoid confusion.

        ","tags":["RUF100"]},{"location":"rules/unused-noqa/#example","title":"Example","text":"
        import foo  # noqa: F401\n\n\ndef bar():\n    foo.bar()\n

        Use instead:

        import foo\n\n\ndef bar():\n    foo.bar()\n
        ","tags":["RUF100"]},{"location":"rules/unused-noqa/#options","title":"Options","text":"
        • lint.external
        ","tags":["RUF100"]},{"location":"rules/unused-noqa/#references","title":"References","text":"
        • Ruff error suppression
        ","tags":["RUF100"]},{"location":"rules/unused-private-protocol/","title":"unused-private-protocol (PYI046)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI046"]},{"location":"rules/unused-private-protocol/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused private typing.Protocol definitions.

        ","tags":["PYI046"]},{"location":"rules/unused-private-protocol/#why-is-this-bad","title":"Why is this bad?","text":"

        A private typing.Protocol that is defined but not used is likely a mistake. It should either be used, made public, or removed to avoid confusion.

        ","tags":["PYI046"]},{"location":"rules/unused-private-protocol/#example","title":"Example","text":"
        import typing\n\nclass _PrivateProtocol(typing.Protocol):\n    foo: int\n

        Use instead:

        import typing\n\nclass _PrivateProtocol(typing.Protocol):\n    foo: int\n\ndef func(arg: _PrivateProtocol) -> None: ...\n
        ","tags":["PYI046"]},{"location":"rules/unused-private-type-alias/","title":"unused-private-type-alias (PYI047)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI047"]},{"location":"rules/unused-private-type-alias/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused private type aliases.

        ","tags":["PYI047"]},{"location":"rules/unused-private-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        A private type alias that is defined but not used is likely a mistake. It should either be used, made public, or removed to avoid confusion.

        ","tags":["PYI047"]},{"location":"rules/unused-private-type-alias/#example","title":"Example","text":"
        import typing\n\n_UnusedTypeAlias: typing.TypeAlias = int\n

        Use instead:

        import typing\n\n_UsedTypeAlias: typing.TypeAlias = int\n\ndef func(arg: _UsedTypeAlias) -> _UsedTypeAlias: ...\n
        ","tags":["PYI047"]},{"location":"rules/unused-private-type-var/","title":"unused-private-type-var (PYI018)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI018"]},{"location":"rules/unused-private-type-var/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused private TypeVar, ParamSpec or TypeVarTuple declarations.

        ","tags":["PYI018"]},{"location":"rules/unused-private-type-var/#why-is-this-bad","title":"Why is this bad?","text":"

        A private TypeVar that is defined but not used is likely a mistake. It should either be used, made public, or removed to avoid confusion. A type variable is considered \"private\" if its name starts with an underscore.

        ","tags":["PYI018"]},{"location":"rules/unused-private-type-var/#example","title":"Example","text":"
        import typing\nimport typing_extensions\n\n_T = typing.TypeVar(\"_T\")\n_Ts = typing_extensions.TypeVarTuple(\"_Ts\")\n
        ","tags":["PYI018"]},{"location":"rules/unused-private-type-var/#fix-safety","title":"Fix safety","text":"

        The fix is always marked as unsafe, as it would break your code if the type variable is imported by another module.

        ","tags":["PYI018"]},{"location":"rules/unused-private-typed-dict/","title":"unused-private-typed-dict (PYI049)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI049"]},{"location":"rules/unused-private-typed-dict/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused private typing.TypedDict definitions.

        ","tags":["PYI049"]},{"location":"rules/unused-private-typed-dict/#why-is-this-bad","title":"Why is this bad?","text":"

        A private typing.TypedDict that is defined but not used is likely a mistake. It should either be used, made public, or removed to avoid confusion.

        ","tags":["PYI049"]},{"location":"rules/unused-private-typed-dict/#example","title":"Example","text":"
        import typing\n\nclass _UnusedPrivateTypedDict(typing.TypedDict):\n    foo: list[int]\n

        Use instead:

        import typing\n\nclass _UsedPrivateTypedDict(typing.TypedDict):\n    foo: set[str]\n\ndef func(arg: _UsedPrivateTypedDict) -> _UsedPrivateTypedDict: ...\n
        ","tags":["PYI049"]},{"location":"rules/unused-static-method-argument/","title":"unused-static-method-argument (ARG004)","text":"

        Derived from the flake8-unused-arguments linter.

        ","tags":["ARG004"]},{"location":"rules/unused-static-method-argument/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused arguments in static method definitions.

        ","tags":["ARG004"]},{"location":"rules/unused-static-method-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An argument that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["ARG004"]},{"location":"rules/unused-static-method-argument/#example","title":"Example","text":"
        class Class:\n    @staticmethod\n    def foo(arg1, arg2):\n        print(arg1)\n

        Use instead:

        class Class:\n    @staticmethod\n    def foo(arg1):\n        print(arg1)\n
        ","tags":["ARG004"]},{"location":"rules/unused-static-method-argument/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["ARG004"]},{"location":"rules/unused-unpacked-variable/","title":"unused-unpacked-variable (RUF059)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF059"]},{"location":"rules/unused-unpacked-variable/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused variables in unpacked assignments.

        ","tags":["RUF059"]},{"location":"rules/unused-unpacked-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        A variable that is defined but never used can confuse readers.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["RUF059"]},{"location":"rules/unused-unpacked-variable/#example","title":"Example","text":"
        def get_pair():\n    return 1, 2\n\n\ndef foo():\n    x, y = get_pair()\n    return x\n

        Use instead:

        def foo():\n    x, _ = get_pair()\n    return x\n
        ","tags":["RUF059"]},{"location":"rules/unused-unpacked-variable/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["RUF059"]},{"location":"rules/unused-variable/","title":"unused-variable (F841)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F841"]},{"location":"rules/unused-variable/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused variables in function scopes.

        ","tags":["F841"]},{"location":"rules/unused-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        A variable that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["F841"]},{"location":"rules/unused-variable/#example","title":"Example","text":"
        def foo():\n    x = 1\n    y = 2\n    return x\n

        Use instead:

        def foo():\n    x = 1\n    return x\n
        ","tags":["F841"]},{"location":"rules/unused-variable/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because removing an unused variable assignment may delete comments that are attached to the assignment.

        ","tags":["F841"]},{"location":"rules/unused-variable/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["F841"]},{"location":"rules/used-dummy-variable/","title":"used-dummy-variable (RUF052)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#what-it-does","title":"What it does","text":"

        Checks for \"dummy variables\" (variables that are named as if to indicate they are unused) that are in fact used.

        By default, \"dummy variables\" are any variables with names that start with leading underscores. However, this is customisable using the lint.dummy-variable-rgx setting).

        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        Marking a variable with a leading underscore conveys that it is intentionally unused within the function or method. When these variables are later referenced in the code, it causes confusion and potential misunderstandings about the code's intention. If a variable marked as \"unused\" is subsequently used, it suggests that either the variable could be given a clearer name, or that the code is accidentally making use of the wrong variable.

        Sometimes leading underscores are used to avoid variables shadowing other variables, Python builtins, or Python keywords. However, PEP 8 recommends to use trailing underscores for this rather than leading underscores.

        Dunder variables are ignored by this rule, as are variables named _. Only local variables in function scopes are flagged by the rule.

        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#example","title":"Example","text":"
        def function():\n    _variable = 3\n    # important: avoid shadowing the builtin `id()` function!\n    _id = 4\n    return _variable + _id\n

        Use instead:

        def function():\n    variable = 3\n    # important: avoid shadowing the builtin `id()` function!\n    id_ = 4\n    return variable + id_\n
        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#fix-availability","title":"Fix availability","text":"

        The rule's fix is only available for variables that start with leading underscores. It will also only be available if the \"obvious\" new name for the variable would not shadow any other known variables already accessible from the scope in which the variable is defined.

        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe.

        For this rule's fix, Ruff renames the variable and fixes up all known references to it so they point to the renamed variable. However, some renamings also require other changes such as different arguments to constructor calls or alterations to comments. Ruff is aware of some of these cases: _T = TypeVar(\"_T\") will be fixed to T = TypeVar(\"T\") if the _T binding is flagged by this rule. However, in general, cases like these are hard to detect and hard to automatically fix.

        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["RUF052"]},{"location":"rules/useless-comparison/","title":"useless-comparison (B015)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B015"]},{"location":"rules/useless-comparison/#what-it-does","title":"What it does","text":"

        Checks for useless comparisons.

        ","tags":["B015"]},{"location":"rules/useless-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Useless comparisons have no effect on the program, and are often included by mistake. If the comparison is intended to enforce an invariant, prepend the comparison with an assert. Otherwise, remove it entirely.

        ","tags":["B015"]},{"location":"rules/useless-comparison/#example","title":"Example","text":"
        foo == bar\n

        Use instead:

        assert foo == bar, \"`foo` and `bar` should be equal.\"\n
        ","tags":["B015"]},{"location":"rules/useless-comparison/#notebook-behavior","title":"Notebook behavior","text":"

        For Jupyter Notebooks, this rule is not applied to the last top-level expression in a cell. This is because it's common to have a notebook cell that ends with an expression, which will result in the repr of the evaluated expression being printed as the cell's output.

        ","tags":["B015"]},{"location":"rules/useless-comparison/#references","title":"References","text":"
        • Python documentation: assert statement
        ","tags":["B015"]},{"location":"rules/useless-contextlib-suppress/","title":"useless-contextlib-suppress (B022)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B022"]},{"location":"rules/useless-contextlib-suppress/#what-it-does","title":"What it does","text":"

        Checks for contextlib.suppress without arguments.

        ","tags":["B022"]},{"location":"rules/useless-contextlib-suppress/#why-is-this-bad","title":"Why is this bad?","text":"

        contextlib.suppress is a context manager that suppresses exceptions. It takes, as arguments, the exceptions to suppress within the enclosed block. If no exceptions are specified, then the context manager won't suppress any exceptions, and is thus redundant.

        Consider adding exceptions to the contextlib.suppress call, or removing the context manager entirely.

        ","tags":["B022"]},{"location":"rules/useless-contextlib-suppress/#example","title":"Example","text":"
        import contextlib\n\nwith contextlib.suppress():\n    foo()\n

        Use instead:

        import contextlib\n\nwith contextlib.suppress(Exception):\n    foo()\n
        ","tags":["B022"]},{"location":"rules/useless-contextlib-suppress/#references","title":"References","text":"
        • Python documentation: contextlib.suppress
        ","tags":["B022"]},{"location":"rules/useless-else-on-loop/","title":"useless-else-on-loop (PLW0120)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLW0120"]},{"location":"rules/useless-else-on-loop/#what-it-does","title":"What it does","text":"

        Checks for else clauses on loops without a break statement.

        ","tags":["PLW0120"]},{"location":"rules/useless-else-on-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        When a loop includes an else statement, the code inside the else clause will be executed if the loop terminates \"normally\" (i.e., without a break).

        If a loop always terminates \"normally\" (i.e., does not contain a break), then the else clause is redundant, as the code inside the else clause will always be executed.

        In such cases, the code inside the else clause can be moved outside the loop entirely, and the else clause can be removed.

        ","tags":["PLW0120"]},{"location":"rules/useless-else-on-loop/#example","title":"Example","text":"
        for item in items:\n    print(item)\nelse:\n    print(\"All items printed\")\n

        Use instead:

        for item in items:\n    print(item)\nprint(\"All items printed\")\n
        ","tags":["PLW0120"]},{"location":"rules/useless-else-on-loop/#references","title":"References","text":"
        • Python documentation: break and continue Statements, and else Clauses on Loops
        ","tags":["PLW0120"]},{"location":"rules/useless-exception-statement/","title":"useless-exception-statement (PLW0133)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLW0133"]},{"location":"rules/useless-exception-statement/#what-it-does","title":"What it does","text":"

        Checks for an exception that is not raised.

        ","tags":["PLW0133"]},{"location":"rules/useless-exception-statement/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to create an exception without raising it. For example, ValueError(\"...\") on its own will have no effect (unlike raise ValueError(\"...\")) and is likely a mistake.

        ","tags":["PLW0133"]},{"location":"rules/useless-exception-statement/#known-problems","title":"Known problems","text":"

        This rule only detects built-in exceptions, like ValueError, and does not catch user-defined exceptions.

        ","tags":["PLW0133"]},{"location":"rules/useless-exception-statement/#example","title":"Example","text":"
        ValueError(\"...\")\n

        Use instead:

        raise ValueError(\"...\")\n
        ","tags":["PLW0133"]},{"location":"rules/useless-exception-statement/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as converting a useless exception statement to a raise statement will change the program's behavior.

        ","tags":["PLW0133"]},{"location":"rules/useless-expression/","title":"useless-expression (B018)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B018"]},{"location":"rules/useless-expression/#what-it-does","title":"What it does","text":"

        Checks for useless expressions.

        ","tags":["B018"]},{"location":"rules/useless-expression/#why-is-this-bad","title":"Why is this bad?","text":"

        Useless expressions have no effect on the program, and are often included by mistake. Assign a useless expression to a variable, or remove it entirely.

        ","tags":["B018"]},{"location":"rules/useless-expression/#example","title":"Example","text":"
        1 + 1\n

        Use instead:

        foo = 1 + 1\n
        ","tags":["B018"]},{"location":"rules/useless-expression/#notebook-behavior","title":"Notebook behavior","text":"

        For Jupyter Notebooks, this rule is not applied to the last top-level expression in a cell. This is because it's common to have a notebook cell that ends with an expression, which will result in the repr of the evaluated expression being printed as the cell's output.

        ","tags":["B018"]},{"location":"rules/useless-expression/#known-problems","title":"Known problems","text":"

        This rule ignores expression types that are commonly used for their side effects, such as function calls.

        However, if a seemingly useless expression (like an attribute access) is needed to trigger a side effect, consider assigning it to an anonymous variable, to indicate that the return value is intentionally ignored.

        For example, given:

        with errors.ExceptionRaisedContext():\n    obj.attribute\n

        Use instead:

        with errors.ExceptionRaisedContext():\n    _ = obj.attribute\n
        ","tags":["B018"]},{"location":"rules/useless-if-else/","title":"useless-if-else (RUF034)","text":"","tags":["RUF034"]},{"location":"rules/useless-if-else/#what-it-does","title":"What it does","text":"

        Checks for useless if-else conditions with identical arms.

        ","tags":["RUF034"]},{"location":"rules/useless-if-else/#why-is-this-bad","title":"Why is this bad?","text":"

        Useless if-else conditions add unnecessary complexity to the code without providing any logical benefit. Assigning the value directly is clearer.

        ","tags":["RUF034"]},{"location":"rules/useless-if-else/#example","title":"Example","text":"
        foo = x if y else x\n

        Use instead:

        foo = x\n
        ","tags":["RUF034"]},{"location":"rules/useless-import-alias/","title":"useless-import-alias (PLC0414)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLC0414"]},{"location":"rules/useless-import-alias/#what-it-does","title":"What it does","text":"

        Checks for import aliases that do not rename the original package.

        ","tags":["PLC0414"]},{"location":"rules/useless-import-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        The import alias is redundant and should be removed to avoid confusion.

        ","tags":["PLC0414"]},{"location":"rules/useless-import-alias/#fix-safety","title":"Fix safety","text":"

        This fix is marked as always unsafe because the user may be intentionally re-exporting the import. While statements like import numpy as numpy appear redundant, they can have semantic meaning in certain contexts.

        ","tags":["PLC0414"]},{"location":"rules/useless-import-alias/#example","title":"Example","text":"
        import numpy as numpy\n

        Use instead:

        import numpy as np\n

        or

        import numpy\n
        ","tags":["PLC0414"]},{"location":"rules/useless-metaclass-type/","title":"useless-metaclass-type (UP001)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP001"]},{"location":"rules/useless-metaclass-type/#what-it-does","title":"What it does","text":"

        Checks for the use of __metaclass__ = type in class definitions.

        ","tags":["UP001"]},{"location":"rules/useless-metaclass-type/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3, __metaclass__ = type is implied and can thus be omitted.

        ","tags":["UP001"]},{"location":"rules/useless-metaclass-type/#example","title":"Example","text":"
        class Foo:\n    __metaclass__ = type\n

        Use instead:

        class Foo: ...\n
        ","tags":["UP001"]},{"location":"rules/useless-metaclass-type/#references","title":"References","text":"
        • PEP 3115 \u2013 Metaclasses in Python 3000
        ","tags":["UP001"]},{"location":"rules/useless-object-inheritance/","title":"useless-object-inheritance (UP004)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP004"]},{"location":"rules/useless-object-inheritance/#what-it-does","title":"What it does","text":"

        Checks for classes that inherit from object.

        ","tags":["UP004"]},{"location":"rules/useless-object-inheritance/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3, all classes inherit from object by default, so object can be omitted from the list of base classes.

        ","tags":["UP004"]},{"location":"rules/useless-object-inheritance/#example","title":"Example","text":"
        class Foo(object): ...\n

        Use instead:

        class Foo: ...\n
        ","tags":["UP004"]},{"location":"rules/useless-object-inheritance/#references","title":"References","text":"
        • PEP 3115 \u2013 Metaclasses in Python 3000
        ","tags":["UP004"]},{"location":"rules/useless-return/","title":"useless-return (PLR1711)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLR1711"]},{"location":"rules/useless-return/#what-it-does","title":"What it does","text":"

        Checks for functions that end with an unnecessary return or return None, and contain no other return statements.

        ","tags":["PLR1711"]},{"location":"rules/useless-return/#why-is-this-bad","title":"Why is this bad?","text":"

        Python implicitly assumes a None return at the end of a function, making it unnecessary to explicitly write return None.

        ","tags":["PLR1711"]},{"location":"rules/useless-return/#example","title":"Example","text":"
        def f():\n    print(5)\n    return None\n

        Use instead:

        def f():\n    print(5)\n
        ","tags":["PLR1711"]},{"location":"rules/useless-semicolon/","title":"useless-semicolon (E703)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["E703"]},{"location":"rules/useless-semicolon/#what-it-does","title":"What it does","text":"

        Checks for statements that end with an unnecessary semicolon.

        ","tags":["E703"]},{"location":"rules/useless-semicolon/#why-is-this-bad","title":"Why is this bad?","text":"

        A trailing semicolon is unnecessary and should be removed.

        ","tags":["E703"]},{"location":"rules/useless-semicolon/#example","title":"Example","text":"
        do_four();  # useless semicolon\n

        Use instead:

        do_four()\n
        ","tags":["E703"]},{"location":"rules/useless-try-except/","title":"useless-try-except (TRY203)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY203"]},{"location":"rules/useless-try-except/#what-it-does","title":"What it does","text":"

        Checks for immediate uses of raise within exception handlers.

        ","tags":["TRY203"]},{"location":"rules/useless-try-except/#why-is-this-bad","title":"Why is this bad?","text":"

        Capturing an exception, only to immediately reraise it, has no effect. Instead, remove the error-handling code and let the exception propagate upwards without the unnecessary try-except block.

        ","tags":["TRY203"]},{"location":"rules/useless-try-except/#example","title":"Example","text":"
        def foo():\n    try:\n        bar()\n    except NotImplementedError:\n        raise\n

        Use instead:

        def foo():\n    bar()\n
        ","tags":["TRY203"]},{"location":"rules/useless-with-lock/","title":"useless-with-lock (PLW2101)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW2101"]},{"location":"rules/useless-with-lock/#what-it-does","title":"What it does","text":"

        Checks for lock objects that are created and immediately discarded in with statements.

        ","tags":["PLW2101"]},{"location":"rules/useless-with-lock/#why-is-this-bad","title":"Why is this bad?","text":"

        Creating a lock (via threading.Lock or similar) in a with statement has no effect, as locks are only relevant when shared between threads.

        Instead, assign the lock to a variable outside the with statement, and share that variable between threads.

        ","tags":["PLW2101"]},{"location":"rules/useless-with-lock/#example","title":"Example","text":"
        import threading\n\ncounter = 0\n\n\ndef increment():\n    global counter\n\n    with threading.Lock():\n        counter += 1\n

        Use instead:

        import threading\n\ncounter = 0\nlock = threading.Lock()\n\n\ndef increment():\n    global counter\n\n    with lock:\n        counter += 1\n
        ","tags":["PLW2101"]},{"location":"rules/useless-with-lock/#references","title":"References","text":"
        • Python documentation: Lock Objects
        ","tags":["PLW2101"]},{"location":"rules/utf8-encoding-declaration/","title":"utf8-encoding-declaration (UP009)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP009"]},{"location":"rules/utf8-encoding-declaration/#what-it-does","title":"What it does","text":"

        Checks for unnecessary UTF-8 encoding declarations.

        ","tags":["UP009"]},{"location":"rules/utf8-encoding-declaration/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 3120 makes UTF-8 the default encoding, so a UTF-8 encoding declaration is unnecessary.

        ","tags":["UP009"]},{"location":"rules/utf8-encoding-declaration/#example","title":"Example","text":"
        # -*- coding: utf-8 -*-\nprint(\"Hello, world!\")\n

        Use instead:

        print(\"Hello, world!\")\n
        ","tags":["UP009"]},{"location":"rules/verbose-decimal-constructor/","title":"verbose-decimal-constructor (FURB157)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB157"]},{"location":"rules/verbose-decimal-constructor/#what-it-does","title":"What it does","text":"

        Checks for unnecessary string literal or float casts in Decimal constructors.

        ","tags":["FURB157"]},{"location":"rules/verbose-decimal-constructor/#why-is-this-bad","title":"Why is this bad?","text":"

        The Decimal constructor accepts a variety of arguments, including integers, floats, and strings. However, it's not necessary to cast integer literals to strings when passing them to the Decimal.

        Similarly, Decimal accepts inf, -inf, and nan as string literals, so there's no need to wrap those values in a float call when passing them to the Decimal constructor.

        Prefer the more concise form of argument passing for Decimal constructors, as it's more readable and idiomatic.

        ","tags":["FURB157"]},{"location":"rules/verbose-decimal-constructor/#example","title":"Example","text":"
        Decimal(\"0\")\nDecimal(float(\"Infinity\"))\n

        Use instead:

        Decimal(0)\nDecimal(\"Infinity\")\n
        ","tags":["FURB157"]},{"location":"rules/verbose-decimal-constructor/#references","title":"References","text":"
        • Python documentation: decimal
        ","tags":["FURB157"]},{"location":"rules/verbose-log-message/","title":"verbose-log-message (TRY401)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY401"]},{"location":"rules/verbose-log-message/#what-it-does","title":"What it does","text":"

        Checks for excessive logging of exception objects.

        ","tags":["TRY401"]},{"location":"rules/verbose-log-message/#why-is-this-bad","title":"Why is this bad?","text":"

        When logging exceptions via logging.exception, the exception object is logged automatically. Including the exception object in the log message is redundant and can lead to excessive logging.

        ","tags":["TRY401"]},{"location":"rules/verbose-log-message/#example","title":"Example","text":"
        try:\n    ...\nexcept ValueError as e:\n    logger.exception(f\"Found an error: {e}\")\n

        Use instead:

        try:\n    ...\nexcept ValueError:\n    logger.exception(\"Found an error\")\n
        ","tags":["TRY401"]},{"location":"rules/verbose-raise/","title":"verbose-raise (TRY201)","text":"

        Derived from the tryceratops linter.

        Fix is always available.

        ","tags":["TRY201"]},{"location":"rules/verbose-raise/#what-it-does","title":"What it does","text":"

        Checks for needless exception names in raise statements.

        ","tags":["TRY201"]},{"location":"rules/verbose-raise/#why-is-this-bad","title":"Why is this bad?","text":"

        It's redundant to specify the exception name in a raise statement if the exception is being re-raised.

        ","tags":["TRY201"]},{"location":"rules/verbose-raise/#example","title":"Example","text":"
        def foo():\n    try:\n        ...\n    except ValueError as exc:\n        raise exc\n

        Use instead:

        def foo():\n    try:\n        ...\n    except ValueError:\n        raise\n
        ","tags":["TRY201"]},{"location":"rules/verbose-raise/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it doesn't properly handle bound exceptions that are shadowed between the except and raise statements.

        ","tags":["TRY201"]},{"location":"rules/wait-for-process-in-async-function/","title":"wait-for-process-in-async-function (ASYNC222)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC222"]},{"location":"rules/wait-for-process-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not wait on processes with blocking methods.

        ","tags":["ASYNC222"]},{"location":"rules/wait-for-process-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a blocking call will block the entire event loop, preventing it from executing other tasks while waiting for the call to complete, negating the benefits of asynchronous programming.

        Instead of making a blocking call, use an equivalent asynchronous library or function, like trio.to_thread.run_sync() or anyio.to_thread.run_sync().

        ","tags":["ASYNC222"]},{"location":"rules/wait-for-process-in-async-function/#example","title":"Example","text":"
        async def foo():\n    os.waitpid(0)\n

        Use instead:

        def wait_for_process():\n    os.waitpid(0)\n\n\nasync def foo():\n    await asyncio.loop.run_in_executor(None, wait_for_process)\n
        ","tags":["ASYNC222"]},{"location":"rules/weak-cryptographic-key/","title":"weak-cryptographic-key (S505)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S505"]},{"location":"rules/weak-cryptographic-key/#what-it-does","title":"What it does","text":"

        Checks for uses of cryptographic keys with vulnerable key sizes.

        ","tags":["S505"]},{"location":"rules/weak-cryptographic-key/#why-is-this-bad","title":"Why is this bad?","text":"

        Small keys are easily breakable. For DSA and RSA, keys should be at least 2048 bits long. For EC, keys should be at least 224 bits long.

        ","tags":["S505"]},{"location":"rules/weak-cryptographic-key/#example","title":"Example","text":"
        from cryptography.hazmat.primitives.asymmetric import dsa, ec\n\ndsa.generate_private_key(key_size=512)\nec.generate_private_key(curve=ec.SECT163K1())\n

        Use instead:

        from cryptography.hazmat.primitives.asymmetric import dsa, ec\n\ndsa.generate_private_key(key_size=4096)\nec.generate_private_key(curve=ec.SECP384R1())\n
        ","tags":["S505"]},{"location":"rules/weak-cryptographic-key/#references","title":"References","text":"
        • CSRC: Transitioning the Use of Cryptographic Algorithms and Key Lengths
        ","tags":["S505"]},{"location":"rules/whitespace-after-decorator/","title":"whitespace-after-decorator (E204)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E204"]},{"location":"rules/whitespace-after-decorator/#what-it-does","title":"What it does","text":"

        Checks for trailing whitespace after a decorator's opening @.

        ","tags":["E204"]},{"location":"rules/whitespace-after-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        Including whitespace after the @ symbol is not compliant with PEP 8.

        ","tags":["E204"]},{"location":"rules/whitespace-after-decorator/#example","title":"Example","text":"
        @ decorator\ndef func():\n   pass\n

        Use instead:

        @decorator\ndef func():\n  pass\n
        ","tags":["E204"]},{"location":"rules/whitespace-after-open-bracket/","title":"whitespace-after-open-bracket (E201)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E201"]},{"location":"rules/whitespace-after-open-bracket/#what-it-does","title":"What it does","text":"

        Checks for the use of extraneous whitespace after \"(\", \"[\" or \"{\".

        ","tags":["E201"]},{"location":"rules/whitespace-after-open-bracket/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the omission of whitespace in the following cases:

        • \"Immediately inside parentheses, brackets or braces.\"
        • \"Immediately before a comma, semicolon, or colon.\"
        ","tags":["E201"]},{"location":"rules/whitespace-after-open-bracket/#example","title":"Example","text":"
        spam( ham[1], {eggs: 2})\nspam(ham[ 1], {eggs: 2})\nspam(ham[1], { eggs: 2})\n

        Use instead:

        spam(ham[1], {eggs: 2})\n
        ","tags":["E201"]},{"location":"rules/whitespace-before-close-bracket/","title":"whitespace-before-close-bracket (E202)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E202"]},{"location":"rules/whitespace-before-close-bracket/#what-it-does","title":"What it does","text":"

        Checks for the use of extraneous whitespace before \")\", \"]\" or \"}\".

        ","tags":["E202"]},{"location":"rules/whitespace-before-close-bracket/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the omission of whitespace in the following cases:

        • \"Immediately inside parentheses, brackets or braces.\"
        • \"Immediately before a comma, semicolon, or colon.\"
        ","tags":["E202"]},{"location":"rules/whitespace-before-close-bracket/#example","title":"Example","text":"
        spam(ham[1], {eggs: 2} )\nspam(ham[1 ], {eggs: 2})\nspam(ham[1], {eggs: 2 })\n

        Use instead:

        spam(ham[1], {eggs: 2})\n
        ","tags":["E202"]},{"location":"rules/whitespace-before-parameters/","title":"whitespace-before-parameters (E211)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E211"]},{"location":"rules/whitespace-before-parameters/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace immediately preceding an open parenthesis or bracket.

        ","tags":["E211"]},{"location":"rules/whitespace-before-parameters/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, open parentheses and brackets should not be preceded by any trailing whitespace.

        ","tags":["E211"]},{"location":"rules/whitespace-before-parameters/#example","title":"Example","text":"
        spam (1)\n

        Use instead:

        spam(1)\n
        ","tags":["E211"]},{"location":"rules/whitespace-before-punctuation/","title":"whitespace-before-punctuation (E203)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E203"]},{"location":"rules/whitespace-before-punctuation/#what-it-does","title":"What it does","text":"

        Checks for the use of extraneous whitespace before \",\", \";\" or \":\".

        ","tags":["E203"]},{"location":"rules/whitespace-before-punctuation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the omission of whitespace in the following cases:

        • \"Immediately inside parentheses, brackets or braces.\"
        • \"Immediately before a comma, semicolon, or colon.\"
        ","tags":["E203"]},{"location":"rules/whitespace-before-punctuation/#example","title":"Example","text":"
        if x == 4: print(x, y); x, y = y , x\n

        Use instead:

        if x == 4: print(x, y); x, y = y, x\n
        ","tags":["E203"]},{"location":"rules/write-whole-file/","title":"write-whole-file (FURB103)","text":"

        Derived from the refurb linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB103"]},{"location":"rules/write-whole-file/#what-it-does","title":"What it does","text":"

        Checks for uses of open and write that can be replaced by pathlib methods, like Path.write_text and Path.write_bytes.

        ","tags":["FURB103"]},{"location":"rules/write-whole-file/#why-is-this-bad","title":"Why is this bad?","text":"

        When writing a single string to a file, it's simpler and more concise to use pathlib methods like Path.write_text and Path.write_bytes instead of open and write calls via with statements.

        ","tags":["FURB103"]},{"location":"rules/write-whole-file/#example","title":"Example","text":"
        with open(filename, \"w\") as f:\n    f.write(contents)\n

        Use instead:

        from pathlib import Path\n\nPath(filename).write_text(contents)\n
        ","tags":["FURB103"]},{"location":"rules/write-whole-file/#references","title":"References","text":"
        • Python documentation: Path.write_bytes
        • Python documentation: Path.write_text
        ","tags":["FURB103"]},{"location":"rules/wrong-tuple-length-version-comparison/","title":"wrong-tuple-length-version-comparison (PYI005)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI005"]},{"location":"rules/wrong-tuple-length-version-comparison/#what-it-does","title":"What it does","text":"

        Checks for Python version comparisons that compare against a tuple of the wrong length.

        ","tags":["PYI005"]},{"location":"rules/wrong-tuple-length-version-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files support simple conditionals to test for differences in Python versions and platforms. When comparing against sys.version_info, avoid comparing against tuples of the wrong length, which can lead to unexpected behavior.

        ","tags":["PYI005"]},{"location":"rules/wrong-tuple-length-version-comparison/#example","title":"Example","text":"
        import sys\n\nif sys.version_info[:2] == (3,): ...\n

        Use instead:

        import sys\n\nif sys.version_info[0] == 3: ...\n
        ","tags":["PYI005"]},{"location":"rules/wrong-tuple-length-version-comparison/#references","title":"References","text":"
        • Typing documentation: Version and Platform checking
        ","tags":["PYI005"]},{"location":"rules/yield-from-in-async-function/","title":"yield-from-in-async-function (PLE1700)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1700"]},{"location":"rules/yield-from-in-async-function/#what-it-does","title":"What it does","text":"

        Checks for uses of yield from in async functions.

        ","tags":["PLE1700"]},{"location":"rules/yield-from-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Python doesn't support the use of yield from in async functions, and will raise a SyntaxError in such cases.

        Instead, considering refactoring the code to use an async for loop instead.

        ","tags":["PLE1700"]},{"location":"rules/yield-from-in-async-function/#example","title":"Example","text":"
        async def numbers():\n    yield from [1, 2, 3, 4, 5]\n

        Use instead:

        async def numbers():\n    async for number in [1, 2, 3, 4, 5]:\n        yield number\n
        ","tags":["PLE1700"]},{"location":"rules/yield-in-for-loop/","title":"yield-in-for-loop (UP028)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP028"]},{"location":"rules/yield-in-for-loop/#what-it-does","title":"What it does","text":"

        Checks for for loops that can be replaced with yield from expressions.

        ","tags":["UP028"]},{"location":"rules/yield-in-for-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        If a for loop only contains a yield statement, it can be replaced with a yield from expression, which is more concise and idiomatic.

        ","tags":["UP028"]},{"location":"rules/yield-in-for-loop/#example","title":"Example","text":"
        for x in foo:\n    yield x\n\nglobal y\nfor y in foo:\n    yield y\n

        Use instead:

        yield from foo\n\nfor _element in foo:\n    y = _element\n    yield y\n
        ","tags":["UP028"]},{"location":"rules/yield-in-for-loop/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as converting a for loop to a yield from expression can change the behavior of the program in rare cases. For example, if a generator is being sent values via send, then rewriting to a yield from could lead to an attribute error if the underlying generator does not implement the send method.

        Additionally, if at least one target is global or nonlocal, no fix will be offered.

        In most cases, however, the fix is safe, and such a modification should have no effect on the behavior of the program.

        ","tags":["UP028"]},{"location":"rules/yield-in-for-loop/#references","title":"References","text":"
        • Python documentation: The yield statement
        • PEP 380 \u2013 Syntax for Delegating to a Subgenerator
        ","tags":["UP028"]},{"location":"rules/yield-in-init/","title":"yield-in-init (PLE0100)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0100"]},{"location":"rules/yield-in-init/#what-it-does","title":"What it does","text":"

        Checks for __init__ methods that are turned into generators by the inclusion of yield or yield from expressions.

        ","tags":["PLE0100"]},{"location":"rules/yield-in-init/#why-is-this-bad","title":"Why is this bad?","text":"

        The __init__ method is the constructor for a given Python class, responsible for initializing, rather than creating, new objects.

        The __init__ method has to return None. By including a yield or yield from expression in an __init__, the method will return a generator object when called at runtime, resulting in a runtime error.

        ","tags":["PLE0100"]},{"location":"rules/yield-in-init/#example","title":"Example","text":"
        class InitIsGenerator:\n    def __init__(self, i):\n        yield i\n
        ","tags":["PLE0100"]},{"location":"rules/yield-in-init/#references","title":"References","text":"
        • CodeQL: py-init-method-is-generator
        ","tags":["PLE0100"]},{"location":"rules/yield-outside-function/","title":"yield-outside-function (F704)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F704"]},{"location":"rules/yield-outside-function/#what-it-does","title":"What it does","text":"

        Checks for yield, yield from, and await usages outside of functions.

        ","tags":["F704"]},{"location":"rules/yield-outside-function/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of yield, yield from, or await outside of a function will raise a SyntaxError.

        ","tags":["F704"]},{"location":"rules/yield-outside-function/#example","title":"Example","text":"
        class Foo:\n    yield 1\n
        ","tags":["F704"]},{"location":"rules/yield-outside-function/#notebook-behavior","title":"Notebook behavior","text":"

        As an exception, await is allowed at the top level of a Jupyter notebook (see: autoawait).

        ","tags":["F704"]},{"location":"rules/yield-outside-function/#references","title":"References","text":"
        • Python documentation: yield
        ","tags":["F704"]},{"location":"rules/yoda-conditions/","title":"yoda-conditions (SIM300)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM300"]},{"location":"rules/yoda-conditions/#what-it-does","title":"What it does","text":"

        Checks for conditions that position a constant on the left-hand side of the comparison operator, rather than the right-hand side.

        ","tags":["SIM300"]},{"location":"rules/yoda-conditions/#why-is-this-bad","title":"Why is this bad?","text":"

        These conditions (sometimes referred to as \"Yoda conditions\") are less readable than conditions that place the variable on the left-hand side of the comparison operator.

        In some languages, Yoda conditions are used to prevent accidental assignment in conditions (i.e., accidental uses of the = operator, instead of the == operator). However, Python does not allow assignments in conditions unless using the := operator, so Yoda conditions provide no benefit in this regard.

        ","tags":["SIM300"]},{"location":"rules/yoda-conditions/#example","title":"Example","text":"
        if \"Foo\" == foo:\n    ...\n

        Use instead:

        if foo == \"Foo\":\n    ...\n
        ","tags":["SIM300"]},{"location":"rules/yoda-conditions/#references","title":"References","text":"
        • Python documentation: Comparisons
        • Python documentation: Assignment statements
        ","tags":["SIM300"]},{"location":"rules/zip-dict-keys-and-values/","title":"zip-dict-keys-and-values (SIM911)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM911"]},{"location":"rules/zip-dict-keys-and-values/#what-it-does","title":"What it does","text":"

        Checks for use of zip() to iterate over keys and values of a dictionary at once.

        ","tags":["SIM911"]},{"location":"rules/zip-dict-keys-and-values/#why-is-this-bad","title":"Why is this bad?","text":"

        The dict type provides an .items() method which is faster and more readable.

        ","tags":["SIM911"]},{"location":"rules/zip-dict-keys-and-values/#example","title":"Example","text":"
        flag_stars = {\"USA\": 50, \"Slovenia\": 3, \"Panama\": 2, \"Australia\": 6}\n\nfor country, stars in zip(flag_stars.keys(), flag_stars.values()):\n    print(f\"{country}'s flag has {stars} stars.\")\n

        Use instead:

        flag_stars = {\"USA\": 50, \"Slovenia\": 3, \"Panama\": 2, \"Australia\": 6}\n\nfor country, stars in flag_stars.items():\n    print(f\"{country}'s flag has {stars} stars.\")\n
        ","tags":["SIM911"]},{"location":"rules/zip-dict-keys-and-values/#references","title":"References","text":"
        • Python documentation: dict.items
        ","tags":["SIM911"]},{"location":"rules/zip-instead-of-pairwise/","title":"zip-instead-of-pairwise (RUF007)","text":"

        Fix is sometimes available.

        ","tags":["RUF007"]},{"location":"rules/zip-instead-of-pairwise/#what-it-does","title":"What it does","text":"

        Checks for use of zip() to iterate over successive pairs of elements.

        ","tags":["RUF007"]},{"location":"rules/zip-instead-of-pairwise/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over successive pairs of elements, prefer itertools.pairwise() over zip().

        itertools.pairwise() is more readable and conveys the intent of the code more clearly.

        ","tags":["RUF007"]},{"location":"rules/zip-instead-of-pairwise/#example","title":"Example","text":"
        letters = \"ABCD\"\nzip(letters, letters[1:])  # (\"A\", \"B\"), (\"B\", \"C\"), (\"C\", \"D\")\n

        Use instead:

        from itertools import pairwise\n\nletters = \"ABCD\"\npairwise(letters)  # (\"A\", \"B\"), (\"B\", \"C\"), (\"C\", \"D\")\n
        ","tags":["RUF007"]},{"location":"rules/zip-instead-of-pairwise/#fix-safety","title":"Fix safety","text":"

        The fix is always marked unsafe because it assumes that slicing an object (e.g., obj[1:]) produces a value with the same type and iteration behavior as the original object, which is not guaranteed for user-defined types that override __getitem__ without properly handling slices. Moreover, the fix could delete comments.

        ","tags":["RUF007"]},{"location":"rules/zip-instead-of-pairwise/#references","title":"References","text":"
        • Python documentation: itertools.pairwise
        ","tags":["RUF007"]},{"location":"rules/zip-without-explicit-strict/","title":"zip-without-explicit-strict (B905)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B905"]},{"location":"rules/zip-without-explicit-strict/#what-it-does","title":"What it does","text":"

        Checks for zip calls without an explicit strict parameter.

        ","tags":["B905"]},{"location":"rules/zip-without-explicit-strict/#why-is-this-bad","title":"Why is this bad?","text":"

        By default, if the iterables passed to zip are of different lengths, the resulting iterator will be silently truncated to the length of the shortest iterable. This can lead to subtle bugs.

        Pass strict=True to raise a ValueError if the iterables are of non-uniform length. Alternatively, if the iterables are deliberately of different lengths, pass strict=False to make the intention explicit.

        ","tags":["B905"]},{"location":"rules/zip-without-explicit-strict/#example","title":"Example","text":"
        zip(a, b)\n

        Use instead:

        zip(a, b, strict=True)\n
        ","tags":["B905"]},{"location":"rules/zip-without-explicit-strict/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for zip calls that contain **kwargs, as adding a strict keyword argument to such a call may lead to a duplicate keyword argument error.

        ","tags":["B905"]},{"location":"rules/zip-without-explicit-strict/#references","title":"References","text":"
        • Python documentation: zip
        ","tags":["B905"]}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"","title":"Ruff","text":"

        Docs | Playground

        An extremely fast Python linter and code formatter, written in Rust.

        Linting the CPython codebase from scratch.

        • \u26a1\ufe0f 10-100x faster than existing linters (like Flake8) and formatters (like Black)
        • \ud83d\udc0d Installable via pip
        • \ud83d\udee0\ufe0f pyproject.toml support
        • \ud83e\udd1d Python 3.13 compatibility
        • \u2696\ufe0f Drop-in parity with Flake8, isort, and Black
        • \ud83d\udce6 Built-in caching, to avoid re-analyzing unchanged files
        • \ud83d\udd27 Fix support, for automatic error correction (e.g., automatically remove unused imports)
        • \ud83d\udccf Over 800 built-in rules, with native re-implementations of popular Flake8 plugins, like flake8-bugbear
        • \u2328\ufe0f First-party editor integrations for VS Code and more
        • \ud83c\udf0e Monorepo-friendly, with hierarchical and cascading configuration

        Ruff aims to be orders of magnitude faster than alternative tools while integrating more functionality behind a single, common interface.

        Ruff can be used to replace Flake8 (plus dozens of plugins), Black, isort, pydocstyle, pyupgrade, autoflake, and more, all while executing tens or hundreds of times faster than any individual tool.

        Ruff is extremely actively developed and used in major open-source projects like:

        • Apache Airflow
        • Apache Superset
        • FastAPI
        • Hugging Face
        • Pandas
        • SciPy

        ...and many more.

        Ruff is backed by Astral. Read the launch post, or the original project announcement.

        "},{"location":"#testimonials","title":"Testimonials","text":"

        Sebasti\u00e1n Ram\u00edrez, creator of FastAPI:

        Ruff is so fast that sometimes I add an intentional bug in the code just to confirm it's actually running and checking the code.

        Nick Schrock, founder of Elementl, co-creator of GraphQL:

        Why is Ruff a gamechanger? Primarily because it is nearly 1000x faster. Literally. Not a typo. On our largest module (dagster itself, 250k LOC) pylint takes about 2.5 minutes, parallelized across 4 cores on my M1. Running ruff against our entire codebase takes .4 seconds.

        Bryan Van de Ven, co-creator of Bokeh, original author of Conda:

        Ruff is ~150-200x faster than flake8 on my machine, scanning the whole repo takes ~0.2s instead of ~20s. This is an enormous quality of life improvement for local dev. It's fast enough that I added it as an actual commit hook, which is terrific.

        Timothy Crosley, creator of isort:

        Just switched my first project to Ruff. Only one downside so far: it's so fast I couldn't believe it was working till I intentionally introduced some errors.

        Tim Abbott, lead developer of Zulip:

        This is just ridiculously fast... ruff is amazing.

        "},{"location":"configuration/","title":"Configuring Ruff","text":"

        Ruff can be configured through a pyproject.toml, ruff.toml, or .ruff.toml file.

        Whether you're using Ruff as a linter, formatter, or both, the underlying configuration strategy and semantics are the same.

        For a complete enumeration of the available configuration options, see Settings.

        If left unspecified, Ruff's default configuration is equivalent to:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Exclude a variety of commonly ignored directories.\nexclude = [\n    \".bzr\",\n    \".direnv\",\n    \".eggs\",\n    \".git\",\n    \".git-rewrite\",\n    \".hg\",\n    \".ipynb_checkpoints\",\n    \".mypy_cache\",\n    \".nox\",\n    \".pants.d\",\n    \".pyenv\",\n    \".pytest_cache\",\n    \".pytype\",\n    \".ruff_cache\",\n    \".svn\",\n    \".tox\",\n    \".venv\",\n    \".vscode\",\n    \"__pypackages__\",\n    \"_build\",\n    \"buck-out\",\n    \"build\",\n    \"dist\",\n    \"node_modules\",\n    \"site-packages\",\n    \"venv\",\n]\n\n# Same as Black.\nline-length = 88\nindent-width = 4\n\n# Assume Python 3.9\ntarget-version = \"py39\"\n\n[tool.ruff.lint]\n# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.\n# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or\n# McCabe complexity (`C901`) by default.\nselect = [\"E4\", \"E7\", \"E9\", \"F\"]\nignore = []\n\n# Allow fix for all enabled rules (when `--fix`) is provided.\nfixable = [\"ALL\"]\nunfixable = []\n\n# Allow unused variables when underscore-prefixed.\ndummy-variable-rgx = \"^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$\"\n\n[tool.ruff.format]\n# Like Black, use double quotes for strings.\nquote-style = \"double\"\n\n# Like Black, indent with spaces, rather than tabs.\nindent-style = \"space\"\n\n# Like Black, respect magic trailing commas.\nskip-magic-trailing-comma = false\n\n# Like Black, automatically detect the appropriate line ending.\nline-ending = \"auto\"\n\n# Enable auto-formatting of code examples in docstrings. Markdown,\n# reStructuredText code/literal blocks and doctests are all supported.\n#\n# This is currently disabled by default, but it is planned for this\n# to be opt-out in the future.\ndocstring-code-format = false\n\n# Set the line length limit used when formatting code snippets in\n# docstrings.\n#\n# This only has an effect when the `docstring-code-format` setting is\n# enabled.\ndocstring-code-line-length = \"dynamic\"\n
        # Exclude a variety of commonly ignored directories.\nexclude = [\n    \".bzr\",\n    \".direnv\",\n    \".eggs\",\n    \".git\",\n    \".git-rewrite\",\n    \".hg\",\n    \".ipynb_checkpoints\",\n    \".mypy_cache\",\n    \".nox\",\n    \".pants.d\",\n    \".pyenv\",\n    \".pytest_cache\",\n    \".pytype\",\n    \".ruff_cache\",\n    \".svn\",\n    \".tox\",\n    \".venv\",\n    \".vscode\",\n    \"__pypackages__\",\n    \"_build\",\n    \"buck-out\",\n    \"build\",\n    \"dist\",\n    \"node_modules\",\n    \"site-packages\",\n    \"venv\",\n]\n\n# Same as Black.\nline-length = 88\nindent-width = 4\n\n# Assume Python 3.9\ntarget-version = \"py39\"\n\n[lint]\n# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.\n# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or\n# McCabe complexity (`C901`) by default.\nselect = [\"E4\", \"E7\", \"E9\", \"F\"]\nignore = []\n\n# Allow fix for all enabled rules (when `--fix`) is provided.\nfixable = [\"ALL\"]\nunfixable = []\n\n# Allow unused variables when underscore-prefixed.\ndummy-variable-rgx = \"^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$\"\n\n[format]\n# Like Black, use double quotes for strings.\nquote-style = \"double\"\n\n# Like Black, indent with spaces, rather than tabs.\nindent-style = \"space\"\n\n# Like Black, respect magic trailing commas.\nskip-magic-trailing-comma = false\n\n# Like Black, automatically detect the appropriate line ending.\nline-ending = \"auto\"\n\n# Enable auto-formatting of code examples in docstrings. Markdown,\n# reStructuredText code/literal blocks and doctests are all supported.\n#\n# This is currently disabled by default, but it is planned for this\n# to be opt-out in the future.\ndocstring-code-format = false\n\n# Set the line length limit used when formatting code snippets in\n# docstrings.\n#\n# This only has an effect when the `docstring-code-format` setting is\n# enabled.\ndocstring-code-line-length = \"dynamic\"\n

        As an example, the following would configure Ruff to:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# 1. Enable flake8-bugbear (`B`) rules, in addition to the defaults.\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"B\"]\n\n# 2. Avoid enforcing line-length violations (`E501`)\nignore = [\"E501\"]\n\n# 3. Avoid trying to fix flake8-bugbear (`B`) violations.\nunfixable = [\"B\"]\n\n# 4. Ignore `E402` (import violations) in all `__init__.py` files, and in selected subdirectories.\n[tool.ruff.lint.per-file-ignores]\n\"__init__.py\" = [\"E402\"]\n\"**/{tests,docs,tools}/*\" = [\"E402\"]\n\n[tool.ruff.format]\n# 5. Use single quotes in `ruff format`.\nquote-style = \"single\"\n
        [lint]\n# 1. Enable flake8-bugbear (`B`) rules, in addition to the defaults.\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"B\"]\n\n# 2. Avoid enforcing line-length violations (`E501`)\nignore = [\"E501\"]\n\n# 3. Avoid trying to fix flake8-bugbear (`B`) violations.\nunfixable = [\"B\"]\n\n# 4. Ignore `E402` (import violations) in all `__init__.py` files, and in selected subdirectories.\n[lint.per-file-ignores]\n\"__init__.py\" = [\"E402\"]\n\"**/{tests,docs,tools}/*\" = [\"E402\"]\n\n[format]\n# 5. Use single quotes in `ruff format`.\nquote-style = \"single\"\n

        Linter plugin configurations are expressed as subsections, e.g.:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Add \"Q\" to the list of enabled codes.\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"Q\"]\n\n[tool.ruff.lint.flake8-quotes]\ndocstring-quotes = \"double\"\n
        [lint]\n# Add \"Q\" to the list of enabled codes.\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"Q\"]\n\n[lint.flake8-quotes]\ndocstring-quotes = \"double\"\n

        Ruff respects pyproject.toml, ruff.toml, and .ruff.toml files. All three implement an equivalent schema (though in the ruff.toml and .ruff.toml versions, the [tool.ruff] header and tool.ruff section prefix is omitted).

        For a complete enumeration of the available configuration options, see Settings.

        "},{"location":"configuration/#config-file-discovery","title":"Config file discovery","text":"

        Similar to ESLint, Ruff supports hierarchical configuration, such that the \"closest\" config file in the directory hierarchy is used for every individual file, with all paths in the config file (e.g., exclude globs, src paths) being resolved relative to the directory containing that config file.

        There are a few exceptions to these rules:

        1. In locating the \"closest\" pyproject.toml file for a given path, Ruff ignores any pyproject.toml files that lack a [tool.ruff] section.
        2. If a configuration file is passed directly via --config, those settings are used for all analyzed files, and any relative paths in that configuration file (like exclude globs or src paths) are resolved relative to the current working directory.
        3. If no config file is found in the filesystem hierarchy, Ruff will fall back to using a default configuration. If a user-specific configuration file exists at ${config_dir}/ruff/pyproject.toml, that file will be used instead of the default configuration, with ${config_dir} being determined via etcetera's native strategy, and all relative paths being again resolved relative to the current working directory.
        4. Any config-file-supported settings that are provided on the command-line (e.g., via --select) will override the settings in every resolved configuration file.

        Unlike ESLint, Ruff does not merge settings across configuration files; instead, the \"closest\" configuration file is used, and any parent configuration files are ignored. In lieu of this implicit cascade, Ruff supports an extend field, which allows you to inherit the settings from another config file, like so:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Extend the `pyproject.toml` file in the parent directory...\nextend = \"../pyproject.toml\"\n\n# ...but use a different line length.\nline-length = 100\n
        # Extend the `ruff.toml` file in the parent directory...\nextend = \"../ruff.toml\"\n\n# ...but use a different line length.\nline-length = 100\n

        All of the above rules apply equivalently to pyproject.toml, ruff.toml, and .ruff.toml files. If Ruff detects multiple configuration files in the same directory, the .ruff.toml file will take precedence over the ruff.toml file, and the ruff.toml file will take precedence over the pyproject.toml file.

        "},{"location":"configuration/#inferring-the-python-version","title":"Inferring the Python version","text":"

        When no discovered configuration specifies a target-version, Ruff will attempt to fall back to the minimum version compatible with the requires-python field in a nearby pyproject.toml. The rules for this behavior are as follows:

        1. If a configuration file is passed directly, Ruff does not attempt to infer a missing target-version.
        2. If a configuration file is found in the filesystem hierarchy, Ruff will infer a missing target-version from the requires-python field in a pyproject.toml file in the same directory as the found configuration.
        3. If we are using a user-level configuration from ${config_dir}/ruff/pyproject.toml, the requires-python field in the first pyproject.toml file found in an ancestor of the current working directory takes precedence over the target-version in the user-level configuration.
        4. If no configuration files are found, Ruff will infer the target-version from the requires-python field in the first pyproject.toml file found in an ancestor of the current working directory.

        Note that in these last two cases, the behavior of Ruff may differ depending on the working directory from which it is invoked.

        "},{"location":"configuration/#python-file-discovery","title":"Python file discovery","text":"

        When passed a path on the command-line, Ruff will automatically discover all Python files in that path, taking into account the exclude and extend-exclude settings in each directory's configuration file.

        Files can also be selectively excluded from linting or formatting by scoping the exclude setting to the tool-specific configuration tables. For example, the following would prevent ruff from formatting .pyi files, but would continue to include them in linting:

        pyproject.tomlruff.toml
        [tool.ruff.format]\nexclude = [\"*.pyi\"]\n
        [format]\nexclude = [\"*.pyi\"]\n

        By default, Ruff will also skip any files that are omitted via .ignore, .gitignore, .git/info/exclude, and global gitignore files (see: respect-gitignore).

        Files that are passed to ruff directly are always analyzed, regardless of the above criteria. For example, ruff check /path/to/excluded/file.py will always lint file.py.

        "},{"location":"configuration/#default-inclusions","title":"Default inclusions","text":"

        By default, Ruff will discover files matching *.py, *.pyi, *.ipynb, or pyproject.toml.

        To lint or format files with additional file extensions, use the extend-include setting. You can also change the default selection using the include setting.

        pyproject.tomlruff.toml
        [tool.ruff]\ninclude = [\"pyproject.toml\", \"src/**/*.py\", \"scripts/**/*.py\"]\n
        include = [\"pyproject.toml\", \"src/**/*.py\", \"scripts/**/*.py\"]\n

        Warning

        Paths provided to include must match files. For example, include = [\"src\"] will fail since it matches a directory.

        "},{"location":"configuration/#jupyter-notebook-discovery","title":"Jupyter Notebook discovery","text":"

        Ruff has built-in support for linting and formatting Jupyter Notebooks, which are linted and formatted by default on version 0.6.0 and higher.

        If you'd prefer to either only lint or only format Jupyter Notebook files, you can use the section-specific exclude option to do so. For example, the following would only lint Jupyter Notebook files and not format them:

        pyproject.tomlruff.toml
        [tool.ruff.format]\nexclude = [\"*.ipynb\"]\n
        [format]\nexclude = [\"*.ipynb\"]\n

        And, conversely, the following would only format Jupyter Notebook files and not lint them:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nexclude = [\"*.ipynb\"]\n
        [lint]\nexclude = [\"*.ipynb\"]\n

        You can completely disable Jupyter Notebook support by updating the extend-exclude setting:

        pyproject.tomlruff.toml
        [tool.ruff]\nextend-exclude = [\"*.ipynb\"]\n
        extend-exclude = [\"*.ipynb\"]\n

        If you'd like to ignore certain rules specifically for Jupyter Notebook files, you can do so by using the per-file-ignores setting:

        pyproject.tomlruff.toml
        [tool.ruff.lint.per-file-ignores]\n\"*.ipynb\" = [\"T20\"]\n
        [lint.per-file-ignores]\n\"*.ipynb\" = [\"T20\"]\n

        Some rules have different behavior when applied to Jupyter Notebook files. For example, when applied to .py files the module-import-not-at-top-of-file (E402) rule detect imports at the top of a file, but for notebooks it detects imports at the top of a cell. For a given rule, the rule's documentation will always specify if it has different behavior when applied to Jupyter Notebook files.

        "},{"location":"configuration/#command-line-interface","title":"Command-line interface","text":"

        Some configuration options can be provided or overridden via dedicated flags on the command line. This includes those related to rule enablement and disablement, file discovery, logging level, and more:

        $ ruff check path/to/code/ --select F401 --select F403 --quiet\n

        All other configuration options can be set via the command line using the --config flag, detailed below.

        "},{"location":"configuration/#the-config-cli-flag","title":"The --config CLI flag","text":"

        The --config flag has two uses. It is most often used to point to the configuration file that you would like Ruff to use, for example:

        $ ruff check path/to/directory --config path/to/ruff.toml\n

        However, the --config flag can also be used to provide arbitrary overrides of configuration settings using TOML <KEY> = <VALUE> pairs. This is mostly useful in situations where you wish to override a configuration setting that does not have a dedicated command-line flag.

        In the below example, the --config flag is the only way of overriding the dummy-variable-rgx configuration setting from the command line, since this setting has no dedicated CLI flag. The per-file-ignores setting could also have been overridden via the --per-file-ignores dedicated flag, but using --config to override the setting is also fine:

        $ ruff check path/to/file --config path/to/ruff.toml --config \"lint.dummy-variable-rgx = '__.*'\" --config \"lint.per-file-ignores = {'some_file.py' = ['F841']}\"\n

        Configuration options passed to --config are parsed in the same way as configuration options in a ruff.toml file. As such, options specific to the Ruff linter need to be prefixed with lint. (--config \"lint.dummy-variable-rgx = '__.*'\" rather than simply --config \"dummy-variable-rgx = '__.*'\"), and options specific to the Ruff formatter need to be prefixed with format..

        If a specific configuration option is simultaneously overridden by a dedicated flag and by the --config flag, the dedicated flag takes priority. In this example, the maximum permitted line length will be set to 90, not 100:

        $ ruff format path/to/file --line-length=90 --config \"line-length=100\"\n

        Specifying --config \"line-length=90\" will override the line-length setting from all configuration files detected by Ruff, including configuration files discovered in subdirectories. In this respect, specifying --config \"line-length=90\" has the same effect as specifying --line-length=90, which will similarly override the line-length setting from all configuration files detected by Ruff, regardless of where a specific configuration file is located.

        "},{"location":"configuration/#full-command-line-interface","title":"Full command-line interface","text":"

        See ruff help for the full list of Ruff's top-level commands:

        Ruff: An extremely fast Python linter and code formatter.\n\nUsage: ruff [OPTIONS] <COMMAND>\n\nCommands:\n  check    Run Ruff on the given files or directories\n  rule     Explain a rule (or all rules)\n  config   List or describe the available configuration options\n  linter   List all supported upstream linters\n  clean    Clear any caches in the current directory and any subdirectories\n  format   Run the Ruff formatter on the given files or directories\n  server   Run the language server\n  analyze  Run analysis over Python source code\n  version  Display Ruff's version\n  help     Print this message or the help of the given subcommand(s)\n\nOptions:\n  -h, --help     Print help\n  -V, --version  Print version\n\nLog levels:\n  -v, --verbose  Enable verbose logging\n  -q, --quiet    Print diagnostics, but nothing else\n  -s, --silent   Disable all logging (but still exit with status code \"1\" upon\n                 detecting diagnostics)\n\nGlobal options:\n      --config <CONFIG_OPTION>\n          Either a path to a TOML configuration file (`pyproject.toml` or\n          `ruff.toml`), or a TOML `<KEY> = <VALUE>` pair (such as you might\n          find in a `ruff.toml` configuration file) overriding a specific\n          configuration option. Overrides of individual settings using this\n          option always take precedence over all configuration files, including\n          configuration files that were also specified using `--config`\n      --isolated\n          Ignore all configuration files\n\nFor help with a specific command, see: `ruff help <command>`.\n

        Or ruff help check for more on the linting command:

        Run Ruff on the given files or directories\n\nUsage: ruff check [OPTIONS] [FILES]...\n\nArguments:\n  [FILES]...  List of files or directories to check [default: .]\n\nOptions:\n      --fix\n          Apply fixes to resolve lint violations. Use `--no-fix` to disable or\n          `--unsafe-fixes` to include unsafe fixes\n      --unsafe-fixes\n          Include fixes that may not retain the original intent of the code.\n          Use `--no-unsafe-fixes` to disable\n      --show-fixes\n          Show an enumeration of all fixed lint violations. Use\n          `--no-show-fixes` to disable\n      --diff\n          Avoid writing any fixed files back; instead, output a diff for each\n          changed file to stdout, and exit 0 if there are no diffs. Implies\n          `--fix-only`\n  -w, --watch\n          Run in watch mode by re-running whenever files change\n      --fix-only\n          Apply fixes to resolve lint violations, but don't report on, or exit\n          non-zero for, leftover violations. Implies `--fix`. Use\n          `--no-fix-only` to disable or `--unsafe-fixes` to include unsafe\n          fixes\n      --ignore-noqa\n          Ignore any `# noqa` comments\n      --output-format <OUTPUT_FORMAT>\n          Output serialization format for violations. The default serialization\n          format is \"full\" [env: RUFF_OUTPUT_FORMAT=] [possible values:\n          concise, full, json, json-lines, junit, grouped, github, gitlab,\n          pylint, rdjson, azure, sarif]\n  -o, --output-file <OUTPUT_FILE>\n          Specify file to write the linter output to (default: stdout) [env:\n          RUFF_OUTPUT_FILE=]\n      --target-version <TARGET_VERSION>\n          The minimum Python version that should be supported [possible values:\n          py37, py38, py39, py310, py311, py312, py313, py314]\n      --preview\n          Enable preview mode; checks will include unstable rules and fixes.\n          Use `--no-preview` to disable\n      --extension <EXTENSION>\n          List of mappings from file extension to language (one of `python`,\n          `ipynb`, `pyi`). For example, to treat `.ipy` files as IPython\n          notebooks, use `--extension ipy:ipynb`\n      --statistics\n          Show counts for every rule with at least one violation\n      --add-noqa\n          Enable automatic additions of `noqa` directives to failing lines\n      --show-files\n          See the files Ruff will be run against with the current settings\n      --show-settings\n          See the settings Ruff will use to lint a given Python file\n  -h, --help\n          Print help\n\nRule selection:\n      --select <RULE_CODE>\n          Comma-separated list of rule codes to enable (or ALL, to enable all\n          rules)\n      --ignore <RULE_CODE>\n          Comma-separated list of rule codes to disable\n      --extend-select <RULE_CODE>\n          Like --select, but adds additional rule codes on top of those already\n          specified\n      --per-file-ignores <PER_FILE_IGNORES>\n          List of mappings from file pattern to code to exclude\n      --extend-per-file-ignores <EXTEND_PER_FILE_IGNORES>\n          Like `--per-file-ignores`, but adds additional ignores on top of\n          those already specified\n      --fixable <RULE_CODE>\n          List of rule codes to treat as eligible for fix. Only applicable when\n          fix itself is enabled (e.g., via `--fix`)\n      --unfixable <RULE_CODE>\n          List of rule codes to treat as ineligible for fix. Only applicable\n          when fix itself is enabled (e.g., via `--fix`)\n      --extend-fixable <RULE_CODE>\n          Like --fixable, but adds additional rule codes on top of those\n          already specified\n\nFile selection:\n      --exclude <FILE_PATTERN>\n          List of paths, used to omit files and/or directories from analysis\n      --extend-exclude <FILE_PATTERN>\n          Like --exclude, but adds additional files and directories on top of\n          those already excluded\n      --respect-gitignore\n          Respect file exclusions via `.gitignore` and other standard ignore\n          files. Use `--no-respect-gitignore` to disable\n      --force-exclude\n          Enforce exclusions, even for paths passed to Ruff directly on the\n          command-line. Use `--no-force-exclude` to disable\n\nMiscellaneous:\n  -n, --no-cache\n          Disable cache reads [env: RUFF_NO_CACHE=]\n      --cache-dir <CACHE_DIR>\n          Path to the cache directory [env: RUFF_CACHE_DIR=]\n      --stdin-filename <STDIN_FILENAME>\n          The name of the file when passing it through stdin\n  -e, --exit-zero\n          Exit with status code \"0\", even upon detecting lint violations\n      --exit-non-zero-on-fix\n          Exit with a non-zero status code if any files were modified via fix,\n          even if no lint violations remain\n\nLog levels:\n  -v, --verbose  Enable verbose logging\n  -q, --quiet    Print diagnostics, but nothing else\n  -s, --silent   Disable all logging (but still exit with status code \"1\" upon\n                 detecting diagnostics)\n\nGlobal options:\n      --config <CONFIG_OPTION>\n          Either a path to a TOML configuration file (`pyproject.toml` or\n          `ruff.toml`), or a TOML `<KEY> = <VALUE>` pair (such as you might\n          find in a `ruff.toml` configuration file) overriding a specific\n          configuration option. Overrides of individual settings using this\n          option always take precedence over all configuration files, including\n          configuration files that were also specified using `--config`\n      --isolated\n          Ignore all configuration files\n

        Or ruff help format for more on the formatting command:

        Run the Ruff formatter on the given files or directories\n\nUsage: ruff format [OPTIONS] [FILES]...\n\nArguments:\n  [FILES]...  List of files or directories to format [default: .]\n\nOptions:\n      --check\n          Avoid writing any formatted files back; instead, exit with a non-zero\n          status code if any files would have been modified, and zero otherwise\n      --diff\n          Avoid writing any formatted files back; instead, exit with a non-zero\n          status code and the difference between the current file and how the\n          formatted file would look like\n      --extension <EXTENSION>\n          List of mappings from file extension to language (one of `python`,\n          `ipynb`, `pyi`). For example, to treat `.ipy` files as IPython\n          notebooks, use `--extension ipy:ipynb`\n      --target-version <TARGET_VERSION>\n          The minimum Python version that should be supported [possible values:\n          py37, py38, py39, py310, py311, py312, py313, py314]\n      --preview\n          Enable preview mode; enables unstable formatting. Use `--no-preview`\n          to disable\n  -h, --help\n          Print help (see more with '--help')\n\nMiscellaneous:\n  -n, --no-cache\n          Disable cache reads [env: RUFF_NO_CACHE=]\n      --cache-dir <CACHE_DIR>\n          Path to the cache directory [env: RUFF_CACHE_DIR=]\n      --stdin-filename <STDIN_FILENAME>\n          The name of the file when passing it through stdin\n      --exit-non-zero-on-format\n          Exit with a non-zero status code if any files were modified via\n          format, even if all files were formatted successfully\n\nFile selection:\n      --respect-gitignore\n          Respect file exclusions via `.gitignore` and other standard ignore\n          files. Use `--no-respect-gitignore` to disable\n      --exclude <FILE_PATTERN>\n          List of paths, used to omit files and/or directories from analysis\n      --force-exclude\n          Enforce exclusions, even for paths passed to Ruff directly on the\n          command-line. Use `--no-force-exclude` to disable\n\nFormat configuration:\n      --line-length <LINE_LENGTH>  Set the line-length\n\nEditor options:\n      --range <RANGE>  When specified, Ruff will try to only format the code in\n                       the given range.\n                       It might be necessary to extend the start backwards or\n                       the end forwards, to fully enclose a logical line.\n                       The `<RANGE>` uses the format\n                       `<start_line>:<start_column>-<end_line>:<end_column>`.\n\nLog levels:\n  -v, --verbose  Enable verbose logging\n  -q, --quiet    Print diagnostics, but nothing else\n  -s, --silent   Disable all logging (but still exit with status code \"1\" upon\n                 detecting diagnostics)\n\nGlobal options:\n      --config <CONFIG_OPTION>\n          Either a path to a TOML configuration file (`pyproject.toml` or\n          `ruff.toml`), or a TOML `<KEY> = <VALUE>` pair (such as you might\n          find in a `ruff.toml` configuration file) overriding a specific\n          configuration option. Overrides of individual settings using this\n          option always take precedence over all configuration files, including\n          configuration files that were also specified using `--config`\n      --isolated\n          Ignore all configuration files\n
        "},{"location":"configuration/#shell-autocompletion","title":"Shell autocompletion","text":"

        Ruff supports autocompletion for most shells. A shell-specific completion script can be generated by ruff generate-shell-completion <SHELL>, where <SHELL> is one of bash, elvish, fig, fish, powershell, or zsh.

        The exact steps required to enable autocompletion will vary by shell. For example instructions, see the Poetry or ripgrep documentation.

        As an example: to enable autocompletion for Zsh, run ruff generate-shell-completion zsh > ~/.zfunc/_ruff. Then add the following line to your ~/.zshrc file, if they're not already present:

        fpath+=~/.zfunc\nautoload -Uz compinit && compinit\n
        "},{"location":"contributing/","title":"Contributing to Ruff","text":"

        Welcome! We're happy to have you here. Thank you in advance for your contribution to Ruff.

        Note

        This guide is for Ruff. If you're looking to contribute to ty, please see the ty contributing guide.

        "},{"location":"contributing/#the-basics","title":"The Basics","text":"

        Ruff welcomes contributions in the form of pull requests.

        For small changes (e.g., bug fixes), feel free to submit a PR.

        For larger changes (e.g., new lint rules, new functionality, new configuration options), consider creating an issue outlining your proposed change. You can also join us on Discord to discuss your idea with the community. We've labeled beginner-friendly tasks in the issue tracker, along with bugs and improvements that are ready for contributions.

        If you have suggestions on how we might improve the contributing documentation, let us know!

        "},{"location":"contributing/#prerequisites","title":"Prerequisites","text":"

        Ruff is written in Rust. You'll need to install the Rust toolchain for development.

        You'll also need Insta to update snapshot tests:

        cargo install cargo-insta\n

        You'll need uv (or pipx and pip) to run Python utility commands.

        You can optionally install pre-commit hooks to automatically run the validation checks when making a commit:

        uv tool install pre-commit\npre-commit install\n

        We recommend nextest to run Ruff's test suite (via cargo nextest run), though it's not strictly necessary:

        cargo install cargo-nextest --locked\n

        Throughout this guide, any usages of cargo test can be replaced with cargo nextest run, if you choose to install nextest.

        "},{"location":"contributing/#development","title":"Development","text":"

        After cloning the repository, run Ruff locally from the repository root with:

        cargo run -p ruff -- check /path/to/file.py --no-cache\n

        Prior to opening a pull request, ensure that your code has been auto-formatted, and that it passes both the lint and test validation checks:

        cargo clippy --workspace --all-targets --all-features -- -D warnings  # Rust linting\nRUFF_UPDATE_SCHEMA=1 cargo test  # Rust testing and updating ruff.schema.json\nuvx pre-commit run --all-files --show-diff-on-failure  # Rust and Python formatting, Markdown and Python linting, etc.\n

        These checks will run on GitHub Actions when you open your pull request, but running them locally will save you time and expedite the merge process.

        If you're using VS Code, you can also install the recommended rust-analyzer extension to get these checks while editing.

        Note that many code changes also require updating the snapshot tests, which is done interactively after running cargo test like so:

        cargo insta review\n

        If your pull request relates to a specific lint rule, include the category and rule code in the title, as in the following examples:

        • [flake8-bugbear] Avoid false positive for usage after continue (B031)
        • [flake8-simplify] Detect implicit else cases in needless-bool (SIM103)
        • [pycodestyle] Implement redundant-backslash (E502)

        Your pull request will be reviewed by a maintainer, which may involve a few rounds of iteration prior to merging.

        "},{"location":"contributing/#project-structure","title":"Project Structure","text":"

        Ruff is structured as a monorepo with a flat crate structure, such that all crates are contained in a flat crates directory.

        The vast majority of the code, including all lint rules, lives in the ruff_linter crate (located at crates/ruff_linter). As a contributor, that's the crate that'll be most relevant to you.

        At the time of writing, the repository includes the following crates:

        • crates/ruff_linter: library crate containing all lint rules and the core logic for running them. If you're working on a rule, this is the crate for you.
        • crates/ruff_benchmark: binary crate for running micro-benchmarks.
        • crates/ruff_cache: library crate for caching lint results.
        • crates/ruff: binary crate containing Ruff's command-line interface.
        • crates/ruff_dev: binary crate containing utilities used in the development of Ruff itself (e.g., cargo dev generate-all), see the cargo dev section below.
        • crates/ruff_diagnostics: library crate for the rule-independent abstractions in the lint diagnostics APIs.
        • crates/ruff_formatter: library crate for language agnostic code formatting logic based on an intermediate representation. The backend for ruff_python_formatter.
        • crates/ruff_index: library crate inspired by rustc_index.
        • crates/ruff_macros: proc macro crate containing macros used by Ruff.
        • crates/ruff_notebook: library crate for parsing and manipulating Jupyter notebooks.
        • crates/ruff_python_ast: library crate containing Python-specific AST types and utilities.
        • crates/ruff_python_codegen: library crate containing utilities for generating Python source code.
        • crates/ruff_python_formatter: library crate implementing the Python formatter. Emits an intermediate representation for each node, which ruff_formatter prints based on the configured line length.
        • crates/ruff_python_semantic: library crate containing Python-specific semantic analysis logic, including Ruff's semantic model. Used to resolve queries like \"What import does this variable refer to?\"
        • crates/ruff_python_stdlib: library crate containing Python-specific standard library data, e.g. the names of all built-in exceptions and which standard library types are immutable.
        • crates/ruff_python_trivia: library crate containing Python-specific trivia utilities (e.g., for analyzing indentation, newlines, etc.).
        • crates/ruff_python_parser: library crate containing the Python parser.
        • crates/ruff_wasm: library crate for exposing Ruff as a WebAssembly module. Powers the Ruff Playground.
        "},{"location":"contributing/#example-adding-a-new-lint-rule","title":"Example: Adding a new lint rule","text":"

        At a high level, the steps involved in adding a new lint rule are as follows:

        1. Determine a name for the new rule as per our rule naming convention (e.g., AssertFalse, as in, \"allow assert False\").

        2. Create a file for your rule (e.g., crates/ruff_linter/src/rules/flake8_bugbear/rules/assert_false.rs).

        3. In that file, define a violation struct (e.g., pub struct AssertFalse). You can grep for #[derive(ViolationMetadata)] to see examples.

        4. In that file, define a function that adds the violation to the diagnostic list as appropriate (e.g., pub(crate) fn assert_false) based on whatever inputs are required for the rule (e.g., an ast::StmtAssert node).

        5. Define the logic for invoking the diagnostic in crates/ruff_linter/src/checkers/ast/analyze (for AST-based rules), crates/ruff_linter/src/checkers/tokens.rs (for token-based rules), crates/ruff_linter/src/checkers/physical_lines.rs (for text-based rules), crates/ruff_linter/src/checkers/filesystem.rs (for filesystem-based rules), etc. For AST-based rules, you'll likely want to modify analyze/statement.rs (if your rule is based on analyzing statements, like imports) or analyze/expression.rs (if your rule is based on analyzing expressions, like function calls).

        6. Map the violation struct to a rule code in crates/ruff_linter/src/codes.rs (e.g., B011). New rules should be added in RuleGroup::Preview.

        7. Add proper testing for your rule.

        8. Update the generated files (documentation and generated code).

        To trigger the violation, you'll likely want to augment the logic in crates/ruff_linter/src/checkers/ast.rs to call your new function at the appropriate time and with the appropriate inputs. The Checker defined therein is a Python AST visitor, which iterates over the AST, building up a semantic model, and calling out to lint rule analyzer functions as it goes.

        If you need to inspect the AST, you can run cargo dev print-ast with a Python file. Grep for the Diagnostic::new invocations to understand how other, similar rules are implemented.

        Once you're satisfied with your code, add tests for your rule (see: rule testing), and regenerate the documentation and associated assets (like our JSON Schema) with cargo dev generate-all.

        Finally, submit a pull request, and include the category, rule name, and rule code in the title, as in:

        [pycodestyle] Implement redundant-backslash (E502)

        "},{"location":"contributing/#rule-naming-convention","title":"Rule naming convention","text":"

        Like Clippy, Ruff's rule names should make grammatical and logical sense when read as \"allow ${rule}\" or \"allow ${rule} items\", as in the context of suppression comments.

        For example, AssertFalse fits this convention: it flags assert False statements, and so a suppression comment would be framed as \"allow assert False\".

        As such, rule names should...

        • Highlight the pattern that is being linted against, rather than the preferred alternative. For example, AssertFalse guards against assert False statements.

        • Not contain instructions on how to fix the violation, which instead belong in the rule documentation and the fix_title.

        • Not contain a redundant prefix, like Disallow or Banned, which are already implied by the convention.

        When re-implementing rules from other linters, we prioritize adhering to this convention over preserving the original rule name.

        "},{"location":"contributing/#rule-testing-fixtures-and-snapshots","title":"Rule testing: fixtures and snapshots","text":"

        To test rules, Ruff uses snapshots of Ruff's output for a given file (fixture). Generally, there will be one file per rule (e.g., E402.py), and each file will contain all necessary examples of both violations and non-violations. cargo insta review will generate a snapshot file containing Ruff's output for each fixture, which you can then commit alongside your changes.

        Once you've completed the code for the rule itself, you can define tests with the following steps:

        1. Add a Python file to crates/ruff_linter/resources/test/fixtures/[linter] that contains the code you want to test. The file name should match the rule name (e.g., E402.py), and it should include examples of both violations and non-violations.

        2. Run Ruff locally against your file and verify the output is as expected. Once you're satisfied with the output (you see the violations you expect, and no others), proceed to the next step. For example, if you're adding a new rule named E402, you would run:

          cargo run -p ruff -- check crates/ruff_linter/resources/test/fixtures/pycodestyle/E402.py --no-cache --preview --select E402\n

          Note: Only a subset of rules are enabled by default. When testing a new rule, ensure that you activate it by adding --select ${rule_code} to the command.

        3. Add the test to the relevant crates/ruff_linter/src/rules/[linter]/mod.rs file. If you're contributing a rule to a pre-existing set, you should be able to find a similar example to pattern-match against. If you're adding a new linter, you'll need to create a new mod.rs file (see, e.g., crates/ruff_linter/src/rules/flake8_bugbear/mod.rs)

        4. Run cargo test. Your test will fail, but you'll be prompted to follow-up with cargo insta review. Run cargo insta review, review and accept the generated snapshot, then commit the snapshot file alongside the rest of your changes.

        5. Run cargo test again to ensure that your test passes.

        "},{"location":"contributing/#example-adding-a-new-configuration-option","title":"Example: Adding a new configuration option","text":"

        Ruff's user-facing settings live in a few different places.

        First, the command-line options are defined via the Args struct in crates/ruff/src/args.rs.

        Second, the pyproject.toml options are defined in crates/ruff_workspace/src/options.rs (via the Options struct), crates/ruff_workspace/src/configuration.rs (via the Configuration struct), and crates/ruff_workspace/src/settings.rs (via the Settings struct), which then includes the LinterSettings struct as a field.

        These represent, respectively: the schema used to parse the pyproject.toml file; an internal, intermediate representation; and the final, internal representation used to power Ruff.

        To add a new configuration option, you'll likely want to modify these latter few files (along with args.rs, if appropriate). If you want to pattern-match against an existing example, grep for dummy_variable_rgx, which defines a regular expression to match against acceptable unused variables (e.g., _).

        Note that plugin-specific configuration options are defined in their own modules (e.g., Settings in crates/ruff_linter/src/flake8_unused_arguments/settings.rs coupled with Flake8UnusedArgumentsOptions in crates/ruff_workspace/src/options.rs).

        Finally, regenerate the documentation and generated code with cargo dev generate-all.

        "},{"location":"contributing/#mkdocs","title":"MkDocs","text":"

        To preview any changes to the documentation locally:

        1. Install the Rust toolchain.

        2. Generate the MkDocs site with:

          uv run --no-project --isolated --with-requirements docs/requirements.txt scripts/generate_mkdocs.py\n
        3. Run the development server with:

          # For contributors.\nuvx --with-requirements docs/requirements.txt -- mkdocs serve -f mkdocs.public.yml\n\n# For members of the Astral org, which has access to MkDocs Insiders via sponsorship.\nuvx --with-requirements docs/requirements-insiders.txt -- mkdocs serve -f mkdocs.insiders.yml\n

        The documentation should then be available locally at http://127.0.0.1:8000/ruff/.

        "},{"location":"contributing/#release-process","title":"Release Process","text":"

        As of now, Ruff has an ad hoc release process: releases are cut with high frequency via GitHub Actions, which automatically generates the appropriate wheels across architectures and publishes them to PyPI.

        Ruff follows the semver versioning standard. However, as pre-1.0 software, even patch releases may contain non-backwards-compatible changes.

        "},{"location":"contributing/#creating-a-new-release","title":"Creating a new release","text":"
        1. Install uv: curl -LsSf https://astral.sh/uv/install.sh | sh

        2. Run ./scripts/release.sh; this command will:

          • Generate a temporary virtual environment with rooster
          • Generate a changelog entry in CHANGELOG.md
          • Update versions in pyproject.toml and Cargo.toml
          • Update references to versions in the README.md and documentation
          • Display contributors for the release
        3. The changelog should then be editorialized for consistency

          • Often labels will be missing from pull requests they will need to be manually organized into the proper section
          • Changes should be edited to be user-facing descriptions, avoiding internal details
        4. Highlight any breaking changes in BREAKING_CHANGES.md

        5. Run cargo check. This should update the lock file with new versions.

        6. Create a pull request with the changelog and version updates

        7. Merge the PR

        8. Run the release workflow with:

          • The new version number (without starting v)
        9. The release workflow will do the following:

          1. Build all the assets. If this fails (even though we tested in step 4), we haven't tagged or uploaded anything, you can restart after pushing a fix. If you just need to rerun the build, make sure you're re-running all the failed jobs and not just a single failed job.
          2. Upload to PyPI.
          3. Create and push the Git tag (as extracted from pyproject.toml). We create the Git tag only after building the wheels and uploading to PyPI, since we can't delete or modify the tag (#4468).
          4. Attach artifacts to draft GitHub release
          5. Trigger downstream repositories. This can fail non-catastrophically, as we can run any downstream jobs manually if needed.
        10. Verify the GitHub release:

          1. The Changelog should match the content of CHANGELOG.md
          2. Append the contributors from the scripts/release.sh script
        11. If needed, update the schemastore.

          1. One can determine if an update is needed when git diff old-version-tag new-version-tag -- ruff.schema.json returns a non-empty diff.
          2. Once run successfully, you should follow the link in the output to create a PR.
        12. If needed, update the ruff-lsp and ruff-vscode repositories and follow the release instructions in those repositories. ruff-lsp should always be updated before ruff-vscode.

          This step is generally not required for a patch release, but should always be done for a minor release.

        "},{"location":"contributing/#ecosystem-ci","title":"Ecosystem CI","text":"

        GitHub Actions will run your changes against a number of real-world projects from GitHub and report on any linter or formatter differences. You can also run those checks locally via:

        uvx --from ./python/ruff-ecosystem ruff-ecosystem check ruff \"./target/debug/ruff\"\nuvx --from ./python/ruff-ecosystem ruff-ecosystem format ruff \"./target/debug/ruff\"\n

        See the ruff-ecosystem package for more details.

        "},{"location":"contributing/#upgrading-rust","title":"Upgrading Rust","text":"
        1. Change the channel in ./rust-toolchain.toml to the new Rust version (<latest>)
        2. Change the rust-version in the ./Cargo.toml to <latest> - 2 (e.g. 1.84 if the latest is 1.86)
        3. Run cargo clippy --fix --allow-dirty --allow-staged to fix new clippy warnings
        4. Create and merge the PR
        5. Bump the Rust version in Ruff's conda forge recipe. See this PR for an example.
        6. Enjoy the new Rust version!
        "},{"location":"contributing/#benchmarking-and-profiling","title":"Benchmarking and Profiling","text":"

        We have several ways of benchmarking and profiling Ruff:

        • Our main performance benchmark comparing Ruff with other tools on the CPython codebase
        • Microbenchmarks which run the linter or the formatter on individual files. These run on pull requests.
        • Profiling the linter on either the microbenchmarks or entire projects

        Note When running benchmarks, ensure that your CPU is otherwise idle (e.g., close any background applications, like web browsers). You may also want to switch your CPU to a \"performance\" mode, if it exists, especially when benchmarking short-lived processes.

        "},{"location":"contributing/#cpython-benchmark","title":"CPython Benchmark","text":"

        First, clone CPython. It's a large and diverse Python codebase, which makes it a good target for benchmarking.

        git clone --branch 3.10 https://github.com/python/cpython.git crates/ruff_linter/resources/test/cpython\n

        Install hyperfine:

        cargo install hyperfine\n

        To benchmark the release build:

        cargo build --release --bin ruff && hyperfine --warmup 10 \\\n  \"./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ --no-cache -e\" \\\n  \"./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ -e\"\n\nBenchmark 1: ./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache\n  Time (mean \u00b1 \u03c3):     293.8 ms \u00b1   3.2 ms    [User: 2384.6 ms, System: 90.3 ms]\n  Range (min \u2026 max):   289.9 ms \u2026 301.6 ms    10 runs\n\nBenchmark 2: ./target/release/ruff ./crates/ruff_linter/resources/test/cpython/\n  Time (mean \u00b1 \u03c3):      48.0 ms \u00b1   3.1 ms    [User: 65.2 ms, System: 124.7 ms]\n  Range (min \u2026 max):    45.0 ms \u2026  66.7 ms    62 runs\n\nSummary\n  './target/release/ruff ./crates/ruff_linter/resources/test/cpython/' ran\n    6.12 \u00b1 0.41 times faster than './target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache'\n

        To benchmark against the ecosystem's existing tools:

        hyperfine --ignore-failure --warmup 5 \\\n  \"./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ --no-cache\" \\\n  \"pyflakes crates/ruff_linter/resources/test/cpython\" \\\n  \"autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython\" \\\n  \"pycodestyle crates/ruff_linter/resources/test/cpython\" \\\n  \"flake8 crates/ruff_linter/resources/test/cpython\"\n\nBenchmark 1: ./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache\n  Time (mean \u00b1 \u03c3):     294.3 ms \u00b1   3.3 ms    [User: 2467.5 ms, System: 89.6 ms]\n  Range (min \u2026 max):   291.1 ms \u2026 302.8 ms    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 2: pyflakes crates/ruff_linter/resources/test/cpython\n  Time (mean \u00b1 \u03c3):     15.786 s \u00b1  0.143 s    [User: 15.560 s, System: 0.214 s]\n  Range (min \u2026 max):   15.640 s \u2026 16.157 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 3: autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython\n  Time (mean \u00b1 \u03c3):      6.175 s \u00b1  0.169 s    [User: 54.102 s, System: 1.057 s]\n  Range (min \u2026 max):    5.950 s \u2026  6.391 s    10 runs\n\nBenchmark 4: pycodestyle crates/ruff_linter/resources/test/cpython\n  Time (mean \u00b1 \u03c3):     46.921 s \u00b1  0.508 s    [User: 46.699 s, System: 0.202 s]\n  Range (min \u2026 max):   46.171 s \u2026 47.863 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 5: flake8 crates/ruff_linter/resources/test/cpython\n  Time (mean \u00b1 \u03c3):     12.260 s \u00b1  0.321 s    [User: 102.934 s, System: 1.230 s]\n  Range (min \u2026 max):   11.848 s \u2026 12.933 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nSummary\n  './target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache' ran\n   20.98 \u00b1 0.62 times faster than 'autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython'\n   41.66 \u00b1 1.18 times faster than 'flake8 crates/ruff_linter/resources/test/cpython'\n   53.64 \u00b1 0.77 times faster than 'pyflakes crates/ruff_linter/resources/test/cpython'\n  159.43 \u00b1 2.48 times faster than 'pycodestyle crates/ruff_linter/resources/test/cpython'\n

        To benchmark a subset of rules, e.g. LineTooLong and DocLineTooLong:

        cargo build --release && hyperfine --warmup 10 \\\n  \"./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ --no-cache -e --select W505,E501\"\n

        You can run uv venv --project ./scripts/benchmarks, activate the venv and then run uv sync --project ./scripts/benchmarks to create a working environment for the above. All reported benchmarks were computed using the versions specified by ./scripts/benchmarks/pyproject.toml on Python 3.11.

        To benchmark Pylint, remove the following files from the CPython repository:

        rm Lib/test/bad_coding.py \\\n  Lib/test/bad_coding2.py \\\n  Lib/test/bad_getattr.py \\\n  Lib/test/bad_getattr2.py \\\n  Lib/test/bad_getattr3.py \\\n  Lib/test/badcert.pem \\\n  Lib/test/badkey.pem \\\n  Lib/test/badsyntax_3131.py \\\n  Lib/test/badsyntax_future10.py \\\n  Lib/test/badsyntax_future3.py \\\n  Lib/test/badsyntax_future4.py \\\n  Lib/test/badsyntax_future5.py \\\n  Lib/test/badsyntax_future6.py \\\n  Lib/test/badsyntax_future7.py \\\n  Lib/test/badsyntax_future8.py \\\n  Lib/test/badsyntax_future9.py \\\n  Lib/test/badsyntax_pep3120.py \\\n  Lib/test/test_asyncio/test_runners.py \\\n  Lib/test/test_copy.py \\\n  Lib/test/test_inspect.py \\\n  Lib/test/test_typing.py\n

        Then, from crates/ruff_linter/resources/test/cpython, run: time pylint -j 0 -E $(git ls-files '*.py'). This will execute Pylint with maximum parallelism and only report errors.

        To benchmark Pyupgrade, run the following from crates/ruff_linter/resources/test/cpython:

        hyperfine --ignore-failure --warmup 5 --prepare \"git reset --hard HEAD\" \\\n  \"find . -type f -name \\\"*.py\\\" | xargs -P 0 pyupgrade --py311-plus\"\n\nBenchmark 1: find . -type f -name \"*.py\" | xargs -P 0 pyupgrade --py311-plus\n  Time (mean \u00b1 \u03c3):     30.119 s \u00b1  0.195 s    [User: 28.638 s, System: 0.390 s]\n  Range (min \u2026 max):   29.813 s \u2026 30.356 s    10 runs\n
        "},{"location":"contributing/#microbenchmarks","title":"Microbenchmarks","text":"

        The ruff_benchmark crate benchmarks the linter and the formatter on individual files.

        You can run the benchmarks with

        cargo benchmark\n

        cargo benchmark is an alias for cargo bench -p ruff_benchmark --bench linter --bench formatter --

        "},{"location":"contributing/#benchmark-driven-development","title":"Benchmark-driven Development","text":"

        Ruff uses Criterion.rs for benchmarks. You can use --save-baseline=<name> to store an initial baseline benchmark (e.g., on main) and then use --benchmark=<name> to compare against that benchmark. Criterion will print a message telling you if the benchmark improved/regressed compared to that baseline.

        # Run once on your \"baseline\" code\ncargo bench -p ruff_benchmark -- --save-baseline=main\n\n# Then iterate with\ncargo bench -p ruff_benchmark -- --baseline=main\n
        "},{"location":"contributing/#pr-summary","title":"PR Summary","text":"

        You can use --save-baseline and critcmp to get a pretty comparison between two recordings. This is useful to illustrate the improvements of a PR.

        # On main\ncargo bench -p ruff_benchmark -- --save-baseline=main\n\n# After applying your changes\ncargo bench -p ruff_benchmark -- --save-baseline=pr\n\ncritcmp main pr\n

        You must install critcmp for the comparison.

        cargo install critcmp\n
        "},{"location":"contributing/#tips","title":"Tips","text":"
        • Use cargo bench -p ruff_benchmark <filter> to only run specific benchmarks. For example: cargo bench -p ruff_benchmark lexer to only run the lexer benchmarks.
        • Use cargo bench -p ruff_benchmark -- --quiet for a more cleaned up output (without statistical relevance)
        • Use cargo bench -p ruff_benchmark -- --quick to get faster results (more prone to noise)
        "},{"location":"contributing/#profiling-projects","title":"Profiling Projects","text":"

        You can either use the microbenchmarks from above or a project directory for benchmarking. There are a lot of profiling tools out there, The Rust Performance Book lists some examples.

        "},{"location":"contributing/#linux","title":"Linux","text":"

        Install perf and build ruff_benchmark with the profiling profile and then run it with perf

        cargo bench -p ruff_benchmark --no-run --profile=profiling && perf record --call-graph dwarf -F 9999 cargo bench -p ruff_benchmark --profile=profiling -- --profile-time=1\n

        You can also use the ruff_dev launcher to run ruff check multiple times on a repository to gather enough samples for a good flamegraph (change the 999, the sample rate, and the 30, the number of checks, to your liking)

        cargo build --bin ruff_dev --profile=profiling\nperf record -g -F 999 target/profiling/ruff_dev repeat --repeat 30 --exit-zero --no-cache path/to/cpython > /dev/null\n

        Then convert the recorded profile

        perf script -F +pid > /tmp/test.perf\n

        You can now view the converted file with firefox profiler. To learn more about Firefox profiler, read the Firefox profiler profiling-guide.

        An alternative is to convert the perf data to flamegraph.svg using flamegraph (cargo install flamegraph):

        flamegraph --perfdata perf.data --no-inline\n
        "},{"location":"contributing/#mac","title":"Mac","text":"

        Install cargo-instruments:

        cargo install cargo-instruments\n

        Then run the profiler with

        cargo instruments -t time --bench linter --profile profiling -p ruff_benchmark -- --profile-time=1\n
        • -t: Specifies what to profile. Useful options are time to profile the wall time and alloc for profiling the allocations.
        • You may want to pass an additional filter to run a single test file

        Otherwise, follow the instructions from the linux section.

        "},{"location":"contributing/#cargo-dev","title":"cargo dev","text":"

        cargo dev is a shortcut for cargo run --package ruff_dev --bin ruff_dev. You can run some useful utils with it:

        • cargo dev print-ast <file>: Print the AST of a python file using Ruff's Python parser. For if True: pass # comment, you can see the syntax tree, the byte offsets for start and stop of each node and also how the : token, the comment and whitespace are not represented anymore:
        [\n    If(\n        StmtIf {\n            range: 0..13,\n            test: Constant(\n                ExprConstant {\n                    range: 3..7,\n                    value: Bool(\n                        true,\n                    ),\n                    kind: None,\n                },\n            ),\n            body: [\n                Pass(\n                    StmtPass {\n                        range: 9..13,\n                    },\n                ),\n            ],\n            orelse: [],\n        },\n    ),\n]\n
        • cargo dev print-tokens <file>: Print the tokens that the AST is built upon. Again for if True: pass # comment:
        0 If 2\n3 True 7\n7 Colon 8\n9 Pass 13\n14 Comment(\n    \"# comment\",\n) 23\n23 Newline 24\n
        • cargo dev print-cst <file>: Print the CST of a Python file using LibCST, which is used in addition to the RustPython parser in Ruff. For example, for if True: pass # comment, everything, including the whitespace, is represented:
        Module {\n    body: [\n        Compound(\n            If(\n                If {\n                    test: Name(\n                        Name {\n                            value: \"True\",\n                            lpar: [],\n                            rpar: [],\n                        },\n                    ),\n                    body: SimpleStatementSuite(\n                        SimpleStatementSuite {\n                            body: [\n                                Pass(\n                                    Pass {\n                                        semicolon: None,\n                                    },\n                                ),\n                            ],\n                            leading_whitespace: SimpleWhitespace(\n                                \" \",\n                            ),\n                            trailing_whitespace: TrailingWhitespace {\n                                whitespace: SimpleWhitespace(\n                                    \" \",\n                                ),\n                                comment: Some(\n                                    Comment(\n                                        \"# comment\",\n                                    ),\n                                ),\n                                newline: Newline(\n                                    None,\n                                    Real,\n                                ),\n                            },\n                        },\n                    ),\n                    orelse: None,\n                    leading_lines: [],\n                    whitespace_before_test: SimpleWhitespace(\n                        \" \",\n                    ),\n                    whitespace_after_test: SimpleWhitespace(\n                        \"\",\n                    ),\n                    is_elif: false,\n                },\n            ),\n        ),\n    ],\n    header: [],\n    footer: [],\n    default_indent: \"    \",\n    default_newline: \"\\n\",\n    has_trailing_newline: true,\n    encoding: \"utf-8\",\n}\n
        • cargo dev generate-all: Update ruff.schema.json, docs/configuration.md and docs/rules. You can also set RUFF_UPDATE_SCHEMA=1 to update ruff.schema.json during cargo test.
        • cargo dev generate-cli-help, cargo dev generate-docs and cargo dev generate-json-schema: Update just docs/configuration.md, docs/rules and ruff.schema.json respectively.
        • cargo dev generate-options: Generate a markdown-compatible table of all pyproject.toml options. Used for https://docs.astral.sh/ruff/settings/.
        • cargo dev generate-rules-table: Generate a markdown-compatible table of all rules. Used for https://docs.astral.sh/ruff/rules/.
        • cargo dev round-trip <python file or jupyter notebook>: Read a Python file or Jupyter Notebook, parse it, serialize the parsed representation and write it back. Used to check how good our representation is so that fixes don't rewrite irrelevant parts of a file.
        • cargo dev format_dev: See ruff_python_formatter README.md
        "},{"location":"contributing/#subsystems","title":"Subsystems","text":""},{"location":"contributing/#compilation-pipeline","title":"Compilation Pipeline","text":"

        If we view Ruff as a compiler, in which the inputs are paths to Python files and the outputs are diagnostics, then our current compilation pipeline proceeds as follows:

        1. File discovery: Given paths like foo/, locate all Python files in any specified subdirectories, taking into account our hierarchical settings system and any exclude options.

        2. Package resolution: Determine the \"package root\" for every file by traversing over its parent directories and looking for __init__.py files.

        3. Cache initialization: For every \"package root\", initialize an empty cache.

        4. Analysis: For every file, in parallel:

          1. Cache read: If the file is cached (i.e., its modification timestamp hasn't changed since it was last analyzed), short-circuit, and return the cached diagnostics.

          2. Tokenization: Run the lexer over the file to generate a token stream.

          3. Indexing: Extract metadata from the token stream, such as: comment ranges, # noqa locations, # isort: off locations, \"doc lines\", etc.

          4. Token-based rule evaluation: Run any lint rules that are based on the contents of the token stream (e.g., commented-out code).

          5. Filesystem-based rule evaluation: Run any lint rules that are based on the contents of the filesystem (e.g., lack of __init__.py file in a package).

          6. Logical line-based rule evaluation: Run any lint rules that are based on logical lines (e.g., stylistic rules).

          7. Parsing: Run the parser over the token stream to produce an AST. (This consumes the token stream, so anything that relies on the token stream needs to happen before parsing.)

          8. AST-based rule evaluation: Run any lint rules that are based on the AST. This includes the vast majority of lint rules. As part of this step, we also build the semantic model for the current file as we traverse over the AST. Some lint rules are evaluated eagerly, as we iterate over the AST, while others are evaluated in a deferred manner (e.g., unused imports, since we can't determine whether an import is unused until we've finished analyzing the entire file), after we've finished the initial traversal.

          9. Import-based rule evaluation: Run any lint rules that are based on the module's imports (e.g., import sorting). These could, in theory, be included in the AST-based rule evaluation phase \u2014 they're just separated for simplicity.

          10. Physical line-based rule evaluation: Run any lint rules that are based on physical lines (e.g., line-length).

          11. Suppression enforcement: Remove any violations that are suppressed via # noqa directives or per-file-ignores.

          12. Cache write: Write the generated diagnostics to the package cache using the file as a key.

        5. Reporting: Print diagnostics in the specified format (text, JSON, etc.), to the specified output channel (stdout, a file, etc.).

        "},{"location":"contributing/#import-categorization","title":"Import Categorization","text":"

        To understand Ruff's import categorization system, we first need to define two concepts:

        • \"Project root\": The directory containing the pyproject.toml, ruff.toml, or .ruff.toml file, discovered by identifying the \"closest\" such directory for each Python file. (If you're running via ruff --config /path/to/pyproject.toml, then the current working directory is used as the \"project root\".)
        • \"Package root\": The top-most directory defining the Python package that includes a given Python file. To find the package root for a given Python file, traverse up its parent directories until you reach a parent directory that doesn't contain an __init__.py file (and isn't in a subtree marked as a namespace package); take the directory just before that, i.e., the first directory in the package.

        For example, given:

        my_project\n\u251c\u2500\u2500 pyproject.toml\n\u2514\u2500\u2500 src\n    \u2514\u2500\u2500 foo\n        \u251c\u2500\u2500 __init__.py\n        \u2514\u2500\u2500 bar\n            \u251c\u2500\u2500 __init__.py\n            \u2514\u2500\u2500 baz.py\n

        Then when analyzing baz.py, the project root would be the top-level directory (./my_project), and the package root would be ./my_project/src/foo.

        "},{"location":"contributing/#project-root","title":"Project root","text":"

        The project root does not have a significant impact beyond that all relative paths within the loaded configuration file are resolved relative to the project root.

        For example, to indicate that bar above is a namespace package (it isn't, but let's run with it), the pyproject.toml would list namespace-packages = [\"./src/bar\"], which would resolve to my_project/src/bar.

        The same logic applies when providing a configuration file via --config. In that case, the current working directory is used as the project root, and so all paths in that configuration file are resolved relative to the current working directory. (As a general rule, we want to avoid relying on the current working directory as much as possible, to ensure that Ruff exhibits the same behavior regardless of where and how you invoke it \u2014 but that's hard to avoid in this case.)

        Additionally, if a pyproject.toml file extends another configuration file, Ruff will still use the directory containing that pyproject.toml file as the project root. For example, if ./my_project/pyproject.toml contains:

        [tool.ruff]\nextend = \"/path/to/pyproject.toml\"\n

        Then Ruff will use ./my_project as the project root, even though the configuration file extends /path/to/pyproject.toml. As such, if the configuration file at /path/to/pyproject.toml contains any relative paths, they will be resolved relative to ./my_project.

        If a project uses nested configuration files, then Ruff would detect multiple project roots, one for each configuration file.

        "},{"location":"contributing/#package-root","title":"Package root","text":"

        The package root is used to determine a file's \"module path\". Consider, again, baz.py. In that case, ./my_project/src/foo was identified as the package root, so the module path for baz.py would resolve to foo.bar.baz \u2014 as computed by taking the relative path from the package root (inclusive of the root itself). The module path can be thought of as \"the path you would use to import the module\" (e.g., import foo.bar.baz).

        The package root and module path are used to, e.g., convert relative to absolute imports, and for import categorization, as described below.

        "},{"location":"contributing/#import-categorization_1","title":"Import categorization","text":"

        When sorting and formatting import blocks, Ruff categorizes every import into one of five categories:

        1. \"Future\": the import is a __future__ import. That's easy: just look at the name of the imported module!
        2. \"Standard library\": the import comes from the Python standard library (e.g., import os). This is easy too: we include a list of all known standard library modules in Ruff itself, so it's a simple lookup.
        3. \"Local folder\": the import is a relative import (e.g., from .foo import bar). This is easy too: just check if the import includes a level (i.e., a dot-prefix).
        4. \"First party\": the import is part of the current project. (More on this below.)
        5. \"Third party\": everything else.

        The real challenge lies in determining whether an import is first-party \u2014 everything else is either trivial, or (as in the case of third-party) merely defined as \"not first-party\".

        There are three ways in which an import can be categorized as \"first-party\":

        1. Explicit settings: the import is marked as such via the known-first-party setting. (This should generally be seen as an escape hatch.)
        2. Same-package: the imported module is in the same package as the current file. This gets back to the importance of the \"package root\" and the file's \"module path\". Imagine that we're analyzing baz.py above. If baz.py contains any imports that appear to come from the foo package (e.g., from foo import bar or import foo.bar), they'll be classified as first-party automatically. This check is as simple as comparing the first segment of the current file's module path to the first segment of the import.
        3. Source roots: Ruff supports a src setting, which sets the directories to scan when identifying first-party imports. The algorithm is straightforward: given an import, like import foo, iterate over the directories enumerated in the src setting and, for each directory, check for the existence of a subdirectory foo or a file foo.py.

        By default, src is set to the project root, along with \"src\" subdirectory in the project root. This ensures that Ruff supports both flat and \"src\" layouts out of the box.

        "},{"location":"faq/","title":"FAQ","text":""},{"location":"faq/#is-the-ruff-linter-compatible-with-black","title":"Is the Ruff linter compatible with Black?","text":"

        Yes. The Ruff linter is compatible with Black out-of-the-box, as long as the line-length setting is consistent between the two.

        Ruff is designed to be used alongside a formatter (like Ruff's own formatter, or Black) and, as such, will defer implementing stylistic rules that are obviated by automated formatting.

        Note that Ruff's linter and Black treat line-length enforcement a little differently. Black, like Ruff's formatter, makes a best-effort attempt to adhere to the line-length, but avoids automatic line-wrapping in some cases (e.g., within comments). Ruff, on the other hand, will flag line-too-long (E501) for any line that exceeds the line-length setting. As such, if line-too-long (E501) is enabled, Ruff can still trigger line-length violations even when Black or ruff format is enabled.

        "},{"location":"faq/#how-does-ruffs-formatter-compare-to-black","title":"How does Ruff's formatter compare to Black?","text":"

        The Ruff formatter is designed to be a drop-in replacement for Black.

        Specifically, the formatter is intended to emit near-identical output when run over Black-formatted code. When run over extensive Black-formatted projects like Django and Zulip, > 99.9% of lines are formatted identically. When migrating an existing project from Black to Ruff, you should expect to see a few differences on the margins, but the vast majority of your code should be unchanged.

        When run over non-Black-formatted code, the formatter makes some different decisions than Black, and so more deviations should be expected, especially around the treatment of end-of-line comments.

        See Style Guide for more.

        "},{"location":"faq/#how-does-ruffs-linter-compare-to-flake8","title":"How does Ruff's linter compare to Flake8?","text":"

        Ruff can be used as a drop-in replacement for Flake8 when used (1) without or with a small number of plugins, (2) alongside Black, and (3) on Python 3 code.

        Under those conditions, Ruff implements every rule in Flake8. In practice, that means Ruff implements all of the F rules (which originate from Pyflakes), along with a subset of the E and W rules (which originate from pycodestyle).

        Ruff also re-implements some of the most popular Flake8 plugins and related code quality tools natively, including:

        • autoflake
        • eradicate
        • flake8-2020
        • flake8-annotations
        • flake8-async
        • flake8-bandit (#1646)
        • flake8-blind-except
        • flake8-boolean-trap
        • flake8-bugbear
        • flake8-builtins
        • flake8-commas
        • flake8-comprehensions
        • flake8-copyright
        • flake8-datetimez
        • flake8-debugger
        • flake8-django
        • flake8-docstrings
        • flake8-eradicate
        • flake8-errmsg
        • flake8-executable
        • flake8-gettext
        • flake8-implicit-str-concat
        • flake8-import-conventions
        • flake8-logging
        • flake8-logging-format
        • flake8-no-pep420
        • flake8-pie
        • flake8-print
        • flake8-pyi
        • flake8-pytest-style
        • flake8-quotes
        • flake8-raise
        • flake8-return
        • flake8-self
        • flake8-simplify
        • flake8-slots
        • flake8-super
        • flake8-tidy-imports
        • flake8-todos
        • flake8-type-checking
        • flake8-use-pathlib
        • flynt (#2102)
        • isort
        • mccabe
        • pandas-vet
        • pep8-naming
        • perflint (#4789)
        • pydocstyle
        • pygrep-hooks
        • pyupgrade
        • tryceratops
        • yesqa

        Note that, in some cases, Ruff uses different rule codes and prefixes than would be found in the originating Flake8 plugins. For example, Ruff uses TID252 to represent the I252 rule from flake8-tidy-imports. This helps minimize conflicts across plugins and allows any individual plugin to be toggled on or off with a single (e.g.) --select TID, as opposed to --select I2 (to avoid conflicts with the isort rules, like I001).

        Beyond the rule set, Ruff's primary limitation vis-\u00e0-vis Flake8 is that it does not support custom lint rules. (Instead, popular Flake8 plugins are re-implemented in Rust as part of Ruff itself.) One minor difference is that Ruff doesn't include all the 'opinionated' rules from flake8-bugbear.

        "},{"location":"faq/#how-does-ruffs-linter-compare-to-pylint","title":"How does Ruff's linter compare to Pylint?","text":"

        At time of writing, Pylint implements ~409 total rules, while Ruff implements over 800, of which at least 209 overlap with the Pylint rule set (see: #970).

        Pylint implements many rules that Ruff does not, and vice versa. For example, Pylint does more type inference than Ruff (e.g., Pylint can validate the number of arguments in a function call). As such, Ruff is not a \"pure\" drop-in replacement for Pylint (and vice versa), as they enforce different sets of rules.

        Despite these differences, many users have successfully switched from Pylint to Ruff, especially those using Ruff alongside a type checker, which can cover some of the functionality that Pylint provides.

        Like Flake8, Pylint supports plugins (called \"checkers\"), while Ruff implements all rules natively and does not support custom or third-party rules. Unlike Pylint, Ruff is capable of automatically fixing its own lint violations.

        In some cases, Ruff's rules may yield slightly different results than their Pylint counterparts. For example, Ruff's too-many-branches does not count try blocks as their own branches, unlike Pylint's R0912. Ruff's PL rule group also includes a small number of rules from Pylint extensions (like magic-value-comparison), which need to be explicitly activated when using Pylint. By enabling Ruff's PL group, you may see violations for rules that weren't previously enabled through your Pylint configuration.

        Pylint parity is being tracked in #970.

        "},{"location":"faq/#how-does-ruff-compare-to-mypy-or-pyright-or-pyre","title":"How does Ruff compare to Mypy, or Pyright, or Pyre?","text":"

        Ruff is a linter, not a type checker. It can detect some of the same problems that a type checker can, but a type checker will catch certain errors that Ruff would miss. The opposite is also true: Ruff will catch certain errors that a type checker would typically ignore.

        For example, unlike a type checker, Ruff will notify you if an import is unused, by looking for references to that import in the source code; on the other hand, a type checker could flag that you passed an integer argument to a function that expects a string, which Ruff would miss. The tools are complementary.

        It's recommended that you use Ruff in conjunction with a type checker, like Mypy, Pyright, or Pyre, with Ruff providing faster feedback on lint violations and the type checker providing more detailed feedback on type errors.

        "},{"location":"faq/#which-tools-does-ruff-replace","title":"Which tools does Ruff replace?","text":"

        Today, Ruff can be used to replace Flake8 when used with any of the following plugins:

        • flake8-2020
        • flake8-annotations
        • flake8-async
        • flake8-bandit (#1646)
        • flake8-blind-except
        • flake8-boolean-trap
        • flake8-bugbear
        • flake8-builtins
        • flake8-commas
        • flake8-comprehensions
        • flake8-copyright
        • flake8-datetimez
        • flake8-debugger
        • flake8-django
        • flake8-docstrings
        • flake8-eradicate
        • flake8-errmsg
        • flake8-executable
        • flake8-gettext
        • flake8-implicit-str-concat
        • flake8-import-conventions
        • flake8-logging
        • flake8-logging-format
        • flake8-no-pep420
        • flake8-pie
        • flake8-print
        • flake8-pytest-style
        • flake8-quotes
        • flake8-raise
        • flake8-return
        • flake8-self
        • flake8-simplify
        • flake8-slots
        • flake8-super
        • flake8-tidy-imports
        • flake8-todos
        • flake8-type-checking
        • flake8-use-pathlib
        • flynt (#2102)
        • mccabe
        • pandas-vet
        • pep8-naming
        • perflint (#4789)
        • pydocstyle
        • tryceratops

        Ruff can also replace Black, isort, yesqa, eradicate, and most of the rules implemented in pyupgrade.

        If you're looking to use Ruff, but rely on an unsupported Flake8 plugin, feel free to file an issue.

        "},{"location":"faq/#do-i-have-to-use-ruffs-linter-and-formatter-together","title":"Do I have to use Ruff's linter and formatter together?","text":"

        Nope! Ruff's linter and formatter can be used independently of one another -- you can use Ruff as a formatter, but not a linter, or vice versa.

        "},{"location":"faq/#what-versions-of-python-does-ruff-support","title":"What versions of Python does Ruff support?","text":"

        Ruff can lint code for any Python version from 3.7 onwards, including Python 3.13.

        Ruff does not support Python 2. Ruff may run on pre-Python 3.7 code, although such versions are not officially supported (e.g., Ruff does not respect type comments).

        Ruff is installable under any Python version from 3.7 onwards.

        "},{"location":"faq/#do-i-need-to-install-rust-to-use-ruff","title":"Do I need to install Rust to use Ruff?","text":"

        Nope! Ruff is available as ruff on PyPI. We recommend installing Ruff with uv, though it's also installable with pip, pipx, and a variety of other package managers:

        $ # Install Ruff globally.\n$ uv tool install ruff@latest\n\n$ # Or add Ruff to your project.\n$ uv add --dev ruff\n\n$ # With pip.\n$ pip install ruff\n\n$ # With pipx.\n$ pipx install ruff\n

        Starting with version 0.5.0, Ruff can also be installed with our standalone installers:

        $ # On macOS and Linux.\n$ curl -LsSf https://astral.sh/ruff/install.sh | sh\n\n$ # On Windows.\n$ powershell -c \"irm https://astral.sh/ruff/install.ps1 | iex\"\n\n$ # For a specific version.\n$ curl -LsSf https://astral.sh/ruff/0.5.0/install.sh | sh\n$ powershell -c \"irm https://astral.sh/ruff/0.5.0/install.ps1 | iex\"\n

        Ruff ships with wheels for all major platforms, which enables uv, pip, and other tools to install Ruff without relying on a Rust toolchain at all.

        "},{"location":"faq/#can-i-write-my-own-linter-plugins-for-ruff","title":"Can I write my own linter plugins for Ruff?","text":"

        Ruff does not yet support third-party plugins, though a plugin system is within-scope for the project. See #283 for more.

        "},{"location":"faq/#how-does-ruffs-import-sorting-compare-to-isort","title":"How does Ruff's import sorting compare to isort?","text":"

        Ruff's import sorting is intended to be near-equivalent to isort's when using isort's profile = \"black\".

        There are a few known differences in how Ruff and isort treat aliased imports, and in how Ruff and isort treat inline comments in some cases (see: #1381, #2104).

        For example, Ruff tends to group non-aliased imports from the same module:

        from numpy import cos, int8, int16, int32, int64, tan, uint8, uint16, uint32, uint64\nfrom numpy import sin as np_sin\n

        Whereas isort splits them into separate import statements at each aliased boundary:

        from numpy import cos, int8, int16, int32, int64\nfrom numpy import sin as np_sin\nfrom numpy import tan, uint8, uint16, uint32, uint64\n

        Ruff also correctly classifies some modules as standard-library that aren't recognized by isort, like _string and idlelib.

        Like isort, Ruff's import sorting is compatible with Black.

        "},{"location":"faq/#how-does-ruff-determine-which-of-my-imports-are-first-party-third-party-etc","title":"How does Ruff determine which of my imports are first-party, third-party, etc.?","text":"

        Ruff accepts a src option that in your pyproject.toml, ruff.toml, or .ruff.toml file, specifies the directories that Ruff should consider when determining whether an import is first-party.

        For example, if you have a project with the following structure:

        my_project\n\u251c\u2500\u2500 pyproject.toml\n\u2514\u2500\u2500 src\n    \u2514\u2500\u2500 foo\n        \u251c\u2500\u2500 __init__.py\n        \u2514\u2500\u2500 bar\n            \u251c\u2500\u2500 __init__.py\n            \u2514\u2500\u2500 baz.py\n

        When Ruff sees an import like import foo, it will then iterate over the src directories, looking for a corresponding Python module (in reality, a directory named foo or a file named foo.py). For module paths with multiple components like import foo.bar, the default behavior is to search only for a directory named foo or a file named foo.py. However, if preview is enabled, Ruff will require that the full relative path foo/bar exists as a directory, or that foo/bar.py or foo/bar.pyi exist as files. Finally, imports of the form from foo import bar, Ruff will only use foo when determining whether a module is first-party or third-party.

        If there is a directory whose name matches a third-party package, but does not contain Python code, it could happen that the above algorithm incorrectly infers an import to be first-party. To prevent this, you can modify the known-third-party setting. For example, if you import the package wandb but also have a subdirectory of your src with the same name, you can add the following:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nknown-third-party = [\"wandb\"]\n
        [lint.isort]\nknown-third-party = [\"wandb\"]\n

        If the src field is omitted, Ruff will default to using the \"project root\", along with a \"src\" subdirectory, as the first-party sources, to support both flat and nested project layouts. The \"project root\" is typically the directory containing your pyproject.toml, ruff.toml, or .ruff.toml file, unless a configuration file is provided on the command-line via the --config option, in which case, the current working directory is used as the project root.

        In this case, Ruff would check the \"src\" directory by default, but we can configure it as an explicit, exclusive first-party source like so:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Ruff supports a top-level `src` option in lieu of isort's `src_paths` setting.\n# All paths are relative to the project root, which is the directory containing the pyproject.toml.\nsrc = [\"src\"]\n
        # Ruff supports a top-level `src` option in lieu of isort's `src_paths` setting.\n# All paths are relative to the project root, which is the directory containing the pyproject.toml.\nsrc = [\"src\"]\n

        If your pyproject.toml, ruff.toml, or .ruff.toml extends another configuration file, Ruff will still use the directory containing your pyproject.toml, ruff.toml, or .ruff.toml file as the project root (as opposed to the directory of the file pointed to via the extends option).

        For example, if you add a configuration file to the tests directory in the above example, you'll want to explicitly set the src option in the extended configuration file:

        pyproject.tomlruff.toml
        [tool.ruff]\nextend = \"../pyproject.toml\"\nsrc = [\"../src\"]\n
        extend = \"../pyproject.toml\"\nsrc = [\"../src\"]\n

        Beyond this src-based detection, Ruff will also attempt to determine the current Python package for a given Python file, and mark imports from within the same package as first-party. For example, above, baz.py would be identified as part of the Python package beginning at ./my_project/src/foo, and so any imports in baz.py that begin with foo (like import foo.bar) would be considered first-party based on this same-package heuristic.

        For a detailed explanation of src resolution, see the contributing guide.

        Ruff can also be configured to treat certain modules as (e.g.) always first-party, regardless of their location on the filesystem. For example, you can set known-first-party like so:

        pyproject.tomlruff.toml
        [tool.ruff]\nsrc = [\"src\", \"tests\"]\n\n[tool.ruff.lint]\nselect = [\n    # Pyflakes\n    \"F\",\n    # Pycodestyle\n    \"E\",\n    \"W\",\n    # isort\n    \"I001\"\n]\n\n[tool.ruff.lint.isort]\nknown-first-party = [\"my_module1\", \"my_module2\"]\n
        src = [\"src\", \"tests\"]\n\n[lint]\nselect = [\n    # Pyflakes\n    \"F\",\n    # Pycodestyle\n    \"E\",\n    \"W\",\n    # isort\n    \"I001\"\n]\n\n[lint.isort]\nknown-first-party = [\"my_module1\", \"my_module2\"]\n

        Ruff does not yet support all of isort's configuration options, though it does support many of them. You can find the supported settings in the API reference.

        "},{"location":"faq/#does-ruff-support-jupyter-notebooks","title":"Does Ruff support Jupyter Notebooks?","text":"

        Ruff has built-in support for linting and formatting Jupyter Notebooks. Refer to the Jupyter Notebook section for more details.

        Ruff also integrates with nbQA, a tool for running linters and code formatters over Jupyter Notebooks.

        After installing ruff and nbqa, you can run Ruff over a notebook like so:

        $ nbqa ruff Untitled.ipynb\nUntitled.ipynb:cell_1:2:5: F841 Local variable `x` is assigned to but never used\nUntitled.ipynb:cell_2:1:1: E402 Module level import not at top of file\nUntitled.ipynb:cell_2:1:8: F401 `os` imported but unused\nFound 3 errors.\n1 potentially fixable with the --fix option.\n
        "},{"location":"faq/#does-ruff-support-numpy-or-google-style-docstrings","title":"Does Ruff support NumPy- or Google-style docstrings?","text":"

        Yes! To enforce a docstring convention, add a convention setting following to your configuration file:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydocstyle]\nconvention = \"google\"  # Accepts: \"google\", \"numpy\", or \"pep257\".\n
        [lint.pydocstyle]\nconvention = \"google\"  # Accepts: \"google\", \"numpy\", or \"pep257\".\n

        For example, if you're coming from flake8-docstrings, and your originating configuration uses --docstring-convention=numpy, you'd instead set convention = \"numpy\" in your pyproject.toml, as above.

        Alongside convention, you'll want to explicitly enable the D rule code prefix, since the D rules are not enabled by default:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nselect = [\"D\"]\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n
        [lint]\nselect = [\"D\"]\n\n[lint.pydocstyle]\nconvention = \"google\"\n

        Enabling a convention will disable any rules that are not included in the specified convention. As such, the intended workflow is to enable a convention and then selectively enable or disable any additional rules on top of it:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nselect = [\n    \"D\",\n    # Augment the convention by requiring an imperative mood for all docstrings.\n    \"D401\",\n]\n\nignore = [\n    # Relax the convention by _not_ requiring documentation for every function parameter.\n    \"D417\",\n]\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n
        [lint]\nselect = [\n    \"D\",\n    # Augment the convention by requiring an imperative mood for all docstrings.\n    \"D401\",\n]\n\nignore = [\n    # Relax the convention by _not_ requiring documentation for every function parameter.\n    \"D417\",\n]\n\n[lint.pydocstyle]\nconvention = \"google\"\n

        The PEP 257 convention includes all D errors apart from: D203, D212, D213, D214, D215, D404, D405, D406, D407, D408, D409, D410, D411, D413, D415, D416, and D417.

        The NumPy convention includes all D errors apart from: D107, D203, D212, D213, D402, D413, D415, D416, and D417.

        The Google convention includes all D errors apart from: D203, D204, D213, D215, D400, D401, D404, D406, D407, D408, D409, and D413.

        By default, no convention is set, and so the enabled rules are determined by the select setting alone.

        "},{"location":"faq/#what-is-preview","title":"What is \"preview\"?","text":"

        Preview enables a collection of newer rules and fixes that are considered experimental or unstable. See the preview documentation for more details; or, to see which rules are currently in preview, visit the rules reference.

        "},{"location":"faq/#how-can-i-tell-what-settings-ruff-is-using-to-check-my-code","title":"How can I tell what settings Ruff is using to check my code?","text":"

        Run ruff check /path/to/code.py --show-settings to view the resolved settings for a given file.

        "},{"location":"faq/#i-want-to-use-ruff-but-i-dont-want-to-use-pyprojecttoml-what-are-my-options","title":"I want to use Ruff, but I don't want to use pyproject.toml. What are my options?","text":"

        In lieu of a pyproject.toml file, you can use a ruff.toml file for configuration. The two files are functionally equivalent and have an identical schema, with the exception that a ruff.toml file can omit the [tool.ruff] section header. For example:

        pyproject.toml
        [tool.ruff]\nline-length = 88\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n
        ruff.toml
        line-length = 88\n\n[lint.pydocstyle]\nconvention = \"google\"\n

        Ruff doesn't currently support INI files, like setup.cfg or tox.ini.

        "},{"location":"faq/#how-can-i-change-ruffs-default-configuration","title":"How can I change Ruff's default configuration?","text":"

        When no configuration file is found, Ruff will look for a user-specific ruff.toml file as a last resort. This behavior is similar to Flake8's ~/.config/flake8.

        On macOS and Linux, Ruff expects that file to be located at ~/.config/ruff/ruff.toml, and respects the XDG_CONFIG_HOME specification.

        On Windows, Ruff expects that file to be located at ~\\AppData\\Roaming\\ruff\\ruff.toml.

        Note

        Prior to v0.5.0, Ruff would read user-specific configuration from ~/Library/Application Support/ruff/ruff.toml on macOS. While Ruff will still respect such configuration files, the use of ~/Library/Application Support is considered deprecated.

        For more, see the etcetera crate.

        "},{"location":"faq/#ruff-tried-to-fix-something-but-it-broke-my-code-whats-going-on","title":"Ruff tried to fix something \u2014 but it broke my code. What's going on?","text":"

        Ruff labels fixes as \"safe\" and \"unsafe\". By default, Ruff will fix all violations for which safe fixes are available, while unsafe fixes can be enabled via the unsafe-fixes setting, or passing the --unsafe-fixes flag to ruff check. For more, see the fix documentation.

        Even still, given the dynamic nature of Python, it's difficult to have complete certainty when making changes to code, even for seemingly trivial fixes. If a \"safe\" fix breaks your code, please file an Issue.

        "},{"location":"faq/#how-can-i-disableforce-ruffs-color-output","title":"How can I disable/force Ruff's color output?","text":"

        Ruff's color output is powered by the colored crate, which attempts to automatically detect whether the output stream supports color. However, you can force colors off by setting the NO_COLOR environment variable to any value (e.g., NO_COLOR=1), or force colors on by setting FORCE_COLOR to any non-empty value (e.g., FORCE_COLOR=1).

        colored also supports the CLICOLOR and CLICOLOR_FORCE environment variables (see the spec).

        "},{"location":"faq/#source-code-actions-in-notebooks","title":"Ruff behaves unexpectedly when using source.* code actions in Notebooks. What's going on?","text":"

        Ruff does not support source.organizeImports and source.fixAll code actions in Jupyter Notebooks (notebook.codeActionsOnSave in VS Code). It's recommended to use the notebook prefixed code actions for the same such as notebook.source.organizeImports and notebook.source.fixAll respectively.

        Ruff requires to have a full view of the notebook to provide accurate diagnostics and fixes. For example, if you have a cell that imports a module and another cell that uses that module, Ruff needs to see both cells to mark the import as used. If Ruff were to only see one cell at a time, it would incorrectly mark the import as unused.

        When using the source.* code actions for a Notebook, Ruff will be asked to fix any issues for each cell in parallel, which can lead to unexpected behavior. For example, if a user has configured to run source.organizeImports code action on save for a Notebook, Ruff will attempt to fix the imports for the entire notebook corresponding to each cell. This leads to the client making the same changes to the notebook multiple times, which can lead to unexpected behavior (astral-sh/ruff-vscode#680, astral-sh/ruff-vscode#640, astral-sh/ruff-vscode#391).

        "},{"location":"formatter/","title":"The Ruff Formatter","text":"

        The Ruff formatter is an extremely fast Python code formatter designed as a drop-in replacement for Black, available as part of the ruff CLI via ruff format.

        "},{"location":"formatter/#ruff-format","title":"ruff format","text":"

        ruff format is the primary entrypoint to the formatter. It accepts a list of files or directories, and formats all discovered Python files:

        ruff format                   # Format all files in the current directory.\nruff format path/to/code/     # Format all files in `path/to/code` (and any subdirectories).\nruff format path/to/file.py   # Format a single file.\n

        Similar to Black, running ruff format /path/to/file.py will format the given file or directory in-place, while ruff format --check /path/to/file.py will avoid writing any formatted files back, and instead exit with a non-zero status code upon detecting any unformatted files.

        For the full list of supported options, run ruff format --help.

        "},{"location":"formatter/#philosophy","title":"Philosophy","text":"

        The initial goal of the Ruff formatter is not to innovate on code style, but rather, to innovate on performance, and provide a unified toolchain across Ruff's linter, formatter, and any and all future tools.

        As such, the formatter is designed as a drop-in replacement for Black, but with an excessive focus on performance and direct integration with Ruff. Given Black's popularity within the Python ecosystem, targeting Black compatibility ensures that formatter adoption is minimally disruptive for the vast majority of projects.

        Specifically, the formatter is intended to emit near-identical output when run over existing Black-formatted code. When run over extensive Black-formatted projects like Django and Zulip, > 99.9% of lines are formatted identically. (See: Style Guide.)

        Given this focus on Black compatibility, the formatter thus adheres to Black's (stable) code style, which aims for \"consistency, generality, readability and reducing git diffs\". To give you a sense for the enforced code style, here's an example:

        # Input\ndef _make_ssl_transport(\n    rawsock, protocol, sslcontext, waiter=None,\n    *, server_side=False, server_hostname=None,\n    extra=None, server=None,\n    ssl_handshake_timeout=None,\n    call_connection_made=True):\n    '''Make an SSL transport.'''\n    if waiter is None:\n      waiter = Future(loop=loop)\n\n    if extra is None:\n      extra = {}\n\n    ...\n\n# Ruff\ndef _make_ssl_transport(\n    rawsock,\n    protocol,\n    sslcontext,\n    waiter=None,\n    *,\n    server_side=False,\n    server_hostname=None,\n    extra=None,\n    server=None,\n    ssl_handshake_timeout=None,\n    call_connection_made=True,\n):\n    \"\"\"Make an SSL transport.\"\"\"\n    if waiter is None:\n        waiter = Future(loop=loop)\n\n    if extra is None:\n        extra = {}\n\n    ...\n

        Like Black, the Ruff formatter does not support extensive code style configuration; however, unlike Black, it does support configuring the desired quote style, indent style, line endings, and more. (See: Configuration.)

        While the formatter is designed to be a drop-in replacement for Black, it is not intended to be used interchangeably with Black on an ongoing basis, as the formatter does differ from Black in a few conscious ways (see: Known deviations). In general, deviations are limited to cases in which Ruff's behavior was deemed more consistent, or significantly simpler to support (with negligible end-user impact) given the differences in the underlying implementations between Black and Ruff.

        Going forward, the Ruff Formatter will support Black's preview style under Ruff's own preview mode.

        "},{"location":"formatter/#configuration","title":"Configuration","text":"

        The Ruff Formatter exposes a small set of configuration options, some of which are also supported by Black (like line width), some of which are unique to Ruff (like quote, indentation style and formatting code examples in docstrings).

        For example, to configure the formatter to use single quotes, format code examples in docstrings, a line width of 100, and tab indentation, add the following to your configuration file:

        pyproject.tomlruff.toml
        [tool.ruff]\nline-length = 100\n\n[tool.ruff.format]\nquote-style = \"single\"\nindent-style = \"tab\"\ndocstring-code-format = true\n
        line-length = 100\n\n[format]\nquote-style = \"single\"\nindent-style = \"tab\"\ndocstring-code-format = true\n

        For the full list of supported settings, see Settings. For more on configuring Ruff via pyproject.toml, see Configuring Ruff.

        Given the focus on Black compatibility (and unlike formatters like YAPF), Ruff does not currently expose any other configuration options.

        "},{"location":"formatter/#docstring-formatting","title":"Docstring formatting","text":"

        The Ruff formatter provides an opt-in feature for automatically formatting Python code examples in docstrings. The Ruff formatter currently recognizes code examples in the following formats:

        • The Python doctest format.
        • CommonMark fenced code blocks with the following info strings: python, py, python3, or py3. Fenced code blocks without an info string are assumed to be Python code examples and also formatted.
        • reStructuredText literal blocks. While literal blocks may contain things other than Python, this is meant to reflect a long-standing convention in the Python ecosystem where literal blocks often contain Python code.
        • reStructuredText [code-block and sourcecode directives]. As with Markdown, the language names recognized for Python are python, py, python3, or py3.

        If a code example is recognized and treated as Python, the Ruff formatter will automatically skip it if the code does not parse as valid Python or if the reformatted code would produce an invalid Python program.

        Users may also configure the line length limit used for reformatting Python code examples in docstrings. The default is a special value, dynamic, which instructs the formatter to respect the line length limit setting for the surrounding Python code. The dynamic setting ensures that even when code examples are found inside indented docstrings, the line length limit configured for the surrounding Python code will not be exceeded. Users may also configure a fixed line length limit for code examples in docstrings.

        For example, this configuration shows how to enable docstring code formatting with a fixed line length limit:

        pyproject.tomlruff.toml
        [tool.ruff.format]\ndocstring-code-format = true\ndocstring-code-line-length = 20\n
        [format]\ndocstring-code-format = true\ndocstring-code-line-length = 20\n

        With the above configuration, this code:

        def f(x):\n    '''\n    Something about `f`. And an example:\n\n    .. code-block:: python\n\n        foo, bar, quux = this_is_a_long_line(lion, hippo, lemur, bear)\n    '''\n    pass\n

        ... will be reformatted (assuming the rest of the options are set to their defaults) as:

        def f(x):\n    \"\"\"\n    Something about `f`. And an example:\n\n    .. code-block:: python\n\n        (\n            foo,\n            bar,\n            quux,\n        ) = this_is_a_long_line(\n            lion,\n            hippo,\n            lemur,\n            bear,\n        )\n    \"\"\"\n    pass\n
        "},{"location":"formatter/#format-suppression","title":"Format suppression","text":"

        Like Black, Ruff supports # fmt: on, # fmt: off, and # fmt: skip pragma comments, which can be used to temporarily disable formatting for a given code block.

        # fmt: on and # fmt: off comments are enforced at the statement level:

        # fmt: off\nnot_formatted=3\nalso_not_formatted=4\n# fmt: on\n

        As such, adding # fmt: on and # fmt: off comments within expressions will have no effect. In the following example, both list entries will be formatted, despite the # fmt: off:

        [\n    # fmt: off\n    '1',\n    # fmt: on\n    '2',\n]\n

        Instead, apply the # fmt: off comment to the entire statement:

        # fmt: off\n[\n    '1',\n    '2',\n]\n# fmt: on\n

        Like Black, Ruff will also recognize YAPF's # yapf: disable and # yapf: enable pragma comments, which are treated equivalently to # fmt: off and # fmt: on, respectively.

        # fmt: skip comments suppress formatting for a preceding statement, case header, decorator, function definition, or class definition:

        if True:\n    pass\nelif False: # fmt: skip\n    pass\n\n@Test\n@Test2 # fmt: skip\ndef test(): ...\n\na = [1, 2, 3, 4, 5] # fmt: skip\n\ndef test(a, b, c, d, e, f) -> int: # fmt: skip\n    pass\n

        As such, adding an # fmt: skip comment at the end of an expression will have no effect. In the following example, the list entry '1' will be formatted, despite the # fmt: skip:

        a = call(\n    [\n        '1',  # fmt: skip\n        '2',\n    ],\n    b\n)\n

        Instead, apply the # fmt: skip comment to the entire statement:

        a = call(\n  [\n    '1',\n    '2',\n  ],\n  b\n)  # fmt: skip\n
        "},{"location":"formatter/#conflicting-lint-rules","title":"Conflicting lint rules","text":"

        Ruff's formatter is designed to be used alongside the linter. However, the linter includes some rules that, when enabled, can cause conflicts with the formatter, leading to unexpected behavior. When configured appropriately, the goal of Ruff's formatter-linter compatibility is such that running the formatter should never introduce new lint errors.

        When using Ruff as a formatter, we recommend avoiding the following lint rules:

        • tab-indentation (W191)
        • indentation-with-invalid-multiple (E111)
        • indentation-with-invalid-multiple-comment (E114)
        • over-indented (E117)
        • docstring-tab-indentation (D206)
        • triple-single-quotes (D300)
        • bad-quotes-inline-string (Q000)
        • bad-quotes-multiline-string (Q001)
        • bad-quotes-docstring (Q002)
        • avoidable-escaped-quote (Q003)
        • missing-trailing-comma (COM812)
        • prohibited-trailing-comma (COM819)
        • multi-line-implicit-string-concatenation (ISC002) if used without ISC001 and flake8-implicit-str-concat.allow-multiline = false

        While the line-too-long (E501) rule can be used alongside the formatter, the formatter only makes a best-effort attempt to wrap lines at the configured line-length. As such, formatted code may exceed the line length, leading to line-too-long (E501) errors.

        None of the above are included in Ruff's default configuration. However, if you've enabled any of these rules or their parent categories (like Q), we recommend disabling them via the linter's lint.ignore setting.

        Similarly, we recommend avoiding the following isort settings, which are incompatible with the formatter's treatment of import statements when set to non-default values:

        • force-single-line
        • force-wrap-aliases
        • lines-after-imports
        • lines-between-types
        • split-on-trailing-comma

        If you've configured any of these settings to take on non-default values, we recommend removing them from your Ruff configuration.

        When an incompatible lint rule or setting is enabled, ruff format will emit a warning. If your ruff format is free of warnings, you're good to go!

        "},{"location":"formatter/#exit-codes","title":"Exit codes","text":"

        ruff format exits with the following status codes:

        • 0 if Ruff terminates successfully, regardless of whether any files were formatted.
        • 2 if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an internal error.

        Meanwhile, ruff format --check exits with the following status codes:

        • 0 if Ruff terminates successfully, and no files would be formatted if --check were not specified.
        • 1 if Ruff terminates successfully, and one or more files would be formatted if --check were not specified.
        • 2 if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an internal error.
        "},{"location":"formatter/#style-guide","title":"Style Guide","text":"

        The formatter is designed to be a drop-in replacement for Black. This section documents the areas where the Ruff formatter goes beyond Black in terms of code style.

        "},{"location":"formatter/#intentional-deviations","title":"Intentional deviations","text":"

        While the Ruff formatter aims to be a drop-in replacement for Black, it does differ from Black in a few known ways. Some of these differences emerge from conscious attempts to improve upon Black's code style, while others fall out of differences in the underlying implementations.

        For a complete enumeration of these intentional deviations, see Known deviations.

        Unintentional deviations from Black are tracked in the issue tracker. If you've identified a new deviation, please file an issue.

        "},{"location":"formatter/#preview-style","title":"Preview style","text":"

        Similar to Black, Ruff implements formatting changes under the preview flag, promoting them to stable through minor releases, in accordance with our versioning policy.

        "},{"location":"formatter/#f-string-formatting","title":"F-string formatting","text":"

        Stabilized in Ruff 0.9.0

        Unlike Black, Ruff formats the expression parts of f-strings which are the parts inside the curly braces {...}. This is a known deviation from Black.

        Ruff employs several heuristics to determine how an f-string should be formatted which are detailed below.

        "},{"location":"formatter/#quotes","title":"Quotes","text":"

        Ruff will use the configured quote style for the f-string expression unless doing so would result in invalid syntax for the target Python version or requires more backslash escapes than the original expression. Specifically, Ruff will preserve the original quote style for the following cases:

        When the target Python version is < 3.12 and a self-documenting f-string contains a string literal with the configured quote style:

        # format.quote-style = \"double\"\n\nf'{10 + len(\"hello\")=}'\n# This f-string cannot be formatted as follows when targeting Python < 3.12\nf\"{10 + len(\"hello\")=}\"\n

        When the target Python version is < 3.12 and an f-string contains any triple-quoted string, byte or f-string literal that contains the configured quote style:

        # format.quote-style = \"double\"\n\nf'{\"\"\"nested \" \"\"\"}'\n# This f-string cannot be formatted as follows when targeting Python < 3.12\nf\"{'''nested \" '''}\"\n

        For all target Python versions, when a self-documenting f-string contains an expression between the curly braces ({...}) with a format specifier containing the configured quote style:

        # format.quote-style = \"double\"\n\nf'{1=:\"foo}'\n# This f-string cannot be formatted as follows for all target Python versions\nf\"{1=:\"foo}\"\n

        For nested f-strings, Ruff alternates quote styles, starting with the configured quote style for the outermost f-string. For example, consider the following f-string:

        # format.quote-style = \"double\"\n\nf\"outer f-string {f\"nested f-string {f\"another nested f-string\"} end\"} end\"\n

        Ruff formats it as:

        f\"outer f-string {f'nested f-string {f\"another nested f-string\"} end'} end\"\n
        "},{"location":"formatter/#line-breaks","title":"Line breaks","text":"

        Starting with Python 3.12 (PEP 701), the expression parts of an f-string can span multiple lines. Ruff needs to decide when to introduce a line break in an f-string expression. This depends on the semantic content of the expression parts of an f-string - for example, introducing a line break in the middle of a natural-language sentence is undesirable. Since Ruff doesn't have enough information to make that decision, it adopts a heuristic similar to Prettier: it will only split the expression parts of an f-string across multiple lines if there was already a line break within any of the expression parts.

        For example, the following code:

        f\"this f-string has a multiline expression {\n  ['red', 'green', 'blue', 'yellow',]} and does not fit within the line length\"\n

        ... is formatted as:

        # The list expression is split across multiple lines because of the trailing comma\nf\"this f-string has a multiline expression {\n    [\n        'red',\n        'green',\n        'blue',\n        'yellow',\n    ]\n} and does not fit within the line length\"\n

        But, the following will not be split across multiple lines even though it exceeds the line length:

        f\"this f-string has a multiline expression {['red', 'green', 'blue', 'yellow']} and does not fit within the line length\"\n

        If you want Ruff to split an f-string across multiple lines, ensure there's a linebreak somewhere within the {...} parts of an f-string.

        "},{"location":"formatter/#sorting-imports","title":"Sorting imports","text":"

        Currently, the Ruff formatter does not sort imports. In order to both sort imports and format, call the Ruff linter and then the formatter:

        ruff check --select I --fix\nruff format\n

        A unified command for both linting and formatting is planned.

        "},{"location":"installation/","title":"Installing Ruff","text":"

        Ruff is available as ruff on PyPI.

        Ruff can be invoked directly with uvx:

        uvx ruff check   # Lint all files in the current directory.\nuvx ruff format  # Format all files in the current directory.\n

        Or installed with uv (recommended), pip, or pipx:

        $ # Install Ruff globally.\n$ uv tool install ruff@latest\n\n$ # Or add Ruff to your project.\n$ uv add --dev ruff\n\n$ # With pip.\n$ pip install ruff\n\n$ # With pipx.\n$ pipx install ruff\n

        Once installed, you can run Ruff from the command line:

        $ ruff check   # Lint all files in the current directory.\n$ ruff format  # Format all files in the current directory.\n

        Starting with version 0.5.0, Ruff can also be installed with our standalone installers:

        $ # On macOS and Linux.\n$ curl -LsSf https://astral.sh/ruff/install.sh | sh\n\n$ # On Windows.\n$ powershell -c \"irm https://astral.sh/ruff/install.ps1 | iex\"\n\n$ # For a specific version.\n$ curl -LsSf https://astral.sh/ruff/0.5.0/install.sh | sh\n$ powershell -c \"irm https://astral.sh/ruff/0.5.0/install.ps1 | iex\"\n

        For macOS Homebrew and Linuxbrew users, Ruff is also available as ruff on Homebrew:

        $ brew install ruff\n

        For Conda users, Ruff is also available as ruff on conda-forge:

        $ conda install -c conda-forge ruff\n

        For pkgx users, Ruff is also available as ruff on the pkgx registry:

        $ pkgx install ruff\n

        For Arch Linux users, Ruff is also available as ruff on the official repositories:

        $ pacman -S ruff\n

        For Alpine users, Ruff is also available as ruff on the testing repositories:

        $ apk add ruff\n

        For openSUSE Tumbleweed users, Ruff is also available in the distribution repository:

        $ sudo zypper install python3-ruff\n

        On Docker, it is published as ghcr.io/astral-sh/ruff, tagged for each release and latest for the latest release.

        $ docker run -v .:/io --rm ghcr.io/astral-sh/ruff check\n$ docker run -v .:/io --rm ghcr.io/astral-sh/ruff:0.3.0 check\n\n$ # Or, for Podman on SELinux.\n$ docker run -v .:/io:Z --rm ghcr.io/astral-sh/ruff check\n

        "},{"location":"integrations/","title":"Integrations","text":""},{"location":"integrations/#github-actions","title":"GitHub Actions","text":"

        GitHub Actions has everything you need to run Ruff out-of-the-box:

        name: CI\non: push\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: \"3.11\"\n      - name: Install dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install ruff\n      # Update output format to enable automatic inline annotations.\n      - name: Run Ruff\n        run: ruff check --output-format=github .\n

        Ruff can also be used as a GitHub Action via ruff-action.

        By default, ruff-action runs as a pass-fail test to ensure that a given repository doesn't contain any lint rule violations as per its configuration. However, under-the-hood, ruff-action installs and runs ruff directly, so it can be used to execute any supported ruff command (e.g., ruff check --fix).

        ruff-action supports all GitHub-hosted runners, and can be used with any published Ruff version (i.e., any version available on PyPI).

        To use ruff-action, create a file (e.g., .github/workflows/ruff.yml) inside your repository with:

        name: Ruff\non: [ push, pull_request ]\njobs:\n  ruff:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: astral-sh/ruff-action@v3\n

        Alternatively, you can include ruff-action as a step in any other workflow file:

              - uses: astral-sh/ruff-action@v3\n

        ruff-action accepts optional configuration parameters via with:, including:

        • version: The Ruff version to install (default: latest).
        • args: The command-line arguments to pass to Ruff (default: \"check\").
        • src: The source paths to pass to Ruff (default: [\".\", \"src\"]).

        For example, to run ruff check --select B ./src using Ruff version 0.8.0:

        - uses: astral-sh/ruff-action@v3\n  with:\n    version: 0.8.0\n    args: check --select B\n    src: \"./src\"\n
        "},{"location":"integrations/#gitlab-cicd","title":"GitLab CI/CD","text":"

        You can add the following configuration to .gitlab-ci.yml to run a ruff format in parallel with a ruff check compatible with GitLab's codequality report.

        .base_ruff:\n  stage: build\n  interruptible: true\n  image:\n    name: ghcr.io/astral-sh/ruff:0.11.11-alpine\n  before_script:\n    - cd $CI_PROJECT_DIR\n    - ruff --version\n\nRuff Check:\n  extends: .base_ruff\n  script:\n    - ruff check --output-format=gitlab > code-quality-report.json\n  artifacts:\n    reports:\n      codequality: $CI_PROJECT_DIR/code-quality-report.json\n\nRuff Format:\n  extends: .base_ruff\n  script:\n    - ruff format --diff\n
        "},{"location":"integrations/#pre-commit","title":"pre-commit","text":"

        Ruff can be used as a pre-commit hook via ruff-pre-commit:

        - repo: https://github.com/astral-sh/ruff-pre-commit\n  # Ruff version.\n  rev: v0.11.11\n  hooks:\n    # Run the linter.\n    - id: ruff\n    # Run the formatter.\n    - id: ruff-format\n

        To enable lint fixes, add the --fix argument to the lint hook:

        - repo: https://github.com/astral-sh/ruff-pre-commit\n  # Ruff version.\n  rev: v0.11.11\n  hooks:\n    # Run the linter.\n    - id: ruff\n      args: [ --fix ]\n    # Run the formatter.\n    - id: ruff-format\n

        To avoid running on Jupyter Notebooks, remove jupyter from the list of allowed filetypes:

        - repo: https://github.com/astral-sh/ruff-pre-commit\n  # Ruff version.\n  rev: v0.11.11\n  hooks:\n    # Run the linter.\n    - id: ruff\n      types_or: [ python, pyi ]\n      args: [ --fix ]\n    # Run the formatter.\n    - id: ruff-format\n      types_or: [ python, pyi ]\n

        When running with --fix, Ruff's lint hook should be placed before Ruff's formatter hook, and before Black, isort, and other formatting tools, as Ruff's fix behavior can output code changes that require reformatting.

        When running without --fix, Ruff's formatter hook can be placed before or after Ruff's lint hook.

        (As long as your Ruff configuration avoids any linter-formatter incompatibilities, ruff format should never introduce new lint errors, so it's safe to run Ruff's format hook after ruff check --fix.)

        "},{"location":"integrations/#mdformat","title":"mdformat","text":"

        mdformat is capable of formatting code blocks within Markdown. The mdformat-ruff plugin enables mdformat to format Python code blocks with Ruff.

        "},{"location":"integrations/#docker","title":"Docker","text":"

        Ruff provides a distroless Docker image including the ruff binary. The following tags are published:

        • ruff:latest
        • ruff:{major}.{minor}.{patch}, e.g., ruff:0.6.6
        • ruff:{major}.{minor}, e.g., ruff:0.6 (the latest patch version)

        In addition, ruff publishes the following images:

        • Based on alpine:3.20:
        • ruff:alpine
        • ruff:alpine3.20
        • Based on debian:bookworm-slim:
        • ruff:debian-slim
        • ruff:bookworm-slim
        • Based on buildpack-deps:bookworm:
        • ruff:debian
        • ruff:bookworm

        As with the distroless image, each image is published with ruff version tags as ruff:{major}.{minor}.{patch}-{base} and ruff:{major}.{minor}-{base}, e.g., ruff:0.6.6-alpine.

        "},{"location":"linter/","title":"The Ruff Linter","text":"

        The Ruff Linter is an extremely fast Python linter designed as a drop-in replacement for Flake8 (plus dozens of plugins), isort, pydocstyle, pyupgrade, autoflake, and more.

        "},{"location":"linter/#ruff-check","title":"ruff check","text":"

        ruff check is the primary entrypoint to the Ruff linter. It accepts a list of files or directories, and lints all discovered Python files, optionally fixing any fixable errors. When linting a directory, Ruff searches for Python files recursively in that directory and all its subdirectories:

        $ ruff check                  # Lint files in the current directory.\n$ ruff check --fix            # Lint files in the current directory and fix any fixable errors.\n$ ruff check --watch          # Lint files in the current directory and re-lint on change.\n$ ruff check path/to/code/    # Lint files in `path/to/code`.\n

        For the full list of supported options, run ruff check --help.

        "},{"location":"linter/#rule-selection","title":"Rule selection","text":"

        The set of enabled rules is controlled via the lint.select, lint.extend-select, and lint.ignore settings.

        Ruff's linter mirrors Flake8's rule code system, in which each rule code consists of a one-to-three letter prefix, followed by three digits (e.g., F401). The prefix indicates that \"source\" of the rule (e.g., F for Pyflakes, E for pycodestyle, ANN for flake8-annotations).

        Rule selectors like lint.select and lint.ignore accept either a full rule code (e.g., F401) or any valid prefix (e.g., F). For example, given the following configuration file:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nselect = [\"E\", \"F\"]\nignore = [\"F401\"]\n
        [lint]\nselect = [\"E\", \"F\"]\nignore = [\"F401\"]\n

        Ruff would enable all rules with the E (pycodestyle) or F (Pyflakes) prefix, with the exception of F401. For more on configuring Ruff via pyproject.toml, see Configuring Ruff.

        As a special-case, Ruff also supports the ALL code, which enables all rules. Note that some pydocstyle rules conflict (e.g., D203 and D211) as they represent alternative docstring formats. Ruff will automatically disable any conflicting rules when ALL is enabled.

        If you're wondering how to configure Ruff, here are some recommended guidelines:

        • Prefer lint.select over lint.extend-select to make your rule set explicit.
        • Use ALL with discretion. Enabling ALL will implicitly enable new rules whenever you upgrade.
        • Start with a small set of rules (select = [\"E\", \"F\"]) and add a category at-a-time. For example, you might consider expanding to select = [\"E\", \"F\", \"B\"] to enable the popular flake8-bugbear extension.

        For example, a configuration that enables some of the most popular rules (without being too pedantic) might look like the following:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nselect = [\n    # pycodestyle\n    \"E\",\n    # Pyflakes\n    \"F\",\n    # pyupgrade\n    \"UP\",\n    # flake8-bugbear\n    \"B\",\n    # flake8-simplify\n    \"SIM\",\n    # isort\n    \"I\",\n]\n
        [lint]\nselect = [\n    # pycodestyle\n    \"E\",\n    # Pyflakes\n    \"F\",\n    # pyupgrade\n    \"UP\",\n    # flake8-bugbear\n    \"B\",\n    # flake8-simplify\n    \"SIM\",\n    # isort\n    \"I\",\n]\n

        To resolve the enabled rule set, Ruff may need to reconcile lint.select and lint.ignore from a variety of sources, including the current pyproject.toml, any inherited pyproject.toml files, and the CLI (e.g., --select).

        In those scenarios, Ruff uses the \"highest-priority\" select as the basis for the rule set, and then applies extend-select and ignore adjustments. CLI options are given higher priority than pyproject.toml options, and the current pyproject.toml file is given higher priority than any inherited pyproject.toml files.

        For example, given the following configuration file:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nselect = [\"E\", \"F\"]\nignore = [\"F401\"]\n
        [lint]\nselect = [\"E\", \"F\"]\nignore = [\"F401\"]\n

        Running ruff check --select F401 would result in Ruff enforcing F401, and no other rules.

        Running ruff check --extend-select B would result in Ruff enforcing the E, F, and B rules, with the exception of F401.

        "},{"location":"linter/#fixes","title":"Fixes","text":"

        Ruff supports automatic fixes for a variety of lint errors. For example, Ruff can remove unused imports, reformat docstrings, rewrite type annotations to use newer Python syntax, and more.

        To enable fixes, pass the --fix flag to ruff check:

        $ ruff check --fix\n

        By default, Ruff will fix all violations for which safe fixes are available; to determine whether a rule supports fixing, see Rules.

        "},{"location":"linter/#fix-safety","title":"Fix safety","text":"

        Ruff labels fixes as \"safe\" and \"unsafe\". The meaning and intent of your code will be retained when applying safe fixes, but the meaning could change when applying unsafe fixes.

        Specifically, an unsafe fix could lead to a change in runtime behavior, the removal of comments, or both, while safe fixes are intended to preserve runtime behavior and will only remove comments when deleting entire statements or expressions (e.g., removing unused imports).

        For example, unnecessary-iterable-allocation-for-first-element (RUF015) is a rule which checks for potentially unperformant use of list(...)[0]. The fix replaces this pattern with next(iter(...)) which can result in a drastic speedup:

        $ python -m timeit \"head = list(range(99999999))[0]\"\n1 loop, best of 5: 1.69 sec per loop\n
        $ python -m timeit \"head = next(iter(range(99999999)))\"\n5000000 loops, best of 5: 70.8 nsec per loop\n

        However, when the collection is empty, this raised exception changes from an IndexError to StopIteration:

        $ python -c 'list(range(0))[0]'\nTraceback (most recent call last):\n  File \"<string>\", line 1, in <module>\nIndexError: list index out of range\n
        $ python -c 'next(iter(range(0)))[0]'\nTraceback (most recent call last):\n  File \"<string>\", line 1, in <module>\nStopIteration\n

        Since the change in exception type could break error handling upstream, this fix is categorized as unsafe.

        Ruff only enables safe fixes by default. Unsafe fixes can be enabled by settings unsafe-fixes in your configuration file or passing the --unsafe-fixes flag to ruff check:

        # Show unsafe fixes\nruff check --unsafe-fixes\n\n# Apply unsafe fixes\nruff check --fix --unsafe-fixes\n

        By default, Ruff will display a hint when unsafe fixes are available but not enabled. The suggestion can be silenced by setting the unsafe-fixes setting to false or using the --no-unsafe-fixes flag.

        The safety of fixes can be adjusted per rule using the lint.extend-safe-fixes and lint.extend-unsafe-fixes settings.

        For example, the following configuration would promote unsafe fixes for F601 to safe fixes and demote safe fixes for UP034 to unsafe fixes:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nextend-safe-fixes = [\"F601\"]\nextend-unsafe-fixes = [\"UP034\"]\n
        [lint]\nextend-safe-fixes = [\"F601\"]\nextend-unsafe-fixes = [\"UP034\"]\n

        You may use prefixes to select rules as well, e.g., F can be used to promote fixes for all rules in Pyflakes to safe.

        Note

        All fixes will always be displayed by Ruff when using the json output format. The safety of each fix is available under the applicability field.

        "},{"location":"linter/#disabling-fixes","title":"Disabling fixes","text":"

        To limit the set of rules that Ruff should fix, use the lint.fixable or lint.extend-fixable, and lint.unfixable settings.

        For example, the following configuration would enable fixes for all rules except unused-imports (F401):

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nfixable = [\"ALL\"]\nunfixable = [\"F401\"]\n
        [lint]\nfixable = [\"ALL\"]\nunfixable = [\"F401\"]\n

        Conversely, the following configuration would only enable fixes for F401:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nfixable = [\"F401\"]\n
        [lint]\nfixable = [\"F401\"]\n
        "},{"location":"linter/#error-suppression","title":"Error suppression","text":"

        Ruff supports several mechanisms for suppressing lint errors, be they false positives or permissible violations.

        To omit a lint rule entirely, add it to the \"ignore\" list via the lint.ignore setting, either on the command-line or in your pyproject.toml or ruff.toml file.

        To suppress a violation inline, Ruff uses a noqa system similar to Flake8. To ignore an individual violation, add # noqa: {code} to the end of the line, like so:

        # Ignore F841.\nx = 1  # noqa: F841\n\n# Ignore E741 and F841.\ni = 1  # noqa: E741, F841\n\n# Ignore _all_ violations.\nx = 1  # noqa\n

        For multi-line strings (like docstrings), the noqa directive should come at the end of the string (after the closing triple quote), and will apply to the entire string, like so:

        \"\"\"Lorem ipsum dolor sit amet.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.\n\"\"\"  # noqa: E501\n

        For import sorting, the noqa should come at the end of the first line in the import block, and will apply to all imports in the block, like so:

        import os  # noqa: I001\nimport abc\n

        To ignore all violations across an entire file, add the line # ruff: noqa anywhere in the file, preferably towards the top, like so:

        # ruff: noqa\n

        To ignore a specific rule across an entire file, add the line # ruff: noqa: {code} anywhere in the file, preferably towards the top, like so:

        # ruff: noqa: F841\n

        Or see the lint.per-file-ignores setting, which enables the same functionality from within your pyproject.toml or ruff.toml file.

        Global noqa comments must be on their own line to disambiguate from comments which ignore violations on a single line.

        Note that Ruff will also respect Flake8's # flake8: noqa directive, and will treat it as equivalent to # ruff: noqa.

        "},{"location":"linter/#full-suppression-comment-specification","title":"Full suppression comment specification","text":"

        The full specification is as follows:

        • An inline blanket noqa comment is given by a case-insensitive match for #noqa with optional whitespace after the # symbol, followed by either: the end of the comment, the beginning of a new comment (#), or whitespace followed by any character other than :.
        • An inline rule suppression is given by first finding a case-insensitive match for #noqa with optional whitespace after the # symbol, optional whitespace after noqa, and followed by the symbol :. After this we are expected to have a list of rule codes which is given by sequences of uppercase ASCII characters followed by ASCII digits, separated by whitespace or commas. The list ends at the last valid code. We will attempt to interpret rules with a missing delimiter (e.g. F401F841), though a warning will be emitted in this case.
        • A file-level exemption comment is given by a case-sensitive match for #ruff: or #flake8:, with optional whitespace after # and before :, followed by optional whitespace and a case-insensitive match for noqa. After this, the specification is as in the inline case.
        "},{"location":"linter/#detecting-unused-suppression-comments","title":"Detecting unused suppression comments","text":"

        Ruff implements a special rule, unused-noqa, under the RUF100 code, to enforce that your noqa directives are \"valid\", in that the violations they say they ignore are actually being triggered on that line (and thus suppressed). To flag unused noqa directives, run: ruff check /path/to/file.py --extend-select RUF100.

        Ruff can also remove any unused noqa directives via its fix functionality. To remove any unused noqa directives, run: ruff check /path/to/file.py --extend-select RUF100 --fix.

        "},{"location":"linter/#inserting-necessary-suppression-comments","title":"Inserting necessary suppression comments","text":"

        Ruff can automatically add noqa directives to all lines that contain violations, which is useful when migrating a new codebase to Ruff. To automatically add noqa directives to all relevant lines (with the appropriate rule codes), run: ruff check /path/to/file.py --add-noqa.

        "},{"location":"linter/#action-comments","title":"Action comments","text":"

        Ruff respects isort's action comments (# isort: skip_file, # isort: on, # isort: off, # isort: skip, and # isort: split), which enable selectively enabling and disabling import sorting for blocks of code and other inline configuration.

        Ruff will also respect variants of these action comments with a # ruff: prefix (e.g., # ruff: isort: skip_file, # ruff: isort: on, and so on). These variants more clearly convey that the action comment is intended for Ruff, but are functionally equivalent to the isort variants.

        Unlike isort, Ruff does not respect action comments within docstrings.

        See the isort documentation for more.

        "},{"location":"linter/#exit-codes","title":"Exit codes","text":"

        By default, ruff check exits with the following status codes:

        • 0 if no violations were found, or if all present violations were fixed automatically.
        • 1 if violations were found.
        • 2 if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an internal error.

        This convention mirrors that of tools like ESLint, Prettier, and RuboCop.

        ruff check supports two command-line flags that alter its exit code behavior:

        • --exit-zero will cause Ruff to exit with a status code of 0 even if violations were found. Note that Ruff will still exit with a status code of 2 if it terminates abnormally.
        • --exit-non-zero-on-fix will cause Ruff to exit with a status code of 1 if violations were found, even if all such violations were fixed automatically. Note that the use of --exit-non-zero-on-fix can result in a non-zero exit code even if no violations remain after fixing.
        "},{"location":"preview/","title":"Preview","text":"

        Ruff includes an opt-in preview mode to provide an opportunity for community feedback and increase confidence that changes are a net-benefit before enabling them for everyone.

        Preview mode enables a collection of unstable features such as new lint rules and fixes, formatter style changes, interface updates, and more. Warnings about deprecated features may turn into errors when using preview mode.

        Enabling preview mode does not on its own enable all preview rules. See the rules section for details on selecting preview rules.

        "},{"location":"preview/#enabling-preview-mode","title":"Enabling preview mode","text":"

        Preview mode can be enabled with the --preview flag on the CLI or by setting preview = true in your Ruff configuration file.

        Preview mode can be configured separately for linting and formatting. To enable preview lint rules without preview style formatting:

        pyproject.tomlruff.tomlCLI
        [tool.ruff.lint]\npreview = true\n
        [lint]\npreview = true\n
        ruff check --preview\n

        To enable preview style formatting without enabling any preview lint rules:

        pyproject.tomlruff.tomlCLI
        [tool.ruff.format]\npreview = true\n
        [format]\npreview = true\n
        ruff format --preview\n
        "},{"location":"preview/#using-rules-that-are-in-preview","title":"Using rules that are in preview","text":"

        If a rule is marked as preview, it can only be selected if preview mode is enabled. For example, consider a hypothetical rule, HYP001. If HYP001 were in preview, it would not be enabled by adding it to the selected rule set.

        pyproject.tomlruff.tomlCLI
        [tool.ruff.lint]\nextend-select = [\"HYP001\"]\n
        [lint]\nextend-select = [\"HYP001\"]\n
        ruff check --extend-select HYP001\n

        It also would not be enabled by selecting the HYP category, like so:

        pyproject.tomlruff.tomlCLI
        [tool.ruff.lint]\nextend-select = [\"HYP\"]\n
        [lint]\nextend-select = [\"HYP\"]\n
        ruff check --extend-select HYP\n

        Similarly, it would not be enabled via the ALL selector:

        pyproject.tomlruff.tomlCLI
        [tool.ruff.lint]\nselect = [\"ALL\"]\n
        [lint]\nselect = [\"ALL\"]\n
        ruff check --select ALL\n

        However, it would be enabled in any of the above cases if you enabled preview mode:

        pyproject.tomlruff.tomlCLI
        [tool.ruff.lint]\nextend-select = [\"HYP\"]\npreview = true\n
        [lint]\nextend-select = [\"HYP\"]\npreview = true\n
        ruff check --extend-select HYP --preview\n

        To see which rules are currently in preview, visit the rules reference.

        "},{"location":"preview/#selecting-single-preview-rules","title":"Selecting single preview rules","text":"

        When preview mode is enabled, selecting rule categories or prefixes will include all preview rules that match. If you'd prefer to opt in to each preview rule individually, you can toggle the explicit-preview-rules setting in your configuration file:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\npreview = true\nexplicit-preview-rules = true\n
        [lint]\npreview = true\nexplicit-preview-rules = true\n

        In our previous example, --select with ALL HYP, HYP0, or HYP00 would not enable HYP001. Each preview rule will need to be selected with its exact code: for example, --select ALL,HYP001.

        If preview mode is not enabled, this setting has no effect.

        "},{"location":"preview/#deprecated-rules","title":"Deprecated rules","text":"

        When preview mode is enabled, deprecated rules will be disabled. If a deprecated rule is selected explicitly, an error will be raised. Deprecated rules will not be included if selected via a rule category or prefix.

        "},{"location":"rules/","title":"Rules","text":"

        Ruff supports over 800 lint rules, many of which are inspired by popular tools like Flake8, isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in Rust as a first-party feature.

        By default, Ruff enables Flake8's F rules, along with a subset of the E rules, omitting any stylistic rules that overlap with the use of a formatter, like ruff format or Black.

        If you're just getting started with Ruff, the default rule set is a great place to start: it catches a wide variety of common errors (like unused imports) with zero configuration.

        "},{"location":"rules/#legend","title":"Legend","text":"

        \u00a0\u00a0\u00a0\u00a0\u2714\ufe0f\u00a0\u00a0\u00a0\u00a0 The rule is stable.\u00a0\u00a0\u00a0\u00a0\ud83e\uddea\u00a0\u00a0\u00a0\u00a0 The rule is unstable and is in \"preview\".\u00a0\u00a0\u00a0\u00a0\u26a0\ufe0f\u00a0\u00a0\u00a0\u00a0 The rule has been deprecated and will be removed in a future release.\u00a0\u00a0\u00a0\u00a0\u274c\u00a0\u00a0\u00a0\u00a0 The rule has been removed only the documentation is available.\u00a0\u00a0\u00a0\u00a0\ud83d\udee0\ufe0f\u00a0\u00a0\u00a0\u00a0 The rule is automatically fixable by the --fix command-line option.

        "},{"location":"rules/#airflow-air","title":"Airflow (AIR)","text":"

        For more, see Airflow on PyPI.

        Code Name Message AIR001 airflow-variable-name-task-id-mismatch Task variable name should match the task_id: \"{task_id}\" \u2714\ufe0f \ud83d\udee0\ufe0f AIR002 airflow-dag-no-schedule-argument DAG should have an explicit schedule argument \ud83e\uddea \ud83d\udee0\ufe0f AIR301 airflow3-removal {deprecated} is removed in Airflow 3.0 \ud83e\uddea \ud83d\udee0\ufe0f AIR302 airflow3-moved-to-provider {deprecated} is removed in Airflow 3.0 \ud83e\uddea \ud83d\udee0\ufe0f AIR311 airflow3-suggested-update {deprecated} is removed in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version. \ud83e\uddea \ud83d\udee0\ufe0f AIR312 airflow3-suggested-to-move-to-provider {deprecated} is removed in Airflow 3.0 \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#eradicate-era","title":"eradicate (ERA)","text":"

        For more, see eradicate on PyPI.

        Code Name Message ERA001 commented-out-code Found commented-out code \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#fastapi-fast","title":"FastAPI (FAST)","text":"

        For more, see FastAPI on PyPI.

        Code Name Message FAST001 fast-api-redundant-response-model FastAPI route with redundant response_model argument \u2714\ufe0f \ud83d\udee0\ufe0f FAST002 fast-api-non-annotated-dependency FastAPI dependency without Annotated \u2714\ufe0f \ud83d\udee0\ufe0f FAST003 fast-api-unused-path-parameter Parameter {arg_name} appears in route path, but not in {function_name} signature \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-2020-ytt","title":"flake8-2020 (YTT)","text":"

        For more, see flake8-2020 on PyPI.

        Code Name Message YTT101 sys-version-slice3 sys.version[:3] referenced (python3.10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f YTT102 sys-version2 sys.version[2] referenced (python3.10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f YTT103 sys-version-cmp-str3 sys.version compared to string (python3.10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f YTT201 sys-version-info0-eq3 sys.version_info[0] == 3 referenced (python4), use >= \u2714\ufe0f \ud83d\udee0\ufe0f YTT202 six-py3 six.PY3 referenced (python4), use not six.PY2 \u2714\ufe0f \ud83d\udee0\ufe0f YTT203 sys-version-info1-cmp-int sys.version_info[1] compared to integer (python4), compare sys.version_info to tuple \u2714\ufe0f \ud83d\udee0\ufe0f YTT204 sys-version-info-minor-cmp-int sys.version_info.minor compared to integer (python4), compare sys.version_info to tuple \u2714\ufe0f \ud83d\udee0\ufe0f YTT301 sys-version0 sys.version[0] referenced (python10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f YTT302 sys-version-cmp-str10 sys.version compared to string (python10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f YTT303 sys-version-slice1 sys.version[:1] referenced (python10), use sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-annotations-ann","title":"flake8-annotations (ANN)","text":"

        For more, see flake8-annotations on PyPI.

        For related settings, see flake8-annotations.

        Code Name Message ANN001 missing-type-function-argument Missing type annotation for function argument {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN002 missing-type-args Missing type annotation for *{name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN003 missing-type-kwargs Missing type annotation for **{name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN101 missing-type-self Missing type annotation for {name} in method \u274c \ud83d\udee0\ufe0f ANN102 missing-type-cls Missing type annotation for {name} in classmethod \u274c \ud83d\udee0\ufe0f ANN201 missing-return-type-undocumented-public-function Missing return type annotation for public function {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN202 missing-return-type-private-function Missing return type annotation for private function {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN204 missing-return-type-special-method Missing return type annotation for special method {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN205 missing-return-type-static-method Missing return type annotation for staticmethod {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN206 missing-return-type-class-method Missing return type annotation for classmethod {name} \u2714\ufe0f \ud83d\udee0\ufe0f ANN401 any-type Dynamically typed expressions (typing.Any) are disallowed in {name} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-async-async","title":"flake8-async (ASYNC)","text":"

        For more, see flake8-async on PyPI.

        Code Name Message ASYNC100 cancel-scope-no-checkpoint A with {method_name}(...): context does not contain any await statements. This makes it pointless, as the timeout can only be triggered by a checkpoint. \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC105 trio-sync-call Call to {method_name} is not immediately awaited \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC109 async-function-with-timeout Async function definition with a timeout parameter \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC110 async-busy-wait Use {module}.Event instead of awaiting {module}.sleep in a while loop \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC115 async-zero-sleep Use {module}.lowlevel.checkpoint() instead of {module}.sleep(0) \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC116 long-sleep-not-forever {module}.sleep() with >24 hour interval should usually be {module}.sleep_forever() \ud83e\uddea \ud83d\udee0\ufe0f ASYNC210 blocking-http-call-in-async-function Async functions should not call blocking HTTP methods \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC220 create-subprocess-in-async-function Async functions should not create subprocesses with blocking methods \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC221 run-process-in-async-function Async functions should not run processes with blocking methods \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC222 wait-for-process-in-async-function Async functions should not wait on processes with blocking methods \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC230 blocking-open-call-in-async-function Async functions should not open files with blocking methods like open \u2714\ufe0f \ud83d\udee0\ufe0f ASYNC251 blocking-sleep-in-async-function Async functions should not call time.sleep \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-bandit-s","title":"flake8-bandit (S)","text":"

        For more, see flake8-bandit on PyPI.

        For related settings, see flake8-bandit.

        Code Name Message S101 assert Use of assert detected \u2714\ufe0f \ud83d\udee0\ufe0f S102 exec-builtin Use of exec detected \u2714\ufe0f \ud83d\udee0\ufe0f S103 bad-file-permissions os.chmod setting a permissive mask {mask:#o} on file or directory \u2714\ufe0f \ud83d\udee0\ufe0f S104 hardcoded-bind-all-interfaces Possible binding to all interfaces \u2714\ufe0f \ud83d\udee0\ufe0f S105 hardcoded-password-string Possible hardcoded password assigned to: \"{}\" \u2714\ufe0f \ud83d\udee0\ufe0f S106 hardcoded-password-func-arg Possible hardcoded password assigned to argument: \"{}\" \u2714\ufe0f \ud83d\udee0\ufe0f S107 hardcoded-password-default Possible hardcoded password assigned to function default: \"{}\" \u2714\ufe0f \ud83d\udee0\ufe0f S108 hardcoded-temp-file Probable insecure usage of temporary file or directory: \"{}\" \u2714\ufe0f \ud83d\udee0\ufe0f S110 try-except-pass try-except-pass detected, consider logging the exception \u2714\ufe0f \ud83d\udee0\ufe0f S112 try-except-continue try-except-continue detected, consider logging the exception \u2714\ufe0f \ud83d\udee0\ufe0f S113 request-without-timeout Probable use of {module} call without timeout \u2714\ufe0f \ud83d\udee0\ufe0f S201 flask-debug-true Use of debug=True in Flask app detected \u2714\ufe0f \ud83d\udee0\ufe0f S202 tarfile-unsafe-members Uses of tarfile.extractall() \u2714\ufe0f \ud83d\udee0\ufe0f S301 suspicious-pickle-usage pickle and modules that wrap it can be unsafe when used to deserialize untrusted data, possible security issue \u2714\ufe0f \ud83d\udee0\ufe0f S302 suspicious-marshal-usage Deserialization with the marshal module is possibly dangerous \u2714\ufe0f \ud83d\udee0\ufe0f S303 suspicious-insecure-hash-usage Use of insecure MD2, MD4, MD5, or SHA1 hash function \u2714\ufe0f \ud83d\udee0\ufe0f S304 suspicious-insecure-cipher-usage Use of insecure cipher, replace with a known secure cipher such as AES \u2714\ufe0f \ud83d\udee0\ufe0f S305 suspicious-insecure-cipher-mode-usage Use of insecure block cipher mode, replace with a known secure mode such as CBC or CTR \u2714\ufe0f \ud83d\udee0\ufe0f S306 suspicious-mktemp-usage Use of insecure and deprecated function (mktemp) \u2714\ufe0f \ud83d\udee0\ufe0f S307 suspicious-eval-usage Use of possibly insecure function; consider using ast.literal_eval \u2714\ufe0f \ud83d\udee0\ufe0f S308 suspicious-mark-safe-usage Use of mark_safe may expose cross-site scripting vulnerabilities \u2714\ufe0f \ud83d\udee0\ufe0f S310 suspicious-url-open-usage Audit URL open for permitted schemes. Allowing use of file: or custom schemes is often unexpected. \u2714\ufe0f \ud83d\udee0\ufe0f S311 suspicious-non-cryptographic-random-usage Standard pseudo-random generators are not suitable for cryptographic purposes \u2714\ufe0f \ud83d\udee0\ufe0f S312 suspicious-telnet-usage Telnet is considered insecure. Use SSH or some other encrypted protocol. \u2714\ufe0f \ud83d\udee0\ufe0f S313 suspicious-xmlc-element-tree-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S314 suspicious-xml-element-tree-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S315 suspicious-xml-expat-reader-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S316 suspicious-xml-expat-builder-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S317 suspicious-xml-sax-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S318 suspicious-xml-mini-dom-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S319 suspicious-xml-pull-dom-usage Using xml to parse untrusted data is known to be vulnerable to XML attacks; use defusedxml equivalents \u2714\ufe0f \ud83d\udee0\ufe0f S320 suspicious-xmle-tree-usage Using lxml to parse untrusted data is known to be vulnerable to XML attacks \u26a0\ufe0f \ud83d\udee0\ufe0f S321 suspicious-ftp-lib-usage FTP-related functions are being called. FTP is considered insecure. Use SSH/SFTP/SCP or some other encrypted protocol. \u2714\ufe0f \ud83d\udee0\ufe0f S323 suspicious-unverified-context-usage Python allows using an insecure context via the _create_unverified_context that reverts to the previous behavior that does not validate certificates or perform hostname checks. \u2714\ufe0f \ud83d\udee0\ufe0f S324 hashlib-insecure-hash-function Probable use of insecure hash functions in {library}: {string} \u2714\ufe0f \ud83d\udee0\ufe0f S401 suspicious-telnetlib-import telnetlib and related modules are considered insecure. Use SSH or another encrypted protocol. \ud83e\uddea \ud83d\udee0\ufe0f S402 suspicious-ftplib-import ftplib and related modules are considered insecure. Use SSH, SFTP, SCP, or another encrypted protocol. \ud83e\uddea \ud83d\udee0\ufe0f S403 suspicious-pickle-import pickle, cPickle, dill, and shelve modules are possibly insecure \ud83e\uddea \ud83d\udee0\ufe0f S404 suspicious-subprocess-import subprocess module is possibly insecure \ud83e\uddea \ud83d\udee0\ufe0f S405 suspicious-xml-etree-import xml.etree methods are vulnerable to XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S406 suspicious-xml-sax-import xml.sax methods are vulnerable to XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S407 suspicious-xml-expat-import xml.dom.expatbuilder is vulnerable to XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S408 suspicious-xml-minidom-import xml.dom.minidom is vulnerable to XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S409 suspicious-xml-pulldom-import xml.dom.pulldom is vulnerable to XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S410 suspicious-lxml-import lxml is vulnerable to XML attacks \u274c \ud83d\udee0\ufe0f S411 suspicious-xmlrpc-import XMLRPC is vulnerable to remote XML attacks \ud83e\uddea \ud83d\udee0\ufe0f S412 suspicious-httpoxy-import httpoxy is a set of vulnerabilities that affect application code running inCGI, or CGI-like environments. The use of CGI for web applications should be avoided \ud83e\uddea \ud83d\udee0\ufe0f S413 suspicious-pycrypto-import pycrypto library is known to have publicly disclosed buffer overflow vulnerability \ud83e\uddea \ud83d\udee0\ufe0f S415 suspicious-pyghmi-import An IPMI-related module is being imported. Prefer an encrypted protocol over IPMI. \ud83e\uddea \ud83d\udee0\ufe0f S501 request-with-no-cert-validation Probable use of {string} call with verify=False disabling SSL certificate checks \u2714\ufe0f \ud83d\udee0\ufe0f S502 ssl-insecure-version Call made with insecure SSL protocol: {protocol} \u2714\ufe0f \ud83d\udee0\ufe0f S503 ssl-with-bad-defaults Argument default set to insecure SSL protocol: {protocol} \u2714\ufe0f \ud83d\udee0\ufe0f S504 ssl-with-no-version ssl.wrap_socket called without an `ssl_version`` \u2714\ufe0f \ud83d\udee0\ufe0f S505 weak-cryptographic-key {cryptographic_key} key sizes below {minimum_key_size} bits are considered breakable \u2714\ufe0f \ud83d\udee0\ufe0f S506 unsafe-yaml-load Probable use of unsafe loader {name} with yaml.load. Allows instantiation of arbitrary objects. Consider yaml.safe_load. \u2714\ufe0f \ud83d\udee0\ufe0f S507 ssh-no-host-key-verification Paramiko call with policy set to automatically trust the unknown host key \u2714\ufe0f \ud83d\udee0\ufe0f S508 snmp-insecure-version The use of SNMPv1 and SNMPv2 is insecure. Use SNMPv3 if able. \u2714\ufe0f \ud83d\udee0\ufe0f S509 snmp-weak-cryptography You should not use SNMPv3 without encryption. noAuthNoPriv & authNoPriv is insecure. \u2714\ufe0f \ud83d\udee0\ufe0f S601 paramiko-call Possible shell injection via Paramiko call; check inputs are properly sanitized \u2714\ufe0f \ud83d\udee0\ufe0f S602 subprocess-popen-with-shell-equals-true subprocess call with shell=True seems safe, but may be changed in the future; consider rewriting without shell \u2714\ufe0f \ud83d\udee0\ufe0f S603 subprocess-without-shell-equals-true subprocess call: check for execution of untrusted input \u2714\ufe0f \ud83d\udee0\ufe0f S604 call-with-shell-equals-true Function call with shell=True parameter identified, security issue \u2714\ufe0f \ud83d\udee0\ufe0f S605 start-process-with-a-shell Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without shell \u2714\ufe0f \ud83d\udee0\ufe0f S606 start-process-with-no-shell Starting a process without a shell \u2714\ufe0f \ud83d\udee0\ufe0f S607 start-process-with-partial-path Starting a process with a partial executable path \u2714\ufe0f \ud83d\udee0\ufe0f S608 hardcoded-sql-expression Possible SQL injection vector through string-based query construction \u2714\ufe0f \ud83d\udee0\ufe0f S609 unix-command-wildcard-injection Possible wildcard injection in call due to * usage \u2714\ufe0f \ud83d\udee0\ufe0f S610 django-extra Use of Django extra can lead to SQL injection vulnerabilities \u2714\ufe0f \ud83d\udee0\ufe0f S611 django-raw-sql Use of RawSQL can lead to SQL injection vulnerabilities \u2714\ufe0f \ud83d\udee0\ufe0f S612 logging-config-insecure-listen Use of insecure logging.config.listen detected \u2714\ufe0f \ud83d\udee0\ufe0f S701 jinja2-autoescape-false Using jinja2 templates with autoescape=False is dangerous and can lead to XSS. Ensure autoescape=True or use the select_autoescape function. \u2714\ufe0f \ud83d\udee0\ufe0f S702 mako-templates Mako templates allow HTML and JavaScript rendering by default and are inherently open to XSS attacks \u2714\ufe0f \ud83d\udee0\ufe0f S704 unsafe-markup-use Unsafe use of {name} detected \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-blind-except-ble","title":"flake8-blind-except (BLE)","text":"

        For more, see flake8-blind-except on PyPI.

        Code Name Message BLE001 blind-except Do not catch blind exception: {name} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-boolean-trap-fbt","title":"flake8-boolean-trap (FBT)","text":"

        For more, see flake8-boolean-trap on PyPI.

        For related settings, see flake8-boolean-trap.

        Code Name Message FBT001 boolean-type-hint-positional-argument Boolean-typed positional argument in function definition \u2714\ufe0f \ud83d\udee0\ufe0f FBT002 boolean-default-value-positional-argument Boolean default positional argument in function definition \u2714\ufe0f \ud83d\udee0\ufe0f FBT003 boolean-positional-value-in-call Boolean positional value in function call \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-bugbear-b","title":"flake8-bugbear (B)","text":"

        For more, see flake8-bugbear on PyPI.

        For related settings, see flake8-bugbear.

        Code Name Message B002 unary-prefix-increment-decrement Python does not support the unary prefix increment operator (++) \u2714\ufe0f \ud83d\udee0\ufe0f B003 assignment-to-os-environ Assigning to os.environ doesn't clear the environment \u2714\ufe0f \ud83d\udee0\ufe0f B004 unreliable-callable-check Using hasattr(x, \"__call__\") to test if x is callable is unreliable. Use callable(x) for consistent results. \u2714\ufe0f \ud83d\udee0\ufe0f B005 strip-with-multi-characters Using .strip() with multi-character strings is misleading \u2714\ufe0f \ud83d\udee0\ufe0f B006 mutable-argument-default Do not use mutable data structures for argument defaults \u2714\ufe0f \ud83d\udee0\ufe0f B007 unused-loop-control-variable Loop control variable {name} not used within loop body \u2714\ufe0f \ud83d\udee0\ufe0f B008 function-call-in-default-argument Do not perform function call {name} in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable \u2714\ufe0f \ud83d\udee0\ufe0f B009 get-attr-with-constant Do not call getattr with a constant attribute value. It is not any safer than normal property access. \u2714\ufe0f \ud83d\udee0\ufe0f B010 set-attr-with-constant Do not call setattr with a constant attribute value. It is not any safer than normal property access. \u2714\ufe0f \ud83d\udee0\ufe0f B011 assert-false Do not assert False (python -O removes these calls), raise AssertionError() \u2714\ufe0f \ud83d\udee0\ufe0f B012 jump-statement-in-finally {name} inside finally blocks cause exceptions to be silenced \u2714\ufe0f \ud83d\udee0\ufe0f B013 redundant-tuple-in-exception-handler A length-one tuple literal is redundant in exception handlers \u2714\ufe0f \ud83d\udee0\ufe0f B014 duplicate-handler-exception Exception handler with duplicate exception: {name} \u2714\ufe0f \ud83d\udee0\ufe0f B015 useless-comparison Pointless comparison. Did you mean to assign a value? Otherwise, prepend assert or remove it. \u2714\ufe0f \ud83d\udee0\ufe0f B016 raise-literal Cannot raise a literal. Did you intend to return it or raise an Exception? \u2714\ufe0f \ud83d\udee0\ufe0f B017 assert-raises-exception Do not assert blind exception: {exception} \u2714\ufe0f \ud83d\udee0\ufe0f B018 useless-expression Found useless expression. Either assign it to a variable or remove it. \u2714\ufe0f \ud83d\udee0\ufe0f B019 cached-instance-method Use of functools.lru_cache or functools.cache on methods can lead to memory leaks \u2714\ufe0f \ud83d\udee0\ufe0f B020 loop-variable-overrides-iterator Loop control variable {name} overrides iterable it iterates \u2714\ufe0f \ud83d\udee0\ufe0f B021 f-string-docstring f-string used as docstring. Python will interpret this as a joined string, rather than a docstring. \u2714\ufe0f \ud83d\udee0\ufe0f B022 useless-contextlib-suppress No arguments passed to contextlib.suppress. No exceptions will be suppressed and therefore this context manager is redundant \u2714\ufe0f \ud83d\udee0\ufe0f B023 function-uses-loop-variable Function definition does not bind loop variable {name} \u2714\ufe0f \ud83d\udee0\ufe0f B024 abstract-base-class-without-abstract-method {name} is an abstract base class, but it has no abstract methods or properties \u2714\ufe0f \ud83d\udee0\ufe0f B025 duplicate-try-block-exception try-except* block with duplicate exception {name} \u2714\ufe0f \ud83d\udee0\ufe0f B026 star-arg-unpacking-after-keyword-arg Star-arg unpacking after a keyword argument is strongly discouraged \u2714\ufe0f \ud83d\udee0\ufe0f B027 empty-method-without-abstract-decorator {name} is an empty method in an abstract base class, but has no abstract decorator \u2714\ufe0f \ud83d\udee0\ufe0f B028 no-explicit-stacklevel No explicit stacklevel keyword argument found \u2714\ufe0f \ud83d\udee0\ufe0f B029 except-with-empty-tuple Using except* (): with an empty tuple does not catch anything; add exceptions to handle \u2714\ufe0f \ud83d\udee0\ufe0f B030 except-with-non-exception-classes except* handlers should only be exception classes or tuples of exception classes \u2714\ufe0f \ud83d\udee0\ufe0f B031 reuse-of-groupby-generator Using the generator returned from itertools.groupby() more than once will do nothing on the second usage \u2714\ufe0f \ud83d\udee0\ufe0f B032 unintentional-type-annotation Possible unintentional type annotation (using :). Did you mean to assign (using =)? \u2714\ufe0f \ud83d\udee0\ufe0f B033 duplicate-value Sets should not contain duplicate item {value} \u2714\ufe0f \ud83d\udee0\ufe0f B034 re-sub-positional-args {method} should pass {param_name} and flags as keyword arguments to avoid confusion due to unintuitive argument positions \u2714\ufe0f \ud83d\udee0\ufe0f B035 static-key-dict-comprehension Dictionary comprehension uses static key: {key} \u2714\ufe0f \ud83d\udee0\ufe0f B039 mutable-contextvar-default Do not use mutable data structures for ContextVar defaults \u2714\ufe0f \ud83d\udee0\ufe0f B901 return-in-generator Using yield and return {value} in a generator function can lead to confusing behavior \ud83e\uddea \ud83d\udee0\ufe0f B903 class-as-data-structure Class could be dataclass or namedtuple \ud83e\uddea \ud83d\udee0\ufe0f B904 raise-without-from-inside-except Within an except* clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling \u2714\ufe0f \ud83d\udee0\ufe0f B905 zip-without-explicit-strict zip() without an explicit strict= parameter \u2714\ufe0f \ud83d\udee0\ufe0f B909 loop-iterator-mutation Mutation to loop iterable {name} during iteration \ud83e\uddea \ud83d\udee0\ufe0f B911 batched-without-explicit-strict itertools.batched() without an explicit strict parameter \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-builtins-a","title":"flake8-builtins (A)","text":"

        For more, see flake8-builtins on PyPI.

        For related settings, see flake8-builtins.

        Code Name Message A001 builtin-variable-shadowing Variable {name} is shadowing a Python builtin \u2714\ufe0f \ud83d\udee0\ufe0f A002 builtin-argument-shadowing Function argument {name} is shadowing a Python builtin \u2714\ufe0f \ud83d\udee0\ufe0f A003 builtin-attribute-shadowing Python builtin is shadowed by class attribute {name} from {row} \u2714\ufe0f \ud83d\udee0\ufe0f A004 builtin-import-shadowing Import {name} is shadowing a Python builtin \u2714\ufe0f \ud83d\udee0\ufe0f A005 stdlib-module-shadowing Module {name} shadows a Python standard-library module \u2714\ufe0f \ud83d\udee0\ufe0f A006 builtin-lambda-argument-shadowing Lambda argument {name} is shadowing a Python builtin \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-commas-com","title":"flake8-commas (COM)","text":"

        For more, see flake8-commas on PyPI.

        Code Name Message COM812 missing-trailing-comma Trailing comma missing \u2714\ufe0f \ud83d\udee0\ufe0f COM818 trailing-comma-on-bare-tuple Trailing comma on bare tuple prohibited \u2714\ufe0f \ud83d\udee0\ufe0f COM819 prohibited-trailing-comma Trailing comma prohibited \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-comprehensions-c4","title":"flake8-comprehensions (C4)","text":"

        For more, see flake8-comprehensions on PyPI.

        For related settings, see flake8-comprehensions.

        Code Name Message C400 unnecessary-generator-list Unnecessary generator (rewrite using list()) \u2714\ufe0f \ud83d\udee0\ufe0f C401 unnecessary-generator-set Unnecessary generator (rewrite using set()) \u2714\ufe0f \ud83d\udee0\ufe0f C402 unnecessary-generator-dict Unnecessary generator (rewrite as a dict comprehension) \u2714\ufe0f \ud83d\udee0\ufe0f C403 unnecessary-list-comprehension-set Unnecessary list comprehension (rewrite as a set comprehension) \u2714\ufe0f \ud83d\udee0\ufe0f C404 unnecessary-list-comprehension-dict Unnecessary list comprehension (rewrite as a dict comprehension) \u2714\ufe0f \ud83d\udee0\ufe0f C405 unnecessary-literal-set Unnecessary {kind} literal (rewrite as a set literal) \u2714\ufe0f \ud83d\udee0\ufe0f C406 unnecessary-literal-dict Unnecessary {obj_type} literal (rewrite as a dict literal) \u2714\ufe0f \ud83d\udee0\ufe0f C408 unnecessary-collection-call Unnecessary {kind}() call (rewrite as a literal) \u2714\ufe0f \ud83d\udee0\ufe0f C409 unnecessary-literal-within-tuple-call Unnecessary list literal passed to tuple() (rewrite as a tuple literal) \u2714\ufe0f \ud83d\udee0\ufe0f C410 unnecessary-literal-within-list-call Unnecessary list literal passed to list() (remove the outer call to list()) \u2714\ufe0f \ud83d\udee0\ufe0f C411 unnecessary-list-call Unnecessary list() call (remove the outer call to list()) \u2714\ufe0f \ud83d\udee0\ufe0f C413 unnecessary-call-around-sorted Unnecessary {func}() call around sorted() \u2714\ufe0f \ud83d\udee0\ufe0f C414 unnecessary-double-cast-or-process Unnecessary {inner}() call within {outer}() \u2714\ufe0f \ud83d\udee0\ufe0f C415 unnecessary-subscript-reversal Unnecessary subscript reversal of iterable within {func}() \u2714\ufe0f \ud83d\udee0\ufe0f C416 unnecessary-comprehension Unnecessary {kind} comprehension (rewrite using {kind}()) \u2714\ufe0f \ud83d\udee0\ufe0f C417 unnecessary-map Unnecessary map() usage (rewrite using a {object_type}) \u2714\ufe0f \ud83d\udee0\ufe0f C418 unnecessary-literal-within-dict-call Unnecessary dict {kind} passed to dict() (remove the outer call to dict()) \u2714\ufe0f \ud83d\udee0\ufe0f C419 unnecessary-comprehension-in-call Unnecessary list comprehension \u2714\ufe0f \ud83d\udee0\ufe0f C420 unnecessary-dict-comprehension-for-iterable Unnecessary dict comprehension for iterable; use dict.fromkeys instead \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-copyright-cpy","title":"flake8-copyright (CPY)","text":"

        For more, see flake8-copyright on PyPI.

        For related settings, see flake8-copyright.

        Code Name Message CPY001 missing-copyright-notice Missing copyright notice at top of file \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-datetimez-dtz","title":"flake8-datetimez (DTZ)","text":"

        For more, see flake8-datetimez on PyPI.

        Code Name Message DTZ001 call-datetime-without-tzinfo datetime.datetime() called without a tzinfo argument \u2714\ufe0f \ud83d\udee0\ufe0f DTZ002 call-datetime-today datetime.datetime.today() used \u2714\ufe0f \ud83d\udee0\ufe0f DTZ003 call-datetime-utcnow datetime.datetime.utcnow() used \u2714\ufe0f \ud83d\udee0\ufe0f DTZ004 call-datetime-utcfromtimestamp datetime.datetime.utcfromtimestamp() used \u2714\ufe0f \ud83d\udee0\ufe0f DTZ005 call-datetime-now-without-tzinfo datetime.datetime.now() called without a tz argument \u2714\ufe0f \ud83d\udee0\ufe0f DTZ006 call-datetime-fromtimestamp datetime.datetime.fromtimestamp() called without a tz argument \u2714\ufe0f \ud83d\udee0\ufe0f DTZ007 call-datetime-strptime-without-zone Naive datetime constructed using datetime.datetime.strptime() without %z \u2714\ufe0f \ud83d\udee0\ufe0f DTZ011 call-date-today datetime.date.today() used \u2714\ufe0f \ud83d\udee0\ufe0f DTZ012 call-date-fromtimestamp datetime.date.fromtimestamp() used \u2714\ufe0f \ud83d\udee0\ufe0f DTZ901 datetime-min-max Use of datetime.datetime.{min_max} without timezone information \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-debugger-t10","title":"flake8-debugger (T10)","text":"

        For more, see flake8-debugger on PyPI.

        Code Name Message T100 debugger Trace found: {name} used \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-django-dj","title":"flake8-django (DJ)","text":"

        For more, see flake8-django on PyPI.

        Code Name Message DJ001 django-nullable-model-string-field Avoid using null=True on string-based fields such as {field_name} \u2714\ufe0f \ud83d\udee0\ufe0f DJ003 django-locals-in-render-function Avoid passing locals() as context to a render function \u2714\ufe0f \ud83d\udee0\ufe0f DJ006 django-exclude-with-model-form Do not use exclude with ModelForm, use fields instead \u2714\ufe0f \ud83d\udee0\ufe0f DJ007 django-all-with-model-form Do not use __all__ with ModelForm, use fields instead \u2714\ufe0f \ud83d\udee0\ufe0f DJ008 django-model-without-dunder-str Model does not define __str__ method \u2714\ufe0f \ud83d\udee0\ufe0f DJ012 django-unordered-body-content-in-model Order of model's inner classes, methods, and fields does not follow the Django Style Guide: {element_type} should come before {prev_element_type} \u2714\ufe0f \ud83d\udee0\ufe0f DJ013 django-non-leading-receiver-decorator @receiver decorator must be on top of all the other decorators \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-errmsg-em","title":"flake8-errmsg (EM)","text":"

        For more, see flake8-errmsg on PyPI.

        For related settings, see flake8-errmsg.

        Code Name Message EM101 raw-string-in-exception Exception must not use a string literal, assign to variable first \u2714\ufe0f \ud83d\udee0\ufe0f EM102 f-string-in-exception Exception must not use an f-string literal, assign to variable first \u2714\ufe0f \ud83d\udee0\ufe0f EM103 dot-format-in-exception Exception must not use a .format() string directly, assign to variable first \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-executable-exe","title":"flake8-executable (EXE)","text":"

        For more, see flake8-executable on PyPI.

        Code Name Message EXE001 shebang-not-executable Shebang is present but file is not executable \u2714\ufe0f \ud83d\udee0\ufe0f EXE002 shebang-missing-executable-file The file is executable but no shebang is present \u2714\ufe0f \ud83d\udee0\ufe0f EXE003 shebang-missing-python Shebang should contain python, pytest, or uv run \u2714\ufe0f \ud83d\udee0\ufe0f EXE004 shebang-leading-whitespace Avoid whitespace before shebang \u2714\ufe0f \ud83d\udee0\ufe0f EXE005 shebang-not-first-line Shebang should be at the beginning of the file \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-fixme-fix","title":"flake8-fixme (FIX)","text":"

        For more, see flake8-fixme on GitHub.

        Code Name Message FIX001 line-contains-fixme Line contains FIXME, consider resolving the issue \u2714\ufe0f \ud83d\udee0\ufe0f FIX002 line-contains-todo Line contains TODO, consider resolving the issue \u2714\ufe0f \ud83d\udee0\ufe0f FIX003 line-contains-xxx Line contains XXX, consider resolving the issue \u2714\ufe0f \ud83d\udee0\ufe0f FIX004 line-contains-hack Line contains HACK, consider resolving the issue \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-future-annotations-fa","title":"flake8-future-annotations (FA)","text":"

        For more, see flake8-future-annotations on PyPI.

        Code Name Message FA100 future-rewritable-type-annotation Add from __future__ import annotations to simplify {name} \u2714\ufe0f \ud83d\udee0\ufe0f FA102 future-required-type-annotation Missing from __future__ import annotations, but uses {reason} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-gettext-int","title":"flake8-gettext (INT)","text":"

        For more, see flake8-gettext on PyPI.

        For related settings, see flake8-gettext.

        Code Name Message INT001 f-string-in-get-text-func-call f-string is resolved before function call; consider _(\"string %s\") % arg \u2714\ufe0f \ud83d\udee0\ufe0f INT002 format-in-get-text-func-call format method argument is resolved before function call; consider _(\"string %s\") % arg \u2714\ufe0f \ud83d\udee0\ufe0f INT003 printf-in-get-text-func-call printf-style format is resolved before function call; consider _(\"string %s\") % arg \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-implicit-str-concat-isc","title":"flake8-implicit-str-concat (ISC)","text":"

        For more, see flake8-implicit-str-concat on PyPI.

        For related settings, see flake8-implicit-str-concat.

        Code Name Message ISC001 single-line-implicit-string-concatenation Implicitly concatenated string literals on one line \u2714\ufe0f \ud83d\udee0\ufe0f ISC002 multi-line-implicit-string-concatenation Implicitly concatenated string literals over multiple lines \u2714\ufe0f \ud83d\udee0\ufe0f ISC003 explicit-string-concatenation Explicitly concatenated string should be implicitly concatenated \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-import-conventions-icn","title":"flake8-import-conventions (ICN)","text":"

        For more, see flake8-import-conventions on GitHub.

        For related settings, see flake8-import-conventions.

        Code Name Message ICN001 unconventional-import-alias {name} should be imported as {asname} \u2714\ufe0f \ud83d\udee0\ufe0f ICN002 banned-import-alias {name} should not be imported as {asname} \u2714\ufe0f \ud83d\udee0\ufe0f ICN003 banned-import-from Members of {name} should not be imported explicitly \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-logging-log","title":"flake8-logging (LOG)","text":"

        For more, see flake8-logging on PyPI.

        Code Name Message LOG001 direct-logger-instantiation Use logging.getLogger() to instantiate loggers \u2714\ufe0f \ud83d\udee0\ufe0f LOG002 invalid-get-logger-argument Use __name__ with logging.getLogger() \u2714\ufe0f \ud83d\udee0\ufe0f LOG004 log-exception-outside-except-handler .exception() call outside exception handlers \ud83e\uddea \ud83d\udee0\ufe0f LOG007 exception-without-exc-info Use of logging.exception with falsy exc_info \u2714\ufe0f \ud83d\udee0\ufe0f LOG009 undocumented-warn Use of undocumented logging.WARN constant \u2714\ufe0f \ud83d\udee0\ufe0f LOG014 exc-info-outside-except-handler exc_info= outside exception handlers \ud83e\uddea \ud83d\udee0\ufe0f LOG015 root-logger-call {}() call on root logger \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-logging-format-g","title":"flake8-logging-format (G)","text":"

        For more, see flake8-logging-format on PyPI.

        Code Name Message G001 logging-string-format Logging statement uses str.format \u2714\ufe0f \ud83d\udee0\ufe0f G002 logging-percent-format Logging statement uses % \u2714\ufe0f \ud83d\udee0\ufe0f G003 logging-string-concat Logging statement uses + \u2714\ufe0f \ud83d\udee0\ufe0f G004 logging-f-string Logging statement uses f-string \u2714\ufe0f \ud83d\udee0\ufe0f G010 logging-warn Logging statement uses warn instead of warning \u2714\ufe0f \ud83d\udee0\ufe0f G101 logging-extra-attr-clash Logging statement uses an extra field that clashes with a LogRecord field: {key} \u2714\ufe0f \ud83d\udee0\ufe0f G201 logging-exc-info Logging .exception(...) should be used instead of .error(..., exc_info=True) \u2714\ufe0f \ud83d\udee0\ufe0f G202 logging-redundant-exc-info Logging statement has redundant exc_info \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-no-pep420-inp","title":"flake8-no-pep420 (INP)","text":"

        For more, see flake8-no-pep420 on PyPI.

        Code Name Message INP001 implicit-namespace-package File {filename} is part of an implicit namespace package. Add an __init__.py. \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-pie-pie","title":"flake8-pie (PIE)","text":"

        For more, see flake8-pie on PyPI.

        Code Name Message PIE790 unnecessary-placeholder Unnecessary pass statement \u2714\ufe0f \ud83d\udee0\ufe0f PIE794 duplicate-class-field-definition Class field {name} is defined multiple times \u2714\ufe0f \ud83d\udee0\ufe0f PIE796 non-unique-enums Enum contains duplicate value: {value} \u2714\ufe0f \ud83d\udee0\ufe0f PIE800 unnecessary-spread Unnecessary spread ** \u2714\ufe0f \ud83d\udee0\ufe0f PIE804 unnecessary-dict-kwargs Unnecessary dict kwargs \u2714\ufe0f \ud83d\udee0\ufe0f PIE807 reimplemented-container-builtin Prefer {container} over useless lambda \u2714\ufe0f \ud83d\udee0\ufe0f PIE808 unnecessary-range-start Unnecessary start argument in range \u2714\ufe0f \ud83d\udee0\ufe0f PIE810 multiple-starts-ends-with Call {attr} once with a tuple \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-print-t20","title":"flake8-print (T20)","text":"

        For more, see flake8-print on PyPI.

        Code Name Message T201 print print found \u2714\ufe0f \ud83d\udee0\ufe0f T203 p-print pprint found \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-pyi-pyi","title":"flake8-pyi (PYI)","text":"

        For more, see flake8-pyi on PyPI.

        Code Name Message PYI001 unprefixed-type-param Name of private {kind} must start with _ \u2714\ufe0f \ud83d\udee0\ufe0f PYI002 complex-if-statement-in-stub if test must be a simple comparison against sys.platform or sys.version_info \u2714\ufe0f \ud83d\udee0\ufe0f PYI003 unrecognized-version-info-check Unrecognized sys.version_info check \u2714\ufe0f \ud83d\udee0\ufe0f PYI004 patch-version-comparison Version comparison must use only major and minor version \u2714\ufe0f \ud83d\udee0\ufe0f PYI005 wrong-tuple-length-version-comparison Version comparison must be against a length-{expected_length} tuple \u2714\ufe0f \ud83d\udee0\ufe0f PYI006 bad-version-info-comparison Use < or >= for sys.version_info comparisons \u2714\ufe0f \ud83d\udee0\ufe0f PYI007 unrecognized-platform-check Unrecognized sys.platform check \u2714\ufe0f \ud83d\udee0\ufe0f PYI008 unrecognized-platform-name Unrecognized platform {platform} \u2714\ufe0f \ud83d\udee0\ufe0f PYI009 pass-statement-stub-body Empty body should contain ..., not pass \u2714\ufe0f \ud83d\udee0\ufe0f PYI010 non-empty-stub-body Function body must contain only ... \u2714\ufe0f \ud83d\udee0\ufe0f PYI011 typed-argument-default-in-stub Only simple default values allowed for typed arguments \u2714\ufe0f \ud83d\udee0\ufe0f PYI012 pass-in-class-body Class body must not contain pass \u2714\ufe0f \ud83d\udee0\ufe0f PYI013 ellipsis-in-non-empty-class-body Non-empty class body must not contain ... \u2714\ufe0f \ud83d\udee0\ufe0f PYI014 argument-default-in-stub Only simple default values allowed for arguments \u2714\ufe0f \ud83d\udee0\ufe0f PYI015 assignment-default-in-stub Only simple default values allowed for assignments \u2714\ufe0f \ud83d\udee0\ufe0f PYI016 duplicate-union-member Duplicate union member {} \u2714\ufe0f \ud83d\udee0\ufe0f PYI017 complex-assignment-in-stub Stubs should not contain assignments to attributes or multiple targets \u2714\ufe0f \ud83d\udee0\ufe0f PYI018 unused-private-type-var Private {type_var_like_kind} {type_var_like_name} is never used \u2714\ufe0f \ud83d\udee0\ufe0f PYI019 custom-type-var-for-self Use Self instead of custom TypeVar {} \u2714\ufe0f \ud83d\udee0\ufe0f PYI020 quoted-annotation-in-stub Quoted annotations should not be included in stubs \u2714\ufe0f \ud83d\udee0\ufe0f PYI021 docstring-in-stub Docstrings should not be included in stubs \u2714\ufe0f \ud83d\udee0\ufe0f PYI024 collections-named-tuple Use typing.NamedTuple instead of collections.namedtuple \u2714\ufe0f \ud83d\udee0\ufe0f PYI025 unaliased-collections-abc-set-import Use from collections.abc import Set as AbstractSet to avoid confusion with the set builtin \u2714\ufe0f \ud83d\udee0\ufe0f PYI026 type-alias-without-annotation Use {module}.TypeAlias for type alias, e.g., {name}: TypeAlias = {value} \u2714\ufe0f \ud83d\udee0\ufe0f PYI029 str-or-repr-defined-in-stub Defining {name} in a stub is almost always redundant \u2714\ufe0f \ud83d\udee0\ufe0f PYI030 unnecessary-literal-union Multiple literal members in a union. Use a single literal, e.g. Literal[{}] \u2714\ufe0f \ud83d\udee0\ufe0f PYI032 any-eq-ne-annotation Prefer object to Any for the second parameter to {method_name} \u2714\ufe0f \ud83d\udee0\ufe0f PYI033 type-comment-in-stub Don't use type comments in stub file \u2714\ufe0f \ud83d\udee0\ufe0f PYI034 non-self-return-type __new__ methods usually return self at runtime \u2714\ufe0f \ud83d\udee0\ufe0f PYI035 unassigned-special-variable-in-stub {name} in a stub file must have a value, as it has the same semantics as {name} at runtime \u2714\ufe0f \ud83d\udee0\ufe0f PYI036 bad-exit-annotation Star-args in {method_name} should be annotated with object \u2714\ufe0f \ud83d\udee0\ufe0f PYI041 redundant-numeric-union Use {supertype} instead of {subtype} | {supertype} \u2714\ufe0f \ud83d\udee0\ufe0f PYI042 snake-case-type-alias Type alias {name} should be CamelCase \u2714\ufe0f \ud83d\udee0\ufe0f PYI043 t-suffixed-type-alias Private type alias {name} should not be suffixed with T (the T suffix implies that an object is a TypeVar) \u2714\ufe0f \ud83d\udee0\ufe0f PYI044 future-annotations-in-stub from __future__ import annotations has no effect in stub files, since type checkers automatically treat stubs as having those semantics \u2714\ufe0f \ud83d\udee0\ufe0f PYI045 iter-method-return-iterable __aiter__ methods should return an AsyncIterator, not an AsyncIterable \u2714\ufe0f \ud83d\udee0\ufe0f PYI046 unused-private-protocol Private protocol {name} is never used \u2714\ufe0f \ud83d\udee0\ufe0f PYI047 unused-private-type-alias Private TypeAlias {name} is never used \u2714\ufe0f \ud83d\udee0\ufe0f PYI048 stub-body-multiple-statements Function body must contain exactly one statement \u2714\ufe0f \ud83d\udee0\ufe0f PYI049 unused-private-typed-dict Private TypedDict {name} is never used \u2714\ufe0f \ud83d\udee0\ufe0f PYI050 no-return-argument-annotation-in-stub Prefer {module}.Never over NoReturn for argument annotations \u2714\ufe0f \ud83d\udee0\ufe0f PYI051 redundant-literal-union Literal[{literal}] is redundant in a union with {builtin_type} \u2714\ufe0f \ud83d\udee0\ufe0f PYI052 unannotated-assignment-in-stub Need type annotation for {name} \u2714\ufe0f \ud83d\udee0\ufe0f PYI053 string-or-bytes-too-long String and bytes literals longer than 50 characters are not permitted \u2714\ufe0f \ud83d\udee0\ufe0f PYI054 numeric-literal-too-long Numeric literals with a string representation longer than ten characters are not permitted \u2714\ufe0f \ud83d\udee0\ufe0f PYI055 unnecessary-type-union Multiple type members in a union. Combine them into one, e.g., type[{union_str}]. \u2714\ufe0f \ud83d\udee0\ufe0f PYI056 unsupported-method-call-on-all Calling .{name}() on __all__ may not be supported by all type checkers (use += instead) \u2714\ufe0f \ud83d\udee0\ufe0f PYI057 byte-string-usage Do not use {origin}.ByteString, which has unclear semantics and is deprecated \u2714\ufe0f \ud83d\udee0\ufe0f PYI058 generator-return-from-iter-method Use {return_type} as the return value for simple {method} methods \u2714\ufe0f \ud83d\udee0\ufe0f PYI059 generic-not-last-base-class Generic[] should always be the last base class \ud83e\uddea \ud83d\udee0\ufe0f PYI061 redundant-none-literal Use None rather than Literal[None] \ud83e\uddea \ud83d\udee0\ufe0f PYI062 duplicate-literal-member Duplicate literal member {} \u2714\ufe0f \ud83d\udee0\ufe0f PYI063 pep484-style-positional-only-parameter Use PEP 570 syntax for positional-only parameters \u2714\ufe0f \ud83d\udee0\ufe0f PYI064 redundant-final-literal Final[Literal[{literal}]] can be replaced with a bare Final \u2714\ufe0f \ud83d\udee0\ufe0f PYI066 bad-version-info-order Put branches for newer Python versions first when branching on sys.version_info comparisons \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-pytest-style-pt","title":"flake8-pytest-style (PT)","text":"

        For more, see flake8-pytest-style on PyPI.

        For related settings, see flake8-pytest-style.

        Code Name Message PT001 pytest-fixture-incorrect-parentheses-style Use @pytest.fixture{expected} over @pytest.fixture{actual} \u2714\ufe0f \ud83d\udee0\ufe0f PT002 pytest-fixture-positional-args Configuration for fixture {function} specified via positional args, use kwargs \u2714\ufe0f \ud83d\udee0\ufe0f PT003 pytest-extraneous-scope-function scope='function' is implied in @pytest.fixture() \u2714\ufe0f \ud83d\udee0\ufe0f PT004 pytest-missing-fixture-name-underscore Fixture {function} does not return anything, add leading underscore \u274c \ud83d\udee0\ufe0f PT005 pytest-incorrect-fixture-name-underscore Fixture {function} returns a value, remove leading underscore \u274c \ud83d\udee0\ufe0f PT006 pytest-parametrize-names-wrong-type Wrong type passed to first argument of pytest.mark.parametrize; expected {expected_string} \u2714\ufe0f \ud83d\udee0\ufe0f PT007 pytest-parametrize-values-wrong-type Wrong values type in pytest.mark.parametrize expected {values} of {row} \u2714\ufe0f \ud83d\udee0\ufe0f PT008 pytest-patch-with-lambda Use return_value= instead of patching with lambda \u2714\ufe0f \ud83d\udee0\ufe0f PT009 pytest-unittest-assertion Use a regular assert instead of unittest-style {assertion} \u2714\ufe0f \ud83d\udee0\ufe0f PT010 pytest-raises-without-exception Set the expected exception in pytest.raises() \u2714\ufe0f \ud83d\udee0\ufe0f PT011 pytest-raises-too-broad pytest.raises({exception}) is too broad, set the match parameter or use a more specific exception \u2714\ufe0f \ud83d\udee0\ufe0f PT012 pytest-raises-with-multiple-statements pytest.raises() block should contain a single simple statement \u2714\ufe0f \ud83d\udee0\ufe0f PT013 pytest-incorrect-pytest-import Incorrect import of pytest; use import pytest instead \u2714\ufe0f \ud83d\udee0\ufe0f PT014 pytest-duplicate-parametrize-test-cases Duplicate of test case at index {index} in pytest.mark.parametrize \u2714\ufe0f \ud83d\udee0\ufe0f PT015 pytest-assert-always-false Assertion always fails, replace with pytest.fail() \u2714\ufe0f \ud83d\udee0\ufe0f PT016 pytest-fail-without-message No message passed to pytest.fail() \u2714\ufe0f \ud83d\udee0\ufe0f PT017 pytest-assert-in-except Found assertion on exception {name} in except block, use pytest.raises() instead \u2714\ufe0f \ud83d\udee0\ufe0f PT018 pytest-composite-assertion Assertion should be broken down into multiple parts \u2714\ufe0f \ud83d\udee0\ufe0f PT019 pytest-fixture-param-without-value Fixture {name} without value is injected as parameter, use @pytest.mark.usefixtures instead \u2714\ufe0f \ud83d\udee0\ufe0f PT020 pytest-deprecated-yield-fixture @pytest.yield_fixture is deprecated, use @pytest.fixture \u2714\ufe0f \ud83d\udee0\ufe0f PT021 pytest-fixture-finalizer-callback Use yield instead of request.addfinalizer \u2714\ufe0f \ud83d\udee0\ufe0f PT022 pytest-useless-yield-fixture No teardown in fixture {name}, use return instead of yield \u2714\ufe0f \ud83d\udee0\ufe0f PT023 pytest-incorrect-mark-parentheses-style Use @pytest.mark.{mark_name}{expected_parens} over @pytest.mark.{mark_name}{actual_parens} \u2714\ufe0f \ud83d\udee0\ufe0f PT024 pytest-unnecessary-asyncio-mark-on-fixture pytest.mark.asyncio is unnecessary for fixtures \u2714\ufe0f \ud83d\udee0\ufe0f PT025 pytest-erroneous-use-fixtures-on-fixture pytest.mark.usefixtures has no effect on fixtures \u2714\ufe0f \ud83d\udee0\ufe0f PT026 pytest-use-fixtures-without-parameters Useless pytest.mark.usefixtures without parameters \u2714\ufe0f \ud83d\udee0\ufe0f PT027 pytest-unittest-raises-assertion Use pytest.raises instead of unittest-style {assertion} \u2714\ufe0f \ud83d\udee0\ufe0f PT028 pytest-parameter-with-default-argument Test function parameter {} has default argument \ud83e\uddea \ud83d\udee0\ufe0f PT029 pytest-warns-without-warning Set the expected warning in pytest.warns() \ud83e\uddea \ud83d\udee0\ufe0f PT030 pytest-warns-too-broad pytest.warns({warning}) is too broad, set the match parameter or use a more specific warning \ud83e\uddea \ud83d\udee0\ufe0f PT031 pytest-warns-with-multiple-statements pytest.warns() block should contain a single simple statement \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-quotes-q","title":"flake8-quotes (Q)","text":"

        For more, see flake8-quotes on PyPI.

        For related settings, see flake8-quotes.

        Code Name Message Q000 bad-quotes-inline-string Single quotes found but double quotes preferred \u2714\ufe0f \ud83d\udee0\ufe0f Q001 bad-quotes-multiline-string Single quote multiline found but double quotes preferred \u2714\ufe0f \ud83d\udee0\ufe0f Q002 bad-quotes-docstring Single quote docstring found but double quotes preferred \u2714\ufe0f \ud83d\udee0\ufe0f Q003 avoidable-escaped-quote Change outer quotes to avoid escaping inner quotes \u2714\ufe0f \ud83d\udee0\ufe0f Q004 unnecessary-escaped-quote Unnecessary escape on inner quote character \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-raise-rse","title":"flake8-raise (RSE)","text":"

        For more, see flake8-raise on PyPI.

        Code Name Message RSE102 unnecessary-paren-on-raise-exception Unnecessary parentheses on raised exception \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-return-ret","title":"flake8-return (RET)","text":"

        For more, see flake8-return on PyPI.

        Code Name Message RET501 unnecessary-return-none Do not explicitly return None in function if it is the only possible return value \u2714\ufe0f \ud83d\udee0\ufe0f RET502 implicit-return-value Do not implicitly return None in function able to return non-None value \u2714\ufe0f \ud83d\udee0\ufe0f RET503 implicit-return Missing explicit return at the end of function able to return non-None value \u2714\ufe0f \ud83d\udee0\ufe0f RET504 unnecessary-assign Unnecessary assignment to {name} before return statement \u2714\ufe0f \ud83d\udee0\ufe0f RET505 superfluous-else-return Unnecessary {branch} after return statement \u2714\ufe0f \ud83d\udee0\ufe0f RET506 superfluous-else-raise Unnecessary {branch} after raise statement \u2714\ufe0f \ud83d\udee0\ufe0f RET507 superfluous-else-continue Unnecessary {branch} after continue statement \u2714\ufe0f \ud83d\udee0\ufe0f RET508 superfluous-else-break Unnecessary {branch} after break statement \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-self-slf","title":"flake8-self (SLF)","text":"

        For more, see flake8-self on PyPI.

        For related settings, see flake8-self.

        Code Name Message SLF001 private-member-access Private member accessed: {access} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-simplify-sim","title":"flake8-simplify (SIM)","text":"

        For more, see flake8-simplify on PyPI.

        Code Name Message SIM101 duplicate-isinstance-call Multiple isinstance calls for {name}, merge into a single call \u2714\ufe0f \ud83d\udee0\ufe0f SIM102 collapsible-if Use a single if statement instead of nested if statements \u2714\ufe0f \ud83d\udee0\ufe0f SIM103 needless-bool Return the condition {condition} directly \u2714\ufe0f \ud83d\udee0\ufe0f SIM105 suppressible-exception Use contextlib.suppress({exception}) instead of try-except-pass \u2714\ufe0f \ud83d\udee0\ufe0f SIM107 return-in-try-except-finally Don't use return in try-except and finally \u2714\ufe0f \ud83d\udee0\ufe0f SIM108 if-else-block-instead-of-if-exp Use ternary operator {contents} instead of if-else-block \u2714\ufe0f \ud83d\udee0\ufe0f SIM109 compare-with-tuple Use {replacement} instead of multiple equality comparisons \u2714\ufe0f \ud83d\udee0\ufe0f SIM110 reimplemented-builtin Use {replacement} instead of for loop \u2714\ufe0f \ud83d\udee0\ufe0f SIM112 uncapitalized-environment-variables Use capitalized environment variable {expected} instead of {actual} \u2714\ufe0f \ud83d\udee0\ufe0f SIM113 enumerate-for-loop Use enumerate() for index variable {index} in for loop \u2714\ufe0f \ud83d\udee0\ufe0f SIM114 if-with-same-arms Combine if branches using logical or operator \u2714\ufe0f \ud83d\udee0\ufe0f SIM115 open-file-with-context-handler Use a context manager for opening files \u2714\ufe0f \ud83d\udee0\ufe0f SIM116 if-else-block-instead-of-dict-lookup Use a dictionary instead of consecutive if statements \u2714\ufe0f \ud83d\udee0\ufe0f SIM117 multiple-with-statements Use a single with statement with multiple contexts instead of nested with statements \u2714\ufe0f \ud83d\udee0\ufe0f SIM118 in-dict-keys Use key {operator} dict instead of key {operator} dict.keys() \u2714\ufe0f \ud83d\udee0\ufe0f SIM201 negate-equal-op Use {left} != {right} instead of not {left} == {right} \u2714\ufe0f \ud83d\udee0\ufe0f SIM202 negate-not-equal-op Use {left} == {right} instead of not {left} != {right} \u2714\ufe0f \ud83d\udee0\ufe0f SIM208 double-negation Use {expr} instead of not (not {expr}) \u2714\ufe0f \ud83d\udee0\ufe0f SIM210 if-expr-with-true-false Remove unnecessary True if ... else False \u2714\ufe0f \ud83d\udee0\ufe0f SIM211 if-expr-with-false-true Use not ... instead of False if ... else True \u2714\ufe0f \ud83d\udee0\ufe0f SIM212 if-expr-with-twisted-arms Use {expr_else} if {expr_else} else {expr_body} instead of {expr_body} if not {expr_else} else {expr_else} \u2714\ufe0f \ud83d\udee0\ufe0f SIM220 expr-and-not-expr Use False instead of {name} and not {name} \u2714\ufe0f \ud83d\udee0\ufe0f SIM221 expr-or-not-expr Use True instead of {name} or not {name} \u2714\ufe0f \ud83d\udee0\ufe0f SIM222 expr-or-true Use {expr} instead of {replaced} \u2714\ufe0f \ud83d\udee0\ufe0f SIM223 expr-and-false Use {expr} instead of {replaced} \u2714\ufe0f \ud83d\udee0\ufe0f SIM300 yoda-conditions Yoda condition detected \u2714\ufe0f \ud83d\udee0\ufe0f SIM401 if-else-block-instead-of-dict-get Use {contents} instead of an if block \u2714\ufe0f \ud83d\udee0\ufe0f SIM905 split-static-string Consider using a list literal instead of str.split \u2714\ufe0f \ud83d\udee0\ufe0f SIM910 dict-get-with-none-default Use {expected} instead of {actual} \u2714\ufe0f \ud83d\udee0\ufe0f SIM911 zip-dict-keys-and-values Use {expected} instead of {actual} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-slots-slot","title":"flake8-slots (SLOT)","text":"

        For more, see flake8-slots on PyPI.

        Code Name Message SLOT000 no-slots-in-str-subclass Subclasses of str should define __slots__ \u2714\ufe0f \ud83d\udee0\ufe0f SLOT001 no-slots-in-tuple-subclass Subclasses of tuple should define __slots__ \u2714\ufe0f \ud83d\udee0\ufe0f SLOT002 no-slots-in-namedtuple-subclass Subclasses of {namedtuple_kind} should define __slots__ \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-tidy-imports-tid","title":"flake8-tidy-imports (TID)","text":"

        For more, see flake8-tidy-imports on PyPI.

        For related settings, see flake8-tidy-imports.

        Code Name Message TID251 banned-api {name} is banned: {message} \u2714\ufe0f \ud83d\udee0\ufe0f TID252 relative-imports Prefer absolute imports over relative imports from parent modules \u2714\ufe0f \ud83d\udee0\ufe0f TID253 banned-module-level-imports {name} is banned at the module level \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-todos-td","title":"flake8-todos (TD)","text":"

        For more, see flake8-todos on GitHub.

        Code Name Message TD001 invalid-todo-tag Invalid TODO tag: {tag} \u2714\ufe0f \ud83d\udee0\ufe0f TD002 missing-todo-author Missing author in TODO; try: # TODO(<author_name>): ... or # TODO @<author_name>: ... \u2714\ufe0f \ud83d\udee0\ufe0f TD003 missing-todo-link Missing issue link for this TODO \u2714\ufe0f \ud83d\udee0\ufe0f TD004 missing-todo-colon Missing colon in TODO \u2714\ufe0f \ud83d\udee0\ufe0f TD005 missing-todo-description Missing issue description after TODO \u2714\ufe0f \ud83d\udee0\ufe0f TD006 invalid-todo-capitalization Invalid TODO capitalization: {tag} should be TODO \u2714\ufe0f \ud83d\udee0\ufe0f TD007 missing-space-after-todo-colon Missing space after colon in TODO \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-type-checking-tc","title":"flake8-type-checking (TC)","text":"

        For more, see flake8-type-checking on PyPI.

        For related settings, see flake8-type-checking.

        Code Name Message TC001 typing-only-first-party-import Move application import {} into a type-checking block \u2714\ufe0f \ud83d\udee0\ufe0f TC002 typing-only-third-party-import Move third-party import {} into a type-checking block \u2714\ufe0f \ud83d\udee0\ufe0f TC003 typing-only-standard-library-import Move standard library import {} into a type-checking block \u2714\ufe0f \ud83d\udee0\ufe0f TC004 runtime-import-in-type-checking-block Move import {qualified_name} out of type-checking block. Import is used for more than type hinting. \u2714\ufe0f \ud83d\udee0\ufe0f TC005 empty-type-checking-block Found empty type-checking block \u2714\ufe0f \ud83d\udee0\ufe0f TC006 runtime-cast-value Add quotes to type expression in typing.cast() \u2714\ufe0f \ud83d\udee0\ufe0f TC007 unquoted-type-alias Add quotes to type alias \u2714\ufe0f \ud83d\udee0\ufe0f TC008 quoted-type-alias Remove quotes from type alias \ud83e\uddea \ud83d\udee0\ufe0f TC010 runtime-string-union Invalid string member in X | Y-style union type \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-unused-arguments-arg","title":"flake8-unused-arguments (ARG)","text":"

        For more, see flake8-unused-arguments on PyPI.

        For related settings, see flake8-unused-arguments.

        Code Name Message ARG001 unused-function-argument Unused function argument: {name} \u2714\ufe0f \ud83d\udee0\ufe0f ARG002 unused-method-argument Unused method argument: {name} \u2714\ufe0f \ud83d\udee0\ufe0f ARG003 unused-class-method-argument Unused class method argument: {name} \u2714\ufe0f \ud83d\udee0\ufe0f ARG004 unused-static-method-argument Unused static method argument: {name} \u2714\ufe0f \ud83d\udee0\ufe0f ARG005 unused-lambda-argument Unused lambda argument: {name} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flake8-use-pathlib-pth","title":"flake8-use-pathlib (PTH)","text":"

        For more, see flake8-use-pathlib on PyPI.

        Code Name Message PTH100 os-path-abspath os.path.abspath() should be replaced by Path.resolve() \u2714\ufe0f \ud83d\udee0\ufe0f PTH101 os-chmod os.chmod() should be replaced by Path.chmod() \u2714\ufe0f \ud83d\udee0\ufe0f PTH102 os-mkdir os.mkdir() should be replaced by Path.mkdir() \u2714\ufe0f \ud83d\udee0\ufe0f PTH103 os-makedirs os.makedirs() should be replaced by Path.mkdir(parents=True) \u2714\ufe0f \ud83d\udee0\ufe0f PTH104 os-rename os.rename() should be replaced by Path.rename() \u2714\ufe0f \ud83d\udee0\ufe0f PTH105 os-replace os.replace() should be replaced by Path.replace() \u2714\ufe0f \ud83d\udee0\ufe0f PTH106 os-rmdir os.rmdir() should be replaced by Path.rmdir() \u2714\ufe0f \ud83d\udee0\ufe0f PTH107 os-remove os.remove() should be replaced by Path.unlink() \u2714\ufe0f \ud83d\udee0\ufe0f PTH108 os-unlink os.unlink() should be replaced by Path.unlink() \u2714\ufe0f \ud83d\udee0\ufe0f PTH109 os-getcwd os.getcwd() should be replaced by Path.cwd() \u2714\ufe0f \ud83d\udee0\ufe0f PTH110 os-path-exists os.path.exists() should be replaced by Path.exists() \u2714\ufe0f \ud83d\udee0\ufe0f PTH111 os-path-expanduser os.path.expanduser() should be replaced by Path.expanduser() \u2714\ufe0f \ud83d\udee0\ufe0f PTH112 os-path-isdir os.path.isdir() should be replaced by Path.is_dir() \u2714\ufe0f \ud83d\udee0\ufe0f PTH113 os-path-isfile os.path.isfile() should be replaced by Path.is_file() \u2714\ufe0f \ud83d\udee0\ufe0f PTH114 os-path-islink os.path.islink() should be replaced by Path.is_symlink() \u2714\ufe0f \ud83d\udee0\ufe0f PTH115 os-readlink os.readlink() should be replaced by Path.readlink() \u2714\ufe0f \ud83d\udee0\ufe0f PTH116 os-stat os.stat() should be replaced by Path.stat(), Path.owner(), or Path.group() \u2714\ufe0f \ud83d\udee0\ufe0f PTH117 os-path-isabs os.path.isabs() should be replaced by Path.is_absolute() \u2714\ufe0f \ud83d\udee0\ufe0f PTH118 os-path-join os.{module}.join() should be replaced by Path with / operator \u2714\ufe0f \ud83d\udee0\ufe0f PTH119 os-path-basename os.path.basename() should be replaced by Path.name \u2714\ufe0f \ud83d\udee0\ufe0f PTH120 os-path-dirname os.path.dirname() should be replaced by Path.parent \u2714\ufe0f \ud83d\udee0\ufe0f PTH121 os-path-samefile os.path.samefile() should be replaced by Path.samefile() \u2714\ufe0f \ud83d\udee0\ufe0f PTH122 os-path-splitext os.path.splitext() should be replaced by Path.suffix, Path.stem, and Path.parent \u2714\ufe0f \ud83d\udee0\ufe0f PTH123 builtin-open open() should be replaced by Path.open() \u2714\ufe0f \ud83d\udee0\ufe0f PTH124 py-path py.path is in maintenance mode, use pathlib instead \u2714\ufe0f \ud83d\udee0\ufe0f PTH201 path-constructor-current-directory Do not pass the current directory explicitly to Path \u2714\ufe0f \ud83d\udee0\ufe0f PTH202 os-path-getsize os.path.getsize should be replaced by Path.stat().st_size \u2714\ufe0f \ud83d\udee0\ufe0f PTH203 os-path-getatime os.path.getatime should be replaced by Path.stat().st_atime \u2714\ufe0f \ud83d\udee0\ufe0f PTH204 os-path-getmtime os.path.getmtime should be replaced by Path.stat().st_mtime \u2714\ufe0f \ud83d\udee0\ufe0f PTH205 os-path-getctime os.path.getctime should be replaced by Path.stat().st_ctime \u2714\ufe0f \ud83d\udee0\ufe0f PTH206 os-sep-split Replace .split(os.sep) with Path.parts \u2714\ufe0f \ud83d\udee0\ufe0f PTH207 glob Replace {function} with Path.glob or Path.rglob \u2714\ufe0f \ud83d\udee0\ufe0f PTH208 os-listdir Use pathlib.Path.iterdir() instead. \u2714\ufe0f \ud83d\udee0\ufe0f PTH210 invalid-pathlib-with-suffix Invalid suffix passed to .with_suffix() \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#flynt-fly","title":"flynt (FLY)","text":"

        For more, see flynt on PyPI.

        Code Name Message FLY002 static-join-to-f-string Consider {expression} instead of string join \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#isort-i","title":"isort (I)","text":"

        For more, see isort on PyPI.

        For related settings, see isort.

        Code Name Message I001 unsorted-imports Import block is un-sorted or un-formatted \u2714\ufe0f \ud83d\udee0\ufe0f I002 missing-required-import Missing required import: {name} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#mccabe-c90","title":"mccabe (C90)","text":"

        For more, see mccabe on PyPI.

        For related settings, see mccabe.

        Code Name Message C901 complex-structure {name} is too complex ({complexity} > {max_complexity}) \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#numpy-specific-rules-npy","title":"NumPy-specific rules (NPY)","text":"Code Name Message NPY001 numpy-deprecated-type-alias Type alias np.{type_name} is deprecated, replace with builtin type \u2714\ufe0f \ud83d\udee0\ufe0f NPY002 numpy-legacy-random Replace legacy np.random.{method_name} call with np.random.Generator \u2714\ufe0f \ud83d\udee0\ufe0f NPY003 numpy-deprecated-function np.{existing} is deprecated; use np.{replacement} instead \u2714\ufe0f \ud83d\udee0\ufe0f NPY201 numpy2-deprecation np.{existing} will be removed in NumPy 2.0. {migration_guide} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pandas-vet-pd","title":"pandas-vet (PD)","text":"

        For more, see pandas-vet on PyPI.

        Code Name Message PD002 pandas-use-of-inplace-argument inplace=True should be avoided; it has inconsistent behavior \u2714\ufe0f \ud83d\udee0\ufe0f PD003 pandas-use-of-dot-is-null .isna is preferred to .isnull; functionality is equivalent \u2714\ufe0f \ud83d\udee0\ufe0f PD004 pandas-use-of-dot-not-null .notna is preferred to .notnull; functionality is equivalent \u2714\ufe0f \ud83d\udee0\ufe0f PD007 pandas-use-of-dot-ix .ix is deprecated; use more explicit .loc or .iloc \u2714\ufe0f \ud83d\udee0\ufe0f PD008 pandas-use-of-dot-at Use .loc instead of .at. If speed is important, use NumPy. \u2714\ufe0f \ud83d\udee0\ufe0f PD009 pandas-use-of-dot-iat Use .iloc instead of .iat. If speed is important, use NumPy. \u2714\ufe0f \ud83d\udee0\ufe0f PD010 pandas-use-of-dot-pivot-or-unstack .pivot_table is preferred to .pivot or .unstack; provides same functionality \u2714\ufe0f \ud83d\udee0\ufe0f PD011 pandas-use-of-dot-values Use .to_numpy() instead of .values \u2714\ufe0f \ud83d\udee0\ufe0f PD012 pandas-use-of-dot-read-table Use .read_csv instead of .read_table to read CSV files \u2714\ufe0f \ud83d\udee0\ufe0f PD013 pandas-use-of-dot-stack .melt is preferred to .stack; provides same functionality \u2714\ufe0f \ud83d\udee0\ufe0f PD015 pandas-use-of-pd-merge Use .merge method instead of pd.merge function. They have equivalent functionality. \u2714\ufe0f \ud83d\udee0\ufe0f PD101 pandas-nunique-constant-series-check Using series.nunique() for checking that a series is constant is inefficient \u2714\ufe0f \ud83d\udee0\ufe0f PD901 pandas-df-variable-name Avoid using the generic variable name df for DataFrames \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pep8-naming-n","title":"pep8-naming (N)","text":"

        For more, see pep8-naming on PyPI.

        For related settings, see pep8-naming.

        Code Name Message N801 invalid-class-name Class name {name} should use CapWords convention \u2714\ufe0f \ud83d\udee0\ufe0f N802 invalid-function-name Function name {name} should be lowercase \u2714\ufe0f \ud83d\udee0\ufe0f N803 invalid-argument-name Argument name {name} should be lowercase \u2714\ufe0f \ud83d\udee0\ufe0f N804 invalid-first-argument-name-for-class-method First argument of a class method should be named cls \u2714\ufe0f \ud83d\udee0\ufe0f N805 invalid-first-argument-name-for-method First argument of a method should be named self \u2714\ufe0f \ud83d\udee0\ufe0f N806 non-lowercase-variable-in-function Variable {name} in function should be lowercase \u2714\ufe0f \ud83d\udee0\ufe0f N807 dunder-function-name Function name should not start and end with __ \u2714\ufe0f \ud83d\udee0\ufe0f N811 constant-imported-as-non-constant Constant {name} imported as non-constant {asname} \u2714\ufe0f \ud83d\udee0\ufe0f N812 lowercase-imported-as-non-lowercase Lowercase {name} imported as non-lowercase {asname} \u2714\ufe0f \ud83d\udee0\ufe0f N813 camelcase-imported-as-lowercase Camelcase {name} imported as lowercase {asname} \u2714\ufe0f \ud83d\udee0\ufe0f N814 camelcase-imported-as-constant Camelcase {name} imported as constant {asname} \u2714\ufe0f \ud83d\udee0\ufe0f N815 mixed-case-variable-in-class-scope Variable {name} in class scope should not be mixedCase \u2714\ufe0f \ud83d\udee0\ufe0f N816 mixed-case-variable-in-global-scope Variable {name} in global scope should not be mixedCase \u2714\ufe0f \ud83d\udee0\ufe0f N817 camelcase-imported-as-acronym CamelCase {name} imported as acronym {asname} \u2714\ufe0f \ud83d\udee0\ufe0f N818 error-suffix-on-exception-name Exception name {name} should be named with an Error suffix \u2714\ufe0f \ud83d\udee0\ufe0f N999 invalid-module-name Invalid module name: '{name}' \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#perflint-perf","title":"Perflint (PERF)","text":"

        For more, see Perflint on PyPI.

        Code Name Message PERF101 unnecessary-list-cast Do not cast an iterable to list before iterating over it \u2714\ufe0f \ud83d\udee0\ufe0f PERF102 incorrect-dict-iterator When using only the {subset} of a dict use the {subset}() method \u2714\ufe0f \ud83d\udee0\ufe0f PERF203 try-except-in-loop try-except within a loop incurs performance overhead \u2714\ufe0f \ud83d\udee0\ufe0f PERF401 manual-list-comprehension Use {message_str} to create a transformed list \u2714\ufe0f \ud83d\udee0\ufe0f PERF402 manual-list-copy Use list or list.copy to create a copy of a list \u2714\ufe0f \ud83d\udee0\ufe0f PERF403 manual-dict-comprehension Use a dictionary comprehension instead of {modifier} for-loop \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pycodestyle-e-w","title":"pycodestyle (E, W)","text":"

        For more, see pycodestyle on PyPI.

        For related settings, see pycodestyle.

        "},{"location":"rules/#error-e","title":"Error (E)","text":"Code Name Message E101 mixed-spaces-and-tabs Indentation contains mixed spaces and tabs \u2714\ufe0f \ud83d\udee0\ufe0f E111 indentation-with-invalid-multiple Indentation is not a multiple of {indent_width} \ud83e\uddea \ud83d\udee0\ufe0f E112 no-indented-block Expected an indented block \ud83e\uddea \ud83d\udee0\ufe0f E113 unexpected-indentation Unexpected indentation \ud83e\uddea \ud83d\udee0\ufe0f E114 indentation-with-invalid-multiple-comment Indentation is not a multiple of {indent_width} (comment) \ud83e\uddea \ud83d\udee0\ufe0f E115 no-indented-block-comment Expected an indented block (comment) \ud83e\uddea \ud83d\udee0\ufe0f E116 unexpected-indentation-comment Unexpected indentation (comment) \ud83e\uddea \ud83d\udee0\ufe0f E117 over-indented Over-indented (comment) \ud83e\uddea \ud83d\udee0\ufe0f E201 whitespace-after-open-bracket Whitespace after '{symbol}' \ud83e\uddea \ud83d\udee0\ufe0f E202 whitespace-before-close-bracket Whitespace before '{symbol}' \ud83e\uddea \ud83d\udee0\ufe0f E203 whitespace-before-punctuation Whitespace before '{symbol}' \ud83e\uddea \ud83d\udee0\ufe0f E204 whitespace-after-decorator Whitespace after decorator \ud83e\uddea \ud83d\udee0\ufe0f E211 whitespace-before-parameters Whitespace before '{bracket}' \ud83e\uddea \ud83d\udee0\ufe0f E221 multiple-spaces-before-operator Multiple spaces before operator \ud83e\uddea \ud83d\udee0\ufe0f E222 multiple-spaces-after-operator Multiple spaces after operator \ud83e\uddea \ud83d\udee0\ufe0f E223 tab-before-operator Tab before operator \ud83e\uddea \ud83d\udee0\ufe0f E224 tab-after-operator Tab after operator \ud83e\uddea \ud83d\udee0\ufe0f E225 missing-whitespace-around-operator Missing whitespace around operator \ud83e\uddea \ud83d\udee0\ufe0f E226 missing-whitespace-around-arithmetic-operator Missing whitespace around arithmetic operator \ud83e\uddea \ud83d\udee0\ufe0f E227 missing-whitespace-around-bitwise-or-shift-operator Missing whitespace around bitwise or shift operator \ud83e\uddea \ud83d\udee0\ufe0f E228 missing-whitespace-around-modulo-operator Missing whitespace around modulo operator \ud83e\uddea \ud83d\udee0\ufe0f E231 missing-whitespace Missing whitespace after {} \ud83e\uddea \ud83d\udee0\ufe0f E241 multiple-spaces-after-comma Multiple spaces after comma \ud83e\uddea \ud83d\udee0\ufe0f E242 tab-after-comma Tab after comma \ud83e\uddea \ud83d\udee0\ufe0f E251 unexpected-spaces-around-keyword-parameter-equals Unexpected spaces around keyword / parameter equals \ud83e\uddea \ud83d\udee0\ufe0f E252 missing-whitespace-around-parameter-equals Missing whitespace around parameter equals \ud83e\uddea \ud83d\udee0\ufe0f E261 too-few-spaces-before-inline-comment Insert at least two spaces before an inline comment \ud83e\uddea \ud83d\udee0\ufe0f E262 no-space-after-inline-comment Inline comment should start with # \ud83e\uddea \ud83d\udee0\ufe0f E265 no-space-after-block-comment Block comment should start with # \ud83e\uddea \ud83d\udee0\ufe0f E266 multiple-leading-hashes-for-block-comment Too many leading # before block comment \ud83e\uddea \ud83d\udee0\ufe0f E271 multiple-spaces-after-keyword Multiple spaces after keyword \ud83e\uddea \ud83d\udee0\ufe0f E272 multiple-spaces-before-keyword Multiple spaces before keyword \ud83e\uddea \ud83d\udee0\ufe0f E273 tab-after-keyword Tab after keyword \ud83e\uddea \ud83d\udee0\ufe0f E274 tab-before-keyword Tab before keyword \ud83e\uddea \ud83d\udee0\ufe0f E275 missing-whitespace-after-keyword Missing whitespace after keyword \ud83e\uddea \ud83d\udee0\ufe0f E301 blank-line-between-methods Expected {BLANK_LINES_NESTED_LEVEL:?} blank line, found 0 \ud83e\uddea \ud83d\udee0\ufe0f E302 blank-lines-top-level Expected {expected_blank_lines:?} blank lines, found {actual_blank_lines} \ud83e\uddea \ud83d\udee0\ufe0f E303 too-many-blank-lines Too many blank lines ({actual_blank_lines}) \ud83e\uddea \ud83d\udee0\ufe0f E304 blank-line-after-decorator Blank lines found after function decorator ({lines}) \ud83e\uddea \ud83d\udee0\ufe0f E305 blank-lines-after-function-or-class Expected 2 blank lines after class or function definition, found ({blank_lines}) \ud83e\uddea \ud83d\udee0\ufe0f E306 blank-lines-before-nested-definition Expected 1 blank line before a nested definition, found 0 \ud83e\uddea \ud83d\udee0\ufe0f E401 multiple-imports-on-one-line Multiple imports on one line \u2714\ufe0f \ud83d\udee0\ufe0f E402 module-import-not-at-top-of-file Module level import not at top of cell \u2714\ufe0f \ud83d\udee0\ufe0f E501 line-too-long Line too long ({width} > {limit}) \u2714\ufe0f \ud83d\udee0\ufe0f E502 redundant-backslash Redundant backslash \ud83e\uddea \ud83d\udee0\ufe0f E701 multiple-statements-on-one-line-colon Multiple statements on one line (colon) \u2714\ufe0f \ud83d\udee0\ufe0f E702 multiple-statements-on-one-line-semicolon Multiple statements on one line (semicolon) \u2714\ufe0f \ud83d\udee0\ufe0f E703 useless-semicolon Statement ends with an unnecessary semicolon \u2714\ufe0f \ud83d\udee0\ufe0f E711 none-comparison Comparison to None should be cond is None \u2714\ufe0f \ud83d\udee0\ufe0f E712 true-false-comparison Avoid equality comparisons to True; use if {cond}: for truth checks \u2714\ufe0f \ud83d\udee0\ufe0f E713 not-in-test Test for membership should be not in \u2714\ufe0f \ud83d\udee0\ufe0f E714 not-is-test Test for object identity should be is not \u2714\ufe0f \ud83d\udee0\ufe0f E721 type-comparison Use is and is not for type comparisons, or isinstance() for isinstance checks \u2714\ufe0f \ud83d\udee0\ufe0f E722 bare-except Do not use bare except \u2714\ufe0f \ud83d\udee0\ufe0f E731 lambda-assignment Do not assign a lambda expression, use a def \u2714\ufe0f \ud83d\udee0\ufe0f E741 ambiguous-variable-name Ambiguous variable name: {name} \u2714\ufe0f \ud83d\udee0\ufe0f E742 ambiguous-class-name Ambiguous class name: {name} \u2714\ufe0f \ud83d\udee0\ufe0f E743 ambiguous-function-name Ambiguous function name: {name} \u2714\ufe0f \ud83d\udee0\ufe0f E902 io-error {message} \u2714\ufe0f \ud83d\udee0\ufe0f E999 syntax-error SyntaxError \u274c \ud83d\udee0\ufe0f"},{"location":"rules/#warning-w","title":"Warning (W)","text":"Code Name Message W191 tab-indentation Indentation contains tabs \u2714\ufe0f \ud83d\udee0\ufe0f W291 trailing-whitespace Trailing whitespace \u2714\ufe0f \ud83d\udee0\ufe0f W292 missing-newline-at-end-of-file No newline at end of file \u2714\ufe0f \ud83d\udee0\ufe0f W293 blank-line-with-whitespace Blank line contains whitespace \u2714\ufe0f \ud83d\udee0\ufe0f W391 too-many-newlines-at-end-of-file Too many newlines at end of {domain} \ud83e\uddea \ud83d\udee0\ufe0f W505 doc-line-too-long Doc line too long ({width} > {limit}) \u2714\ufe0f \ud83d\udee0\ufe0f W605 invalid-escape-sequence Invalid escape sequence: \\{ch} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pydoclint-doc","title":"pydoclint (DOC)","text":"

        For more, see pydoclint on PyPI.

        For related settings, see pydoclint.

        Code Name Message DOC201 docstring-missing-returns return is not documented in docstring \ud83e\uddea \ud83d\udee0\ufe0f DOC202 docstring-extraneous-returns Docstring should not have a returns section because the function doesn't return anything \ud83e\uddea \ud83d\udee0\ufe0f DOC402 docstring-missing-yields yield is not documented in docstring \ud83e\uddea \ud83d\udee0\ufe0f DOC403 docstring-extraneous-yields Docstring has a \"Yields\" section but the function doesn't yield anything \ud83e\uddea \ud83d\udee0\ufe0f DOC501 docstring-missing-exception Raised exception {id} missing from docstring \ud83e\uddea \ud83d\udee0\ufe0f DOC502 docstring-extraneous-exception Raised exception is not explicitly raised: {id} \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#pydocstyle-d","title":"pydocstyle (D)","text":"

        For more, see pydocstyle on PyPI.

        For related settings, see pydocstyle.

        Code Name Message D100 undocumented-public-module Missing docstring in public module \u2714\ufe0f \ud83d\udee0\ufe0f D101 undocumented-public-class Missing docstring in public class \u2714\ufe0f \ud83d\udee0\ufe0f D102 undocumented-public-method Missing docstring in public method \u2714\ufe0f \ud83d\udee0\ufe0f D103 undocumented-public-function Missing docstring in public function \u2714\ufe0f \ud83d\udee0\ufe0f D104 undocumented-public-package Missing docstring in public package \u2714\ufe0f \ud83d\udee0\ufe0f D105 undocumented-magic-method Missing docstring in magic method \u2714\ufe0f \ud83d\udee0\ufe0f D106 undocumented-public-nested-class Missing docstring in public nested class \u2714\ufe0f \ud83d\udee0\ufe0f D107 undocumented-public-init Missing docstring in __init__ \u2714\ufe0f \ud83d\udee0\ufe0f D200 unnecessary-multiline-docstring One-line docstring should fit on one line \u2714\ufe0f \ud83d\udee0\ufe0f D201 blank-line-before-function No blank lines allowed before function docstring (found {num_lines}) \u2714\ufe0f \ud83d\udee0\ufe0f D202 blank-line-after-function No blank lines allowed after function docstring (found {num_lines}) \u2714\ufe0f \ud83d\udee0\ufe0f D203 incorrect-blank-line-before-class 1 blank line required before class docstring \u2714\ufe0f \ud83d\udee0\ufe0f D204 incorrect-blank-line-after-class 1 blank line required after class docstring \u2714\ufe0f \ud83d\udee0\ufe0f D205 missing-blank-line-after-summary 1 blank line required between summary line and description \u2714\ufe0f \ud83d\udee0\ufe0f D206 docstring-tab-indentation Docstring should be indented with spaces, not tabs \u2714\ufe0f \ud83d\udee0\ufe0f D207 under-indentation Docstring is under-indented \u2714\ufe0f \ud83d\udee0\ufe0f D208 over-indentation Docstring is over-indented \u2714\ufe0f \ud83d\udee0\ufe0f D209 new-line-after-last-paragraph Multi-line docstring closing quotes should be on a separate line \u2714\ufe0f \ud83d\udee0\ufe0f D210 surrounding-whitespace No whitespaces allowed surrounding docstring text \u2714\ufe0f \ud83d\udee0\ufe0f D211 blank-line-before-class No blank lines allowed before class docstring \u2714\ufe0f \ud83d\udee0\ufe0f D212 multi-line-summary-first-line Multi-line docstring summary should start at the first line \u2714\ufe0f \ud83d\udee0\ufe0f D213 multi-line-summary-second-line Multi-line docstring summary should start at the second line \u2714\ufe0f \ud83d\udee0\ufe0f D214 overindented-section Section is over-indented (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D215 overindented-section-underline Section underline is over-indented (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D300 triple-single-quotes Use triple double quotes \"\"\" \u2714\ufe0f \ud83d\udee0\ufe0f D301 escape-sequence-in-docstring Use r\"\"\" if any backslashes in a docstring \u2714\ufe0f \ud83d\udee0\ufe0f D400 missing-trailing-period First line should end with a period \u2714\ufe0f \ud83d\udee0\ufe0f D401 non-imperative-mood First line of docstring should be in imperative mood: \"{first_line}\" \u2714\ufe0f \ud83d\udee0\ufe0f D402 signature-in-docstring First line should not be the function's signature \u2714\ufe0f \ud83d\udee0\ufe0f D403 first-word-uncapitalized First word of the docstring should be capitalized: {} -> {} \u2714\ufe0f \ud83d\udee0\ufe0f D404 docstring-starts-with-this First word of the docstring should not be \"This\" \u2714\ufe0f \ud83d\udee0\ufe0f D405 non-capitalized-section-name Section name should be properly capitalized (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D406 missing-new-line-after-section-name Section name should end with a newline (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D407 missing-dashed-underline-after-section Missing dashed underline after section (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D408 missing-section-underline-after-name Section underline should be in the line following the section's name (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D409 mismatched-section-underline-length Section underline should match the length of its name (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D410 no-blank-line-after-section Missing blank line after section (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D411 no-blank-line-before-section Missing blank line before section (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D412 blank-lines-between-header-and-content No blank lines allowed between a section header and its content (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D413 missing-blank-line-after-last-section Missing blank line after last section (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D414 empty-docstring-section Section has no content (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D415 missing-terminal-punctuation First line should end with a period, question mark, or exclamation point \u2714\ufe0f \ud83d\udee0\ufe0f D416 missing-section-name-colon Section name should end with a colon (\"{name}\") \u2714\ufe0f \ud83d\udee0\ufe0f D417 undocumented-param Missing argument description in the docstring for {definition}: {name} \u2714\ufe0f \ud83d\udee0\ufe0f D418 overload-with-docstring Function decorated with @overload shouldn't contain a docstring \u2714\ufe0f \ud83d\udee0\ufe0f D419 empty-docstring Docstring is empty \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pyflakes-f","title":"Pyflakes (F)","text":"

        For more, see Pyflakes on PyPI.

        Code Name Message F401 unused-import {name} imported but unused; consider using importlib.util.find_spec to test for availability \u2714\ufe0f \ud83d\udee0\ufe0f F402 import-shadowed-by-loop-var Import {name} from {row} shadowed by loop variable \u2714\ufe0f \ud83d\udee0\ufe0f F403 undefined-local-with-import-star from {name} import * used; unable to detect undefined names \u2714\ufe0f \ud83d\udee0\ufe0f F404 late-future-import from __future__ imports must occur at the beginning of the file \u2714\ufe0f \ud83d\udee0\ufe0f F405 undefined-local-with-import-star-usage {name} may be undefined, or defined from star imports \u2714\ufe0f \ud83d\udee0\ufe0f F406 undefined-local-with-nested-import-star-usage from {name} import * only allowed at module level \u2714\ufe0f \ud83d\udee0\ufe0f F407 future-feature-not-defined Future feature {name} is not defined \u2714\ufe0f \ud83d\udee0\ufe0f F501 percent-format-invalid-format %-format string has invalid format string: {message} \u2714\ufe0f \ud83d\udee0\ufe0f F502 percent-format-expected-mapping %-format string expected mapping but got sequence \u2714\ufe0f \ud83d\udee0\ufe0f F503 percent-format-expected-sequence %-format string expected sequence but got mapping \u2714\ufe0f \ud83d\udee0\ufe0f F504 percent-format-extra-named-arguments %-format string has unused named argument(s): {message} \u2714\ufe0f \ud83d\udee0\ufe0f F505 percent-format-missing-argument %-format string is missing argument(s) for placeholder(s): {message} \u2714\ufe0f \ud83d\udee0\ufe0f F506 percent-format-mixed-positional-and-named %-format string has mixed positional and named placeholders \u2714\ufe0f \ud83d\udee0\ufe0f F507 percent-format-positional-count-mismatch %-format string has {wanted} placeholder(s) but {got} substitution(s) \u2714\ufe0f \ud83d\udee0\ufe0f F508 percent-format-star-requires-sequence %-format string * specifier requires sequence \u2714\ufe0f \ud83d\udee0\ufe0f F509 percent-format-unsupported-format-character %-format string has unsupported format character {char} \u2714\ufe0f \ud83d\udee0\ufe0f F521 string-dot-format-invalid-format .format call has invalid format string: {message} \u2714\ufe0f \ud83d\udee0\ufe0f F522 string-dot-format-extra-named-arguments .format call has unused named argument(s): {message} \u2714\ufe0f \ud83d\udee0\ufe0f F523 string-dot-format-extra-positional-arguments .format call has unused arguments at position(s): {message} \u2714\ufe0f \ud83d\udee0\ufe0f F524 string-dot-format-missing-arguments .format call is missing argument(s) for placeholder(s): {message} \u2714\ufe0f \ud83d\udee0\ufe0f F525 string-dot-format-mixing-automatic .format string mixes automatic and manual numbering \u2714\ufe0f \ud83d\udee0\ufe0f F541 f-string-missing-placeholders f-string without any placeholders \u2714\ufe0f \ud83d\udee0\ufe0f F601 multi-value-repeated-key-literal Dictionary key literal {name} repeated \u2714\ufe0f \ud83d\udee0\ufe0f F602 multi-value-repeated-key-variable Dictionary key {name} repeated \u2714\ufe0f \ud83d\udee0\ufe0f F621 expressions-in-star-assignment Too many expressions in star-unpacking assignment \u2714\ufe0f \ud83d\udee0\ufe0f F622 multiple-starred-expressions Two starred expressions in assignment \u2714\ufe0f \ud83d\udee0\ufe0f F631 assert-tuple Assert test is a non-empty tuple, which is always True \u2714\ufe0f \ud83d\udee0\ufe0f F632 is-literal Use == to compare constant literals \u2714\ufe0f \ud83d\udee0\ufe0f F633 invalid-print-syntax Use of >> is invalid with print function \u2714\ufe0f \ud83d\udee0\ufe0f F634 if-tuple If test is a tuple, which is always True \u2714\ufe0f \ud83d\udee0\ufe0f F701 break-outside-loop break outside loop \u2714\ufe0f \ud83d\udee0\ufe0f F702 continue-outside-loop continue not properly in loop \u2714\ufe0f \ud83d\udee0\ufe0f F704 yield-outside-function {keyword} statement outside of a function \u2714\ufe0f \ud83d\udee0\ufe0f F706 return-outside-function return statement outside of a function/method \u2714\ufe0f \ud83d\udee0\ufe0f F707 default-except-not-last An except block as not the last exception handler \u2714\ufe0f \ud83d\udee0\ufe0f F722 forward-annotation-syntax-error Syntax error in forward annotation: {parse_error} \u2714\ufe0f \ud83d\udee0\ufe0f F811 redefined-while-unused Redefinition of unused {name} from {row} \u2714\ufe0f \ud83d\udee0\ufe0f F821 undefined-name Undefined name {name}. {tip} \u2714\ufe0f \ud83d\udee0\ufe0f F822 undefined-export Undefined name {name} in __all__ \u2714\ufe0f \ud83d\udee0\ufe0f F823 undefined-local Local variable {name} referenced before assignment \u2714\ufe0f \ud83d\udee0\ufe0f F841 unused-variable Local variable {name} is assigned to but never used \u2714\ufe0f \ud83d\udee0\ufe0f F842 unused-annotation Local variable {name} is annotated but never used \u2714\ufe0f \ud83d\udee0\ufe0f F901 raise-not-implemented raise NotImplemented should be raise NotImplementedError \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pygrep-hooks-pgh","title":"pygrep-hooks (PGH)","text":"

        For more, see pygrep-hooks on GitHub.

        Code Name Message PGH001 eval No builtin eval() allowed \u274c \ud83d\udee0\ufe0f PGH002 deprecated-log-warn warn is deprecated in favor of warning \u274c \ud83d\udee0\ufe0f PGH003 blanket-type-ignore Use specific rule codes when ignoring type issues \u2714\ufe0f \ud83d\udee0\ufe0f PGH004 blanket-noqa Use specific rule codes when using noqa \u2714\ufe0f \ud83d\udee0\ufe0f PGH005 invalid-mock-access Mock method should be called: {name} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pylint-pl","title":"Pylint (PL)","text":"

        For more, see Pylint on PyPI.

        "},{"location":"rules/#convention-plc","title":"Convention (PLC)","text":"Code Name Message PLC0105 type-name-incorrect-variance {kind} name \"{param_name}\" does not reflect its {variance}; consider renaming it to \"{replacement_name}\" \u2714\ufe0f \ud83d\udee0\ufe0f PLC0131 type-bivariance {kind} cannot be both covariant and contravariant \u2714\ufe0f \ud83d\udee0\ufe0f PLC0132 type-param-name-mismatch {kind} name {param_name} does not match assigned variable name {var_name} \u2714\ufe0f \ud83d\udee0\ufe0f PLC0205 single-string-slots Class __slots__ should be a non-string iterable \u2714\ufe0f \ud83d\udee0\ufe0f PLC0206 dict-index-missing-items Extracting value from dictionary without calling .items() \u2714\ufe0f \ud83d\udee0\ufe0f PLC0208 iteration-over-set Use a sequence type instead of a set when iterating over values \u2714\ufe0f \ud83d\udee0\ufe0f PLC0414 useless-import-alias Import alias does not rename original package \u2714\ufe0f \ud83d\udee0\ufe0f PLC0415 import-outside-top-level import should be at the top-level of a file \ud83e\uddea \ud83d\udee0\ufe0f PLC1802 len-test len({expression}) used as condition without comparison \u2714\ufe0f \ud83d\udee0\ufe0f PLC1901 compare-to-empty-string {existing} can be simplified to {replacement} as an empty string is falsey \ud83e\uddea \ud83d\udee0\ufe0f PLC2401 non-ascii-name {kind} name {name} contains a non-ASCII character \u2714\ufe0f \ud83d\udee0\ufe0f PLC2403 non-ascii-import-name Module alias {name} contains a non-ASCII character \u2714\ufe0f \ud83d\udee0\ufe0f PLC2701 import-private-name Private name import {name} from external module {module} \ud83e\uddea \ud83d\udee0\ufe0f PLC2801 unnecessary-dunder-call Unnecessary dunder call to {method}. {replacement}. \ud83e\uddea \ud83d\udee0\ufe0f PLC3002 unnecessary-direct-lambda-call Lambda expression called directly. Execute the expression inline instead. \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#error-ple","title":"Error (PLE)","text":"Code Name Message PLE0100 yield-in-init __init__ method is a generator \u2714\ufe0f \ud83d\udee0\ufe0f PLE0101 return-in-init Explicit return in __init__ \u2714\ufe0f \ud83d\udee0\ufe0f PLE0115 nonlocal-and-global Name {name} is both nonlocal and global \u2714\ufe0f \ud83d\udee0\ufe0f PLE0116 continue-in-finally continue not supported inside finally clause \u2714\ufe0f \ud83d\udee0\ufe0f PLE0117 nonlocal-without-binding Nonlocal name {name} found without binding \u2714\ufe0f \ud83d\udee0\ufe0f PLE0118 load-before-global-declaration Name {name} is used prior to global declaration on {row} \u2714\ufe0f \ud83d\udee0\ufe0f PLE0237 non-slot-assignment Attribute {name} is not defined in class's __slots__ \u2714\ufe0f \ud83d\udee0\ufe0f PLE0241 duplicate-bases Duplicate base {base} for class {class} \u2714\ufe0f \ud83d\udee0\ufe0f PLE0302 unexpected-special-method-signature The special method {} expects {}, {} {} given \u2714\ufe0f \ud83d\udee0\ufe0f PLE0303 invalid-length-return-type __len__ does not return a non-negative integer \u2714\ufe0f \ud83d\udee0\ufe0f PLE0304 invalid-bool-return-type __bool__ does not return bool \ud83e\uddea \ud83d\udee0\ufe0f PLE0305 invalid-index-return-type __index__ does not return an integer \u2714\ufe0f \ud83d\udee0\ufe0f PLE0307 invalid-str-return-type __str__ does not return str \u2714\ufe0f \ud83d\udee0\ufe0f PLE0308 invalid-bytes-return-type __bytes__ does not return bytes \u2714\ufe0f \ud83d\udee0\ufe0f PLE0309 invalid-hash-return-type __hash__ does not return an integer \u2714\ufe0f \ud83d\udee0\ufe0f PLE0604 invalid-all-object Invalid object in __all__, must contain only strings \u2714\ufe0f \ud83d\udee0\ufe0f PLE0605 invalid-all-format Invalid format for __all__, must be tuple or list \u2714\ufe0f \ud83d\udee0\ufe0f PLE0643 potential-index-error Expression is likely to raise IndexError \u2714\ufe0f \ud83d\udee0\ufe0f PLE0704 misplaced-bare-raise Bare raise statement is not inside an exception handler \u2714\ufe0f \ud83d\udee0\ufe0f PLE1132 repeated-keyword-argument Repeated keyword argument: {duplicate_keyword} \u2714\ufe0f \ud83d\udee0\ufe0f PLE1141 dict-iter-missing-items Unpacking a dictionary in iteration without calling .items() \ud83e\uddea \ud83d\udee0\ufe0f PLE1142 await-outside-async await should be used within an async function \u2714\ufe0f \ud83d\udee0\ufe0f PLE1205 logging-too-many-args Too many arguments for logging format string \u2714\ufe0f \ud83d\udee0\ufe0f PLE1206 logging-too-few-args Not enough arguments for logging format string \u2714\ufe0f \ud83d\udee0\ufe0f PLE1300 bad-string-format-character Unsupported format character '{format_char}' \u2714\ufe0f \ud83d\udee0\ufe0f PLE1307 bad-string-format-type Format type does not match argument type \u2714\ufe0f \ud83d\udee0\ufe0f PLE1310 bad-str-strip-call String {strip} call contains duplicate characters (did you mean {removal}?) \u2714\ufe0f \ud83d\udee0\ufe0f PLE1507 invalid-envvar-value Invalid type for initial os.getenv argument; expected str \u2714\ufe0f \ud83d\udee0\ufe0f PLE1519 singledispatch-method @singledispatch decorator should not be used on methods \u2714\ufe0f \ud83d\udee0\ufe0f PLE1520 singledispatchmethod-function @singledispatchmethod decorator should not be used on non-method functions \u2714\ufe0f \ud83d\udee0\ufe0f PLE1700 yield-from-in-async-function yield from statement in async function; use async for instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE2502 bidirectional-unicode Contains control characters that can permit obfuscated code \u2714\ufe0f \ud83d\udee0\ufe0f PLE2510 invalid-character-backspace Invalid unescaped character backspace, use \"\\b\" instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE2512 invalid-character-sub Invalid unescaped character SUB, use \"\\x1A\" instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE2513 invalid-character-esc Invalid unescaped character ESC, use \"\\x1B\" instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE2514 invalid-character-nul Invalid unescaped character NUL, use \"\\0\" instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE2515 invalid-character-zero-width-space Invalid unescaped character zero-width-space, use \"\\u200B\" instead \u2714\ufe0f \ud83d\udee0\ufe0f PLE4703 modified-iterating-set Iterated set {name} is modified within the for loop \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#refactor-plr","title":"Refactor (PLR)","text":"Code Name Message PLR0124 comparison-with-itself Name compared with itself, consider replacing {actual} \u2714\ufe0f \ud83d\udee0\ufe0f PLR0133 comparison-of-constant Two constants compared in a comparison, consider replacing {left_constant} {op} {right_constant} \u2714\ufe0f \ud83d\udee0\ufe0f PLR0202 no-classmethod-decorator Class method defined without decorator \ud83e\uddea \ud83d\udee0\ufe0f PLR0203 no-staticmethod-decorator Static method defined without decorator \ud83e\uddea \ud83d\udee0\ufe0f PLR0206 property-with-parameters Cannot have defined parameters for properties \u2714\ufe0f \ud83d\udee0\ufe0f PLR0402 manual-from-import Use from {module} import {name} in lieu of alias \u2714\ufe0f \ud83d\udee0\ufe0f PLR0904 too-many-public-methods Too many public methods ({methods} > {max_methods}) \ud83e\uddea \ud83d\udee0\ufe0f PLR0911 too-many-return-statements Too many return statements ({returns} > {max_returns}) \u2714\ufe0f \ud83d\udee0\ufe0f PLR0912 too-many-branches Too many branches ({branches} > {max_branches}) \u2714\ufe0f \ud83d\udee0\ufe0f PLR0913 too-many-arguments Too many arguments in function definition ({c_args} > {max_args}) \u2714\ufe0f \ud83d\udee0\ufe0f PLR0914 too-many-locals Too many local variables ({current_amount}/{max_amount}) \ud83e\uddea \ud83d\udee0\ufe0f PLR0915 too-many-statements Too many statements ({statements} > {max_statements}) \u2714\ufe0f \ud83d\udee0\ufe0f PLR0916 too-many-boolean-expressions Too many Boolean expressions ({expressions} > {max_expressions}) \ud83e\uddea \ud83d\udee0\ufe0f PLR0917 too-many-positional-arguments Too many positional arguments ({c_pos}/{max_pos}) \ud83e\uddea \ud83d\udee0\ufe0f PLR1701 repeated-isinstance-calls Merge isinstance calls: {expression} \u274c \ud83d\udee0\ufe0f PLR1702 too-many-nested-blocks Too many nested blocks ({nested_blocks} > {max_nested_blocks}) \ud83e\uddea \ud83d\udee0\ufe0f PLR1704 redefined-argument-from-local Redefining argument with the local name {name} \u2714\ufe0f \ud83d\udee0\ufe0f PLR1706 and-or-ternary Consider using if-else expression \u274c \ud83d\udee0\ufe0f PLR1711 useless-return Useless return statement at end of function \u2714\ufe0f \ud83d\udee0\ufe0f PLR1714 repeated-equality-comparison Consider merging multiple comparisons: {expression}. Use a set if the elements are hashable. \u2714\ufe0f \ud83d\udee0\ufe0f PLR1716 boolean-chained-comparison Contains chained boolean comparison that can be simplified \u2714\ufe0f \ud83d\udee0\ufe0f PLR1722 sys-exit-alias Use sys.exit() instead of {name} \u2714\ufe0f \ud83d\udee0\ufe0f PLR1730 if-stmt-min-max Replace if statement with {replacement} \u2714\ufe0f \ud83d\udee0\ufe0f PLR1733 unnecessary-dict-index-lookup Unnecessary lookup of dictionary value by key \ud83e\uddea \ud83d\udee0\ufe0f PLR1736 unnecessary-list-index-lookup List index lookup in enumerate() loop \u2714\ufe0f \ud83d\udee0\ufe0f PLR2004 magic-value-comparison Magic value used in comparison, consider replacing {value} with a constant variable \u2714\ufe0f \ud83d\udee0\ufe0f PLR2044 empty-comment Line with empty comment \u2714\ufe0f \ud83d\udee0\ufe0f PLR5501 collapsible-else-if Use elif instead of else then if, to reduce indentation \u2714\ufe0f \ud83d\udee0\ufe0f PLR6104 non-augmented-assignment Use {operator} to perform an augmented assignment directly \ud83e\uddea \ud83d\udee0\ufe0f PLR6201 literal-membership Use a set literal when testing for membership \ud83e\uddea \ud83d\udee0\ufe0f PLR6301 no-self-use Method {method_name} could be a function, class method, or static method \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#warning-plw","title":"Warning (PLW)","text":"Code Name Message PLW0108 unnecessary-lambda Lambda may be unnecessary; consider inlining inner function \ud83e\uddea \ud83d\udee0\ufe0f PLW0120 useless-else-on-loop else clause on loop without a break statement; remove the else and dedent its contents \u2714\ufe0f \ud83d\udee0\ufe0f PLW0127 self-assigning-variable Self-assignment of variable {name} \u2714\ufe0f \ud83d\udee0\ufe0f PLW0128 redeclared-assigned-name Redeclared variable {name} in assignment \u2714\ufe0f \ud83d\udee0\ufe0f PLW0129 assert-on-string-literal Asserting on an empty string literal will never pass \u2714\ufe0f \ud83d\udee0\ufe0f PLW0131 named-expr-without-context Named expression used without context \u2714\ufe0f \ud83d\udee0\ufe0f PLW0133 useless-exception-statement Missing raise statement on exception \u2714\ufe0f \ud83d\udee0\ufe0f PLW0177 nan-comparison Comparing against a NaN value; use math.isnan instead \ud83e\uddea \ud83d\udee0\ufe0f PLW0211 bad-staticmethod-argument First argument of a static method should not be named {argument_name} \u2714\ufe0f \ud83d\udee0\ufe0f PLW0244 redefined-slots-in-subclass Slot {slot_name} redefined from base class {base} \ud83e\uddea \ud83d\udee0\ufe0f PLW0245 super-without-brackets super call is missing parentheses \u2714\ufe0f \ud83d\udee0\ufe0f PLW0406 import-self Module {name} imports itself \u2714\ufe0f \ud83d\udee0\ufe0f PLW0602 global-variable-not-assigned Using global for {name} but no assignment is done \u2714\ufe0f \ud83d\udee0\ufe0f PLW0603 global-statement Using the global statement to update {name} is discouraged \u2714\ufe0f \ud83d\udee0\ufe0f PLW0604 global-at-module-level global at module level is redundant \u2714\ufe0f \ud83d\udee0\ufe0f PLW0642 self-or-cls-assignment Reassigned {} variable in {method_type} method \u2714\ufe0f \ud83d\udee0\ufe0f PLW0711 binary-op-exception Exception to catch is the result of a binary and operation \u2714\ufe0f \ud83d\udee0\ufe0f PLW1501 bad-open-mode {mode} is not a valid mode for open \u2714\ufe0f \ud83d\udee0\ufe0f PLW1507 shallow-copy-environ Shallow copy of os.environ via copy.copy(os.environ) \u2714\ufe0f \ud83d\udee0\ufe0f PLW1508 invalid-envvar-default Invalid type for environment variable default; expected str or None \u2714\ufe0f \ud83d\udee0\ufe0f PLW1509 subprocess-popen-preexec-fn preexec_fn argument is unsafe when using threads \u2714\ufe0f \ud83d\udee0\ufe0f PLW1510 subprocess-run-without-check subprocess.run without explicit check argument \u2714\ufe0f \ud83d\udee0\ufe0f PLW1514 unspecified-encoding {function_name} in text mode without explicit encoding argument \ud83e\uddea \ud83d\udee0\ufe0f PLW1641 eq-without-hash Object does not implement __hash__ method \ud83e\uddea \ud83d\udee0\ufe0f PLW2101 useless-with-lock Threading lock directly created in with statement has no effect \u2714\ufe0f \ud83d\udee0\ufe0f PLW2901 redefined-loop-name Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target \u2714\ufe0f \ud83d\udee0\ufe0f PLW3201 bad-dunder-method-name Dunder method {name} has no special meaning in Python 3 \ud83e\uddea \ud83d\udee0\ufe0f PLW3301 nested-min-max Nested {func} calls can be flattened \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#pyupgrade-up","title":"pyupgrade (UP)","text":"

        For more, see pyupgrade on PyPI.

        For related settings, see pyupgrade.

        Code Name Message UP001 useless-metaclass-type __metaclass__ = type is implied \u2714\ufe0f \ud83d\udee0\ufe0f UP003 type-of-primitive Use {} instead of type(...) \u2714\ufe0f \ud83d\udee0\ufe0f UP004 useless-object-inheritance Class {name} inherits from object \u2714\ufe0f \ud83d\udee0\ufe0f UP005 deprecated-unittest-alias {alias} is deprecated, use {target} \u2714\ufe0f \ud83d\udee0\ufe0f UP006 non-pep585-annotation Use {to} instead of {from} for type annotation \u2714\ufe0f \ud83d\udee0\ufe0f UP007 non-pep604-annotation-union Use X | Y for type annotations \u2714\ufe0f \ud83d\udee0\ufe0f UP008 super-call-with-parameters Use super() instead of super(__class__, self) \u2714\ufe0f \ud83d\udee0\ufe0f UP009 utf8-encoding-declaration UTF-8 encoding declaration is unnecessary \u2714\ufe0f \ud83d\udee0\ufe0f UP010 unnecessary-future-import Unnecessary __future__ import {import} for target Python version \u2714\ufe0f \ud83d\udee0\ufe0f UP011 lru-cache-without-parameters Unnecessary parentheses to functools.lru_cache \u2714\ufe0f \ud83d\udee0\ufe0f UP012 unnecessary-encode-utf8 Unnecessary call to encode as UTF-8 \u2714\ufe0f \ud83d\udee0\ufe0f UP013 convert-typed-dict-functional-to-class Convert {name} from TypedDict functional to class syntax \u2714\ufe0f \ud83d\udee0\ufe0f UP014 convert-named-tuple-functional-to-class Convert {name} from NamedTuple functional to class syntax \u2714\ufe0f \ud83d\udee0\ufe0f UP015 redundant-open-modes Unnecessary mode argument \u2714\ufe0f \ud83d\udee0\ufe0f UP017 datetime-timezone-utc Use datetime.UTC alias \u2714\ufe0f \ud83d\udee0\ufe0f UP018 native-literals Unnecessary {literal_type} call (rewrite as a literal) \u2714\ufe0f \ud83d\udee0\ufe0f UP019 typing-text-str-alias typing.Text is deprecated, use str \u2714\ufe0f \ud83d\udee0\ufe0f UP020 open-alias Use builtin open \u2714\ufe0f \ud83d\udee0\ufe0f UP021 replace-universal-newlines universal_newlines is deprecated, use text \u2714\ufe0f \ud83d\udee0\ufe0f UP022 replace-stdout-stderr Prefer capture_output over sending stdout and stderr to PIPE \u2714\ufe0f \ud83d\udee0\ufe0f UP023 deprecated-c-element-tree cElementTree is deprecated, use ElementTree \u2714\ufe0f \ud83d\udee0\ufe0f UP024 os-error-alias Replace aliased errors with OSError \u2714\ufe0f \ud83d\udee0\ufe0f UP025 unicode-kind-prefix Remove unicode literals from strings \u2714\ufe0f \ud83d\udee0\ufe0f UP026 deprecated-mock-import mock is deprecated, use unittest.mock \u2714\ufe0f \ud83d\udee0\ufe0f UP027 unpacked-list-comprehension Replace unpacked list comprehension with a generator expression \u274c \ud83d\udee0\ufe0f UP028 yield-in-for-loop Replace yield over for loop with yield from \u2714\ufe0f \ud83d\udee0\ufe0f UP029 unnecessary-builtin-import Unnecessary builtin import: {import} \u2714\ufe0f \ud83d\udee0\ufe0f UP030 format-literals Use implicit references for positional format fields \u2714\ufe0f \ud83d\udee0\ufe0f UP031 printf-string-formatting Use format specifiers instead of percent format \u2714\ufe0f \ud83d\udee0\ufe0f UP032 f-string Use f-string instead of format call \u2714\ufe0f \ud83d\udee0\ufe0f UP033 lru-cache-with-maxsize-none Use @functools.cache instead of @functools.lru_cache(maxsize=None) \u2714\ufe0f \ud83d\udee0\ufe0f UP034 extraneous-parentheses Avoid extraneous parentheses \u2714\ufe0f \ud83d\udee0\ufe0f UP035 deprecated-import Import from {target} instead: {names} \u2714\ufe0f \ud83d\udee0\ufe0f UP036 outdated-version-block Version block is outdated for minimum Python version \u2714\ufe0f \ud83d\udee0\ufe0f UP037 quoted-annotation Remove quotes from type annotation \u2714\ufe0f \ud83d\udee0\ufe0f UP038 non-pep604-isinstance Use X | Y in {} call instead of (X, Y) \u26a0\ufe0f \ud83d\udee0\ufe0f UP039 unnecessary-class-parentheses Unnecessary parentheses after class definition \u2714\ufe0f \ud83d\udee0\ufe0f UP040 non-pep695-type-alias Type alias {name} uses {type_alias_method} instead of the type keyword \u2714\ufe0f \ud83d\udee0\ufe0f UP041 timeout-error-alias Replace aliased errors with TimeoutError \u2714\ufe0f \ud83d\udee0\ufe0f UP042 replace-str-enum Class {name} inherits from both str and enum.Enum \ud83e\uddea \ud83d\udee0\ufe0f UP043 unnecessary-default-type-args Unnecessary default type arguments \u2714\ufe0f \ud83d\udee0\ufe0f UP044 non-pep646-unpack Use * for unpacking \u2714\ufe0f \ud83d\udee0\ufe0f UP045 non-pep604-annotation-optional Use X | None for type annotations \ud83e\uddea \ud83d\udee0\ufe0f UP046 non-pep695-generic-class Generic class {name} uses Generic subclass instead of type parameters \ud83e\uddea \ud83d\udee0\ufe0f UP047 non-pep695-generic-function Generic function {name} should use type parameters \ud83e\uddea \ud83d\udee0\ufe0f UP049 private-type-parameter Generic {} uses private type parameters \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#refurb-furb","title":"refurb (FURB)","text":"

        For more, see refurb on PyPI.

        Code Name Message FURB101 read-whole-file open and read should be replaced by Path({filename}).{suggestion} \ud83e\uddea \ud83d\udee0\ufe0f FURB103 write-whole-file open and write should be replaced by Path({filename}).{suggestion} \ud83e\uddea \ud83d\udee0\ufe0f FURB105 print-empty-string Unnecessary empty string passed to print \u2714\ufe0f \ud83d\udee0\ufe0f FURB110 if-exp-instead-of-or-operator Replace ternary if expression with or operator \ud83e\uddea \ud83d\udee0\ufe0f FURB113 repeated-append Use {suggestion} instead of repeatedly calling {name}.append() \ud83e\uddea \ud83d\udee0\ufe0f FURB116 f-string-number-format Replace {function_name} call with {display} \ud83e\uddea \ud83d\udee0\ufe0f FURB118 reimplemented-operator Use operator.{operator} instead of defining a {target} \ud83e\uddea \ud83d\udee0\ufe0f FURB122 for-loop-writes Use of {}.write in a for loop \ud83e\uddea \ud83d\udee0\ufe0f FURB129 readlines-in-for Instead of calling readlines(), iterate over file object directly \u2714\ufe0f \ud83d\udee0\ufe0f FURB131 delete-full-slice Prefer clear over deleting a full slice \ud83e\uddea \ud83d\udee0\ufe0f FURB132 check-and-remove-from-set Use {suggestion} instead of check and remove \ud83e\uddea \ud83d\udee0\ufe0f FURB136 if-expr-min-max Replace if expression with {min_max} call \u2714\ufe0f \ud83d\udee0\ufe0f FURB140 reimplemented-starmap Use itertools.starmap instead of the generator \ud83e\uddea \ud83d\udee0\ufe0f FURB142 for-loop-set-mutations Use of set.{}() in a for loop \ud83e\uddea \ud83d\udee0\ufe0f FURB145 slice-copy Prefer copy method over slicing \ud83e\uddea \ud83d\udee0\ufe0f FURB148 unnecessary-enumerate enumerate value is unused, use for x in range(len(y)) instead \ud83e\uddea \ud83d\udee0\ufe0f FURB152 math-constant Replace {literal} with math.{constant} \ud83e\uddea \ud83d\udee0\ufe0f FURB154 repeated-global Use of repeated consecutive {} \ud83e\uddea \ud83d\udee0\ufe0f FURB156 hardcoded-string-charset Use of hardcoded string charset \ud83e\uddea \ud83d\udee0\ufe0f FURB157 verbose-decimal-constructor Verbose expression in Decimal constructor \ud83e\uddea \ud83d\udee0\ufe0f FURB161 bit-count Use of bin({existing}).count('1') \u2714\ufe0f \ud83d\udee0\ufe0f FURB162 fromisoformat-replace-z Unnecessary timezone replacement with zero offset \ud83e\uddea \ud83d\udee0\ufe0f FURB163 redundant-log-base Prefer math.{log_function}({arg}) over math.log with a redundant base \u2714\ufe0f \ud83d\udee0\ufe0f FURB164 unnecessary-from-float Verbose method {method_name} in {constructor} construction \ud83e\uddea \ud83d\udee0\ufe0f FURB166 int-on-sliced-str Use of int with explicit base={base} after removing prefix \ud83e\uddea \ud83d\udee0\ufe0f FURB167 regex-flag-alias Use of regular expression alias re.{} \u2714\ufe0f \ud83d\udee0\ufe0f FURB168 isinstance-type-none Prefer is operator over isinstance to check if an object is None \u2714\ufe0f \ud83d\udee0\ufe0f FURB169 type-none-comparison When checking against None, use {} instead of comparison with type(None) \u2714\ufe0f \ud83d\udee0\ufe0f FURB171 single-item-membership-test Membership test against single-item container \ud83e\uddea \ud83d\udee0\ufe0f FURB177 implicit-cwd Prefer Path.cwd() over Path().resolve() for current-directory lookups \u2714\ufe0f \ud83d\udee0\ufe0f FURB180 meta-class-abc-meta Use of metaclass=abc.ABCMeta to define abstract base class \ud83e\uddea \ud83d\udee0\ufe0f FURB181 hashlib-digest-hex Use of hashlib's .digest().hex() \u2714\ufe0f \ud83d\udee0\ufe0f FURB187 list-reverse-copy Use of assignment of reversed on list {name} \u2714\ufe0f \ud83d\udee0\ufe0f FURB188 slice-to-remove-prefix-or-suffix Prefer str.removeprefix() over conditionally replacing with slice. \u2714\ufe0f \ud83d\udee0\ufe0f FURB189 subclass-builtin Subclassing {subclass} can be error prone, use collections.{replacement} instead \ud83e\uddea \ud83d\udee0\ufe0f FURB192 sorted-min-max Prefer min over sorted() to compute the minimum value in a sequence \ud83e\uddea \ud83d\udee0\ufe0f"},{"location":"rules/#ruff-specific-rules-ruf","title":"Ruff-specific rules (RUF)","text":"Code Name Message RUF001 ambiguous-unicode-character-string String contains ambiguous {}. Did you mean {}? \u2714\ufe0f \ud83d\udee0\ufe0f RUF002 ambiguous-unicode-character-docstring Docstring contains ambiguous {}. Did you mean {}? \u2714\ufe0f \ud83d\udee0\ufe0f RUF003 ambiguous-unicode-character-comment Comment contains ambiguous {}. Did you mean {}? \u2714\ufe0f \ud83d\udee0\ufe0f RUF005 collection-literal-concatenation Consider {expression} instead of concatenation \u2714\ufe0f \ud83d\udee0\ufe0f RUF006 asyncio-dangling-task Store a reference to the return value of {expr}.{method} \u2714\ufe0f \ud83d\udee0\ufe0f RUF007 zip-instead-of-pairwise Prefer itertools.pairwise() over zip() when iterating over successive pairs \u2714\ufe0f \ud83d\udee0\ufe0f RUF008 mutable-dataclass-default Do not use mutable default values for dataclass attributes \u2714\ufe0f \ud83d\udee0\ufe0f RUF009 function-call-in-dataclass-default-argument Do not perform function call {name} in dataclass defaults \u2714\ufe0f \ud83d\udee0\ufe0f RUF010 explicit-f-string-type-conversion Use explicit conversion flag \u2714\ufe0f \ud83d\udee0\ufe0f RUF011 ruff-static-key-dict-comprehension Dictionary comprehension uses static key \u274c \ud83d\udee0\ufe0f RUF012 mutable-class-default Mutable class attributes should be annotated with typing.ClassVar \u2714\ufe0f \ud83d\udee0\ufe0f RUF013 implicit-optional PEP 484 prohibits implicit Optional \u2714\ufe0f \ud83d\udee0\ufe0f RUF015 unnecessary-iterable-allocation-for-first-element Prefer next({iterable}) over single element slice \u2714\ufe0f \ud83d\udee0\ufe0f RUF016 invalid-index-type Slice in indexed access to type {value_type} uses type {index_type} instead of an integer \u2714\ufe0f \ud83d\udee0\ufe0f RUF017 quadratic-list-summation Avoid quadratic list summation \u2714\ufe0f \ud83d\udee0\ufe0f RUF018 assignment-in-assert Avoid assignment expressions in assert statements \u2714\ufe0f \ud83d\udee0\ufe0f RUF019 unnecessary-key-check Unnecessary key check before dictionary access \u2714\ufe0f \ud83d\udee0\ufe0f RUF020 never-union {never_like} | T is equivalent to T \u2714\ufe0f \ud83d\udee0\ufe0f RUF021 parenthesize-chained-operators Parenthesize a and b expressions when chaining and and or together, to make the precedence clear \u2714\ufe0f \ud83d\udee0\ufe0f RUF022 unsorted-dunder-all __all__ is not sorted \u2714\ufe0f \ud83d\udee0\ufe0f RUF023 unsorted-dunder-slots {}.__slots__ is not sorted \u2714\ufe0f \ud83d\udee0\ufe0f RUF024 mutable-fromkeys-value Do not pass mutable objects as values to dict.fromkeys \u2714\ufe0f \ud83d\udee0\ufe0f RUF026 default-factory-kwarg default_factory is a positional-only argument to defaultdict \u2714\ufe0f \ud83d\udee0\ufe0f RUF027 missing-f-string-syntax Possible f-string without an f prefix \ud83e\uddea \ud83d\udee0\ufe0f RUF028 invalid-formatter-suppression-comment This suppression comment is invalid because {} \ud83e\uddea \ud83d\udee0\ufe0f RUF029 unused-async Function {name} is declared async, but doesn't await or use async features. \ud83e\uddea \ud83d\udee0\ufe0f RUF030 assert-with-print-message print() call in assert statement is likely unintentional \u2714\ufe0f \ud83d\udee0\ufe0f RUF031 incorrectly-parenthesized-tuple-in-subscript Use parentheses for tuples in subscripts \ud83e\uddea \ud83d\udee0\ufe0f RUF032 decimal-from-float-literal Decimal() called with float literal argument \u2714\ufe0f \ud83d\udee0\ufe0f RUF033 post-init-default __post_init__ method with argument defaults \u2714\ufe0f \ud83d\udee0\ufe0f RUF034 useless-if-else Useless if-else condition \u2714\ufe0f \ud83d\udee0\ufe0f RUF035 ruff-unsafe-markup-use Unsafe use of {name} detected \u274c \ud83d\udee0\ufe0f RUF036 none-not-at-end-of-union None not at the end of the type annotation. \ud83e\uddea \ud83d\udee0\ufe0f RUF037 unnecessary-empty-iterable-within-deque-call Unnecessary empty iterable within a deque call \ud83e\uddea \ud83d\udee0\ufe0f RUF038 redundant-bool-literal Literal[True, False, ...] can be replaced with Literal[...] | bool \ud83e\uddea \ud83d\udee0\ufe0f RUF039 unraw-re-pattern First argument to {call} is not raw string \ud83e\uddea \ud83d\udee0\ufe0f RUF040 invalid-assert-message-literal-argument Non-string literal used as assert message \u2714\ufe0f \ud83d\udee0\ufe0f RUF041 unnecessary-nested-literal Unnecessary nested Literal \u2714\ufe0f \ud83d\udee0\ufe0f RUF043 pytest-raises-ambiguous-pattern Pattern passed to match= contains metacharacters but is neither escaped nor raw \ud83e\uddea \ud83d\udee0\ufe0f RUF045 implicit-class-var-in-dataclass Assignment without annotation found in dataclass body \ud83e\uddea \ud83d\udee0\ufe0f RUF046 unnecessary-cast-to-int Value being cast to int is already an integer \u2714\ufe0f \ud83d\udee0\ufe0f RUF047 needless-else Empty else clause \ud83e\uddea \ud83d\udee0\ufe0f RUF048 map-int-version-parsing __version__ may contain non-integral-like elements \u2714\ufe0f \ud83d\udee0\ufe0f RUF049 dataclass-enum An enum class should not be decorated with @dataclass \ud83e\uddea \ud83d\udee0\ufe0f RUF051 if-key-in-dict-del Use pop instead of key in dict followed by del dict[key] \u2714\ufe0f \ud83d\udee0\ufe0f RUF052 used-dummy-variable Local dummy variable {} is accessed \ud83e\uddea \ud83d\udee0\ufe0f RUF053 class-with-mixed-type-vars Class with type parameter list inherits from Generic \ud83e\uddea \ud83d\udee0\ufe0f RUF054 indented-form-feed Indented form feed \ud83e\uddea \ud83d\udee0\ufe0f RUF055 unnecessary-regular-expression Plain string pattern passed to re function \ud83e\uddea \ud83d\udee0\ufe0f RUF056 falsy-dict-get-fallback Avoid providing a falsy fallback to dict.get() in boolean test positions. The default fallback None is already falsy. \ud83e\uddea \ud83d\udee0\ufe0f RUF057 unnecessary-round Value being rounded is already an integer \ud83e\uddea \ud83d\udee0\ufe0f RUF058 starmap-zip itertools.starmap called on zip iterable \ud83e\uddea \ud83d\udee0\ufe0f RUF059 unused-unpacked-variable Unpacked variable {name} is never used \ud83e\uddea \ud83d\udee0\ufe0f RUF060 in-empty-collection Unnecessary membership test on empty collection \ud83e\uddea \ud83d\udee0\ufe0f RUF100 unused-noqa Unused noqa directive \u2714\ufe0f \ud83d\udee0\ufe0f RUF101 redirected-noqa {original} is a redirect to {target} \u2714\ufe0f \ud83d\udee0\ufe0f RUF102 invalid-rule-code Invalid rule code in # noqa: {} \ud83e\uddea \ud83d\udee0\ufe0f RUF200 invalid-pyproject-toml Failed to parse pyproject.toml: {message} \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"rules/#tryceratops-try","title":"tryceratops (TRY)","text":"

        For more, see tryceratops on PyPI.

        Code Name Message TRY002 raise-vanilla-class Create your own exception \u2714\ufe0f \ud83d\udee0\ufe0f TRY003 raise-vanilla-args Avoid specifying long messages outside the exception class \u2714\ufe0f \ud83d\udee0\ufe0f TRY004 type-check-without-type-error Prefer TypeError exception for invalid type \u2714\ufe0f \ud83d\udee0\ufe0f TRY200 reraise-no-cause Use raise from to specify exception cause \u274c \ud83d\udee0\ufe0f TRY201 verbose-raise Use raise without specifying exception name \u2714\ufe0f \ud83d\udee0\ufe0f TRY203 useless-try-except Remove exception handler; error is immediately re-raised \u2714\ufe0f \ud83d\udee0\ufe0f TRY300 try-consider-else Consider moving this statement to an else block \u2714\ufe0f \ud83d\udee0\ufe0f TRY301 raise-within-try Abstract raise to an inner function \u2714\ufe0f \ud83d\udee0\ufe0f TRY400 error-instead-of-exception Use logging.exception instead of logging.error \u2714\ufe0f \ud83d\udee0\ufe0f TRY401 verbose-log-message Redundant exception object included in logging.exception call \u2714\ufe0f \ud83d\udee0\ufe0f"},{"location":"settings/","title":"Settings","text":""},{"location":"settings/#top-level","title":"Top-level","text":""},{"location":"settings/#builtins","title":"builtins","text":"

        A list of builtins to treat as defined references, in addition to the system builtins.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nbuiltins = [\"_\"]\n
        builtins = [\"_\"]\n
        "},{"location":"settings/#cache-dir","title":"cache-dir","text":"

        A path to the cache directory.

        By default, Ruff stores cache results in a .ruff_cache directory in the current project root.

        However, Ruff will also respect the RUFF_CACHE_DIR environment variable, which takes precedence over that default.

        This setting will override even the RUFF_CACHE_DIR environment variable, if set.

        Default value: \".ruff_cache\"

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\ncache-dir = \"~/.cache/ruff\"\n
        cache-dir = \"~/.cache/ruff\"\n
        "},{"location":"settings/#exclude","title":"exclude","text":"

        A list of file patterns to exclude from formatting and linting.

        Exclusions are based on globs, and can be either:

        • Single-path patterns, like .mypy_cache (to exclude any directory named .mypy_cache in the tree), foo.py (to exclude any file named foo.py), or foo_*.py (to exclude any file matching foo_*.py ).
        • Relative patterns, like directory/foo.py (to exclude that specific file) or directory/*.py (to exclude any Python files in directory). Note that these paths are relative to the project root (e.g., the directory containing your pyproject.toml).

        For more information on the glob syntax, refer to the globset documentation.

        Note that you'll typically want to use extend-exclude to modify the excluded paths.

        Default value: [\".bzr\", \".direnv\", \".eggs\", \".git\", \".git-rewrite\", \".hg\", \".mypy_cache\", \".nox\", \".pants.d\", \".pytype\", \".ruff_cache\", \".svn\", \".tox\", \".venv\", \"__pypackages__\", \"_build\", \"buck-out\", \"dist\", \"node_modules\", \"venv\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nexclude = [\".venv\"]\n
        exclude = [\".venv\"]\n
        "},{"location":"settings/#extend","title":"extend","text":"

        A path to a local pyproject.toml file to merge into this configuration. User home directory and environment variables will be expanded.

        To resolve the current pyproject.toml file, Ruff will first resolve this base configuration file, then merge in any properties defined in the current configuration file.

        Default value: null

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Extend the `pyproject.toml` file in the parent directory.\nextend = \"../pyproject.toml\"\n# But use a different line length.\nline-length = 100\n
        # Extend the `pyproject.toml` file in the parent directory.\nextend = \"../pyproject.toml\"\n# But use a different line length.\nline-length = 100\n
        "},{"location":"settings/#extend-exclude","title":"extend-exclude","text":"

        A list of file patterns to omit from formatting and linting, in addition to those specified by exclude.

        Exclusions are based on globs, and can be either:

        • Single-path patterns, like .mypy_cache (to exclude any directory named .mypy_cache in the tree), foo.py (to exclude any file named foo.py), or foo_*.py (to exclude any file matching foo_*.py ).
        • Relative patterns, like directory/foo.py (to exclude that specific file) or directory/*.py (to exclude any Python files in directory). Note that these paths are relative to the project root (e.g., the directory containing your pyproject.toml).

        For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# In addition to the standard set of exclusions, omit all tests, plus a specific file.\nextend-exclude = [\"tests\", \"src/bad.py\"]\n
        # In addition to the standard set of exclusions, omit all tests, plus a specific file.\nextend-exclude = [\"tests\", \"src/bad.py\"]\n
        "},{"location":"settings/#extend-include","title":"extend-include","text":"

        A list of file patterns to include when linting, in addition to those specified by include.

        Inclusion are based on globs, and should be single-path patterns, like *.pyw, to include any file with the .pyw extension.

        For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# In addition to the standard set of inclusions, include `.pyw` files.\nextend-include = [\"*.pyw\"]\n
        # In addition to the standard set of inclusions, include `.pyw` files.\nextend-include = [\"*.pyw\"]\n
        "},{"location":"settings/#fix","title":"fix","text":"

        Enable fix behavior by-default when running ruff (overridden by the --fix and --no-fix command-line flags). Only includes automatic fixes unless --unsafe-fixes is provided.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nfix = true\n
        fix = true\n
        "},{"location":"settings/#fix-only","title":"fix-only","text":"

        Like fix, but disables reporting on leftover violation. Implies fix.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nfix-only = true\n
        fix-only = true\n
        "},{"location":"settings/#force-exclude","title":"force-exclude","text":"

        Whether to enforce exclude and extend-exclude patterns, even for paths that are passed to Ruff explicitly. Typically, Ruff will lint any paths passed in directly, even if they would typically be excluded. Setting force-exclude = true will cause Ruff to respect these exclusions unequivocally.

        This is useful for pre-commit, which explicitly passes all changed files to the ruff-pre-commit plugin, regardless of whether they're marked as excluded by Ruff's own settings.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nforce-exclude = true\n
        force-exclude = true\n
        "},{"location":"settings/#include","title":"include","text":"

        A list of file patterns to include when linting.

        Inclusion are based on globs, and should be single-path patterns, like *.pyw, to include any file with the .pyw extension. pyproject.toml is included here not for configuration but because we lint whether e.g. the [project] matches the schema.

        Notebook files (.ipynb extension) are included by default on Ruff 0.6.0+.

        For more information on the glob syntax, refer to the globset documentation.

        Default value: [\"*.py\", \"*.pyi\", \"*.ipynb\", \"**/pyproject.toml\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\ninclude = [\"*.py\"]\n
        include = [\"*.py\"]\n
        "},{"location":"settings/#indent-width","title":"indent-width","text":"

        The number of spaces per indentation level (tab).

        Used by the formatter and when enforcing long-line violations (like E501) to determine the visual width of a tab.

        This option changes the number of spaces the formatter inserts when using soft-tabs (indent-style = space).

        PEP 8 recommends using 4 spaces per indentation level.

        Default value: 4

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nindent-width = 2\n
        indent-width = 2\n
        "},{"location":"settings/#line-length","title":"line-length","text":"

        The line length to use when enforcing long-lines violations (like E501) and at which isort and the formatter prefers to wrap lines.

        The length is determined by the number of characters per line, except for lines containing East Asian characters or emojis. For these lines, the unicode width of each character is added up to determine the length.

        The value must be greater than 0 and less than or equal to 320.

        Note: While the formatter will attempt to format lines such that they remain within the line-length, it isn't a hard upper bound, and formatted lines may exceed the line-length.

        See pycodestyle.max-line-length to configure different lengths for E501 and the formatter.

        Default value: 88

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Allow lines to be as long as 120.\nline-length = 120\n
        # Allow lines to be as long as 120.\nline-length = 120\n
        "},{"location":"settings/#namespace-packages","title":"namespace-packages","text":"

        Mark the specified directories as namespace packages. For the purpose of module resolution, Ruff will treat those directories and all their subdirectories as if they contained an __init__.py file.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nnamespace-packages = [\"airflow/providers\"]\n
        namespace-packages = [\"airflow/providers\"]\n
        "},{"location":"settings/#output-format","title":"output-format","text":"

        The style in which violation messages should be formatted: \"full\" (default) (shows source), \"concise\", \"grouped\" (group messages by file), \"json\" (machine-readable), \"junit\" (machine-readable XML), \"github\" (GitHub Actions annotations), \"gitlab\" (GitLab CI code quality report), \"pylint\" (Pylint text format) or \"azure\" (Azure Pipeline logging commands).

        Default value: \"full\"

        Type: \"full\" | \"concise\" | \"grouped\" | \"json\" | \"junit\" | \"github\" | \"gitlab\" | \"pylint\" | \"azure\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Group violations by containing file.\noutput-format = \"grouped\"\n
        # Group violations by containing file.\noutput-format = \"grouped\"\n
        "},{"location":"settings/#per-file-target-version","title":"per-file-target-version","text":"

        A list of mappings from glob-style file pattern to Python version to use when checking the corresponding file(s).

        This may be useful for overriding the global Python version settings in target-version or requires-python for a subset of files. For example, if you have a project with a minimum supported Python version of 3.9 but a subdirectory of developer scripts that want to use a newer feature like the match statement from Python 3.10, you can use per-file-target-version to specify \"developer_scripts/*.py\" = \"py310\".

        This setting is used by the linter to enforce any enabled version-specific lint rules, as well as by the formatter for any version-specific formatting options, such as parenthesizing context managers on Python 3.10+.

        Default value: {}

        Type: dict[str, PythonVersion]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.per-file-target-version]\n# Override the project-wide Python version for a developer scripts directory:\n\"scripts/**.py\" = \"py312\"\n
        [per-file-target-version]\n# Override the project-wide Python version for a developer scripts directory:\n\"scripts/**.py\" = \"py312\"\n
        "},{"location":"settings/#preview","title":"preview","text":"

        Whether to enable preview mode. When preview mode is enabled, Ruff will use unstable rules, fixes, and formatting.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Enable preview features.\npreview = true\n
        # Enable preview features.\npreview = true\n
        "},{"location":"settings/#required-version","title":"required-version","text":"

        Enforce a requirement on the version of Ruff, to enforce at runtime. If the version of Ruff does not meet the requirement, Ruff will exit with an error.

        Useful for unifying results across many environments, e.g., with a pyproject.toml file.

        Accepts a PEP 440 specifier, like ==0.3.1 or >=0.3.1.

        Default value: null

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nrequired-version = \">=0.0.193\"\n
        required-version = \">=0.0.193\"\n
        "},{"location":"settings/#respect-gitignore","title":"respect-gitignore","text":"

        Whether to automatically exclude files that are ignored by .ignore, .gitignore, .git/info/exclude, and global gitignore files. Enabled by default.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nrespect-gitignore = false\n
        respect-gitignore = false\n
        "},{"location":"settings/#show-fixes","title":"show-fixes","text":"

        Whether to show an enumeration of all fixed lint violations (overridden by the --show-fixes command-line flag).

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Enumerate all fixed violations.\nshow-fixes = true\n
        # Enumerate all fixed violations.\nshow-fixes = true\n
        "},{"location":"settings/#src","title":"src","text":"

        The directories to consider when resolving first- vs. third-party imports.

        When omitted, the src directory will typically default to including both:

        1. The directory containing the nearest pyproject.toml, ruff.toml, or .ruff.toml file (the \"project root\").
        2. The \"src\" subdirectory of the project root.

        These defaults ensure that Ruff supports both flat layouts and src layouts out-of-the-box. (If a configuration file is explicitly provided (e.g., via the --config command-line flag), the current working directory will be considered the project root.)

        As an example, consider an alternative project structure, like:

        my_project\n\u251c\u2500\u2500 pyproject.toml\n\u2514\u2500\u2500 lib\n    \u2514\u2500\u2500 my_package\n        \u251c\u2500\u2500 __init__.py\n        \u251c\u2500\u2500 foo.py\n        \u2514\u2500\u2500 bar.py\n

        In this case, the ./lib directory should be included in the src option (e.g., src = [\"lib\"]), such that when resolving imports, my_package.foo is considered first-party.

        This field supports globs. For example, if you have a series of Python packages in a python_modules directory, src = [\"python_modules/*\"] would expand to incorporate all packages in that directory. User home directory and environment variables will also be expanded.

        Default value: [\".\", \"src\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Allow imports relative to the \"src\" and \"test\" directories.\nsrc = [\"src\", \"test\"]\n
        # Allow imports relative to the \"src\" and \"test\" directories.\nsrc = [\"src\", \"test\"]\n
        "},{"location":"settings/#target-version","title":"target-version","text":"

        The minimum Python version to target, e.g., when considering automatic code upgrades, like rewriting type annotations. Ruff will not propose changes using features that are not available in the given version.

        For example, to represent supporting Python >=3.10 or ==3.10 specify target-version = \"py310\".

        If you're already using a pyproject.toml file, we recommend project.requires-python instead, as it's based on Python packaging standards, and will be respected by other tools. For example, Ruff treats the following as identical to target-version = \"py38\":

        [project]\nrequires-python = \">=3.8\"\n

        If both are specified, target-version takes precedence over requires-python. See Inferring the Python version for a complete description of how the target-version is determined when left unspecified.

        Note that a stub file can sometimes make use of a typing feature before it is available at runtime, as long as the stub does not make use of new syntax. For example, a type checker will understand int | str in a stub as being a Union type annotation, even if the type checker is run using Python 3.9, despite the fact that the | operator can only be used to create union types at runtime on Python 3.10+. As such, Ruff will often recommend newer features in a stub file than it would for an equivalent runtime file with the same target version.

        Default value: \"py39\"

        Type: \"py37\" | \"py38\" | \"py39\" | \"py310\" | \"py311\" | \"py312\" | \"py313\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Always generate Python 3.7-compatible code.\ntarget-version = \"py37\"\n
        # Always generate Python 3.7-compatible code.\ntarget-version = \"py37\"\n
        "},{"location":"settings/#unsafe-fixes","title":"unsafe-fixes","text":"

        Enable application of unsafe fixes. If excluded, a hint will be displayed when unsafe fixes are available. If set to false, the hint will be hidden.

        Default value: null

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff]\nunsafe-fixes = true\n
        unsafe-fixes = true\n
        "},{"location":"settings/#analyze","title":"analyze","text":"

        Configures Ruff's analyze command.

        "},{"location":"settings/#analyze_detect-string-imports","title":"detect-string-imports","text":"

        Whether to detect imports from string literals. When enabled, Ruff will search for string literals that \"look like\" import paths, and include them in the import map, if they resolve to valid Python modules.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.analyze]\ndetect-string-imports = true\n
        [analyze]\ndetect-string-imports = true\n
        "},{"location":"settings/#analyze_direction","title":"direction","text":"

        Whether to generate a map from file to files that it depends on (dependencies) or files that depend on it (dependents).

        Default value: \"dependencies\"

        Type: \"dependents\" | \"dependencies\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.analyze]\ndirection = \"dependencies\"\n
        [analyze]\ndirection = \"dependencies\"\n
        "},{"location":"settings/#analyze_exclude","title":"exclude","text":"

        A list of file patterns to exclude from analysis in addition to the files excluded globally (see exclude, and extend-exclude).

        Exclusions are based on globs, and can be either:

        • Single-path patterns, like .mypy_cache (to exclude any directory named .mypy_cache in the tree), foo.py (to exclude any file named foo.py), or foo_*.py (to exclude any file matching foo_*.py ).
        • Relative patterns, like directory/foo.py (to exclude that specific file) or directory/*.py (to exclude any Python files in directory). Note that these paths are relative to the project root (e.g., the directory containing your pyproject.toml).

        For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.analyze]\nexclude = [\"generated\"]\n
        [analyze]\nexclude = [\"generated\"]\n
        "},{"location":"settings/#analyze_include-dependencies","title":"include-dependencies","text":"

        A map from file path to the list of Python or non-Python file paths or globs that should be considered dependencies of that file, regardless of whether relevant imports are detected.

        Default value: {}

        Type: dict[str, list[str]]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.analyze.include-dependencies]\n\"foo/bar.py\" = [\"foo/baz/*.py\"]\n\"foo/baz/reader.py\" = [\"configs/bar.json\"]\n
        [analyze.include-dependencies]\n\"foo/bar.py\" = [\"foo/baz/*.py\"]\n\"foo/baz/reader.py\" = [\"configs/bar.json\"]\n
        "},{"location":"settings/#analyze_preview","title":"preview","text":"

        Whether to enable preview mode. When preview mode is enabled, Ruff will expose unstable commands.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.analyze]\n# Enable preview features.\npreview = true\n
        [analyze]\n# Enable preview features.\npreview = true\n
        "},{"location":"settings/#format","title":"format","text":"

        Configures the way Ruff formats your code.

        "},{"location":"settings/#format_docstring-code-format","title":"docstring-code-format","text":"

        Whether to format code snippets in docstrings.

        When this is enabled, Python code examples within docstrings are automatically reformatted.

        For example, when this is enabled, the following code:

        def f(x):\n    \"\"\"\n    Something about `f`. And an example in doctest format:\n\n    >>> f(  x  )\n\n    Markdown is also supported:\n\n    ```py\n    f(  x  )\n    ```\n\n    As are reStructuredText literal blocks::\n\n        f(  x  )\n\n\n    And reStructuredText code blocks:\n\n    .. code-block:: python\n\n        f(  x  )\n    \"\"\"\n    pass\n

        ... will be reformatted (assuming the rest of the options are set to their defaults) as:

        def f(x):\n    \"\"\"\n    Something about `f`. And an example in doctest format:\n\n    >>> f(x)\n\n    Markdown is also supported:\n\n    ```py\n    f(x)\n    ```\n\n    As are reStructuredText literal blocks::\n\n        f(x)\n\n\n    And reStructuredText code blocks:\n\n    .. code-block:: python\n\n        f(x)\n    \"\"\"\n    pass\n

        If a code snippet in a docstring contains invalid Python code or if the formatter would otherwise write invalid Python code, then the code example is ignored by the formatter and kept as-is.

        Currently, doctest, Markdown, reStructuredText literal blocks, and reStructuredText code blocks are all supported and automatically recognized. In the case of unlabeled fenced code blocks in Markdown and reStructuredText literal blocks, the contents are assumed to be Python and reformatted. As with any other format, if the contents aren't valid Python, then the block is left untouched automatically.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Enable reformatting of code snippets in docstrings.\ndocstring-code-format = true\n
        [format]\n# Enable reformatting of code snippets in docstrings.\ndocstring-code-format = true\n
        "},{"location":"settings/#format_docstring-code-line-length","title":"docstring-code-line-length","text":"

        Set the line length used when formatting code snippets in docstrings.

        This only has an effect when the docstring-code-format setting is enabled.

        The default value for this setting is \"dynamic\", which has the effect of ensuring that any reformatted code examples in docstrings adhere to the global line length configuration that is used for the surrounding Python code. The point of this setting is that it takes the indentation of the docstring into account when reformatting code examples.

        Alternatively, this can be set to a fixed integer, which will result in the same line length limit being applied to all reformatted code examples in docstrings. When set to a fixed integer, the indent of the docstring is not taken into account. That is, this may result in lines in the reformatted code example that exceed the globally configured line length limit.

        For example, when this is set to 20 and docstring-code-format is enabled, then this code:

        def f(x):\n    '''\n    Something about `f`. And an example:\n\n    .. code-block:: python\n\n        foo, bar, quux = this_is_a_long_line(lion, hippo, lemur, bear)\n    '''\n    pass\n

        ... will be reformatted (assuming the rest of the options are set to their defaults) as:

        def f(x):\n    \"\"\"\n    Something about `f`. And an example:\n\n    .. code-block:: python\n\n        (\n            foo,\n            bar,\n            quux,\n        ) = this_is_a_long_line(\n            lion,\n            hippo,\n            lemur,\n            bear,\n        )\n    \"\"\"\n    pass\n

        Default value: \"dynamic\"

        Type: int | \"dynamic\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Format all docstring code snippets with a line length of 60.\ndocstring-code-line-length = 60\n
        [format]\n# Format all docstring code snippets with a line length of 60.\ndocstring-code-line-length = 60\n
        "},{"location":"settings/#format_exclude","title":"exclude","text":"

        A list of file patterns to exclude from formatting in addition to the files excluded globally (see exclude, and extend-exclude).

        Exclusions are based on globs, and can be either:

        • Single-path patterns, like .mypy_cache (to exclude any directory named .mypy_cache in the tree), foo.py (to exclude any file named foo.py), or foo_*.py (to exclude any file matching foo_*.py ).
        • Relative patterns, like directory/foo.py (to exclude that specific file) or directory/*.py (to exclude any Python files in directory). Note that these paths are relative to the project root (e.g., the directory containing your pyproject.toml).

        For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\nexclude = [\"generated\"]\n
        [format]\nexclude = [\"generated\"]\n
        "},{"location":"settings/#format_indent-style","title":"indent-style","text":"

        Whether to use spaces or tabs for indentation.

        indent-style = \"space\" (default):

        def f():\n    print(\"Hello\") #  Spaces indent the `print` statement.\n

        indent-style = \"tab\":

        def f():\n    print(\"Hello\") #  A tab `\\t` indents the `print` statement.\n

        PEP 8 recommends using spaces for indentation. We care about accessibility; if you do not need tabs for accessibility, we do not recommend you use them.

        See indent-width to configure the number of spaces per indentation and the tab width.

        Default value: \"space\"

        Type: \"space\" | \"tab\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Use tabs instead of 4 space indentation.\nindent-style = \"tab\"\n
        [format]\n# Use tabs instead of 4 space indentation.\nindent-style = \"tab\"\n
        "},{"location":"settings/#format_line-ending","title":"line-ending","text":"

        The character Ruff uses at the end of a line.

        • auto: The newline style is detected automatically on a file per file basis. Files with mixed line endings will be converted to the first detected line ending. Defaults to \\n for files that contain no line endings.
        • lf: Line endings will be converted to \\n. The default line ending on Unix.
        • cr-lf: Line endings will be converted to \\r\\n. The default line ending on Windows.
        • native: Line endings will be converted to \\n on Unix and \\r\\n on Windows.

        Default value: \"auto\"

        Type: \"auto\" | \"lf\" | \"cr-lf\" | \"native\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Use `\\n` line endings for all files\nline-ending = \"lf\"\n
        [format]\n# Use `\\n` line endings for all files\nline-ending = \"lf\"\n
        "},{"location":"settings/#format_preview","title":"preview","text":"

        Whether to enable the unstable preview style formatting.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Enable preview style formatting.\npreview = true\n
        [format]\n# Enable preview style formatting.\npreview = true\n
        "},{"location":"settings/#format_quote-style","title":"quote-style","text":"

        Configures the preferred quote character for strings. The recommended options are

        • double (default): Use double quotes \"
        • single: Use single quotes '

        In compliance with PEP 8 and PEP 257, Ruff prefers double quotes for triple quoted strings and docstrings even when using quote-style = \"single\".

        Ruff deviates from using the configured quotes if doing so prevents the need for escaping quote characters inside the string:

        a = \"a string without any quotes\"\nb = \"It's monday morning\"\n

        Ruff will change the quotes of the string assigned to a to single quotes when using quote-style = \"single\". However, Ruff uses double quotes for the string assigned to b because using single quotes would require escaping the ', which leads to the less readable code: 'It\\'s monday morning'.

        In addition, Ruff supports the quote style preserve for projects that already use a mixture of single and double quotes and can't migrate to the double or single style. The quote style preserve leaves the quotes of all strings unchanged.

        Default value: \"double\"

        Type: \"double\" | \"single\" | \"preserve\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\n# Prefer single quotes over double quotes.\nquote-style = \"single\"\n
        [format]\n# Prefer single quotes over double quotes.\nquote-style = \"single\"\n
        "},{"location":"settings/#format_skip-magic-trailing-comma","title":"skip-magic-trailing-comma","text":"

        Ruff uses existing trailing commas as an indication that short lines should be left separate. If this option is set to true, the magic trailing comma is ignored.

        For example, Ruff leaves the arguments separate even though collapsing the arguments to a single line doesn't exceed the line length if skip-magic-trailing-comma = false:

        # The arguments remain on separate lines because of the trailing comma after `b`\ndef test(\n    a,\n    b,\n): pass\n

        Setting skip-magic-trailing-comma = true changes the formatting to:

        # The arguments remain on separate lines because of the trailing comma after `b`\ndef test(a, b):\n    pass\n

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.format]\nskip-magic-trailing-comma = true\n
        [format]\nskip-magic-trailing-comma = true\n
        "},{"location":"settings/#lint","title":"lint","text":"

        Configures how Ruff checks your code.

        Options specified in the lint section take precedence over the deprecated top-level settings.

        "},{"location":"settings/#lint_allowed-confusables","title":"allowed-confusables","text":"

        A list of allowed \"confusable\" Unicode characters to ignore when enforcing RUF001, RUF002, and RUF003.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Allow minus-sign (U+2212), greek-small-letter-rho (U+03C1), and the asterisk-operator (U+2217),\n# which could be confused for \"-\", \"p\", and \"*\", respectively.\nallowed-confusables = [\"\u2212\", \"\u03c1\", \"\u2217\"]\n
        [lint]\n# Allow minus-sign (U+2212), greek-small-letter-rho (U+03C1), and the asterisk-operator (U+2217),\n# which could be confused for \"-\", \"p\", and \"*\", respectively.\nallowed-confusables = [\"\u2212\", \"\u03c1\", \"\u2217\"]\n
        "},{"location":"settings/#lint_dummy-variable-rgx","title":"dummy-variable-rgx","text":"

        A regular expression used to identify \"dummy\" variables, or those which should be ignored when enforcing (e.g.) unused-variable rules. The default expression matches _, __, and _var, but not _var_.

        Default value: \"^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$\"

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Only ignore variables named \"_\".\ndummy-variable-rgx = \"^_$\"\n
        [lint]\n# Only ignore variables named \"_\".\ndummy-variable-rgx = \"^_$\"\n
        "},{"location":"settings/#lint_exclude","title":"exclude","text":"

        A list of file patterns to exclude from linting in addition to the files excluded globally (see exclude, and extend-exclude).

        Exclusions are based on globs, and can be either:

        • Single-path patterns, like .mypy_cache (to exclude any directory named .mypy_cache in the tree), foo.py (to exclude any file named foo.py), or foo_*.py (to exclude any file matching foo_*.py ).
        • Relative patterns, like directory/foo.py (to exclude that specific file) or directory/*.py (to exclude any Python files in directory). Note that these paths are relative to the project root (e.g., the directory containing your pyproject.toml).

        For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nexclude = [\"generated\"]\n
        [lint]\nexclude = [\"generated\"]\n
        "},{"location":"settings/#lint_explicit-preview-rules","title":"explicit-preview-rules","text":"

        Whether to require exact codes to select preview rules. When enabled, preview rules will not be selected by prefixes \u2014 the full code of each preview rule will be required to enable the rule.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Require explicit selection of preview rules.\nexplicit-preview-rules = true\n
        [lint]\n# Require explicit selection of preview rules.\nexplicit-preview-rules = true\n
        "},{"location":"settings/#lint_extend-fixable","title":"extend-fixable","text":"

        A list of rule codes or prefixes to consider fixable, in addition to those specified by fixable.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Enable fix for flake8-bugbear (`B`), on top of any rules specified by `fixable`.\nextend-fixable = [\"B\"]\n
        [lint]\n# Enable fix for flake8-bugbear (`B`), on top of any rules specified by `fixable`.\nextend-fixable = [\"B\"]\n
        "},{"location":"settings/#lint_extend-ignore","title":"extend-ignore","text":"

        Deprecated

        This option has been deprecated. The extend-ignore option is now interchangeable with ignore. Please update your configuration to use the ignore option instead.

        A list of rule codes or prefixes to ignore, in addition to those specified by ignore.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Skip unused variable rules (`F841`).\nextend-ignore = [\"F841\"]\n
        [lint]\n# Skip unused variable rules (`F841`).\nextend-ignore = [\"F841\"]\n
        "},{"location":"settings/#lint_extend-per-file-ignores","title":"extend-per-file-ignores","text":"

        A list of mappings from file pattern to rule codes or prefixes to exclude, in addition to any rules excluded by per-file-ignores.

        Default value: {}

        Type: dict[str, list[RuleSelector]]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.extend-per-file-ignores]\n# Also ignore `E402` in all `__init__.py` files.\n\"__init__.py\" = [\"E402\"]\n
        [lint.extend-per-file-ignores]\n# Also ignore `E402` in all `__init__.py` files.\n\"__init__.py\" = [\"E402\"]\n
        "},{"location":"settings/#lint_extend-safe-fixes","title":"extend-safe-fixes","text":"

        A list of rule codes or prefixes for which unsafe fixes should be considered safe.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Allow applying all unsafe fixes in the `E` rules and `F401` without the `--unsafe-fixes` flag\nextend-safe-fixes = [\"E\", \"F401\"]\n
        [lint]\n# Allow applying all unsafe fixes in the `E` rules and `F401` without the `--unsafe-fixes` flag\nextend-safe-fixes = [\"E\", \"F401\"]\n
        "},{"location":"settings/#lint_extend-select","title":"extend-select","text":"

        A list of rule codes or prefixes to enable, in addition to those specified by select.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# On top of the default `select` (`E4`, E7`, `E9`, and `F`), enable flake8-bugbear (`B`) and flake8-quotes (`Q`).\nextend-select = [\"B\", \"Q\"]\n
        [lint]\n# On top of the default `select` (`E4`, E7`, `E9`, and `F`), enable flake8-bugbear (`B`) and flake8-quotes (`Q`).\nextend-select = [\"B\", \"Q\"]\n
        "},{"location":"settings/#lint_extend-unsafe-fixes","title":"extend-unsafe-fixes","text":"

        A list of rule codes or prefixes for which safe fixes should be considered unsafe.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Require the `--unsafe-fixes` flag when fixing the `E` rules and `F401`\nextend-unsafe-fixes = [\"E\", \"F401\"]\n
        [lint]\n# Require the `--unsafe-fixes` flag when fixing the `E` rules and `F401`\nextend-unsafe-fixes = [\"E\", \"F401\"]\n
        "},{"location":"settings/#lint_external","title":"external","text":"

        A list of rule codes or prefixes that are unsupported by Ruff, but should be preserved when (e.g.) validating # noqa directives. Useful for retaining # noqa directives that cover plugins not yet implemented by Ruff.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Avoiding flagging (and removing) any codes starting with `V` from any\n# `# noqa` directives, despite Ruff's lack of support for `vulture`.\nexternal = [\"V\"]\n
        [lint]\n# Avoiding flagging (and removing) any codes starting with `V` from any\n# `# noqa` directives, despite Ruff's lack of support for `vulture`.\nexternal = [\"V\"]\n
        "},{"location":"settings/#lint_fixable","title":"fixable","text":"

        A list of rule codes or prefixes to consider fixable. By default, all rules are considered fixable.

        Default value: [\"ALL\"]

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Only allow fix behavior for `E` and `F` rules.\nfixable = [\"E\", \"F\"]\n
        [lint]\n# Only allow fix behavior for `E` and `F` rules.\nfixable = [\"E\", \"F\"]\n
        "},{"location":"settings/#lint_ignore","title":"ignore","text":"

        A list of rule codes or prefixes to ignore. Prefixes can specify exact rules (like F841), entire categories (like F), or anything in between.

        When breaking ties between enabled and disabled rules (via select and ignore, respectively), more specific prefixes override less specific prefixes. ignore takes precedence over select if the same prefix appears in both.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Skip unused variable rules (`F841`).\nignore = [\"F841\"]\n
        [lint]\n# Skip unused variable rules (`F841`).\nignore = [\"F841\"]\n
        "},{"location":"settings/#lint_ignore-init-module-imports","title":"ignore-init-module-imports","text":"

        Deprecated

        This option has been deprecated in 0.4.4. ignore-init-module-imports will be removed in a future version because F401 now recommends appropriate fixes for unused imports in __init__.py (currently in preview mode). See documentation for more information and please update your configuration.

        Avoid automatically removing unused imports in __init__.py files. Such imports will still be flagged, but with a dedicated message suggesting that the import is either added to the module's __all__ symbol, or re-exported with a redundant alias (e.g., import os as os).

        This option is enabled by default, but you can opt-in to removal of imports via an unsafe fix.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nignore-init-module-imports = false\n
        [lint]\nignore-init-module-imports = false\n
        "},{"location":"settings/#lint_logger-objects","title":"logger-objects","text":"

        A list of objects that should be treated equivalently to a logging.Logger object.

        This is useful for ensuring proper diagnostics (e.g., to identify logging deprecations and other best-practices) for projects that re-export a logging.Logger object from a common module.

        For example, if you have a module logging_setup.py with the following contents:

        import logging\n\nlogger = logging.getLogger(__name__)\n

        Adding \"logging_setup.logger\" to logger-objects will ensure that logging_setup.logger is treated as a logging.Logger object when imported from other modules (e.g., from logging_setup import logger).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\nlogger-objects = [\"logging_setup.logger\"]\n
        [lint]\nlogger-objects = [\"logging_setup.logger\"]\n
        "},{"location":"settings/#lint_per-file-ignores","title":"per-file-ignores","text":"

        A list of mappings from file pattern to rule codes or prefixes to exclude, when considering any matching files. An initial '!' negates the file pattern.

        Default value: {}

        Type: dict[str, list[RuleSelector]]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.per-file-ignores]\n# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.\n\"__init__.py\" = [\"E402\"]\n\"path/to/file.py\" = [\"E402\"]\n# Ignore `D` rules everywhere except for the `src/` directory.\n\"!src/**.py\" = [\"D\"]\n
        [lint.per-file-ignores]\n# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.\n\"__init__.py\" = [\"E402\"]\n\"path/to/file.py\" = [\"E402\"]\n# Ignore `D` rules everywhere except for the `src/` directory.\n\"!src/**.py\" = [\"D\"]\n
        "},{"location":"settings/#lint_preview","title":"preview","text":"

        Whether to enable preview mode. When preview mode is enabled, Ruff will use unstable rules and fixes.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Enable preview features.\npreview = true\n
        [lint]\n# Enable preview features.\npreview = true\n
        "},{"location":"settings/#lint_select","title":"select","text":"

        A list of rule codes or prefixes to enable. Prefixes can specify exact rules (like F841), entire categories (like F), or anything in between.

        When breaking ties between enabled and disabled rules (via select and ignore, respectively), more specific prefixes override less specific prefixes. ignore takes precedence over select if the same prefix appears in both.

        Default value: [\"E4\", \"E7\", \"E9\", \"F\"]

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# On top of the defaults (`E4`, E7`, `E9`, and `F`), enable flake8-bugbear (`B`) and flake8-quotes (`Q`).\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"B\", \"Q\"]\n
        [lint]\n# On top of the defaults (`E4`, E7`, `E9`, and `F`), enable flake8-bugbear (`B`) and flake8-quotes (`Q`).\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"B\", \"Q\"]\n
        "},{"location":"settings/#lint_task-tags","title":"task-tags","text":"

        A list of task tags to recognize (e.g., \"TODO\", \"FIXME\", \"XXX\").

        Comments starting with these tags will be ignored by commented-out code detection (ERA), and skipped by line-length rules (E501) if ignore-overlong-task-comments is set to true.

        Default value: [\"TODO\", \"FIXME\", \"XXX\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\ntask-tags = [\"HACK\"]\n
        [lint]\ntask-tags = [\"HACK\"]\n
        "},{"location":"settings/#lint_typing-extensions","title":"typing-extensions","text":"

        Whether to allow imports from the third-party typing_extensions module for Python versions before a symbol was added to the first-party typing module.

        Many rules try to import symbols from the typing module but fall back to typing_extensions for earlier versions of Python. This option can be used to disable this fallback behavior in cases where typing_extensions is not installed.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Disable `typing_extensions` imports\ntyping-extensions = false\n
        [lint]\n# Disable `typing_extensions` imports\ntyping-extensions = false\n
        "},{"location":"settings/#lint_typing-modules","title":"typing-modules","text":"

        A list of modules whose exports should be treated equivalently to members of the typing module.

        This is useful for ensuring proper type annotation inference for projects that re-export typing and typing_extensions members from a compatibility module. If omitted, any members imported from modules apart from typing and typing_extensions will be treated as ordinary Python objects.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\ntyping-modules = [\"airflow.typing_compat\"]\n
        [lint]\ntyping-modules = [\"airflow.typing_compat\"]\n
        "},{"location":"settings/#lint_unfixable","title":"unfixable","text":"

        A list of rule codes or prefixes to consider non-fixable.

        Default value: []

        Type: list[RuleSelector]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint]\n# Disable fix for unused imports (`F401`).\nunfixable = [\"F401\"]\n
        [lint]\n# Disable fix for unused imports (`F401`).\nunfixable = [\"F401\"]\n
        "},{"location":"settings/#lintflake8-annotations","title":"lint.flake8-annotations","text":"

        Options for the flake8-annotations plugin.

        "},{"location":"settings/#lint_flake8-annotations_allow-star-arg-any","title":"allow-star-arg-any","text":"

        Whether to suppress ANN401 for dynamically typed *args and **kwargs arguments.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-annotations]\nallow-star-arg-any = true\n
        [lint.flake8-annotations]\nallow-star-arg-any = true\n
        "},{"location":"settings/#lint_flake8-annotations_ignore-fully-untyped","title":"ignore-fully-untyped","text":"

        Whether to suppress ANN* rules for any declaration that hasn't been typed at all. This makes it easier to gradually add types to a codebase.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-annotations]\nignore-fully-untyped = true\n
        [lint.flake8-annotations]\nignore-fully-untyped = true\n
        "},{"location":"settings/#lint_flake8-annotations_mypy-init-return","title":"mypy-init-return","text":"

        Whether to allow the omission of a return type hint for __init__ if at least one argument is annotated.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-annotations]\nmypy-init-return = true\n
        [lint.flake8-annotations]\nmypy-init-return = true\n
        "},{"location":"settings/#lint_flake8-annotations_suppress-dummy-args","title":"suppress-dummy-args","text":"

        Whether to suppress ANN000-level violations for arguments matching the \"dummy\" variable regex (like _).

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-annotations]\nsuppress-dummy-args = true\n
        [lint.flake8-annotations]\nsuppress-dummy-args = true\n
        "},{"location":"settings/#lint_flake8-annotations_suppress-none-returning","title":"suppress-none-returning","text":"

        Whether to suppress ANN200-level violations for functions that meet either of the following criteria:

        • Contain no return statement.
        • Explicit return statement(s) all return None (explicitly or implicitly).

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-annotations]\nsuppress-none-returning = true\n
        [lint.flake8-annotations]\nsuppress-none-returning = true\n
        "},{"location":"settings/#lintflake8-bandit","title":"lint.flake8-bandit","text":"

        Options for the flake8-bandit plugin.

        "},{"location":"settings/#lint_flake8-bandit_allowed-markup-calls","title":"allowed-markup-calls","text":"

        A list of callable names, whose result may be safely passed into markupsafe.Markup.

        Expects to receive a list of fully-qualified names (e.g., bleach.clean, rather than clean).

        This setting helps you avoid false positives in code like:

        from bleach import clean\nfrom markupsafe import Markup\n\ncleaned_markup = Markup(clean(some_user_input))\n

        Where the use of bleach.clean usually ensures that there's no XSS vulnerability.

        Although it is not recommended, you may also use this setting to whitelist other kinds of calls, e.g. calls to i18n translation functions, where how safe that is will depend on the implementation and how well the translations are audited.

        Another common use-case is to wrap the output of functions that generate markup like xml.etree.ElementTree.tostring or template rendering engines where sanitization of potential user input is either already baked in or has to happen before rendering.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bandit]\nallowed-markup-calls = [\"bleach.clean\", \"my_package.sanitize\"]\n
        [lint.flake8-bandit]\nallowed-markup-calls = [\"bleach.clean\", \"my_package.sanitize\"]\n
        "},{"location":"settings/#lint_flake8-bandit_check-typed-exception","title":"check-typed-exception","text":"

        Whether to disallow try-except-pass (S110) for specific exception types. By default, try-except-pass is only disallowed for Exception and BaseException.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bandit]\ncheck-typed-exception = true\n
        [lint.flake8-bandit]\ncheck-typed-exception = true\n
        "},{"location":"settings/#lint_flake8-bandit_extend-markup-names","title":"extend-markup-names","text":"

        A list of additional callable names that behave like markupsafe.Markup.

        Expects to receive a list of fully-qualified names (e.g., webhelpers.html.literal, rather than literal).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bandit]\nextend-markup-names = [\"webhelpers.html.literal\", \"my_package.Markup\"]\n
        [lint.flake8-bandit]\nextend-markup-names = [\"webhelpers.html.literal\", \"my_package.Markup\"]\n
        "},{"location":"settings/#lint_flake8-bandit_hardcoded-tmp-directory","title":"hardcoded-tmp-directory","text":"

        A list of directories to consider temporary (see S108).

        Default value: [\"/tmp\", \"/var/tmp\", \"/dev/shm\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bandit]\nhardcoded-tmp-directory = [\"/foo/bar\"]\n
        [lint.flake8-bandit]\nhardcoded-tmp-directory = [\"/foo/bar\"]\n
        "},{"location":"settings/#lint_flake8-bandit_hardcoded-tmp-directory-extend","title":"hardcoded-tmp-directory-extend","text":"

        A list of directories to consider temporary, in addition to those specified by hardcoded-tmp-directory (see S108).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bandit]\nhardcoded-tmp-directory-extend = [\"/foo/bar\"]\n
        [lint.flake8-bandit]\nhardcoded-tmp-directory-extend = [\"/foo/bar\"]\n
        "},{"location":"settings/#lintflake8-boolean-trap","title":"lint.flake8-boolean-trap","text":"

        Options for the flake8-boolean-trap plugin

        "},{"location":"settings/#lint_flake8-boolean-trap_extend-allowed-calls","title":"extend-allowed-calls","text":"

        Additional callable functions with which to allow boolean traps.

        Expects to receive a list of fully-qualified names (e.g., pydantic.Field, rather than Field).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-boolean-trap]\nextend-allowed-calls = [\"pydantic.Field\", \"django.db.models.Value\"]\n
        [lint.flake8-boolean-trap]\nextend-allowed-calls = [\"pydantic.Field\", \"django.db.models.Value\"]\n
        "},{"location":"settings/#lintflake8-bugbear","title":"lint.flake8-bugbear","text":"

        Options for the flake8-bugbear plugin.

        "},{"location":"settings/#lint_flake8-bugbear_extend-immutable-calls","title":"extend-immutable-calls","text":"

        Additional callable functions to consider \"immutable\" when evaluating, e.g., the function-call-in-default-argument rule (B008) or function-call-in-dataclass-defaults rule (RUF009).

        Expects to receive a list of fully-qualified names (e.g., fastapi.Query, rather than Query).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-bugbear]\n# Allow default arguments like, e.g., `data: List[str] = fastapi.Query(None)`.\nextend-immutable-calls = [\"fastapi.Depends\", \"fastapi.Query\"]\n
        [lint.flake8-bugbear]\n# Allow default arguments like, e.g., `data: List[str] = fastapi.Query(None)`.\nextend-immutable-calls = [\"fastapi.Depends\", \"fastapi.Query\"]\n
        "},{"location":"settings/#lintflake8-builtins","title":"lint.flake8-builtins","text":"

        Options for the flake8-builtins plugin.

        "},{"location":"settings/#lint_flake8-builtins_allowed-modules","title":"allowed-modules","text":"

        List of builtin module names to allow.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nallowed-modules = [\"secrets\"]\n
        [lint.flake8-builtins]\nallowed-modules = [\"secrets\"]\n
        "},{"location":"settings/#lint_flake8-builtins_builtins-allowed-modules","title":"builtins-allowed-modules","text":"

        Deprecated

        This option has been deprecated in 0.10.0. builtins-allowed-modules has been renamed to allowed-modules. Use that instead.

        DEPRECATED: This option has been renamed to allowed-modules. Use allowed-modules instead.

        List of builtin module names to allow.

        This option is ignored if both allowed-modules and builtins-allowed-modules are set.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nbuiltins-allowed-modules = [\"secrets\"]\n
        [lint.flake8-builtins]\nbuiltins-allowed-modules = [\"secrets\"]\n
        "},{"location":"settings/#lint_flake8-builtins_builtins-ignorelist","title":"builtins-ignorelist","text":"

        Deprecated

        This option has been deprecated in 0.10.0. builtins-ignorelist has been renamed to ignorelist. Use that instead.

        DEPRECATED: This option has been renamed to ignorelist. Use ignorelist instead.

        Ignore list of builtins.

        This option is ignored if both ignorelist and builtins-ignorelist are set.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nbuiltins-ignorelist = [\"id\"]\n
        [lint.flake8-builtins]\nbuiltins-ignorelist = [\"id\"]\n
        "},{"location":"settings/#lint_flake8-builtins_builtins-strict-checking","title":"builtins-strict-checking","text":"

        Deprecated

        This option has been deprecated in 0.10.0. builtins-strict-checking has been renamed to strict-checking. Use that instead.

        DEPRECATED: This option has been renamed to strict-checking. Use strict-checking instead.

        Compare module names instead of full module paths.

        This option is ignored if both strict-checking and builtins-strict-checking are set.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nbuiltins-strict-checking = true\n
        [lint.flake8-builtins]\nbuiltins-strict-checking = true\n
        "},{"location":"settings/#lint_flake8-builtins_ignorelist","title":"ignorelist","text":"

        Ignore list of builtins.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nignorelist = [\"id\"]\n
        [lint.flake8-builtins]\nignorelist = [\"id\"]\n
        "},{"location":"settings/#lint_flake8-builtins_strict-checking","title":"strict-checking","text":"

        Compare module names instead of full module paths.

        Used by A005 - stdlib-module-shadowing.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-builtins]\nstrict-checking = true\n
        [lint.flake8-builtins]\nstrict-checking = true\n
        "},{"location":"settings/#lintflake8-comprehensions","title":"lint.flake8-comprehensions","text":"

        Options for the flake8-comprehensions plugin.

        "},{"location":"settings/#lint_flake8-comprehensions_allow-dict-calls-with-keyword-arguments","title":"allow-dict-calls-with-keyword-arguments","text":"

        Allow dict calls that make use of keyword arguments (e.g., dict(a=1, b=2)).

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-comprehensions]\nallow-dict-calls-with-keyword-arguments = true\n
        [lint.flake8-comprehensions]\nallow-dict-calls-with-keyword-arguments = true\n
        "},{"location":"settings/#lintflake8-copyright","title":"lint.flake8-copyright","text":"

        Options for the flake8-copyright plugin.

        "},{"location":"settings/#lint_flake8-copyright_author","title":"author","text":"

        Author to enforce within the copyright notice. If provided, the author must be present immediately following the copyright notice.

        Default value: null

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-copyright]\nauthor = \"Ruff\"\n
        [lint.flake8-copyright]\nauthor = \"Ruff\"\n
        "},{"location":"settings/#lint_flake8-copyright_min-file-size","title":"min-file-size","text":"

        A minimum file size (in bytes) required for a copyright notice to be enforced. By default, all files are validated.

        Default value: 0

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-copyright]\n# Avoid enforcing a header on files smaller than 1024 bytes.\nmin-file-size = 1024\n
        [lint.flake8-copyright]\n# Avoid enforcing a header on files smaller than 1024 bytes.\nmin-file-size = 1024\n
        "},{"location":"settings/#lint_flake8-copyright_notice-rgx","title":"notice-rgx","text":"

        The regular expression used to match the copyright notice, compiled with the regex crate. Defaults to (?i)Copyright\\s+((?:\\(C\\)|\u00a9)\\s+)?\\d{4}((-|,\\s)\\d{4})*, which matches the following:

        • Copyright 2023
        • Copyright (C) 2023
        • Copyright 2021-2023
        • Copyright (C) 2021-2023
        • Copyright (C) 2021, 2023

        Default value: \"(?i)Copyright\\s+((?:\\(C\\)|\u00a9)\\s+)?\\d{4}((-|,\\s)\\d{4})*\"

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-copyright]\nnotice-rgx = \"(?i)Copyright \\\\(C\\\\) \\\\d{4}\"\n
        [lint.flake8-copyright]\nnotice-rgx = \"(?i)Copyright \\\\(C\\\\) \\\\d{4}\"\n
        "},{"location":"settings/#lintflake8-errmsg","title":"lint.flake8-errmsg","text":"

        Options for the flake8-errmsg plugin.

        "},{"location":"settings/#lint_flake8-errmsg_max-string-length","title":"max-string-length","text":"

        Maximum string length for string literals in exception messages.

        Default value: 0

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-errmsg]\nmax-string-length = 20\n
        [lint.flake8-errmsg]\nmax-string-length = 20\n
        "},{"location":"settings/#lintflake8-gettext","title":"lint.flake8-gettext","text":"

        Options for the flake8-gettext plugin.

        "},{"location":"settings/#lint_flake8-gettext_extend-function-names","title":"extend-function-names","text":"

        Additional function names to consider as internationalization calls, in addition to those included in function-names.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-gettext]\nextend-function-names = [\"ugettetxt\"]\n
        [lint.flake8-gettext]\nextend-function-names = [\"ugettetxt\"]\n
        "},{"location":"settings/#lint_flake8-gettext_function-names","title":"function-names","text":"

        The function names to consider as internationalization calls.

        Default value: [\"_\", \"gettext\", \"ngettext\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-gettext]\nfunction-names = [\"_\", \"gettext\", \"ngettext\", \"ugettetxt\"]\n
        [lint.flake8-gettext]\nfunction-names = [\"_\", \"gettext\", \"ngettext\", \"ugettetxt\"]\n
        "},{"location":"settings/#lintflake8-implicit-str-concat","title":"lint.flake8-implicit-str-concat","text":"

        Options for the flake8-implicit-str-concat plugin

        "},{"location":"settings/#lint_flake8-implicit-str-concat_allow-multiline","title":"allow-multiline","text":"

        Whether to allow implicit string concatenations for multiline strings. By default, implicit concatenations of multiline strings are allowed (but continuation lines, delimited with a backslash, are prohibited).

        Setting allow-multiline = false will automatically disable the explicit-string-concatenation (ISC003) rule. Otherwise, both implicit and explicit multiline string concatenations would be seen as violations, making it impossible to write a linter-compliant multiline string.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-implicit-str-concat]\nallow-multiline = false\n
        [lint.flake8-implicit-str-concat]\nallow-multiline = false\n
        "},{"location":"settings/#lintflake8-import-conventions","title":"lint.flake8-import-conventions","text":"

        Options for the flake8-import-conventions plugin

        "},{"location":"settings/#lint_flake8-import-conventions_aliases","title":"aliases","text":"

        The conventional aliases for imports. These aliases can be extended by the extend-aliases option.

        Default value: {\"altair\": \"alt\", \"matplotlib\": \"mpl\", \"matplotlib.pyplot\": \"plt\", \"numpy\": \"np\", \"numpy.typing\": \"npt\", \"pandas\": \"pd\", \"seaborn\": \"sns\", \"tensorflow\": \"tf\", \"tkinter\": \"tk\", \"holoviews\": \"hv\", \"panel\": \"pn\", \"plotly.express\": \"px\", \"polars\": \"pl\", \"pyarrow\": \"pa\", \"xml.etree.ElementTree\": \"ET\"}

        Type: dict[str, str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-import-conventions.aliases]\n# Declare the default aliases.\naltair = \"alt\"\n\"matplotlib.pyplot\" = \"plt\"\nnumpy = \"np\"\npandas = \"pd\"\nseaborn = \"sns\"\nscipy = \"sp\"\n
        [lint.flake8-import-conventions.aliases]\n# Declare the default aliases.\naltair = \"alt\"\n\"matplotlib.pyplot\" = \"plt\"\nnumpy = \"np\"\npandas = \"pd\"\nseaborn = \"sns\"\nscipy = \"sp\"\n
        "},{"location":"settings/#lint_flake8-import-conventions_banned-aliases","title":"banned-aliases","text":"

        A mapping from module to its banned import aliases.

        Default value: {}

        Type: dict[str, list[str]]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-import-conventions.banned-aliases]\n# Declare the banned aliases.\n\"tensorflow.keras.backend\" = [\"K\"]\n
        [lint.flake8-import-conventions.banned-aliases]\n# Declare the banned aliases.\n\"tensorflow.keras.backend\" = [\"K\"]\n
        "},{"location":"settings/#lint_flake8-import-conventions_banned-from","title":"banned-from","text":"

        A list of modules that should not be imported from using the from ... import ... syntax.

        For example, given banned-from = [\"pandas\"], from pandas import DataFrame would be disallowed, while import pandas would be allowed.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-import-conventions]\n# Declare the banned `from` imports.\nbanned-from = [\"typing\"]\n
        [lint.flake8-import-conventions]\n# Declare the banned `from` imports.\nbanned-from = [\"typing\"]\n
        "},{"location":"settings/#lint_flake8-import-conventions_extend-aliases","title":"extend-aliases","text":"

        A mapping from module to conventional import alias. These aliases will be added to the aliases mapping.

        Default value: {}

        Type: dict[str, str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-import-conventions.extend-aliases]\n# Declare a custom alias for the `dask` module.\n\"dask.dataframe\" = \"dd\"\n
        [lint.flake8-import-conventions.extend-aliases]\n# Declare a custom alias for the `dask` module.\n\"dask.dataframe\" = \"dd\"\n
        "},{"location":"settings/#lintflake8-pytest-style","title":"lint.flake8-pytest-style","text":"

        Options for the flake8-pytest-style plugin

        "},{"location":"settings/#lint_flake8-pytest-style_fixture-parentheses","title":"fixture-parentheses","text":"

        Boolean flag specifying whether @pytest.fixture() without parameters should have parentheses. If the option is set to false (the default), @pytest.fixture is valid and @pytest.fixture() is invalid. If set to true, @pytest.fixture() is valid and @pytest.fixture is invalid.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nfixture-parentheses = true\n
        [lint.flake8-pytest-style]\nfixture-parentheses = true\n
        "},{"location":"settings/#lint_flake8-pytest-style_mark-parentheses","title":"mark-parentheses","text":"

        Boolean flag specifying whether @pytest.mark.foo() without parameters should have parentheses. If the option is set to false (the default), @pytest.mark.foo is valid and @pytest.mark.foo() is invalid. If set to true, @pytest.mark.foo() is valid and @pytest.mark.foo is invalid.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nmark-parentheses = true\n
        [lint.flake8-pytest-style]\nmark-parentheses = true\n
        "},{"location":"settings/#lint_flake8-pytest-style_parametrize-names-type","title":"parametrize-names-type","text":"

        Expected type for multiple argument names in @pytest.mark.parametrize. The following values are supported:

        • csv \u2014 a comma-separated list, e.g. @pytest.mark.parametrize(\"name1,name2\", ...)
        • tuple (default) \u2014 e.g. @pytest.mark.parametrize((\"name1\", \"name2\"), ...)
        • list \u2014 e.g. @pytest.mark.parametrize([\"name1\", \"name2\"], ...)

        Default value: tuple

        Type: \"csv\" | \"tuple\" | \"list\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nparametrize-names-type = \"list\"\n
        [lint.flake8-pytest-style]\nparametrize-names-type = \"list\"\n
        "},{"location":"settings/#lint_flake8-pytest-style_parametrize-values-row-type","title":"parametrize-values-row-type","text":"

        Expected type for each row of values in @pytest.mark.parametrize in case of multiple parameters. The following values are supported:

        • tuple (default) \u2014 e.g. @pytest.mark.parametrize((\"name1\", \"name2\"), [(1, 2), (3, 4)])
        • list \u2014 e.g. @pytest.mark.parametrize((\"name1\", \"name2\"), [[1, 2], [3, 4]])

        Default value: tuple

        Type: \"tuple\" | \"list\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nparametrize-values-row-type = \"list\"\n
        [lint.flake8-pytest-style]\nparametrize-values-row-type = \"list\"\n
        "},{"location":"settings/#lint_flake8-pytest-style_parametrize-values-type","title":"parametrize-values-type","text":"

        Expected type for the list of values rows in @pytest.mark.parametrize. The following values are supported:

        • tuple \u2014 e.g. @pytest.mark.parametrize(\"name\", (1, 2, 3))
        • list (default) \u2014 e.g. @pytest.mark.parametrize(\"name\", [1, 2, 3])

        Default value: list

        Type: \"tuple\" | \"list\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nparametrize-values-type = \"tuple\"\n
        [lint.flake8-pytest-style]\nparametrize-values-type = \"tuple\"\n
        "},{"location":"settings/#lint_flake8-pytest-style_raises-extend-require-match-for","title":"raises-extend-require-match-for","text":"

        List of additional exception names that require a match= parameter in a pytest.raises() call. This extends the default list of exceptions that require a match= parameter. This option is useful if you want to extend the default list of exceptions that require a match= parameter without having to specify the entire list. Note that this option does not remove any exceptions from the default list.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nraises-extend-require-match-for = [\"requests.RequestException\"]\n
        [lint.flake8-pytest-style]\nraises-extend-require-match-for = [\"requests.RequestException\"]\n
        "},{"location":"settings/#lint_flake8-pytest-style_raises-require-match-for","title":"raises-require-match-for","text":"

        List of exception names that require a match= parameter in a pytest.raises() call.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: [\"BaseException\", \"Exception\", \"ValueError\", \"OSError\", \"IOError\", \"EnvironmentError\", \"socket.error\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nraises-require-match-for = [\"requests.RequestException\"]\n
        [lint.flake8-pytest-style]\nraises-require-match-for = [\"requests.RequestException\"]\n
        "},{"location":"settings/#lint_flake8-pytest-style_warns-extend-require-match-for","title":"warns-extend-require-match-for","text":"

        List of additional warning names that require a match= parameter in a pytest.warns() call. This extends the default list of warnings that require a match= parameter.

        This option is useful if you want to extend the default list of warnings that require a match= parameter without having to specify the entire list.

        Note that this option does not remove any warnings from the default list.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nwarns-extend-require-match-for = [\"requests.RequestsWarning\"]\n
        [lint.flake8-pytest-style]\nwarns-extend-require-match-for = [\"requests.RequestsWarning\"]\n
        "},{"location":"settings/#lint_flake8-pytest-style_warns-require-match-for","title":"warns-require-match-for","text":"

        List of warning names that require a match= parameter in a pytest.warns() call.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: [\"Warning\", \"UserWarning\", \"DeprecationWarning\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-pytest-style]\nwarns-require-match-for = [\"requests.RequestsWarning\"]\n
        [lint.flake8-pytest-style]\nwarns-require-match-for = [\"requests.RequestsWarning\"]\n
        "},{"location":"settings/#lintflake8-quotes","title":"lint.flake8-quotes","text":"

        Options for the flake8-quotes plugin.

        "},{"location":"settings/#lint_flake8-quotes_avoid-escape","title":"avoid-escape","text":"

        Whether to avoid using single quotes if a string contains single quotes, or vice-versa with double quotes, as per PEP 8. This minimizes the need to escape quotation marks within strings.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-quotes]\n# Don't bother trying to avoid escapes.\navoid-escape = false\n
        [lint.flake8-quotes]\n# Don't bother trying to avoid escapes.\navoid-escape = false\n
        "},{"location":"settings/#lint_flake8-quotes_docstring-quotes","title":"docstring-quotes","text":"

        Quote style to prefer for docstrings (either \"single\" or \"double\").

        When using the formatter, only \"double\" is compatible, as the formatter enforces double quotes for docstrings strings.

        Default value: \"double\"

        Type: \"single\" | \"double\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-quotes]\ndocstring-quotes = \"single\"\n
        [lint.flake8-quotes]\ndocstring-quotes = \"single\"\n
        "},{"location":"settings/#lint_flake8-quotes_inline-quotes","title":"inline-quotes","text":"

        Quote style to prefer for inline strings (either \"single\" or \"double\").

        When using the formatter, ensure that format.quote-style is set to the same preferred quote style.

        Default value: \"double\"

        Type: \"single\" | \"double\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-quotes]\ninline-quotes = \"single\"\n
        [lint.flake8-quotes]\ninline-quotes = \"single\"\n
        "},{"location":"settings/#lint_flake8-quotes_multiline-quotes","title":"multiline-quotes","text":"

        Quote style to prefer for multiline strings (either \"single\" or \"double\").

        When using the formatter, only \"double\" is compatible, as the formatter enforces double quotes for multiline strings.

        Default value: \"double\"

        Type: \"single\" | \"double\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-quotes]\nmultiline-quotes = \"single\"\n
        [lint.flake8-quotes]\nmultiline-quotes = \"single\"\n
        "},{"location":"settings/#lintflake8-self","title":"lint.flake8-self","text":"

        Options for the flake8_self plugin.

        "},{"location":"settings/#lint_flake8-self_extend-ignore-names","title":"extend-ignore-names","text":"

        Additional names to ignore when considering flake8-self violations, in addition to those included in ignore-names.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-self]\nextend-ignore-names = [\"_base_manager\", \"_default_manager\",  \"_meta\"]\n
        [lint.flake8-self]\nextend-ignore-names = [\"_base_manager\", \"_default_manager\",  \"_meta\"]\n
        "},{"location":"settings/#lint_flake8-self_ignore-names","title":"ignore-names","text":"

        A list of names to ignore when considering flake8-self violations.

        Default value: [\"_make\", \"_asdict\", \"_replace\", \"_fields\", \"_field_defaults\", \"_name_\", \"_value_\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-self]\nignore-names = [\"_new\"]\n
        [lint.flake8-self]\nignore-names = [\"_new\"]\n
        "},{"location":"settings/#lintflake8-tidy-imports","title":"lint.flake8-tidy-imports","text":"

        Options for the flake8-tidy-imports plugin

        "},{"location":"settings/#lint_flake8-tidy-imports_ban-relative-imports","title":"ban-relative-imports","text":"

        Whether to ban all relative imports (\"all\"), or only those imports that extend into the parent module or beyond (\"parents\").

        Default value: \"parents\"

        Type: \"parents\" | \"all\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-tidy-imports]\n# Disallow all relative imports.\nban-relative-imports = \"all\"\n
        [lint.flake8-tidy-imports]\n# Disallow all relative imports.\nban-relative-imports = \"all\"\n
        "},{"location":"settings/#lint_flake8-tidy-imports_banned-api","title":"banned-api","text":"

        Specific modules or module members that may not be imported or accessed. Note that this rule is only meant to flag accidental uses, and can be circumvented via eval or importlib.

        Default value: {}

        Type: dict[str, { \"msg\": str }]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-tidy-imports.banned-api]\n\"cgi\".msg = \"The cgi module is deprecated, see https://peps.python.org/pep-0594/#cgi.\"\n\"typing.TypedDict\".msg = \"Use typing_extensions.TypedDict instead.\"\n
        [lint.flake8-tidy-imports.banned-api]\n\"cgi\".msg = \"The cgi module is deprecated, see https://peps.python.org/pep-0594/#cgi.\"\n\"typing.TypedDict\".msg = \"Use typing_extensions.TypedDict instead.\"\n
        "},{"location":"settings/#lint_flake8-tidy-imports_banned-module-level-imports","title":"banned-module-level-imports","text":"

        List of specific modules that may not be imported at module level, and should instead be imported lazily (e.g., within a function definition, or an if TYPE_CHECKING: block, or some other nested context).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-tidy-imports]\n# Ban certain modules from being imported at module level, instead requiring\n# that they're imported lazily (e.g., within a function definition).\nbanned-module-level-imports = [\"torch\", \"tensorflow\"]\n
        [lint.flake8-tidy-imports]\n# Ban certain modules from being imported at module level, instead requiring\n# that they're imported lazily (e.g., within a function definition).\nbanned-module-level-imports = [\"torch\", \"tensorflow\"]\n
        "},{"location":"settings/#lintflake8-type-checking","title":"lint.flake8-type-checking","text":"

        Options for the flake8-type-checking plugin

        "},{"location":"settings/#lint_flake8-type-checking_exempt-modules","title":"exempt-modules","text":"

        Exempt certain modules from needing to be moved into type-checking blocks.

        Default value: [\"typing\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-type-checking]\nexempt-modules = [\"typing\", \"typing_extensions\"]\n
        [lint.flake8-type-checking]\nexempt-modules = [\"typing\", \"typing_extensions\"]\n
        "},{"location":"settings/#lint_flake8-type-checking_quote-annotations","title":"quote-annotations","text":"

        Whether to add quotes around type annotations, if doing so would allow the corresponding import to be moved into a type-checking block.

        For example, in the following, Python requires that Sequence be available at runtime, despite the fact that it's only used in a type annotation:

        from collections.abc import Sequence\n\n\ndef func(value: Sequence[int]) -> None:\n    ...\n

        In other words, moving from collections.abc import Sequence into an if TYPE_CHECKING: block above would cause a runtime error, as the type would no longer be available at runtime.

        By default, Ruff will respect such runtime semantics and avoid moving the import to prevent such runtime errors.

        Setting quote-annotations to true will instruct Ruff to add quotes around the annotation (e.g., \"Sequence[int]\"), which in turn enables Ruff to move the import into an if TYPE_CHECKING: block, like so:

        from typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from collections.abc import Sequence\n\n\ndef func(value: \"Sequence[int]\") -> None:\n    ...\n

        Note that this setting has no effect when from __future__ import annotations is present, as __future__ annotations are always treated equivalently to quoted annotations.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-type-checking]\n# Add quotes around type annotations, if doing so would allow\n# an import to be moved into a type-checking block.\nquote-annotations = true\n
        [lint.flake8-type-checking]\n# Add quotes around type annotations, if doing so would allow\n# an import to be moved into a type-checking block.\nquote-annotations = true\n
        "},{"location":"settings/#lint_flake8-type-checking_runtime-evaluated-base-classes","title":"runtime-evaluated-base-classes","text":"

        Exempt classes that list any of the enumerated classes as a base class from needing to be moved into type-checking blocks.

        Common examples include Pydantic's pydantic.BaseModel and SQLAlchemy's sqlalchemy.orm.DeclarativeBase, but can also support user-defined classes that inherit from those base classes. For example, if you define a common DeclarativeBase subclass that's used throughout your project (e.g., class Base(DeclarativeBase) ... in base.py), you can add it to this list (runtime-evaluated-base-classes = [\"base.Base\"]) to exempt models from being moved into type-checking blocks.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-type-checking]\nruntime-evaluated-base-classes = [\"pydantic.BaseModel\", \"sqlalchemy.orm.DeclarativeBase\"]\n
        [lint.flake8-type-checking]\nruntime-evaluated-base-classes = [\"pydantic.BaseModel\", \"sqlalchemy.orm.DeclarativeBase\"]\n
        "},{"location":"settings/#lint_flake8-type-checking_runtime-evaluated-decorators","title":"runtime-evaluated-decorators","text":"

        Exempt classes and functions decorated with any of the enumerated decorators from being moved into type-checking blocks.

        Common examples include Pydantic's @pydantic.validate_call decorator (for functions) and attrs' @attrs.define decorator (for classes).

        This also supports framework decorators like FastAPI's fastapi.FastAPI.get which will work across assignments in the same module.

        For example:

        import fastapi\n\napp = FastAPI(\"app\")\n\n@app.get(\"/home\")\ndef home() -> str: ...\n

        Here app.get will correctly be identified as fastapi.FastAPI.get.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-type-checking]\nruntime-evaluated-decorators = [\"pydantic.validate_call\", \"attrs.define\"]\n
        [lint.flake8-type-checking]\nruntime-evaluated-decorators = [\"pydantic.validate_call\", \"attrs.define\"]\n
        "},{"location":"settings/#lint_flake8-type-checking_strict","title":"strict","text":"

        Enforce TC001, TC002, and TC003 rules even when valid runtime imports are present for the same module.

        See flake8-type-checking's strict option.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-type-checking]\nstrict = true\n
        [lint.flake8-type-checking]\nstrict = true\n
        "},{"location":"settings/#lintflake8-unused-arguments","title":"lint.flake8-unused-arguments","text":"

        Options for the flake8-unused-arguments plugin

        "},{"location":"settings/#lint_flake8-unused-arguments_ignore-variadic-names","title":"ignore-variadic-names","text":"

        Whether to allow unused variadic arguments, like *args and **kwargs.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.flake8-unused-arguments]\nignore-variadic-names = true\n
        [lint.flake8-unused-arguments]\nignore-variadic-names = true\n
        "},{"location":"settings/#lintisort","title":"lint.isort","text":"

        Options for the isort plugin.

        "},{"location":"settings/#lint_isort_case-sensitive","title":"case-sensitive","text":"

        Sort imports taking into account case sensitivity.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\ncase-sensitive = true\n
        [lint.isort]\ncase-sensitive = true\n
        "},{"location":"settings/#lint_isort_classes","title":"classes","text":"

        An override list of tokens to always recognize as a Class for order-by-type regardless of casing.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nclasses = [\"SVC\"]\n
        [lint.isort]\nclasses = [\"SVC\"]\n
        "},{"location":"settings/#lint_isort_combine-as-imports","title":"combine-as-imports","text":"

        Combines as imports on the same line. See isort's combine-as-imports option.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\ncombine-as-imports = true\n
        [lint.isort]\ncombine-as-imports = true\n
        "},{"location":"settings/#lint_isort_constants","title":"constants","text":"

        An override list of tokens to always recognize as a CONSTANT for order-by-type regardless of casing.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nconstants = [\"constant\"]\n
        [lint.isort]\nconstants = [\"constant\"]\n
        "},{"location":"settings/#lint_isort_default-section","title":"default-section","text":"

        Define a default section for any imports that don't fit into the specified section-order.

        Default value: \"third-party\"

        Type: str

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\ndefault-section = \"first-party\"\n
        [lint.isort]\ndefault-section = \"first-party\"\n
        "},{"location":"settings/#lint_isort_detect-same-package","title":"detect-same-package","text":"

        Whether to automatically mark imports from within the same package as first-party. For example, when detect-same-package = true, then when analyzing files within the foo package, any imports from within the foo package will be considered first-party.

        This heuristic is often unnecessary when src is configured to detect all first-party sources; however, if src is not configured, this heuristic can be useful to detect first-party imports from within (but not across) first-party packages.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\ndetect-same-package = false\n
        [lint.isort]\ndetect-same-package = false\n
        "},{"location":"settings/#lint_isort_extra-standard-library","title":"extra-standard-library","text":"

        A list of modules to consider standard-library, in addition to those known to Ruff in advance.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nextra-standard-library = [\"path\"]\n
        [lint.isort]\nextra-standard-library = [\"path\"]\n
        "},{"location":"settings/#lint_isort_force-single-line","title":"force-single-line","text":"

        Forces all from imports to appear on their own line.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nforce-single-line = true\n
        [lint.isort]\nforce-single-line = true\n
        "},{"location":"settings/#lint_isort_force-sort-within-sections","title":"force-sort-within-sections","text":"

        Don't sort straight-style imports (like import sys) before from-style imports (like from itertools import groupby). Instead, sort the imports by module, independent of import style.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nforce-sort-within-sections = true\n
        [lint.isort]\nforce-sort-within-sections = true\n
        "},{"location":"settings/#lint_isort_force-to-top","title":"force-to-top","text":"

        Force specific imports to the top of their appropriate section.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nforce-to-top = [\"src\"]\n
        [lint.isort]\nforce-to-top = [\"src\"]\n
        "},{"location":"settings/#lint_isort_force-wrap-aliases","title":"force-wrap-aliases","text":"

        Force import from statements with multiple members and at least one alias (e.g., import A as B) to wrap such that every line contains exactly one member. For example, this formatting would be retained, rather than condensing to a single line:

        from .utils import (\n    test_directory as test_directory,\n    test_id as test_id\n)\n

        Note that this setting is only effective when combined with combine-as-imports = true. When combine-as-imports isn't enabled, every aliased import from will be given its own line, in which case, wrapping is not necessary.

        When using the formatter, ensure that format.skip-magic-trailing-comma is set to false (default) when enabling force-wrap-aliases to avoid that the formatter collapses members if they all fit on a single line.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nforce-wrap-aliases = true\ncombine-as-imports = true\n
        [lint.isort]\nforce-wrap-aliases = true\ncombine-as-imports = true\n
        "},{"location":"settings/#lint_isort_forced-separate","title":"forced-separate","text":"

        A list of modules to separate into auxiliary block(s) of imports, in the order specified.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nforced-separate = [\"tests\"]\n
        [lint.isort]\nforced-separate = [\"tests\"]\n
        "},{"location":"settings/#lint_isort_from-first","title":"from-first","text":"

        Whether to place import from imports before straight imports when sorting.

        For example, by default, imports will be sorted such that straight imports appear before import from imports, as in:

        import os\nimport sys\nfrom typing import List\n

        Setting from-first = true will instead sort such that import from imports appear before straight imports, as in:

        from typing import List\nimport os\nimport sys\n

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nfrom-first = true\n
        [lint.isort]\nfrom-first = true\n
        "},{"location":"settings/#lint_isort_known-first-party","title":"known-first-party","text":"

        A list of modules to consider first-party, regardless of whether they can be identified as such via introspection of the local filesystem.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nknown-first-party = [\"src\"]\n
        [lint.isort]\nknown-first-party = [\"src\"]\n
        "},{"location":"settings/#lint_isort_known-local-folder","title":"known-local-folder","text":"

        A list of modules to consider being a local folder. Generally, this is reserved for relative imports (from . import module).

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nknown-local-folder = [\"src\"]\n
        [lint.isort]\nknown-local-folder = [\"src\"]\n
        "},{"location":"settings/#lint_isort_known-third-party","title":"known-third-party","text":"

        A list of modules to consider third-party, regardless of whether they can be identified as such via introspection of the local filesystem.

        Supports glob patterns. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nknown-third-party = [\"src\"]\n
        [lint.isort]\nknown-third-party = [\"src\"]\n
        "},{"location":"settings/#lint_isort_length-sort","title":"length-sort","text":"

        Sort imports by their string length, such that shorter imports appear before longer imports. For example, by default, imports will be sorted alphabetically, as in:

        import collections\nimport os\n

        Setting length-sort = true will instead sort such that shorter imports appear before longer imports, as in:

        import os\nimport collections\n

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nlength-sort = true\n
        [lint.isort]\nlength-sort = true\n
        "},{"location":"settings/#lint_isort_length-sort-straight","title":"length-sort-straight","text":"

        Sort straight imports by their string length. Similar to length-sort, but applies only to straight imports and doesn't affect from imports.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nlength-sort-straight = true\n
        [lint.isort]\nlength-sort-straight = true\n
        "},{"location":"settings/#lint_isort_lines-after-imports","title":"lines-after-imports","text":"

        The number of blank lines to place after imports. Use -1 for automatic determination.

        Ruff uses at most one blank line after imports in typing stub files (files with .pyi extension) in accordance to the typing style recommendations (source).

        When using the formatter, only the values -1, 1, and 2 are compatible because it enforces at least one empty and at most two empty lines after imports.

        Default value: -1

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\n# Use a single line after each import block.\nlines-after-imports = 1\n
        [lint.isort]\n# Use a single line after each import block.\nlines-after-imports = 1\n
        "},{"location":"settings/#lint_isort_lines-between-types","title":"lines-between-types","text":"

        The number of lines to place between \"direct\" and import from imports.

        When using the formatter, only the values 0 and 1 are compatible because it preserves up to one empty line after imports in nested blocks.

        Default value: 0

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\n# Use a single line between direct and from import.\nlines-between-types = 1\n
        [lint.isort]\n# Use a single line between direct and from import.\nlines-between-types = 1\n
        "},{"location":"settings/#lint_isort_no-lines-before","title":"no-lines-before","text":"

        A list of sections that should not be delineated from the previous section via empty lines.

        Default value: []

        Type: list[\"future\" | \"standard-library\" | \"third-party\" | \"first-party\" | \"local-folder\" | str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nno-lines-before = [\"future\", \"standard-library\"]\n
        [lint.isort]\nno-lines-before = [\"future\", \"standard-library\"]\n
        "},{"location":"settings/#lint_isort_no-sections","title":"no-sections","text":"

        Put all imports into the same section bucket.

        For example, rather than separating standard library and third-party imports, as in:

        import os\nimport sys\n\nimport numpy\nimport pandas\n

        Setting no-sections = true will instead group all imports into a single section:

        import numpy\nimport os\nimport pandas\nimport sys\n

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nno-sections = true\n
        [lint.isort]\nno-sections = true\n
        "},{"location":"settings/#lint_isort_order-by-type","title":"order-by-type","text":"

        Order imports by type, which is determined by case, in addition to alphabetically.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\norder-by-type = true\n
        [lint.isort]\norder-by-type = true\n
        "},{"location":"settings/#lint_isort_relative-imports-order","title":"relative-imports-order","text":"

        Whether to place \"closer\" imports (fewer . characters, most local) before \"further\" imports (more . characters, least local), or vice versa.

        The default (\"furthest-to-closest\") is equivalent to isort's reverse-relative default (reverse-relative = false); setting this to \"closest-to-furthest\" is equivalent to isort's reverse-relative = true.

        Default value: \"furthest-to-closest\"

        Type: \"furthest-to-closest\" | \"closest-to-furthest\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nrelative-imports-order = \"closest-to-furthest\"\n
        [lint.isort]\nrelative-imports-order = \"closest-to-furthest\"\n
        "},{"location":"settings/#lint_isort_required-imports","title":"required-imports","text":"

        Add the specified import line to all files.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nrequired-imports = [\"from __future__ import annotations\"]\n
        [lint.isort]\nrequired-imports = [\"from __future__ import annotations\"]\n
        "},{"location":"settings/#lint_isort_section-order","title":"section-order","text":"

        Override in which order the sections should be output. Can be used to move custom sections.

        Default value: [\"future\", \"standard-library\", \"third-party\", \"first-party\", \"local-folder\"]

        Type: list[\"future\" | \"standard-library\" | \"third-party\" | \"first-party\" | \"local-folder\" | str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nsection-order = [\"future\", \"standard-library\", \"first-party\", \"local-folder\", \"third-party\"]\n
        [lint.isort]\nsection-order = [\"future\", \"standard-library\", \"first-party\", \"local-folder\", \"third-party\"]\n
        "},{"location":"settings/#lint_isort_sections","title":"sections","text":"

        A list of mappings from section names to modules.

        By default, imports are categorized according to their type (e.g., future, third-party, and so on). This setting allows you to group modules into custom sections, to augment or override the built-in sections.

        For example, to group all testing utilities, you could create a testing section:

        testing = [\"pytest\", \"hypothesis\"]\n

        The values in the list are treated as glob patterns. For example, to match all packages in the LangChain ecosystem (langchain-core, langchain-openai, etc.):

        langchain = [\"langchain-*\"]\n

        Custom sections should typically be inserted into the section-order list to ensure that they're displayed as a standalone group and in the intended order, as in:

        section-order = [\n  \"future\",\n  \"standard-library\",\n  \"third-party\",\n  \"first-party\",\n  \"local-folder\",\n  \"testing\"\n]\n

        If a custom section is omitted from section-order, imports in that section will be assigned to the default-section (which defaults to third-party).

        Default value: {}

        Type: dict[str, list[str]]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort.sections]\n# Group all Django imports into a separate section.\n\"django\" = [\"django\"]\n
        [lint.isort.sections]\n# Group all Django imports into a separate section.\n\"django\" = [\"django\"]\n
        "},{"location":"settings/#lint_isort_single-line-exclusions","title":"single-line-exclusions","text":"

        One or more modules to exclude from the single line rule.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nsingle-line-exclusions = [\"os\", \"json\"]\n
        [lint.isort]\nsingle-line-exclusions = [\"os\", \"json\"]\n
        "},{"location":"settings/#lint_isort_split-on-trailing-comma","title":"split-on-trailing-comma","text":"

        If a comma is placed after the last member in a multi-line import, then the imports will never be folded into one line.

        See isort's split-on-trailing-comma option.

        When using the formatter, ensure that format.skip-magic-trailing-comma is set to false (default) when enabling split-on-trailing-comma to avoid that the formatter removes the trailing commas.

        Default value: true

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nsplit-on-trailing-comma = false\n
        [lint.isort]\nsplit-on-trailing-comma = false\n
        "},{"location":"settings/#lint_isort_variables","title":"variables","text":"

        An override list of tokens to always recognize as a var for order-by-type regardless of casing.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.isort]\nvariables = [\"VAR\"]\n
        [lint.isort]\nvariables = [\"VAR\"]\n
        "},{"location":"settings/#lintmccabe","title":"lint.mccabe","text":"

        Options for the mccabe plugin.

        "},{"location":"settings/#lint_mccabe_max-complexity","title":"max-complexity","text":"

        The maximum McCabe complexity to allow before triggering C901 errors.

        Default value: 10

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.mccabe]\n# Flag errors (`C901`) whenever the complexity level exceeds 5.\nmax-complexity = 5\n
        [lint.mccabe]\n# Flag errors (`C901`) whenever the complexity level exceeds 5.\nmax-complexity = 5\n
        "},{"location":"settings/#lintpep8-naming","title":"lint.pep8-naming","text":"

        Options for the pep8-naming plugin.

        "},{"location":"settings/#lint_pep8-naming_classmethod-decorators","title":"classmethod-decorators","text":"

        A list of decorators that, when applied to a method, indicate that the method should be treated as a class method (in addition to the builtin @classmethod).

        For example, Ruff will expect that any method decorated by a decorator in this list takes a cls argument as its first argument.

        Expects to receive a list of fully-qualified names (e.g., pydantic.validator, rather than validator) or alternatively a plain name which is then matched against the last segment in case the decorator itself consists of a dotted name.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pep8-naming]\nclassmethod-decorators = [\n    # Allow Pydantic's `@validator` decorator to trigger class method treatment.\n    \"pydantic.validator\",\n    # Allow SQLAlchemy's dynamic decorators, like `@field.expression`, to trigger class method treatment.\n    \"declared_attr\",\n    \"expression\",\n    \"comparator\",\n]\n
        [lint.pep8-naming]\nclassmethod-decorators = [\n    # Allow Pydantic's `@validator` decorator to trigger class method treatment.\n    \"pydantic.validator\",\n    # Allow SQLAlchemy's dynamic decorators, like `@field.expression`, to trigger class method treatment.\n    \"declared_attr\",\n    \"expression\",\n    \"comparator\",\n]\n
        "},{"location":"settings/#lint_pep8-naming_extend-ignore-names","title":"extend-ignore-names","text":"

        Additional names (or patterns) to ignore when considering pep8-naming violations, in addition to those included in ignore-names.

        Supports glob patterns. For example, to ignore all names starting with test_ or ending with _test, you could use ignore-names = [\"test_*\", \"*_test\"]. For more information on the glob syntax, refer to the globset documentation.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pep8-naming]\nextend-ignore-names = [\"callMethod\"]\n
        [lint.pep8-naming]\nextend-ignore-names = [\"callMethod\"]\n
        "},{"location":"settings/#lint_pep8-naming_ignore-names","title":"ignore-names","text":"

        A list of names (or patterns) to ignore when considering pep8-naming violations.

        Supports glob patterns. For example, to ignore all names starting with test_ or ending with _test, you could use ignore-names = [\"test_*\", \"*_test\"]. For more information on the glob syntax, refer to the globset documentation.

        Default value: [\"setUp\", \"tearDown\", \"setUpClass\", \"tearDownClass\", \"setUpModule\", \"tearDownModule\", \"asyncSetUp\", \"asyncTearDown\", \"setUpTestData\", \"failureException\", \"longMessage\", \"maxDiff\"]

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pep8-naming]\nignore-names = [\"callMethod\"]\n
        [lint.pep8-naming]\nignore-names = [\"callMethod\"]\n
        "},{"location":"settings/#lint_pep8-naming_staticmethod-decorators","title":"staticmethod-decorators","text":"

        A list of decorators that, when applied to a method, indicate that the method should be treated as a static method (in addition to the builtin @staticmethod).

        For example, Ruff will expect that any method decorated by a decorator in this list has no self or cls argument.

        Expects to receive a list of fully-qualified names (e.g., belay.Device.teardown, rather than teardown) or alternatively a plain name which is then matched against the last segment in case the decorator itself consists of a dotted name.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pep8-naming]\n# Allow Belay's `@Device.teardown` decorator to trigger static method treatment.\nstaticmethod-decorators = [\"belay.Device.teardown\"]\n
        [lint.pep8-naming]\n# Allow Belay's `@Device.teardown` decorator to trigger static method treatment.\nstaticmethod-decorators = [\"belay.Device.teardown\"]\n
        "},{"location":"settings/#lintpycodestyle","title":"lint.pycodestyle","text":"

        Options for the pycodestyle plugin.

        "},{"location":"settings/#lint_pycodestyle_ignore-overlong-task-comments","title":"ignore-overlong-task-comments","text":"

        Whether line-length violations (E501) should be triggered for comments starting with task-tags (by default: \"TODO\", \"FIXME\", and \"XXX\").

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pycodestyle]\nignore-overlong-task-comments = true\n
        [lint.pycodestyle]\nignore-overlong-task-comments = true\n
        "},{"location":"settings/#lint_pycodestyle_max-doc-length","title":"max-doc-length","text":"

        The maximum line length to allow for doc-line-too-long violations within documentation (W505), including standalone comments. By default, this is set to null which disables reporting violations.

        The length is determined by the number of characters per line, except for lines containing Asian characters or emojis. For these lines, the unicode width of each character is added up to determine the length.

        See the doc-line-too-long rule for more information.

        Default value: null

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pycodestyle]\nmax-doc-length = 88\n
        [lint.pycodestyle]\nmax-doc-length = 88\n
        "},{"location":"settings/#lint_pycodestyle_max-line-length","title":"max-line-length","text":"

        The maximum line length to allow for line-too-long violations. By default, this is set to the value of the line-length option.

        Use this option when you want to detect extra-long lines that the formatter can't automatically split by setting pycodestyle.line-length to a value larger than line-length.

        # The formatter wraps lines at a length of 88.\nline-length = 88\n\n[pycodestyle]\n# E501 reports lines that exceed the length of 100.\nmax-line-length = 100\n

        The length is determined by the number of characters per line, except for lines containing East Asian characters or emojis. For these lines, the unicode width of each character is added up to determine the length.

        See the line-too-long rule for more information.

        Default value: null

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pycodestyle]\nmax-line-length = 100\n
        [lint.pycodestyle]\nmax-line-length = 100\n
        "},{"location":"settings/#lintpydoclint","title":"lint.pydoclint","text":"

        Options for the pydoclint plugin.

        "},{"location":"settings/#lint_pydoclint_ignore-one-line-docstrings","title":"ignore-one-line-docstrings","text":"

        Skip docstrings which fit on a single line.

        Note: The corresponding setting in pydoclint is named skip-checking-short-docstrings.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydoclint]\n# Skip docstrings which fit on a single line.\nignore-one-line-docstrings = true\n
        [lint.pydoclint]\n# Skip docstrings which fit on a single line.\nignore-one-line-docstrings = true\n
        "},{"location":"settings/#lintpydocstyle","title":"lint.pydocstyle","text":"

        Options for the pydocstyle plugin.

        "},{"location":"settings/#lint_pydocstyle_convention","title":"convention","text":"

        Whether to use Google-style, NumPy-style conventions, or the PEP 257 defaults when analyzing docstring sections.

        Enabling a convention will disable all rules that are not included in the specified convention. As such, the intended workflow is to enable a convention and then selectively enable or disable any additional rules on top of it.

        For example, to use Google-style conventions but avoid requiring documentation for every function parameter:

        [tool.ruff.lint]\n# Enable all `pydocstyle` rules, limiting to those that adhere to the\n# Google convention via `convention = \"google\"`, below.\nselect = [\"D\"]\n\n# On top of the Google convention, disable `D417`, which requires\n# documentation for every function parameter.\nignore = [\"D417\"]\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n

        To enable an additional rule that's excluded from the convention, select the desired rule via its fully qualified rule code (e.g., D400 instead of D4 or D40):

        [tool.ruff.lint]\n# Enable D400 on top of the Google convention.\nextend-select = [\"D400\"]\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n

        Default value: null

        Type: \"google\" | \"numpy\" | \"pep257\"

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydocstyle]\n# Use Google-style docstrings.\nconvention = \"google\"\n
        [lint.pydocstyle]\n# Use Google-style docstrings.\nconvention = \"google\"\n
        "},{"location":"settings/#lint_pydocstyle_ignore-decorators","title":"ignore-decorators","text":"

        Ignore docstrings for functions or methods decorated with the specified fully-qualified decorators.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydocstyle]\nignore-decorators = [\"typing.overload\"]\n
        [lint.pydocstyle]\nignore-decorators = [\"typing.overload\"]\n
        "},{"location":"settings/#lint_pydocstyle_ignore-var-parameters","title":"ignore-var-parameters","text":"

        If set to true, ignore missing documentation for *args and **kwargs parameters.

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydocstyle]\nignore-var-parameters = true\n
        [lint.pydocstyle]\nignore-var-parameters = true\n
        "},{"location":"settings/#lint_pydocstyle_property-decorators","title":"property-decorators","text":"

        A list of decorators that, when applied to a method, indicate that the method should be treated as a property (in addition to the builtin @property and standard-library @functools.cached_property).

        For example, Ruff will expect that any method decorated by a decorator in this list can use a non-imperative summary line.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pydocstyle]\nproperty-decorators = [\"gi.repository.GObject.Property\"]\n
        [lint.pydocstyle]\nproperty-decorators = [\"gi.repository.GObject.Property\"]\n
        "},{"location":"settings/#lintpyflakes","title":"lint.pyflakes","text":"

        Options for the pyflakes plugin.

        "},{"location":"settings/#lint_pyflakes_allowed-unused-imports","title":"allowed-unused-imports","text":"

        A list of modules to ignore when considering unused imports.

        Used to prevent violations for specific modules that are known to have side effects on import (e.g., hvplot.pandas).

        Modules in this list are expected to be fully-qualified names (e.g., hvplot.pandas). Any submodule of a given module will also be ignored (e.g., given hvplot, hvplot.pandas will also be ignored).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pyflakes]\nallowed-unused-imports = [\"hvplot.pandas\"]\n
        [lint.pyflakes]\nallowed-unused-imports = [\"hvplot.pandas\"]\n
        "},{"location":"settings/#lint_pyflakes_extend-generics","title":"extend-generics","text":"

        Additional functions or classes to consider generic, such that any subscripts should be treated as type annotation (e.g., ForeignKey in django.db.models.ForeignKey[\"User\"].

        Expects to receive a list of fully-qualified names (e.g., django.db.models.ForeignKey, rather than ForeignKey).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pyflakes]\nextend-generics = [\"django.db.models.ForeignKey\"]\n
        [lint.pyflakes]\nextend-generics = [\"django.db.models.ForeignKey\"]\n
        "},{"location":"settings/#lintpylint","title":"lint.pylint","text":"

        Options for the pylint plugin.

        "},{"location":"settings/#lint_pylint_allow-dunder-method-names","title":"allow-dunder-method-names","text":"

        Dunder methods name to allow, in addition to the default set from the Python standard library (see PLW3201).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nallow-dunder-method-names = [\"__tablename__\", \"__table_args__\"]\n
        [lint.pylint]\nallow-dunder-method-names = [\"__tablename__\", \"__table_args__\"]\n
        "},{"location":"settings/#lint_pylint_allow-magic-value-types","title":"allow-magic-value-types","text":"

        Constant types to ignore when used as \"magic values\" (see PLR2004).

        Default value: [\"str\", \"bytes\"]

        Type: list[\"str\" | \"bytes\" | \"complex\" | \"float\" | \"int\"]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nallow-magic-value-types = [\"int\"]\n
        [lint.pylint]\nallow-magic-value-types = [\"int\"]\n
        "},{"location":"settings/#lint_pylint_max-args","title":"max-args","text":"

        Maximum number of arguments allowed for a function or method definition (see PLR0913).

        Default value: 5

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-args = 10\n
        [lint.pylint]\nmax-args = 10\n
        "},{"location":"settings/#lint_pylint_max-bool-expr","title":"max-bool-expr","text":"

        Maximum number of Boolean expressions allowed within a single if statement (see PLR0916).

        Default value: 5

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-bool-expr = 10\n
        [lint.pylint]\nmax-bool-expr = 10\n
        "},{"location":"settings/#lint_pylint_max-branches","title":"max-branches","text":"

        Maximum number of branches allowed for a function or method body (see PLR0912).

        Default value: 12

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-branches = 15\n
        [lint.pylint]\nmax-branches = 15\n
        "},{"location":"settings/#lint_pylint_max-locals","title":"max-locals","text":"

        Maximum number of local variables allowed for a function or method body (see PLR0914).

        Default value: 15

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-locals = 20\n
        [lint.pylint]\nmax-locals = 20\n
        "},{"location":"settings/#lint_pylint_max-nested-blocks","title":"max-nested-blocks","text":"

        Maximum number of nested blocks allowed within a function or method body (see PLR1702).

        Default value: 5

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-nested-blocks = 10\n
        [lint.pylint]\nmax-nested-blocks = 10\n
        "},{"location":"settings/#lint_pylint_max-positional-args","title":"max-positional-args","text":"

        Maximum number of positional arguments allowed for a function or method definition (see PLR0917).

        If not specified, defaults to the value of max-args.

        Default value: 5

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-positional-args = 3\n
        [lint.pylint]\nmax-positional-args = 3\n
        "},{"location":"settings/#lint_pylint_max-public-methods","title":"max-public-methods","text":"

        Maximum number of public methods allowed for a class (see PLR0904).

        Default value: 20

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-public-methods = 30\n
        [lint.pylint]\nmax-public-methods = 30\n
        "},{"location":"settings/#lint_pylint_max-returns","title":"max-returns","text":"

        Maximum number of return statements allowed for a function or method body (see PLR0911)

        Default value: 6

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-returns = 10\n
        [lint.pylint]\nmax-returns = 10\n
        "},{"location":"settings/#lint_pylint_max-statements","title":"max-statements","text":"

        Maximum number of statements allowed for a function or method body (see PLR0915).

        Default value: 50

        Type: int

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pylint]\nmax-statements = 75\n
        [lint.pylint]\nmax-statements = 75\n
        "},{"location":"settings/#lintpyupgrade","title":"lint.pyupgrade","text":"

        Options for the pyupgrade plugin.

        "},{"location":"settings/#lint_pyupgrade_keep-runtime-typing","title":"keep-runtime-typing","text":"

        Whether to avoid PEP 585 (List[int] -> list[int]) and PEP 604 (Union[str, int] -> str | int) rewrites even if a file imports from __future__ import annotations.

        This setting is only applicable when the target Python version is below 3.9 and 3.10 respectively, and is most commonly used when working with libraries like Pydantic and FastAPI, which rely on the ability to parse type annotations at runtime. The use of from __future__ import annotations causes Python to treat the type annotations as strings, which typically allows for the use of language features that appear in later Python versions but are not yet supported by the current version (e.g., str | int). However, libraries that rely on runtime type annotations will break if the annotations are incompatible with the current Python version.

        For example, while the following is valid Python 3.8 code due to the presence of from __future__ import annotations, the use of str | int prior to Python 3.10 will cause Pydantic to raise a TypeError at runtime:

        from __future__ import annotations\n\nimport pydantic\n\nclass Foo(pydantic.BaseModel):\n    bar: str | int\n

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.pyupgrade]\n# Preserve types, even if a file imports `from __future__ import annotations`.\nkeep-runtime-typing = true\n
        [lint.pyupgrade]\n# Preserve types, even if a file imports `from __future__ import annotations`.\nkeep-runtime-typing = true\n
        "},{"location":"settings/#lintruff","title":"lint.ruff","text":"

        Options for the ruff plugin

        "},{"location":"settings/#lint_ruff_allowed-markup-calls","title":"allowed-markup-calls","text":"

        Deprecated

        This option has been deprecated in 0.10.0. The allowed-markup-names option has been moved to the flake8-bandit section of the configuration.

        A list of callable names, whose result may be safely passed into markupsafe.Markup.

        Expects to receive a list of fully-qualified names (e.g., bleach.clean, rather than clean).

        This setting helps you avoid false positives in code like:

        from bleach import clean\nfrom markupsafe import Markup\n\ncleaned_markup = Markup(clean(some_user_input))\n

        Where the use of bleach.clean usually ensures that there's no XSS vulnerability.

        Although it is not recommended, you may also use this setting to whitelist other kinds of calls, e.g. calls to i18n translation functions, where how safe that is will depend on the implementation and how well the translations are audited.

        Another common use-case is to wrap the output of functions that generate markup like xml.etree.ElementTree.tostring or template rendering engines where sanitization of potential user input is either already baked in or has to happen before rendering.

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.ruff]\nallowed-markup-calls = [\"bleach.clean\", \"my_package.sanitize\"]\n
        [lint.ruff]\nallowed-markup-calls = [\"bleach.clean\", \"my_package.sanitize\"]\n
        "},{"location":"settings/#lint_ruff_extend-markup-names","title":"extend-markup-names","text":"

        Deprecated

        This option has been deprecated in 0.10.0. The extend-markup-names option has been moved to the flake8-bandit section of the configuration.

        A list of additional callable names that behave like markupsafe.Markup.

        Expects to receive a list of fully-qualified names (e.g., webhelpers.html.literal, rather than literal).

        Default value: []

        Type: list[str]

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.ruff]\nextend-markup-names = [\"webhelpers.html.literal\", \"my_package.Markup\"]\n
        [lint.ruff]\nextend-markup-names = [\"webhelpers.html.literal\", \"my_package.Markup\"]\n
        "},{"location":"settings/#lint_ruff_parenthesize-tuple-in-subscript","title":"parenthesize-tuple-in-subscript","text":"

        Whether to prefer accessing items keyed by tuples with parentheses around the tuple (see RUF031).

        Default value: false

        Type: bool

        Example usage:

        pyproject.tomlruff.toml
        [tool.ruff.lint.ruff]\n# Make it a violation to use a tuple in a subscript without parentheses.\nparenthesize-tuple-in-subscript = true\n
        [lint.ruff]\n# Make it a violation to use a tuple in a subscript without parentheses.\nparenthesize-tuple-in-subscript = true\n
        "},{"location":"tutorial/","title":"Tutorial","text":"

        This tutorial will walk you through the process of integrating Ruff's linter and formatter into your project. For a more detailed overview, see Configuring Ruff.

        "},{"location":"tutorial/#getting-started","title":"Getting Started","text":"

        To start, we'll initialize a project using uv:

        $ uv init --lib numbers\n

        This command creates a Python project with the following structure:

        numbers\n  \u251c\u2500\u2500 README.md\n  \u251c\u2500\u2500 pyproject.toml\n  \u2514\u2500\u2500 src\n      \u2514\u2500\u2500 numbers\n          \u251c\u2500\u2500 __init__.py\n          \u2514\u2500\u2500 py.typed\n

        We'll then clear out the auto-generated content in src/numbers/__init__.py and create src/numbers/calculate.py with the following code:

        from typing import Iterable\n\nimport os\n\n\ndef sum_even_numbers(numbers: Iterable[int]) -> int:\n    \"\"\"Given an iterable of integers, return the sum of all even numbers in the iterable.\"\"\"\n    return sum(\n        num for num in numbers\n        if num % 2 == 0\n    )\n

        Next, we'll add Ruff to our project:

        $ uv add --dev ruff\n

        We can then run the Ruff linter over our project via uv run ruff check:

        $ uv run ruff check\nsrc/numbers/calculate.py:3:8: F401 [*] `os` imported but unused\nFound 1 error.\n[*] 1 fixable with the `--fix` option.\n

        Note

        As an alternative to uv run, you can also run Ruff by activating the project's virtual environment (source .venv/bin/active on Linux and macOS, or .venv\\Scripts\\activate on Windows) and running ruff check directly.

        Ruff identified an unused import, which is a common error in Python code. Ruff considers this a \"fixable\" error, so we can resolve the issue automatically by running ruff check --fix:

        $ uv run ruff check --fix\nFound 1 error (1 fixed, 0 remaining).\n

        Running git diff shows the following:

        --- a/src/numbers/calculate.py\n+++ b/src/numbers/calculate.py\n@@ -1,7 +1,5 @@\n from typing import Iterable\n\n-import os\n-\n\ndef sum_even_numbers(numbers: Iterable[int]) -> int:\n    \"\"\"Given an iterable of integers, return the sum of all even numbers in the iterable.\"\"\"\n    return sum(\n        num for num in numbers\n        if num % 2 == 0\n    )\n

        Note Ruff runs in the current directory by default, but you can pass specific paths to check:

        $ uv run ruff check src/numbers/calculate.py\n

        Now that our project is passing ruff check, we can run the Ruff formatter via ruff format:

        $ uv run ruff format\n1 file reformatted\n

        Running git diff shows that the sum call was reformatted to fit within the default 88-character line length limit:

        --- a/src/numbers/calculate.py\n+++ b/src/numbers/calculate.py\n@@ -3,7 +3,4 @@ from typing import Iterable\n\n def sum_even_numbers(numbers: Iterable[int]) -> int:\n     \"\"\"Given an iterable of integers, return the sum of all even numbers in the iterable.\"\"\"\n-    return sum(\n-        num for num in numbers\n-        if num % 2 == 0\n-    )\n+    return sum(num for num in numbers if num % 2 == 0)\n

        Thus far, we've been using Ruff's default configuration. Let's take a look at how we can customize Ruff's behavior.

        "},{"location":"tutorial/#configuration","title":"Configuration","text":"

        To determine the appropriate settings for each Python file, Ruff looks for the first pyproject.toml, ruff.toml, or .ruff.toml file in the file's directory or any parent directory.

        To configure Ruff, we'll add the following to the configuration file in our project's root directory:

        pyproject.tomlruff.toml
        [tool.ruff]\n# Set the maximum line length to 79.\nline-length = 79\n\n[tool.ruff.lint]\n# Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that\n# overlap with the use of a formatter, like Black, but we can override this behavior by\n# explicitly adding the rule.\nextend-select = [\"E501\"]\n
        # Set the maximum line length to 79.\nline-length = 79\n\n[lint]\n# Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that\n# overlap with the use of a formatter, like Black, but we can override this behavior by\n# explicitly adding the rule.\nextend-select = [\"E501\"]\n

        Running Ruff again, we see that it now enforces a maximum line width, with a limit of 79:

        $ uv run ruff check\nsrc/numbers/calculate.py:5:80: E501 Line too long (90 > 79)\nFound 1 error.\n

        For a full enumeration of the supported settings, see Settings. For our project specifically, we'll want to make note of the minimum supported Python version:

        pyproject.tomlruff.toml
        [project]\n# Support Python 3.10+.\nrequires-python = \">=3.10\"\n\n[tool.ruff]\n# Set the maximum line length to 79.\nline-length = 79\n\n[tool.ruff.lint]\n# Add the `line-too-long` rule to the enforced rule set.\nextend-select = [\"E501\"]\n
        # Support Python 3.10+.\ntarget-version = \"py310\"\n# Set the maximum line length to 79.\nline-length = 79\n\n[lint]\n# Add the `line-too-long` rule to the enforced rule set.\nextend-select = [\"E501\"]\n
        "},{"location":"tutorial/#rule-selection","title":"Rule Selection","text":"

        Ruff supports over 800 lint rules split across over 50 built-in plugins, but determining the right set of rules will depend on your project's needs: some rules may be too strict, some are framework-specific, and so on.

        By default, Ruff enables Flake8's F rules, along with a subset of the E rules, omitting any stylistic rules that overlap with the use of a formatter, like ruff format or Black.

        If you're introducing a linter for the first time, the default rule set is a great place to start: it's narrow and focused while catching a wide variety of common errors (like unused imports) with zero configuration.

        If you're migrating to Ruff from another linter, you can enable rules that are equivalent to those enforced in your previous configuration. For example, if we want to enforce the pyupgrade rules, we can set our configuration file to the following:

        pyproject.tomlruff.toml
        [project]\nrequires-python = \">=3.10\"\n\n[tool.ruff.lint]\nextend-select = [\n  \"UP\",  # pyupgrade\n]\n
        target-version = \"py310\"\n\n[lint]\nextend-select = [\n  \"UP\",  # pyupgrade\n]\n

        If we run Ruff again, we'll see that it now enforces the pyupgrade rules. In particular, Ruff flags the use of the deprecated typing.Iterable instead of collections.abc.Iterable:

        $ uv run ruff check\nsrc/numbers/calculate.py:1:1: UP035 [*] Import from `collections.abc` instead: `Iterable`\nFound 1 error.\n[*] 1 fixable with the `--fix` option.\n

        Over time, we may choose to enforce additional rules. For example, we may want to enforce that all functions have docstrings:

        pyproject.tomlruff.toml
        [project]\nrequires-python = \">=3.10\"\n\n[tool.ruff.lint]\nextend-select = [\n  \"UP\",  # pyupgrade\n  \"D\",   # pydocstyle\n]\n\n[tool.ruff.lint.pydocstyle]\nconvention = \"google\"\n
        target-version = \"py310\"\n\n[lint]\nextend-select = [\n  \"UP\",  # pyupgrade\n  \"D\",   # pydocstyle\n]\n\n[lint.pydocstyle]\nconvention = \"google\"\n

        If we run Ruff again, we'll see that it now enforces the pydocstyle rules:

        $ uv run ruff check\nsrc/numbers/__init__.py:1:1: D104 Missing docstring in public package\nsrc/numbers/calculate.py:1:1: UP035 [*] Import from `collections.abc` instead: `Iterable`\n  |\n1 | from typing import Iterable\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035\n  |\n  = help: Import from `collections.abc`\n\nsrc/numbers/calculate.py:1:1: D100 Missing docstring in public module\nFound 3 errors.\n[*] 1 fixable with the `--fix` option.\n
        "},{"location":"tutorial/#ignoring-errors","title":"Ignoring Errors","text":"

        Any lint rule can be ignored by adding a # noqa comment to the line in question. For example, let's ignore the UP035 rule for the Iterable import:

        from typing import Iterable  # noqa: UP035\n\n\ndef sum_even_numbers(numbers: Iterable[int]) -> int:\n    \"\"\"Given an iterable of integers, return the sum of all even numbers in the iterable.\"\"\"\n    return sum(num for num in numbers if num % 2 == 0)\n

        Running ruff check again, we'll see that it no longer flags the Iterable import:

        $ uv run ruff check\nsrc/numbers/__init__.py:1:1: D104 Missing docstring in public package\nsrc/numbers/calculate.py:1:1: D100 Missing docstring in public module\nFound 2 errors.\n

        If we want to ignore a rule for an entire file, we can add the line # ruff: noqa: {code} anywhere in the file, preferably towards the top, like so:

        # ruff: noqa: UP035\nfrom typing import Iterable\n\n\ndef sum_even_numbers(numbers: Iterable[int]) -> int:\n    \"\"\"Given an iterable of integers, return the sum of all even numbers in the iterable.\"\"\"\n    return sum(num for num in numbers if num % 2 == 0)\n

        For more in-depth instructions on ignoring errors, please see Error suppression.

        "},{"location":"tutorial/#adding-rules","title":"Adding Rules","text":"

        When enabling a new rule on an existing codebase, you may want to ignore all existing violations of that rule and instead focus on enforcing it going forward.

        Ruff enables this workflow via the --add-noqa flag, which will add a # noqa directive to each line based on its existing violations. We can combine --add-noqa with the --select command-line flag to add # noqa directives to all existing UP035 violations:

        $ uv run ruff check --select UP035 --add-noqa .\nAdded 1 noqa directive.\n

        Running git diff shows the following:

        diff --git a/numbers/src/numbers/calculate.py b/numbers/src/numbers/calculate.py\nindex 71fca60c8d..e92d839f1b 100644\n--- a/numbers/src/numbers/calculate.py\n+++ b/numbers/src/numbers/calculate.py\n@@ -1,4 +1,4 @@\n-from typing import Iterable\n+from typing import Iterable  # noqa: UP035\n
        "},{"location":"tutorial/#integrations","title":"Integrations","text":"

        This tutorial has focused on Ruff's command-line interface, but Ruff can also be used as a pre-commit hook via ruff-pre-commit:

        - repo: https://github.com/astral-sh/ruff-pre-commit\n  # Ruff version.\n  rev: v0.11.11\n  hooks:\n    # Run the linter.\n    - id: ruff\n    # Run the formatter.\n    - id: ruff-format\n

        Ruff can also be integrated into your editor of choice. Refer to the Editors section for more information.

        For other integrations, see the Integrations section.

        "},{"location":"versioning/","title":"Versioning","text":"

        Ruff uses a custom versioning scheme that uses the minor version number for breaking changes and the patch version number for bug fixes. Ruff does not yet have a stable API; once Ruff's API is stable, the major version number and semantic versioning will be used.

        "},{"location":"versioning/#version-changes","title":"Version changes","text":"

        Minor version increases will occur when:

        • A deprecated option or feature is removed
        • Configuration changes in a backwards incompatible way
          • This may occur in minor version changes until 1.0.0, however, it should generally be avoided.
        • Support for a new file type is promoted to stable
        • Support for an end-of-life Python version is dropped
        • Linter:
          • A rule is promoted to stable
          • The behavior of a stable rule is changed
            • The scope of a stable rule is significantly increased
            • The intent of the rule changes
            • Does not include bug fixes that follow the original intent of the rule
          • Stable rules are added to the default set
          • Stable rules are removed from the default set
          • A safe fix for a rule is promoted to stable
        • Formatter:
          • The stable style changed
        • Language server:
          • An existing capability is removed
          • A deprecated server setting is removed

        Patch version increases will occur when:

        • Bugs are fixed, including behavior changes that fix bugs
        • A new configuration option is added in a backwards compatible way (no formatting changes or new lint errors)
        • Support for a new Python version is added
        • Support for a new file type is added in preview
        • An option or feature is deprecated
        • Linter:
          • An unsafe fix for a rule is added
          • A safe fix for a rule is added in preview
          • The scope of a rule is increased in preview
          • A fix\u2019s applicability is demoted
          • A rule is added in preview
          • The behavior of a preview rule is changed
        • Formatter:
          • The stable style changed to prevent invalid syntax, changes to the program's semantics, or removal of comments
          • The preview style changed
        • Language server:
          • Support for a new capability is added
          • A new server setting is added
          • A server setting is deprecated
        "},{"location":"versioning/#minimum-supported-rust-version","title":"Minimum supported Rust version","text":"

        The minimum supported Rust version required to compile Ruff is listed in the rust-version key of the [workspace.package] section in Cargo.toml. It may change in any release (minor or patch). It will never be newer than N-2 Rust versions, where N is the latest stable version. For example, if the latest stable Rust version is 1.85, Ruff's minimum supported Rust version will be at most 1.83.

        This is only relevant to users who build Ruff from source. Installing Ruff from the Python package index usually installs a pre-built binary and does not require Rust compilation.

        "},{"location":"versioning/#preview-mode","title":"Preview mode","text":"

        A preview mode is available to enable new, unstable rules and features, e.g., support for a new file type.

        The preview mode is intended to help us collect community feedback and gain confidence that changes are a net-benefit.

        The preview mode is not intended to gate access to work that is incomplete or features that we are likely to remove. However, we reserve the right to make changes to any behavior gated by the mode including the removal of preview features or rules.

        "},{"location":"versioning/#rule-stabilization","title":"Rule stabilization","text":"

        When modifying or adding rules, we use the following guidelines:

        • New rules should always be added in preview mode
        • New rules will remain in preview mode for at least one minor release before being promoted to stable
          • If added in a patch release i.e. 0.6.1 then a rule will not be eligible for stability until 0.8.0
        • Stable rule behaviors are not changed significantly in patch versions
        • Promotion of rules to stable may be delayed in order to \u201cbatch\u201d them into a single minor release
        • Not all rules in preview need to be promoted in a given minor release
        "},{"location":"versioning/#fix-stabilization","title":"Fix stabilization","text":"

        Fixes have three applicability levels:

        • Display: Never applied, just displayed.
        • Unsafe: Can be applied with explicit opt-in.
        • Safe: Can be applied automatically.

        Fixes for rules may be introduced at a lower applicability, then promoted to a higher applicability. Reducing the applicability of a fix is not a breaking change. The applicability of a given fix may change when the preview mode is enabled.

        "},{"location":"versioning/#visual-studio-code-extension","title":"Visual Studio Code Extension","text":"

        Visual Studio Code doesn't support pre-release tags for extensions. Consequently, Ruff uses the following scheme to distinguish between stable and preview releases:

        Stable releases use even numbers in minor version component: 2024.30.0, 2024.32.0, 2024.34.0, \u2026 Preview releases use odd numbers in minor version component: 2024.31.0, 2024.33.0, 2024.35.0, \u2026

        "},{"location":"editors/","title":"Editor Integrations","text":"

        Ruff can be integrated with various editors and IDEs to provide a seamless development experience. This section provides instructions on how to set up Ruff with your editor and configure it to your liking.

        "},{"location":"editors/#language-server-protocol","title":"Language Server Protocol","text":"

        The editor integration is mainly powered by the Ruff Language Server which implements the Language Server Protocol. The server is written in Rust and is available as part of the ruff CLI via ruff server. It is a single, common backend built directly into Ruff, and a direct replacement for ruff-lsp, our previous language server. You can read more about ruff server in the v0.4.5 blog post.

        The server supports surfacing Ruff diagnostics, providing Code Actions to fix them, and formatting the code using Ruff's built-in formatter. Currently, the server is intended to be used alongside another Python Language Server in order to support features like navigation and autocompletion.

        The Ruff Language Server was available first in Ruff v0.4.5 in beta and stabilized in Ruff v0.5.3.

        Note

        This is the documentation for Ruff's built-in language server written in Rust (ruff server). If you are looking for the documentation for the ruff-lsp language server, please refer to the README of the ruff-lsp repository.

        "},{"location":"editors/features/","title":"Features","text":"

        This section provides a detailed overview of the features provided by the Ruff Language Server.

        "},{"location":"editors/features/#diagnostic-highlighting","title":"Diagnostic Highlighting","text":"

        Provide diagnostics for your Python code in real-time.

        "},{"location":"editors/features/#dynamic-configuration","title":"Dynamic Configuration","text":"

        The server dynamically refreshes the diagnostics when a configuration file is changed in the workspace, whether it's a pyproject.toml, ruff.toml, or .ruff.toml file.

        The server relies on the file watching capabilities of the editor to detect changes to these files. If an editor does not support file watching, the server will not be able to detect changes to the configuration file and thus will not refresh the diagnostics.

        "},{"location":"editors/features/#formatting","title":"Formatting","text":"

        Provide code formatting for your Python code. The server can format an entire document or a specific range of lines.

        The VS Code extension provides the Ruff: Format Document command to format an entire document. In VS Code, the range formatting can be triggered by selecting a range of lines, right-clicking, and selecting Format Selection from the context menu.

        "},{"location":"editors/features/#code-actions","title":"Code Actions","text":"

        Code actions are context-sensitive suggestions that can help you fix issues in your code. They are usually triggered by a shortcut or by clicking a light bulb icon in the editor. The Ruff Language Server provides the following code actions:

        • Apply a quick fix for a diagnostic that has a fix available (e.g., removing an unused import).
        • Ignore a diagnostic with a # noqa comment.
        • Apply all quick fixes available in the document.
        • Organize imports in the document.

        You can even run these actions on-save. For example, to fix all issues and organize imports on save in VS Code, add the following to your settings.json:

        {\n  \"[python]\": {\n    \"editor.codeActionsOnSave\": {\n      \"source.fixAll.ruff\": \"explicit\",\n      \"source.organizeImports.ruff\": \"explicit\"\n    }\n  }\n}\n
        "},{"location":"editors/features/#fix-safety","title":"Fix Safety","text":"

        Ruff's automatic fixes are labeled as \"safe\" and \"unsafe\". By default, the \"Fix all\" action will not apply unsafe fixes. However, unsafe fixes can be applied manually with the \"Quick fix\" action. Application of unsafe fixes when using \"Fix all\" can be enabled by setting unsafe-fixes = true in your Ruff configuration file.

        See the Ruff fix documentation for more details on how fix safety works.

        "},{"location":"editors/features/#hover","title":"Hover","text":"

        The server can provide the rule documentation when focusing over a NoQA code in the comment. Focusing is usually hovering with a mouse, but can also be triggered with a shortcut.

        "},{"location":"editors/features/#jupyter-notebook","title":"Jupyter Notebook","text":"

        Similar to Ruff's CLI, the Ruff Language Server fully supports Jupyter Notebook files with all the capabilities available to Python files.

        Note

        Unlike ruff-lsp and similar to the Ruff's CLI, the native language server requires user to explicitly include the Jupyter Notebook files in the set of files to lint and format. Refer to the Jupyter Notebook discovery section on how to do this.

        "},{"location":"editors/migration/","title":"Migrating from ruff-lsp","text":"

        ruff-lsp is the Language Server Protocol implementation for Ruff to power the editor integrations. It is written in Python and is a separate package from Ruff itself. The native server, however, is the Language Server Protocol implementation which is written in Rust and is available under the ruff server command. This guide is intended to help users migrate from ruff-lsp to the native server.

        Note

        The native server was first introduced in Ruff version 0.3.5. It was marked as beta in version 0.4.5 and officially stabilized in version 0.5.3. It is recommended to use the latest version of Ruff to ensure the best experience.

        The migration process involves any or all of the following:

        1. Migrate deprecated settings to the new settings
        2. Remove settings that are no longer supported
        3. Update the ruff version

        Read on to learn more about the unsupported or new settings, or jump to the examples that enumerate some of the common settings and how to migrate them.

        "},{"location":"editors/migration/#unsupported-settings","title":"Unsupported Settings","text":"

        The following ruff-lsp settings are not supported by the native server:

        • lint.run: This setting is no longer relevant for the native language server, which runs on every keystroke by default.
        • lint.args, format.args: These settings have been replaced by more granular settings in the native server like lint.select, format.preview, etc. along with the ability to override any configuration using the configuration setting.

        The following settings are not accepted by the language server but are still used by the VS Code extension. Refer to their respective documentation for more information on how each is used by the extension:

        • path
        • interpreter
        "},{"location":"editors/migration/#removed-settings","title":"Removed Settings","text":"

        Additionally, the following settings are not supported by the native server and should be removed:

        • ignoreStandardLibrary
        • showNotifications
        "},{"location":"editors/migration/#new-settings","title":"New Settings","text":"

        The native server introduces several new settings that ruff-lsp does not have:

        • configuration
        • configurationPreference
        • exclude
        • format.preview
        • lineLength
        • lint.select
        • lint.extendSelect
        • lint.ignore
        • lint.preview
        "},{"location":"editors/migration/#examples","title":"Examples","text":"

        All of the examples mentioned below are only valid for the VS Code extension. For other editors, please refer to their respective documentation sections in the settings page.

        "},{"location":"editors/migration/#configuration-file","title":"Configuration file","text":"

        If you've been providing a configuration file as shown below:

        {\n    \"ruff.lint.args\": \"--config ~/.config/custom_ruff_config.toml\",\n    \"ruff.format.args\": \"--config ~/.config/custom_ruff_config.toml\"\n}\n

        You can migrate to the new server by using the configuration setting like below which will apply the configuration to both the linter and the formatter:

        {\n    \"ruff.configuration\": \"~/.config/custom_ruff_config.toml\"\n}\n
        "},{"location":"editors/migration/#lintargs","title":"lint.args","text":"

        If you're providing the linter flags by using ruff.lint.args like so:

        {\n    \"ruff.lint.args\": \"--select=E,F --unfixable=F401 --unsafe-fixes\"\n}\n

        You can migrate to the new server by using the lint.select and configuration setting like so:

        {\n    \"ruff.lint.select\": [\"E\", \"F\"],\n    \"ruff.configuration\": {\n        \"unsafe-fixes\": true,\n        \"lint\": {\n            \"unfixable\": [\"F401\"]\n        }\n    }\n}\n

        The following options can be set directly in the editor settings:

        • lint.select
        • lint.extendSelect
        • lint.ignore
        • lint.preview

        The remaining options can be set using the configuration setting.

        "},{"location":"editors/migration/#formatargs","title":"format.args","text":"

        If you're also providing formatter flags by using ruff.format.args like so:

        {\n    \"ruff.format.args\": \"--line-length 80 --config='format.quote-style=double'\"\n}\n

        You can migrate to the new server by using the lineLength and configuration setting like so:

        {\n    \"ruff.lineLength\": 80,\n    \"ruff.configuration\": {\n        \"format\": {\n            \"quote-style\": \"double\"\n        }\n    }\n}\n

        The following options can be set directly in the editor settings:

        • lineLength
        • format.preview

        The remaining options can be set using the configuration setting.

        "},{"location":"editors/settings/","title":"Settings","text":"

        The Ruff Language Server provides a set of configuration options to customize its behavior along with the ability to use an existing pyproject.toml or ruff.toml file to configure the linter and formatter. This is done by providing these settings while initializing the server. VS Code provides a UI to configure these settings, while other editors may require manual configuration. The setup section provides instructions on where to place these settings as per the editor.

        "},{"location":"editors/settings/#top-level","title":"Top-level","text":""},{"location":"editors/settings/#configuration","title":"configuration","text":"

        The configuration setting allows you to configure editor-specific Ruff behavior. This can be done in one of the following ways:

        1. Configuration file path: Specify the path to a ruff.toml or pyproject.toml file that contains the configuration. User home directory and environment variables will be expanded.
        2. Inline JSON configuration: Directly provide the configuration as a JSON object.

        Added in Ruff 0.9.8

        The Inline JSON configuration option was introduced in Ruff 0.9.8.

        The default behavior, if configuration is unset, is to load the settings from the project's configuration (a ruff.toml or pyproject.toml in the project's directory), consistent with when running Ruff on the command-line.

        The configurationPreference setting controls the precedence if both an editor-provided configuration (configuration) and a project level configuration file are present.

        "},{"location":"editors/settings/#configuration_resolution_order","title":"Resolution order","text":"

        In an editor, Ruff supports three sources of configuration, prioritized as follows (from highest to lowest):

        1. Specific settings: Individual settings like lineLength or lint.select defined in the editor
        2. ruff.configuration: Settings provided via the configuration field (either a path to a configuration file or an inline configuration object)
        3. Configuration file: Settings defined in a ruff.toml or pyproject.toml file in the project's directory (if present)

        For example, if the line length is specified in all three sources, Ruff will use the value from the lineLength setting.

        Default value: null

        Type: string

        Example usage:

        Using configuration file path:

        VS CodeNeovimZed
        {\n    \"ruff.configuration\": \"~/path/to/ruff.toml\"\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    configuration = \"~/path/to/ruff.toml\"\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"configuration\": \"~/path/to/ruff.toml\"\n        }\n      }\n    }\n  }\n}\n

        Using inline configuration:

        VS CodeNeovimZed
        {\n    \"ruff.configuration\": {\n        \"lint\": {\n            \"unfixable\": [\"F401\"],\n            \"extend-select\": [\"TID251\"],\n            \"flake8-tidy-imports\": {\n                \"banned-api\": {\n                    \"typing.TypedDict\": {\n                        \"msg\": \"Use `typing_extensions.TypedDict` instead\",\n                    }\n                }\n            }\n        },\n        \"format\": {\n            \"quote-style\": \"single\"\n        }\n    }\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    configuration = {\n      lint = {\n        unfixable = {\"F401\"},\n        [\"extend-select\"] = {\"TID251\"},\n        [\"flake8-tidy-imports\"] = {\n          [\"banned-api\"] = {\n            [\"typing.TypedDict\"] = {\n              msg = \"Use `typing_extensions.TypedDict` instead\"\n            }\n          }\n        }\n      },\n      format = {\n        [\"quote-style\"] = \"single\"\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"configuration\": {\n            \"lint\": {\n              \"unfixable\": [\"F401\"],\n              \"extend-select\": [\"TID251\"],\n              \"flake8-tidy-imports\": {\n                \"banned-api\": {\n                  \"typing.TypedDict\": {\n                    \"msg\": \"Use `typing_extensions.TypedDict` instead\"\n                  }\n                }\n              }\n            },\n            \"format\": {\n              \"quote-style\": \"single\"\n            }\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#configurationpreference","title":"configurationPreference","text":"

        The strategy to use when resolving settings across VS Code and the filesystem. By default, editor configuration is prioritized over ruff.toml and pyproject.toml files.

        • \"editorFirst\": Editor settings take priority over configuration files present in the workspace.
        • \"filesystemFirst\": Configuration files present in the workspace takes priority over editor settings.
        • \"editorOnly\": Ignore configuration files entirely i.e., only use editor settings.

        Default value: \"editorFirst\"

        Type: \"editorFirst\" | \"filesystemFirst\" | \"editorOnly\"

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.configurationPreference\": \"filesystemFirst\"\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      configurationPreference = \"filesystemFirst\"\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"configurationPreference\": \"filesystemFirst\"\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#exclude","title":"exclude","text":"

        A list of file patterns to exclude from linting and formatting. See the documentation for more details.

        Default value: null

        Type: string[]

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.exclude\": [\"**/tests/**\"]\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      exclude = [\"**/tests/**\"]\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"exclude\": [\"**/tests/**\"]\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#linelength","title":"lineLength","text":"

        The line length to use for the linter and formatter.

        Default value: null

        Type: int

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lineLength\": 100\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lineLength = 100\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lineLength\": 100\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#fixall","title":"fixAll","text":"

        Whether to register the server as capable of handling source.fixAll code actions.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.fixAll\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      fixAll = false\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"fixAll\": false\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#organizeimports","title":"organizeImports","text":"

        Whether to register the server as capable of handling source.organizeImports code actions.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.organizeImports\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      organizeImports = false\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"organizeImports\": false\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#showsyntaxerrors","title":"showSyntaxErrors","text":"

        New in Ruff v0.5.0

        Whether to show syntax error diagnostics.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.showSyntaxErrors\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      showSyntaxErrors = false\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"showSyntaxErrors\": false\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#loglevel","title":"logLevel","text":"

        The log level to use for the server.

        Default value: \"info\"

        Type: \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\"

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.logLevel\": \"debug\"\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      logLevel = \"debug\"\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"logLevel\": \"debug\"\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#logfile","title":"logFile","text":"

        Path to the log file to use for the server.

        If not set, logs will be written to stderr.

        Default value: null

        Type: string

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.logFile\": \"~/path/to/ruff.log\"\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      logFile = \"~/path/to/ruff.log\"\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"logFile\": \"~/path/to/ruff.log\"\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#codeaction","title":"codeAction","text":"

        Enable or disable code actions provided by the server.

        "},{"location":"editors/settings/#disablerulecommentenable","title":"disableRuleComment.enable","text":"

        Whether to display Quick Fix actions to disable rules via noqa suppression comments.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.codeAction.disableRuleComment.enable\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      codeAction = {\n        disableRuleComment = {\n          enable = false\n        }\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"codeAction\": {\n            \"disableRuleComment\": {\n              \"enable\": false\n            }\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#fixviolationenable","title":"fixViolation.enable","text":"

        Whether to display Quick Fix actions to autofix violations.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.codeAction.fixViolation.enable\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      codeAction = {\n        fixViolation = {\n          enable = false\n        }\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"codeAction\": {\n            \"fixViolation\": = {\n              \"enable\": false\n            }\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#lint","title":"lint","text":"

        Settings specific to the Ruff linter.

        "},{"location":"editors/settings/#lint_enable","title":"enable","text":"

        Whether to enable linting. Set to false to use Ruff exclusively as a formatter.

        Default value: true

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lint.enable\": false\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lint = {\n        enable = false\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lint\": {\n            \"enable\": false\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#lint_preview","title":"preview","text":"

        Whether to enable Ruff's preview mode when linting.

        Default value: null

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lint.preview\": true\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lint = {\n        preview = true\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lint\": {\n            \"preview\": true\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#select","title":"select","text":"

        Rules to enable by default. See the documentation.

        Default value: null

        Type: string[]

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lint.select\": [\"E\", \"F\"]\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lint = {\n        select = {\"E\", \"F\"}\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lint\": {\n            \"select\": [\"E\", \"F\"]\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#extendselect","title":"extendSelect","text":"

        Rules to enable in addition to those in lint.select.

        Default value: null

        Type: string[]

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lint.extendSelect\": [\"W\"]\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lint = {\n        extendSelect = {\"W\"}\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lint\": {\n            \"extendSelect\": [\"W\"]\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#ignore","title":"ignore","text":"

        Rules to disable by default. See the documentation.

        Default value: null

        Type: string[]

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.lint.ignore\": [\"E4\", \"E7\"]\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      lint = {\n        ignore = {\"E4\", \"E7\"}\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"lint\": {\n            \"ignore\": [\"E4\", \"E7\"]\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#format","title":"format","text":"

        Settings specific to the Ruff formatter.

        "},{"location":"editors/settings/#format_preview","title":"preview","text":"

        Whether to enable Ruff's preview mode when formatting.

        Default value: null

        Type: bool

        Example usage:

        VS CodeNeovimZed
        {\n    \"ruff.format.preview\": true\n}\n
        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      format = {\n        preview = true\n      }\n    }\n  }\n}\n
        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          \"format\": {\n            \"preview\": true\n          }\n        }\n      }\n    }\n  }\n}\n
        "},{"location":"editors/settings/#vs-code-specific","title":"VS Code specific","text":"

        Additionally, the Ruff extension provides the following settings specific to VS Code. These settings are not used by the language server and are only relevant to the extension.

        "},{"location":"editors/settings/#enable","title":"enable","text":"

        Whether to enable the Ruff extension. Modifying this setting requires restarting VS Code to take effect.

        Default value: true

        Type: bool

        Example usage:

        {\n    \"ruff.enable\": false\n}\n
        "},{"location":"editors/settings/#formatargs","title":"format.args","text":"

        Deprecated

        This setting is only used by ruff-lsp which is deprecated in favor of the native language server. Refer to the migration guide for more information.

        This setting is not used by the native language server.

        Additional arguments to pass to the Ruff formatter.

        Default value: []

        Type: string[]

        Example usage:

        {\n    \"ruff.format.args\": [\"--line-length\", \"100\"]\n}\n
        "},{"location":"editors/settings/#ignorestandardlibrary","title":"ignoreStandardLibrary","text":"

        Deprecated

        This setting is only used by ruff-lsp which is deprecated in favor of the native language server. Refer to the migration guide for more information.

        This setting is not used by the native language server.

        Whether to ignore files that are inferred to be part of the Python standard library.

        Default value: true

        Type: bool

        Example usage:

        {\n    \"ruff.ignoreStandardLibrary\": false\n}\n
        "},{"location":"editors/settings/#importstrategy","title":"importStrategy","text":"

        Strategy for loading the ruff executable.

        • fromEnvironment finds Ruff in the environment, falling back to the bundled version
        • useBundled uses the version bundled with the extension

        Default value: \"fromEnvironment\"

        Type: \"fromEnvironment\" | \"useBundled\"

        Example usage:

        {\n    \"ruff.importStrategy\": \"useBundled\"\n}\n
        "},{"location":"editors/settings/#interpreter","title":"interpreter","text":"

        A list of paths to Python interpreters. Even though this is a list, only the first interpreter is used.

        This setting depends on the ruff.nativeServer setting:

        • If using the native server, the interpreter is used to find the ruff executable when ruff.importStrategy is set to fromEnvironment.
        • Otherwise, the interpreter is used to run the ruff-lsp server.

        Default value: []

        Type: string[]

        Example usage:

        {\n    \"ruff.interpreter\": [\"/home/user/.local/bin/python\"]\n}\n
        "},{"location":"editors/settings/#lintargs","title":"lint.args","text":"

        Deprecated

        This setting is only used by ruff-lsp which is deprecated in favor of the native language server. Refer to the migration guide for more information.

        This setting is not used by the native language server.

        Additional arguments to pass to the Ruff linter.

        Default value: []

        Type: string[]

        Example usage:

        {\n    \"ruff.lint.args\": [\"--config\", \"/path/to/pyproject.toml\"]\n}\n
        "},{"location":"editors/settings/#lintrun","title":"lint.run","text":"

        Deprecated

        This setting is only used by ruff-lsp which is deprecated in favor of the native language server. Refer to the migration guide for more information.

        This setting is not used by the native language server.

        Run Ruff on every keystroke (onType) or on save (onSave).

        Default value: \"onType\"

        Type: \"onType\" | \"onSave\"

        Example usage:

        {\n    \"ruff.lint.run\": \"onSave\"\n}\n
        "},{"location":"editors/settings/#nativeserver","title":"nativeServer","text":"

        Whether to use the native language server, ruff-lsp or automatically decide between the two based on the Ruff version and extension settings.

        • \"on\": Use the native language server. A warning will be displayed if deprecated settings are detected.
        • \"off\": Use ruff-lsp. A warning will be displayed if settings specific to the native server are detected.
        • \"auto\": Automatically select between the native language server and ruff-lsp based on the following conditions:
          1. If the Ruff version is >= 0.5.3, use the native language server unless any deprecated settings are detected. In that case, show a warning and use ruff-lsp instead.
          2. If the Ruff version is < 0.5.3, use ruff-lsp. A warning will be displayed if settings specific to the native server are detected.
        • true: Same as on
        • false: Same as off

        Default value: \"auto\"

        Type: \"on\" | \"off\" | \"auto\" | true | false

        Example usage:

        {\n    \"ruff.nativeServer\": \"on\"\n}\n
        "},{"location":"editors/settings/#path","title":"path","text":"

        A list of path to ruff executables.

        The first executable in the list which is exists is used. This setting takes precedence over the ruff.importStrategy setting.

        Default value: []

        Type: string[]

        Example usage:

        {\n    \"ruff.path\": [\"/home/user/.local/bin/ruff\"]\n}\n
        "},{"location":"editors/settings/#shownotifications","title":"showNotifications","text":"

        Deprecated

        This setting is only used by ruff-lsp which is deprecated in favor of the native language server. Refer to the migration guide for more information.

        Setting to control when a notification is shown.

        Default value: \"off\"

        Type: \"off\" | \"onError\" | \"onWarning\" | \"always\"

        Example usage:

        {\n    \"ruff.showNotifications\": \"onWarning\"\n}\n
        "},{"location":"editors/settings/#traceserver","title":"trace.server","text":"

        The trace level for the language server. Refer to the LSP specification for more information.

        Default value: \"off\"

        Type: \"off\" | \"messages\" | \"verbose\"

        Example usage:

        {\n    \"ruff.trace.server\": \"messages\"\n}\n
        "},{"location":"editors/setup/","title":"Setup","text":"

        We have specific setup instructions depending on your editor of choice. If you don't see your editor on this list and would like a setup guide, please open an issue.

        If you're transferring your configuration from ruff-lsp, regardless of editor, there are several settings which have changed or are no longer available. See the migration guide for more.

        Note

        The setup instructions provided below are on a best-effort basis. If you encounter any issues while setting up the Ruff in an editor, please open an issue for assistance and help in improving this documentation.

        Tip

        Regardless of the editor, it is recommended to disable the older language server (ruff-lsp) to prevent any conflicts.

        "},{"location":"editors/setup/#vs-code","title":"VS Code","text":"

        Install the Ruff extension from the VS Code Marketplace. It is recommended to have the Ruff extension version 2024.32.0 or later to get the best experience with the Ruff Language Server.

        For more documentation on the Ruff extension, refer to the README of the extension repository.

        "},{"location":"editors/setup/#neovim","title":"Neovim","text":"

        The nvim-lspconfig plugin can be used to configure the Ruff Language Server in Neovim. To set it up, install nvim-lspconfig plugin, set it up as per the configuration documentation, and add the following to your init.lua:

        Neovim 0.10 (with nvim-lspconfig)Neovim 0.11+ (with vim.lsp.config)
        require('lspconfig').ruff.setup({\n  init_options = {\n    settings = {\n      -- Ruff language server settings go here\n    }\n  }\n})\n
        vim.lsp.config('ruff', {\n  init_options = {\n    settings = {\n      -- Ruff language server settings go here\n    }\n  }\n})\n\nvim.lsp.enable('ruff')\n

        Note

        If the installed version of nvim-lspconfig includes the changes from neovim/nvim-lspconfig@70d1c2c, you will need to use Ruff version 0.5.3 or later.

        If you're using Ruff alongside another language server (like Pyright), you may want to defer to that language server for certain capabilities, like textDocument/hover:

        vim.api.nvim_create_autocmd(\"LspAttach\", {\n  group = vim.api.nvim_create_augroup('lsp_attach_disable_ruff_hover', { clear = true }),\n  callback = function(args)\n    local client = vim.lsp.get_client_by_id(args.data.client_id)\n    if client == nil then\n      return\n    end\n    if client.name == 'ruff' then\n      -- Disable hover in favor of Pyright\n      client.server_capabilities.hoverProvider = false\n    end\n  end,\n  desc = 'LSP: Disable hover capability from Ruff',\n})\n

        If you'd like to use Ruff exclusively for linting, formatting, and organizing imports, you can disable those capabilities for Pyright:

        require('lspconfig').pyright.setup {\n  settings = {\n    pyright = {\n      -- Using Ruff's import organizer\n      disableOrganizeImports = true,\n    },\n    python = {\n      analysis = {\n        -- Ignore all files for analysis to exclusively use Ruff for linting\n        ignore = { '*' },\n      },\n    },\n  },\n}\n

        By default, the log level for Ruff is set to info. To change the log level, you can set the logLevel setting:

        require('lspconfig').ruff.setup {\n  init_options = {\n    settings = {\n      logLevel = 'debug',\n    }\n  }\n}\n

        By default, Ruff will write logs to stderr which will be available in Neovim's LSP client log file (:lua vim.print(vim.lsp.get_log_path())). It's also possible to divert these logs to a separate file with the logFile setting.

        To view the trace logs between Neovim and Ruff, set the log level for Neovim's LSP client to debug:

        vim.lsp.set_log_level('debug')\n
        "},{"location":"editors/setup/#vim","title":"Vim","text":"

        The vim-lsp plugin can be used to configure the Ruff Language Server in Vim. To set it up, install vim-lsp plugin and register the server using the following in your .vimrc:

        if executable('ruff')\n    au User lsp_setup call lsp#register_server({\n        \\ 'name': 'ruff',\n        \\ 'cmd': {server_info->['ruff', 'server']},\n        \\ 'allowlist': ['python'],\n        \\ 'workspace_config': {},\n        \\ })\nendif\n

        See the vim-lsp documentation for more details on how to configure the language server.

        If you're using Ruff alongside another LSP (like Pyright), you may want to defer to that LSP for certain capabilities, like textDocument/hover by adding the following to the function s:on_lsp_buffer_enabled():

        function! s:on_lsp_buffer_enabled() abort\n    \" add your keybindings here (see https://github.com/prabirshrestha/vim-lsp?tab=readme-ov-file#registering-servers)\n\n    let l:capabilities = lsp#get_server_capabilities('ruff')\n    if !empty(l:capabilities)\n      let l:capabilities.hoverProvider = v:false\n    endif\nendfunction\n

        Ruff is also available as part of the coc-pyright extension for coc.nvim.

        With the ALE plugin for Vim or Neovim.
        \" Linters\nlet g:ale_linters = { \"python\": [\"ruff\"] }\n\" Fixers\nlet g:ale_fixers = { \"python\": [\"ruff\", \"ruff_format\"] }\n
        For the fixers, `ruff` will run `ruff check --fix` (to fix all auto-fixable problems) whereas `ruff_format` will run `ruff format`. Ruff can also be integrated via efm language server in just a few lines. Following is an example config for efm to use Ruff for linting and formatting Python files:
        tools:\n  python-ruff:\n    lint-command: \"ruff check --stdin-filename ${INPUT} --output-format concise --quiet -\"\n    lint-stdin: true\n    lint-formats:\n      - \"%f:%l:%c: %m\"\n    format-command: \"ruff format --stdin-filename ${INPUT} --quiet -\"\n    format-stdin: true\n
        With the conform.nvim plugin for Neovim.
        require(\"conform\").setup({\n    formatters_by_ft = {\n        python = {\n          -- To fix auto-fixable lint errors.\n          \"ruff_fix\",\n          -- To run the Ruff formatter.\n          \"ruff_format\",\n          -- To organize the imports.\n          \"ruff_organize_imports\",\n        },\n    },\n})\n
        With the nvim-lint plugin for Neovim.
        require(\"lint\").linters_by_ft = {\n  python = { \"ruff\" },\n}\n
        "},{"location":"editors/setup/#helix","title":"Helix","text":"

        Open the language configuration file for Helix and add the language server as follows:

        [language-server.ruff]\ncommand = \"ruff\"\nargs = [\"server\"]\n

        Then, you'll register the language server as the one to use with Python. If you don't already have a language server registered to use with Python, add this to languages.toml:

        [[language]]\nname = \"python\"\nlanguage-servers = [\"ruff\"]\n

        Otherwise, if you already have language-servers defined, you can simply add \"ruff\" to the list. For example, if you already have pylsp as a language server, you can modify the language entry as follows:

        [[language]]\nname = \"python\"\nlanguage-servers = [\"ruff\", \"pylsp\"]\n

        Note

        Support for multiple language servers for a language is only available in Helix version 23.10 and later.

        If you want to, as an example, turn on auto-formatting, add auto-format = true:

        [[language]]\nname = \"python\"\nlanguage-servers = [\"ruff\", \"pylsp\"]\nauto-format = true\n

        See the Helix documentation for more settings you can use here.

        You can pass settings into ruff server using [language-server.ruff.config.settings]. For example:

        [language-server.ruff.config.settings]\nlineLength = 80\n\n[language-server.ruff.config.settings.lint]\nselect = [\"E4\", \"E7\"]\npreview = false\n\n[language-server.ruff.config.settings.format]\npreview = true\n

        By default, the log level for Ruff is set to info. To change the log level, you can set the logLevel setting:

        [language-server.ruff]\ncommand = \"ruff\"\nargs = [\"server\"]\n\n[language-server.ruff.config.settings]\nlogLevel = \"debug\"\n

        You can also divert Ruff's logs to a separate file with the logFile setting.

        To view the trace logs between Helix and Ruff, pass in the -v (verbose) flag when starting Helix:

        hx -v path/to/file.py\n
        "},{"location":"editors/setup/#kate","title":"Kate","text":"
        1. Activate the LSP Client plugin.
        2. Setup LSP Client as desired.
        3. Finally, add this to Settings -> Configure Kate -> LSP Client -> User Server Settings:
        {\n  \"servers\": {\n    \"python\": {\n      \"command\": [\"ruff\", \"server\"],\n      \"url\": \"https://github.com/astral-sh/ruff\",\n      \"highlightingModeRegex\": \"^Python$\",\n      \"settings\": {}\n    }\n  }\n}\n

        See LSP Client documentation for more details on how to configure the server from there.

        Important

        Kate's LSP Client plugin does not support multiple servers for the same language. As a workaround, you can use the python-lsp-server along with the python-lsp-ruff plugin to use Ruff alongside another language server. Note that this setup won't use the server settings because the python-lsp-ruff plugin uses the ruff executable and not the language server.

        "},{"location":"editors/setup/#sublime-text","title":"Sublime Text","text":"

        To use Ruff with Sublime Text, install Sublime Text's LSP and LSP-ruff package.

        "},{"location":"editors/setup/#pycharm","title":"PyCharm","text":""},{"location":"editors/setup/#via-external-tool","title":"Via External Tool","text":"

        Ruff can be installed as an External Tool in PyCharm. Open the Preferences pane, then navigate to \"Tools\", then \"External Tools\". From there, add a new tool with the following configuration:

        Ruff should then appear as a runnable action:

        "},{"location":"editors/setup/#via-third-party-plugin","title":"Via third-party plugin","text":"

        Ruff is also available as the Ruff plugin on the IntelliJ Marketplace (maintained by @koxudaxi).

        "},{"location":"editors/setup/#emacs","title":"Emacs","text":"

        Ruff can be utilized as a language server via Eglot, which is in Emacs's core. To enable Ruff with automatic formatting on save, use the following configuration:

        (add-hook 'python-mode-hook 'eglot-ensure)\n(with-eval-after-load 'eglot\n  (add-to-list 'eglot-server-programs\n               '(python-mode . (\"ruff\" \"server\")))\n  (add-hook 'after-save-hook 'eglot-format))\n

        Ruff is available as flymake-ruff on MELPA:

        (require 'flymake-ruff)\n(add-hook 'python-mode-hook #'flymake-ruff-load)\n

        Ruff is also available as emacs-ruff-format:

        (require 'ruff-format)\n(add-hook 'python-mode-hook 'ruff-format-on-save-mode)\n

        Alternatively, it can be used via the Apheleia formatter library, by setting this configuration:

        ;; Replace default (black) to use ruff for sorting import and formatting.\n(setf (alist-get 'python-mode apheleia-mode-alist)\n      '(ruff-isort ruff))\n(setf (alist-get 'python-ts-mode apheleia-mode-alist)\n      '(ruff-isort ruff))\n
        "},{"location":"editors/setup/#textmate","title":"TextMate","text":"

        Ruff is also available via the textmate2-ruff-linter bundle for TextMate.

        "},{"location":"editors/setup/#zed","title":"Zed","text":"

        Ruff is available as an extension for the Zed editor. To install it:

        1. Open the command palette with Cmd+Shift+P
        2. Search for \"zed: extensions\"
        3. Search for \"ruff\" in the extensions list and click \"Install\"

        To configure Zed to use the Ruff language server for Python files, add the following to your settings.json file:

        {\n  \"languages\": {\n    \"Python\": {\n      \"language_servers\": [\"ruff\"]\n      // Or, if there are other language servers you want to use with Python\n      // \"language_servers\": [\"pyright\", \"ruff\"]\n    }\n  }\n}\n

        To configure the language server, you can provide the server settings under the lsp.ruff.initialization_options.settings key:

        {\n  \"lsp\": {\n    \"ruff\": {\n      \"initialization_options\": {\n        \"settings\": {\n          // Ruff server settings goes here\n          \"lineLength\": 80,\n          \"lint\": {\n            \"extendSelect\": [\"I\"],\n          }\n        }\n      }\n    }\n  }\n}\n

        Note

        Support for multiple formatters for a given language is only available in Zed version 0.146.0 and later.

        You can configure Ruff to format Python code on-save by registering the Ruff formatter and enabling the format_on_save setting:

        Zed 0.146.0+
        {\n  \"languages\": {\n    \"Python\": {\n      \"language_servers\": [\"ruff\"],\n      \"format_on_save\": \"on\",\n      \"formatter\": [\n        {\n          \"language_server\": {\n            \"name\": \"ruff\"\n          }\n        }\n      ]\n    }\n  }\n}\n

        You can configure Ruff to fix lint violations and/or organize imports on-save by enabling the source.fixAll.ruff and source.organizeImports.ruff code actions respectively:

        Zed 0.146.0+
        {\n  \"languages\": {\n    \"Python\": {\n      \"language_servers\": [\"ruff\"],\n      \"format_on_save\": \"on\",\n      \"formatter\": [\n        {\n          \"code_actions\": {\n            // Fix all auto-fixable lint violations\n            \"source.fixAll.ruff\": true,\n            // Organize imports\n            \"source.organizeImports.ruff\": true\n          }\n        }\n      ]\n    }\n  }\n}\n

        Taken together, you can configure Ruff to format, fix, and organize imports on-save via the following settings.json:

        Note

        For this configuration, it is important to use the correct order of the code action and formatter language server settings. The code actions should be defined before the formatter to ensure that the formatter takes care of any remaining style issues after the code actions have been applied.

        Zed 0.146.0+
        {\n  \"languages\": {\n    \"Python\": {\n      \"language_servers\": [\"ruff\"],\n      \"format_on_save\": \"on\",\n      \"formatter\": [\n        {\n          \"code_actions\": {\n            \"source.organizeImports.ruff\": true,\n            \"source.fixAll.ruff\": true\n          }\n        },\n        {\n          \"language_server\": {\n            \"name\": \"ruff\"\n          }\n        }\n      ]\n    }\n  }\n}\n
        "},{"location":"formatter/black/","title":"Known Deviations from Black","text":"

        This document enumerates the known, intentional differences in code style between Black and Ruff's formatter.

        For a list of unintentional deviations, see issue tracker.

        "},{"location":"formatter/black/#trailing-end-of-line-comments","title":"Trailing end-of-line comments","text":"

        Black's priority is to fit an entire statement on a line, even if it contains end-of-line comments. In such cases, Black collapses the statement, and moves the comment to the end of the collapsed statement:

        # Input\nwhile (\n    cond1  # almost always true\n    and cond2  # almost never true\n):\n    print(\"Do something\")\n\n# Black\nwhile cond1 and cond2:  # almost always true  # almost never true\n    print(\"Do something\")\n

        Ruff, like Prettier, expands any statement that contains trailing end-of-line comments. For example, Ruff would avoid collapsing the while test in the snippet above. This ensures that the comments remain close to their original position and retain their original intent, at the cost of retaining additional vertical space.

        This deviation only impacts unformatted code, in that Ruff's output should not deviate for code that has already been formatted by Black.

        "},{"location":"formatter/black/#pragma-comments-are-ignored-when-computing-line-width","title":"Pragma comments are ignored when computing line width","text":"

        Pragma comments (# type, # noqa, # pyright, # pylint, etc.) are ignored when computing the width of a line. This prevents Ruff from moving pragma comments around, thereby modifying their meaning and behavior:

        See Ruff's pragma comment handling proposal for details.

        This is similar to Pyink but a deviation from Black. Black avoids splitting any lines that contain a # type comment (#997), but otherwise avoids special-casing pragma comments.

        As Ruff expands trailing end-of-line comments, Ruff will also avoid moving pragma comments in cases like the following, where moving the # noqa to the end of the line causes it to suppress errors on both first() and second():

        # Input\n[\n    first(),  # noqa\n    second()\n]\n\n# Black\n[first(), second()]  # noqa\n\n# Ruff\n[\n    first(),  # noqa\n    second(),\n]\n
        "},{"location":"formatter/black/#line-width-vs-line-length","title":"Line width vs. line length","text":"

        Ruff uses the Unicode width of a line to determine if a line fits. Black uses Unicode width for strings, and character width for all other tokens. Ruff also uses Unicode width for identifiers and comments.

        "},{"location":"formatter/black/#parenthesizing-long-nested-expressions","title":"Parenthesizing long nested-expressions","text":"

        Black 24 and newer parenthesizes long conditional expressions and type annotations in function parameters:

        # Black\n[\n    \"____________________________\",\n    \"foo\",\n    \"bar\",\n    (\n        \"baz\"\n        if some_really_looooooooong_variable\n        else \"some other looooooooooooooong value\"\n    ),\n]\n\n\ndef foo(\n    i: int,\n    x: (\n        Loooooooooooooooooooooooong\n        | Looooooooooooooooong\n        | Looooooooooooooooooooong\n        | Looooooong\n    ),\n    *,\n    s: str,\n) -> None:\n    pass\n\n# Ruff\n[\n    \"____________________________\",\n    \"foo\",\n    \"bar\",\n    \"baz\"\n    if some_really_looooooooong_variable\n    else \"some other looooooooooooooong value\",\n]\n\n\ndef foo(\n    i: int,\n    x: Loooooooooooooooooooooooong\n    | Looooooooooooooooong\n    | Looooooooooooooooooooong\n    | Looooooong,\n    *,\n    s: str,\n) -> None:\n    pass\n

        We agree that Ruff's formatting (that matches Black's 23) is hard to read and needs improvement. But we aren't convinced that parenthesizing long nested expressions is the best solution, especially when considering expression formatting holistically. That's why we want to defer the decision until we've explored alternative nested expression formatting styles. See psf/Black#4123 for an in-depth explanation of our concerns and an outline of possible alternatives.

        "},{"location":"formatter/black/#call-expressions-with-a-single-multiline-string-argument","title":"Call expressions with a single multiline string argument","text":"

        Unlike Black, Ruff preserves the indentation of a single multiline-string argument in a call expression:

        # Input\ncall(\n  \"\"\"\"\n  A multiline\n  string\n  \"\"\"\n)\n\ndedent(\"\"\"\"\n    A multiline\n    string\n\"\"\")\n\n# Black\ncall(\n  \"\"\"\"\n  A multiline\n  string\n  \"\"\"\n)\n\ndedent(\n  \"\"\"\"\n  A multiline\n  string\n\"\"\"\n)\n\n\n# Ruff\ncall(\n  \"\"\"\"\n  A multiline\n  string\n  \"\"\"\n)\n\ndedent(\"\"\"\"\n    A multiline\n    string\n\"\"\")\n

        Black intended to ship a similar style change as part of the 2024 style that always removes the indent. It turned out that this change was too disruptive to justify the cases where it improved formatting. Ruff introduced the new heuristic of preserving the indent. We believe it's a good compromise that improves formatting but minimizes disruption for users.

        "},{"location":"formatter/black/#blank-lines-at-the-start-of-a-block","title":"Blank lines at the start of a block","text":"

        Black 24 and newer allows blank lines at the start of a block, where Ruff always removes them:

        # Black\nif x:\n\n  a = 123\n\n# Ruff\nif x:\n  a = 123\n

        Currently, we are concerned that allowing blank lines at the start of a block leads to unintentional blank lines when refactoring or moving code. However, we will consider adopting Black's formatting at a later point with an improved heuristic. The style change is tracked in #9745.

        "},{"location":"formatter/black/#f-strings","title":"F-strings","text":"

        Ruff formats expression parts in f-strings whereas Black does not:

        # Input\nf'test{inner   + \"nested_string\"} including math {5 ** 3 + 10}'\n\n# Black\nf'test{inner   + \"nested_string\"} including math {5 ** 3 + 10}'\n\n# Ruff\nf\"test{inner + 'nested_string'} including math {5**3 + 10}\"\n

        For more details on the formatting style, refer to the f-string formatting section.

        "},{"location":"formatter/black/#implicit-concatenated-strings","title":"Implicit concatenated strings","text":"

        Ruff merges implicitly concatenated strings if the entire string fits on a single line:

        # Input\ndef test(max_history):\n    raise argparse.ArgumentTypeError(\n        f\"The value of `--max-history {max_history}` \" f\"is not a positive integer.\"\n    )\n\n# Black\ndef test(max_history):\n    raise argparse.ArgumentTypeError(\n        f\"The value of `--max-history {max_history}` \" f\"is not a positive integer.\"\n    )\n\n# Ruff\ndef test(max_history):\n    raise argparse.ArgumentTypeError(\n        f\"The value of `--max-history {max_history}` is not a positive integer.\"\n    )\n

        Black's unstable style applies the same formatting.

        There are few rare cases where Ruff can't merge the implicitly concatenated strings automatically. In those cases, Ruff preserves if the implicit concatenated strings are formatted over multiple lines:

        # Input\na = (\n    r\"aaaaaaa\"\n    \"bbbbbbbbbbbb\"\n)\n\n# Black\na = r\"aaaaaaa\" \"bbbbbbbbbbbb\"\n\n# Ruff\na = (\n    r\"aaaaaaa\"\n    \"bbbbbbbbbbbb\"\n)\n

        This ensures compatibility with ISC001 (#8272).

        "},{"location":"formatter/black/#assert-statements","title":"assert statements","text":"

        Unlike Black, Ruff prefers breaking the message over breaking the assertion, similar to how both Ruff and Black prefer breaking the assignment value over breaking the assignment target:

        # Input\nassert (\n    len(policy_types) >= priority + num_duplicates\n), f\"This tests needs at least {priority+num_duplicates} many types.\"\n\n\n# Black\nassert (\n    len(policy_types) >= priority + num_duplicates\n), f\"This tests needs at least {priority+num_duplicates} many types.\"\n\n# Ruff\nassert len(policy_types) >= priority + num_duplicates, (\n    f\"This tests needs at least {priority + num_duplicates} many types.\"\n)\n
        "},{"location":"formatter/black/#global-and-nonlocal-names-are-broken-across-multiple-lines-by-continuations","title":"global and nonlocal names are broken across multiple lines by continuations","text":"

        If a global or nonlocal statement includes multiple names, and exceeds the configured line width, Ruff will break them across multiple lines using continuations:

        # Input\nglobal analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model\n\n# Ruff\nglobal \\\n    analyze_featuremap_layer, \\\n    analyze_featuremapcompression_layer, \\\n    analyze_latencies_post, \\\n    analyze_motions_layer, \\\n    analyze_size_model\n
        "},{"location":"formatter/black/#trailing-own-line-comments-on-imports-are-not-moved-to-the-next-line","title":"Trailing own-line comments on imports are not moved to the next line","text":"

        Black enforces a single empty line between an import and a trailing own-line comment. Ruff leaves such comments in-place:

        # Input\nimport os\n# comment\n\nimport sys\n\n# Black\nimport os\n\n# comment\n\nimport sys\n\n# Ruff\nimport os\n# comment\n\nimport sys\n
        "},{"location":"formatter/black/#parentheses-around-awaited-collections-are-not-preserved","title":"Parentheses around awaited collections are not preserved","text":"

        Black preserves parentheses around awaited collections:

        await ([1, 2, 3])\n

        Ruff will instead remove them:

        await [1, 2, 3]\n

        This is more consistent to the formatting of other awaited expressions: Ruff and Black both remove parentheses around, e.g., await (1), only retaining them when syntactically required, as in, e.g., await (x := 1).

        "},{"location":"formatter/black/#implicit-string-concatenations-in-attribute-accesses","title":"Implicit string concatenations in attribute accesses","text":"

        Given the following unformatted code:

        print(\"aaaaaaaaaaaaaaaa\" \"aaaaaaaaaaaaaaaa\".format(bbbbbbbbbbbbbbbbbb + bbbbbbbbbbbbbbbbbb))\n

        Internally, Black's logic will first expand the outermost print call:

        print(\n    \"aaaaaaaaaaaaaaaa\" \"aaaaaaaaaaaaaaaa\".format(bbbbbbbbbbbbbbbbbb + bbbbbbbbbbbbbbbbbb)\n)\n

        Since the argument is still too long, Black will then split on the operator with the highest split precedence. In this case, Black splits on the implicit string concatenation, to produce the following Black-formatted code:

        print(\n    \"aaaaaaaaaaaaaaaa\"\n    \"aaaaaaaaaaaaaaaa\".format(bbbbbbbbbbbbbbbbbb + bbbbbbbbbbbbbbbbbb)\n)\n

        Ruff gives implicit concatenations a \"lower\" priority when breaking lines. As a result, Ruff would instead format the above as:

        print(\n    \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\".format(bbbbbbbbbbbbbbbbbb + bbbbbbbbbbbbbbbbbb)\n)\n

        In general, Black splits implicit string concatenations over multiple lines more often than Ruff, even if those concatenations can fit on a single line. Ruff instead avoids splitting such concatenations unless doing so is necessary to fit within the configured line width.

        "},{"location":"formatter/black/#own-line-comments-on-expressions-dont-cause-the-expression-to-expand","title":"Own-line comments on expressions don't cause the expression to expand","text":"

        Given an expression like:

        (\n    # A comment in the middle\n    some_example_var and some_example_var not in some_example_var\n)\n

        Black associates the comment with some_example_var, thus splitting it over two lines:

        (\n    # A comment in the middle\n    some_example_var\n    and some_example_var not in some_example_var\n)\n

        Ruff will instead associate the comment with the entire boolean expression, thus preserving the initial formatting:

        (\n    # A comment in the middle\n    some_example_var and some_example_var not in some_example_var\n)\n
        "},{"location":"formatter/black/#tuples-are-parenthesized-when-expanded","title":"Tuples are parenthesized when expanded","text":"

        Ruff tends towards parenthesizing tuples (with a few exceptions), while Black tends to remove tuple parentheses more often.

        In particular, Ruff will always insert parentheses around tuples that expand over multiple lines:

        # Input\n(a, b), (c, d,)\n\n# Black\n(a, b), (\n    c,\n    d,\n)\n\n# Ruff\n(\n    (a, b),\n    (\n        c,\n        d,\n    ),\n)\n

        There's one exception here. In for loops, both Ruff and Black will avoid inserting unnecessary parentheses:

        # Input\nfor a, [b, d,] in c:\n    pass\n\n# Black\nfor a, [\n    b,\n    d,\n] in c:\n    pass\n\n# Ruff\nfor a, [\n    b,\n    d,\n] in c:\n    pass\n
        "},{"location":"formatter/black/#single-element-tuples-are-always-parenthesized","title":"Single-element tuples are always parenthesized","text":"

        Ruff always inserts parentheses around single-element tuples, while Black will omit them in some cases:

        # Input\n(a, b),\n\n# Black\n(a, b),\n\n# Ruff\n((a, b),)\n

        Adding parentheses around single-element tuples adds visual distinction and helps avoid \"accidental\" tuples created by extraneous trailing commas (see, e.g., #17181).

        "},{"location":"formatter/black/#parentheses-around-call-chain-assignment-values-are-not-preserved","title":"Parentheses around call-chain assignment values are not preserved","text":"

        Given:

        def update_emission_strength():\n    (\n        get_rgbw_emission_node_tree(self)\n        .nodes[\"Emission\"]\n        .inputs[\"Strength\"]\n        .default_value\n    ) = (self.emission_strength * 2)\n

        Black will preserve the parentheses in (self.emission_strength * 2), whereas Ruff will remove them.

        Both Black and Ruff remove such parentheses in simpler assignments, like:

        # Input\ndef update_emission_strength():\n    value = (self.emission_strength * 2)\n\n# Black\ndef update_emission_strength():\n    value = self.emission_strength * 2\n\n# Ruff\ndef update_emission_strength():\n    value = self.emission_strength * 2\n
        "},{"location":"formatter/black/#call-chain-calls-break-differently-in-some-cases","title":"Call chain calls break differently in some cases","text":"

        Black occasionally breaks call chains differently than Ruff; in particular, Black occasionally expands the arguments for the last call in the chain, as in:

        # Input\ndf.drop(\n    columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]\n).drop_duplicates().rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(path / \"aaaaaa.csv\", index=False)\n\n# Black\ndf.drop(\n    columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]\n).drop_duplicates().rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(\n    path / \"aaaaaa.csv\", index=False\n)\n\n# Ruff\ndf.drop(\n    columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]\n).drop_duplicates().rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(path / \"aaaaaa.csv\", index=False)\n

        Ruff will only expand the arguments if doing so is necessary to fit within the configured line width.

        Note that Black does not apply this last-call argument breaking universally. For example, both Black and Ruff will format the following identically:

        # Input\ndf.drop(\n    columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]\n).drop_duplicates(a).rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(\n    path / \"aaaaaa.csv\", index=False\n).other(a)\n\n# Black\ndf.drop(columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]).drop_duplicates(a).rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(path / \"aaaaaa.csv\", index=False).other(a)\n\n# Ruff\ndf.drop(columns=[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"]).drop_duplicates(a).rename(\n    columns={\n        \"a\": \"a\",\n    }\n).to_csv(path / \"aaaaaa.csv\", index=False).other(a)\n

        Similarly, in some cases, Ruff will collapse composite binary expressions more aggressively than Black, if doing so allows the expression to fit within the configured line width:

        # Black\nassert AAAAAAAAAAAAAAAAAAAAAA.bbbbbb.fooo(\n    aaaaaaaaaaaa=aaaaaaaaaaaa\n).ccccc() == (len(aaaaaaaaaa) + 1) * fooooooooooo * (\n    foooooo + 1\n) * foooooo * len(\n    list(foo(bar(4, foo), foo))\n)\n\n# Ruff\nassert AAAAAAAAAAAAAAAAAAAAAA.bbbbbb.fooo(\n    aaaaaaaaaaaa=aaaaaaaaaaaa\n).ccccc() == (len(aaaaaaaaaa) + 1) * fooooooooooo * (\n    foooooo + 1\n) * foooooo * len(list(foo(bar(4, foo), foo)))\n
        "},{"location":"formatter/black/#single-with-item-targeting-python-38-or-older","title":"Single with item targeting Python 3.8 or older","text":"

        Unlike Black, Ruff uses the same layout for with statements with a single context manager as it does for while, if and other compound statements:

        # Input\ndef run(data_path, model_uri):\n    with pyspark.sql.SparkSession.builder.config(\n        key=\"spark.python.worker.reuse\", value=True\n    ).config(key=\"spark.ui.enabled\", value=False).master(\n        \"local-cluster[2, 1, 1024]\"\n    ).getOrCreate():\n        # ignore spark log output\n        spark.sparkContext.setLogLevel(\"OFF\")\n        print(score_model(spark, data_path, model_uri))\n\n# Black\ndef run(data_path, model_uri):\n    with pyspark.sql.SparkSession.builder.config(\n        key=\"spark.python.worker.reuse\", value=True\n    ).config(key=\"spark.ui.enabled\", value=False).master(\n        \"local-cluster[2, 1, 1024]\"\n    ).getOrCreate():\n        # ignore spark log output\n        spark.sparkContext.setLogLevel(\"OFF\")\n        print(score_model(spark, data_path, model_uri))\n\n# Ruff\ndef run(data_path, model_uri):\n    with (\n        pyspark.sql.SparkSession.builder.config(\n            key=\"spark.python.worker.reuse\", value=True\n        )\n        .config(key=\"spark.ui.enabled\", value=False)\n        .master(\"local-cluster[2, 1, 1024]\")\n        .getOrCreate()\n    ):\n        # ignore spark log output\n        spark.sparkContext.setLogLevel(\"OFF\")\n        print(score_model(spark, data_path, model_uri))\n

        Ruff's formatting matches the formatting of other compound statements:

        def test():\n    if (\n        pyspark.sql.SparkSession.builder.config(\n            key=\"spark.python.worker.reuse\", value=True\n        )\n        .config(key=\"spark.ui.enabled\", value=False)\n        .master(\"local-cluster[2, 1, 1024]\")\n        .getOrCreate()\n    ):\n        # ignore spark log output\n        spark.sparkContext.setLogLevel(\"OFF\")\n        print(score_model(spark, data_path, model_uri))\n
        "},{"location":"formatter/black/#the-last-context-manager-in-a-with-statement-may-be-collapsed-onto-a-single-line","title":"The last context manager in a with statement may be collapsed onto a single line","text":"

        When using a with statement with multiple unparenthesized context managers, Ruff may collapse the last context manager onto a single line, if doing so allows the with statement to fit within the configured line width.

        Black, meanwhile, tends to break the last context manager slightly differently, as in the following example:

        # Black\nwith tempfile.TemporaryDirectory() as d1:\n    symlink_path = Path(d1).joinpath(\"testsymlink\")\n    with tempfile.TemporaryDirectory(dir=d1) as d2, tempfile.TemporaryDirectory(\n        dir=d1\n    ) as d4, tempfile.TemporaryDirectory(dir=d2) as d3, tempfile.NamedTemporaryFile(\n        dir=d4\n    ) as source_file, tempfile.NamedTemporaryFile(\n        dir=d3\n    ) as lock_file:\n        pass\n\n# Ruff\nwith tempfile.TemporaryDirectory() as d1:\n    symlink_path = Path(d1).joinpath(\"testsymlink\")\n    with tempfile.TemporaryDirectory(dir=d1) as d2, tempfile.TemporaryDirectory(\n        dir=d1\n    ) as d4, tempfile.TemporaryDirectory(dir=d2) as d3, tempfile.NamedTemporaryFile(\n        dir=d4\n    ) as source_file, tempfile.NamedTemporaryFile(dir=d3) as lock_file:\n        pass\n

        When targeting Python 3.9 or newer, parentheses will be inserted around the context managers to allow for clearer breaks across multiple lines, as in:

        with tempfile.TemporaryDirectory() as d1:\n    symlink_path = Path(d1).joinpath(\"testsymlink\")\n    with (\n        tempfile.TemporaryDirectory(dir=d1) as d2,\n        tempfile.TemporaryDirectory(dir=d1) as d4,\n        tempfile.TemporaryDirectory(dir=d2) as d3,\n        tempfile.NamedTemporaryFile(dir=d4) as source_file,\n        tempfile.NamedTemporaryFile(dir=d3) as lock_file,\n    ):\n        pass\n
        "},{"location":"formatter/black/#preserving-parentheses-around-single-element-lists","title":"Preserving parentheses around single-element lists","text":"

        Ruff preserves at least one parentheses around list elements, even if the list only contains a single element. The Black 2025 or newer, on the other hand, removes the parentheses for single-element lists if they aren't multiline and doing so does not change semantics:

        # Input\nitems = [(True)]\nitems = [(((((True)))))]\nitems = {(123)}\n\n# Black\nitems = [True]\nitems = [True]\nitems = {123}\n\n# Ruff\nitems = [(True)]\nitems = [(True)]\nitems = {(123)}\n
        "},{"location":"rules/abstract-base-class-without-abstract-method/","title":"abstract-base-class-without-abstract-method (B024)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B024"]},{"location":"rules/abstract-base-class-without-abstract-method/#what-it-does","title":"What it does","text":"

        Checks for abstract classes without abstract methods or properties. Annotated but unassigned class variables are regarded as abstract.

        ","tags":["B024"]},{"location":"rules/abstract-base-class-without-abstract-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Abstract base classes are used to define interfaces. If an abstract base class has no abstract methods or properties, you may have forgotten to add an abstract method or property to the class, or omitted an @abstractmethod decorator.

        If the class is not meant to be used as an interface, consider removing the ABC base class from the class definition.

        ","tags":["B024"]},{"location":"rules/abstract-base-class-without-abstract-method/#example","title":"Example","text":"
        from abc import ABC\nfrom typing import ClassVar\n\n\nclass Foo(ABC):\n    class_var: ClassVar[str] = \"assigned\"\n\n    def method(self):\n        bar()\n

        Use instead:

        from abc import ABC, abstractmethod\nfrom typing import ClassVar\n\n\nclass Foo(ABC):\n    class_var: ClassVar[str]  # unassigned\n\n    @abstractmethod\n    def method(self):\n        bar()\n
        ","tags":["B024"]},{"location":"rules/abstract-base-class-without-abstract-method/#references","title":"References","text":"
        • Python documentation: abc
        • Python documentation: typing.ClassVar
        ","tags":["B024"]},{"location":"rules/airflow-dag-no-schedule-argument/","title":"airflow-dag-no-schedule-argument (AIR002)","text":"

        Derived from the Airflow linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["AIR002"]},{"location":"rules/airflow-dag-no-schedule-argument/#what-it-does","title":"What it does","text":"

        Checks for a DAG() class or @dag() decorator without an explicit schedule (or schedule_interval for Airflow 1) parameter.

        ","tags":["AIR002"]},{"location":"rules/airflow-dag-no-schedule-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        The default value of the schedule parameter on Airflow 2 and schedule_interval on Airflow 1 is timedelta(days=1), which is almost never what a user is looking for. Airflow 3 changed the default value to None, and would break existing dags using the implicit default.

        If your dag does not have an explicit schedule / schedule_interval argument, Airflow 2 schedules a run for it every day (at the time determined by start_date). Such a dag will no longer be scheduled on Airflow 3 at all, without any exceptions or other messages visible to the user.

        ","tags":["AIR002"]},{"location":"rules/airflow-dag-no-schedule-argument/#example","title":"Example","text":"
        from airflow import DAG\n\n\n# Using the implicit default schedule.\ndag = DAG(dag_id=\"my_dag\")\n

        Use instead:

        from datetime import timedelta\n\nfrom airflow import DAG\n\n\ndag = DAG(dag_id=\"my_dag\", schedule=timedelta(days=1))\n
        ","tags":["AIR002"]},{"location":"rules/airflow-variable-name-task-id-mismatch/","title":"airflow-variable-name-task-id-mismatch (AIR001)","text":"

        Derived from the Airflow linter.

        ","tags":["AIR001"]},{"location":"rules/airflow-variable-name-task-id-mismatch/#what-it-does","title":"What it does","text":"

        Checks that the task variable name matches the task_id value for Airflow Operators.

        ","tags":["AIR001"]},{"location":"rules/airflow-variable-name-task-id-mismatch/#why-is-this-bad","title":"Why is this bad?","text":"

        When initializing an Airflow Operator, for consistency, the variable name should match the task_id value. This makes it easier to follow the flow of the DAG.

        ","tags":["AIR001"]},{"location":"rules/airflow-variable-name-task-id-mismatch/#example","title":"Example","text":"
        from airflow.operators import PythonOperator\n\n\nincorrect_name = PythonOperator(task_id=\"my_task\")\n

        Use instead:

        from airflow.operators import PythonOperator\n\n\nmy_task = PythonOperator(task_id=\"my_task\")\n
        ","tags":["AIR001"]},{"location":"rules/airflow3-moved-to-provider/","title":"airflow3-moved-to-provider (AIR302)","text":"

        Derived from the Airflow linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["AIR302"]},{"location":"rules/airflow3-moved-to-provider/#what-it-does","title":"What it does","text":"

        Checks for uses of Airflow functions and values that have been moved to it providers. (e.g., apache-airflow-providers-fab)

        ","tags":["AIR302"]},{"location":"rules/airflow3-moved-to-provider/#why-is-this-bad","title":"Why is this bad?","text":"

        Airflow 3.0 moved various deprecated functions, members, and other values to its providers. The user needs to install the corresponding provider and replace the original usage with the one in the provider

        ","tags":["AIR302"]},{"location":"rules/airflow3-moved-to-provider/#example","title":"Example","text":"
        from airflow.auth.managers.fab.fab_auth_manage import FabAuthManager\n

        Use instead:

        from airflow.providers.fab.auth_manager.fab_auth_manage import FabAuthManager\n
        ","tags":["AIR302"]},{"location":"rules/airflow3-removal/","title":"airflow3-removal (AIR301)","text":"

        Derived from the Airflow linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["AIR301"]},{"location":"rules/airflow3-removal/#what-it-does","title":"What it does","text":"

        Checks for uses of deprecated Airflow functions and values.

        ","tags":["AIR301"]},{"location":"rules/airflow3-removal/#why-is-this-bad","title":"Why is this bad?","text":"

        Airflow 3.0 removed various deprecated functions, members, and other values. Some have more modern replacements. Others are considered too niche and not worth to be maintained in Airflow.

        ","tags":["AIR301"]},{"location":"rules/airflow3-removal/#example","title":"Example","text":"
        from airflow.utils.dates import days_ago\n\n\nyesterday = days_ago(today, 1)\n

        Use instead:

        from datetime import timedelta\n\n\nyesterday = today - timedelta(days=1)\n
        ","tags":["AIR301"]},{"location":"rules/airflow3-suggested-to-move-to-provider/","title":"airflow3-suggested-to-move-to-provider (AIR312)","text":"

        Derived from the Airflow linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["AIR312"]},{"location":"rules/airflow3-suggested-to-move-to-provider/#what-it-does","title":"What it does","text":"

        Checks for uses of Airflow functions and values that have been moved to its providers but still have a compatibility layer (e.g., apache-airflow-providers-standard).

        ","tags":["AIR312"]},{"location":"rules/airflow3-suggested-to-move-to-provider/#why-is-this-bad","title":"Why is this bad?","text":"

        Airflow 3.0 moved various deprecated functions, members, and other values to its providers. Even though these symbols still work fine on Airflow 3.0, they are expected to be removed in a future version. The user is suggested to install the corresponding provider and replace the original usage with the one in the provider.

        ","tags":["AIR312"]},{"location":"rules/airflow3-suggested-to-move-to-provider/#example","title":"Example","text":"
        from airflow.operators.python import PythonOperator\n

        Use instead:

        from airflow.providers.standard.operators.python import PythonOperator\n
        ","tags":["AIR312"]},{"location":"rules/airflow3-suggested-update/","title":"airflow3-suggested-update (AIR311)","text":"

        Derived from the Airflow linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["AIR311"]},{"location":"rules/airflow3-suggested-update/#what-it-does","title":"What it does","text":"

        Checks for uses of deprecated Airflow functions and values that still have a compatibility layer.

        ","tags":["AIR311"]},{"location":"rules/airflow3-suggested-update/#why-is-this-bad","title":"Why is this bad?","text":"

        Airflow 3.0 removed various deprecated functions, members, and other values. Some have more modern replacements. Others are considered too niche and not worth to be maintained in Airflow. Even though these symbols still work fine on Airflow 3.0, they are expected to be removed in a future version. The user is suggested to replace the original usage with the new ones.

        ","tags":["AIR311"]},{"location":"rules/airflow3-suggested-update/#example","title":"Example","text":"
        from airflow import Dataset\n\n\nDataset(uri=\"test://test/\")\n

        Use instead:

        from airflow.sdk import Asset\n\n\nAsset(uri=\"test://test/\")\n
        ","tags":["AIR311"]},{"location":"rules/ambiguous-class-name/","title":"ambiguous-class-name (E742)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E742"]},{"location":"rules/ambiguous-class-name/#what-it-does","title":"What it does","text":"

        Checks for the use of the characters 'l', 'O', or 'I' as class names.

        ","tags":["E742"]},{"location":"rules/ambiguous-class-name/#why-is-this-bad","title":"Why is this bad?","text":"

        In some fonts, these characters are indistinguishable from the numerals one and zero. When tempted to use 'l', use 'L' instead.

        ","tags":["E742"]},{"location":"rules/ambiguous-class-name/#example","title":"Example","text":"
        class I(object): ...\n

        Use instead:

        class Integer(object): ...\n
        ","tags":["E742"]},{"location":"rules/ambiguous-function-name/","title":"ambiguous-function-name (E743)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E743"]},{"location":"rules/ambiguous-function-name/#what-it-does","title":"What it does","text":"

        Checks for the use of the characters 'l', 'O', or 'I' as function names.

        ","tags":["E743"]},{"location":"rules/ambiguous-function-name/#why-is-this-bad","title":"Why is this bad?","text":"

        In some fonts, these characters are indistinguishable from the numerals one and zero. When tempted to use 'l', use 'L' instead.

        ","tags":["E743"]},{"location":"rules/ambiguous-function-name/#example","title":"Example","text":"
        def l(x): ...\n

        Use instead:

        def long_name(x): ...\n
        ","tags":["E743"]},{"location":"rules/ambiguous-unicode-character-comment/","title":"ambiguous-unicode-character-comment (RUF003)","text":"","tags":["RUF003"]},{"location":"rules/ambiguous-unicode-character-comment/#what-it-does","title":"What it does","text":"

        Checks for ambiguous Unicode characters in comments.

        ","tags":["RUF003"]},{"location":"rules/ambiguous-unicode-character-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Some Unicode characters are visually similar to ASCII characters, but have different code points. For example, GREEK CAPITAL LETTER ALPHA (U+0391) is visually similar, but not identical, to the ASCII character A.

        The use of ambiguous Unicode characters can confuse readers, cause subtle bugs, and even make malicious code look harmless.

        In preview, this rule will also flag Unicode characters that are confusable with other, non-preferred Unicode characters. For example, the spec recommends GREEK CAPITAL LETTER OMEGA over OHM SIGN.

        You can omit characters from being flagged as ambiguous via the lint.allowed-confusables setting.

        ","tags":["RUF003"]},{"location":"rules/ambiguous-unicode-character-comment/#example","title":"Example","text":"
        foo()  # n\u043eqa  # \"\u043e\" is Cyrillic (`U+043E`)\n

        Use instead:

        foo()  # noqa  # \"o\" is Latin (`U+006F`)\n
        ","tags":["RUF003"]},{"location":"rules/ambiguous-unicode-character-comment/#options","title":"Options","text":"
        • lint.allowed-confusables
        ","tags":["RUF003"]},{"location":"rules/ambiguous-unicode-character-docstring/","title":"ambiguous-unicode-character-docstring (RUF002)","text":"","tags":["RUF002"]},{"location":"rules/ambiguous-unicode-character-docstring/#what-it-does","title":"What it does","text":"

        Checks for ambiguous Unicode characters in docstrings.

        ","tags":["RUF002"]},{"location":"rules/ambiguous-unicode-character-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        Some Unicode characters are visually similar to ASCII characters, but have different code points. For example, GREEK CAPITAL LETTER ALPHA (U+0391) is visually similar, but not identical, to the ASCII character A.

        The use of ambiguous Unicode characters can confuse readers, cause subtle bugs, and even make malicious code look harmless.

        In preview, this rule will also flag Unicode characters that are confusable with other, non-preferred Unicode characters. For example, the spec recommends GREEK CAPITAL LETTER OMEGA over OHM SIGN.

        You can omit characters from being flagged as ambiguous via the lint.allowed-confusables setting.

        ","tags":["RUF002"]},{"location":"rules/ambiguous-unicode-character-docstring/#example","title":"Example","text":"
        \"\"\"A lovely docstring (with a `U+FF09` parenthesis\uff09.\"\"\"\n

        Use instead:

        \"\"\"A lovely docstring (with no strange parentheses).\"\"\"\n
        ","tags":["RUF002"]},{"location":"rules/ambiguous-unicode-character-docstring/#options","title":"Options","text":"
        • lint.allowed-confusables
        ","tags":["RUF002"]},{"location":"rules/ambiguous-unicode-character-string/","title":"ambiguous-unicode-character-string (RUF001)","text":"","tags":["RUF001"]},{"location":"rules/ambiguous-unicode-character-string/#what-it-does","title":"What it does","text":"

        Checks for ambiguous Unicode characters in strings.

        ","tags":["RUF001"]},{"location":"rules/ambiguous-unicode-character-string/#why-is-this-bad","title":"Why is this bad?","text":"

        Some Unicode characters are visually similar to ASCII characters, but have different code points. For example, GREEK CAPITAL LETTER ALPHA (U+0391) is visually similar, but not identical, to the ASCII character A.

        The use of ambiguous Unicode characters can confuse readers, cause subtle bugs, and even make malicious code look harmless.

        In preview, this rule will also flag Unicode characters that are confusable with other, non-preferred Unicode characters. For example, the spec recommends GREEK CAPITAL LETTER OMEGA over OHM SIGN.

        You can omit characters from being flagged as ambiguous via the lint.allowed-confusables setting.

        ","tags":["RUF001"]},{"location":"rules/ambiguous-unicode-character-string/#example","title":"Example","text":"
        print(\"\u0397ello, world!\")  # \"\u0397\" is the Greek eta (`U+0397`).\n

        Use instead:

        print(\"Hello, world!\")  # \"H\" is the Latin capital H (`U+0048`).\n
        ","tags":["RUF001"]},{"location":"rules/ambiguous-unicode-character-string/#options","title":"Options","text":"
        • lint.allowed-confusables
        ","tags":["RUF001"]},{"location":"rules/ambiguous-variable-name/","title":"ambiguous-variable-name (E741)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E741"]},{"location":"rules/ambiguous-variable-name/#what-it-does","title":"What it does","text":"

        Checks for the use of the characters 'l', 'O', or 'I' as variable names.

        Note: This rule is automatically disabled for all stub files (files with .pyi extensions). The rule has little relevance for authors of stubs: a well-written stub should aim to faithfully represent the interface of the equivalent .py file as it exists at runtime, including any ambiguously named variables in the runtime module.

        ","tags":["E741"]},{"location":"rules/ambiguous-variable-name/#why-is-this-bad","title":"Why is this bad?","text":"

        In some fonts, these characters are indistinguishable from the numerals one and zero. When tempted to use 'l', use 'L' instead.

        ","tags":["E741"]},{"location":"rules/ambiguous-variable-name/#example","title":"Example","text":"
        l = 0\nO = 123\nI = 42\n

        Use instead:

        L = 0\no = 123\ni = 42\n
        ","tags":["E741"]},{"location":"rules/and-or-ternary/","title":"and-or-ternary (PLR1706)","text":"

        Derived from the Pylint linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["PLR1706"]},{"location":"rules/and-or-ternary/#removal","title":"Removal","text":"

        This rule was removed from Ruff because it was common for it to introduce behavioral changes. See #9007 for more information.

        ","tags":["PLR1706"]},{"location":"rules/and-or-ternary/#what-it-does","title":"What it does","text":"

        Checks for uses of the known pre-Python 2.5 ternary syntax.

        ","tags":["PLR1706"]},{"location":"rules/and-or-ternary/#why-is-this-bad","title":"Why is this bad?","text":"

        Prior to the introduction of the if-expression (ternary) operator in Python 2.5, the only way to express a conditional expression was to use the and and or operators.

        The if-expression construct is clearer and more explicit, and should be preferred over the use of and and or for ternary expressions.

        ","tags":["PLR1706"]},{"location":"rules/and-or-ternary/#example","title":"Example","text":"
        x, y = 1, 2\nmaximum = x >= y and x or y\n

        Use instead:

        x, y = 1, 2\nmaximum = x if x >= y else y\n
        ","tags":["PLR1706"]},{"location":"rules/any-eq-ne-annotation/","title":"any-eq-ne-annotation (PYI032)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI032"]},{"location":"rules/any-eq-ne-annotation/#what-it-does","title":"What it does","text":"

        Checks for __eq__ and __ne__ implementations that use typing.Any as the type annotation for their second parameter.

        ","tags":["PYI032"]},{"location":"rules/any-eq-ne-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        The Python documentation recommends the use of object to \"indicate that a value could be any type in a typesafe manner\". Any, on the other hand, should be seen as an \"escape hatch when you need to mix dynamically and statically typed code\". Since using Any allows you to write highly unsafe code, you should generally only use Any when the semantics of your code would otherwise be inexpressible to the type checker.

        The expectation in Python is that a comparison of two arbitrary objects using == or != should never raise an exception. This contract can be fully expressed in the type system and does not involve requesting unsound behaviour from a type checker. As such, object is a more appropriate annotation than Any for the second parameter of the methods implementing these comparison operators -- __eq__ and __ne__.

        ","tags":["PYI032"]},{"location":"rules/any-eq-ne-annotation/#example","title":"Example","text":"
        class Foo:\n    def __eq__(self, obj: typing.Any) -> bool: ...\n

        Use instead:

        class Foo:\n    def __eq__(self, obj: object) -> bool: ...\n
        ","tags":["PYI032"]},{"location":"rules/any-eq-ne-annotation/#references","title":"References","text":"
        • Python documentation: The Any type
        • Mypy documentation: Any vs. object
        ","tags":["PYI032"]},{"location":"rules/any-type/","title":"any-type (ANN401)","text":"

        Derived from the flake8-annotations linter.

        ","tags":["ANN401"]},{"location":"rules/any-type/#what-it-does","title":"What it does","text":"

        Checks that function arguments are annotated with a more specific type than Any.

        ","tags":["ANN401"]},{"location":"rules/any-type/#why-is-this-bad","title":"Why is this bad?","text":"

        Any is a special type indicating an unconstrained type. When an expression is annotated with type Any, type checkers will allow all operations on it.

        It's better to be explicit about the type of an expression, and to use Any as an \"escape hatch\" only when it is really needed.

        ","tags":["ANN401"]},{"location":"rules/any-type/#example","title":"Example","text":"
        def foo(x: Any): ...\n

        Use instead:

        def foo(x: int): ...\n
        ","tags":["ANN401"]},{"location":"rules/any-type/#known-problems","title":"Known problems","text":"

        Type aliases are unsupported and can lead to false positives. For example, the following will trigger this rule inadvertently:

        from typing import Any\n\nMyAny = Any\n\n\ndef foo(x: MyAny): ...\n
        ","tags":["ANN401"]},{"location":"rules/any-type/#references","title":"References","text":"
        • Typing spec: Any
        • Python documentation: typing.Any
        • Mypy documentation: The Any type
        ","tags":["ANN401"]},{"location":"rules/argument-default-in-stub/","title":"argument-default-in-stub (PYI014)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI014"]},{"location":"rules/argument-default-in-stub/#what-it-does","title":"What it does","text":"

        Checks for untyped function arguments in stubs with default values that are not \"simple\" /// (i.e., int, float, complex, bytes, str, bool, None, ..., or simple container literals).

        ","tags":["PYI014"]},{"location":"rules/argument-default-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub (.pyi) files exist to define type hints, and are not evaluated at runtime. As such, function arguments in stub files should not have default values, as they are ignored by type checkers.

        However, the use of default values may be useful for IDEs and other consumers of stub files, and so \"simple\" values may be worth including and are permitted by this rule.

        Instead of including and reproducing a complex value, use ... to indicate that the assignment has a default value, but that the value is non-simple or varies according to the current platform or Python version.

        ","tags":["PYI014"]},{"location":"rules/argument-default-in-stub/#example","title":"Example","text":"
        def foo(arg=[]) -> None: ...\n

        Use instead:

        def foo(arg=...) -> None: ...\n
        ","tags":["PYI014"]},{"location":"rules/argument-default-in-stub/#references","title":"References","text":"
        • flake8-pyi
        ","tags":["PYI014"]},{"location":"rules/assert-false/","title":"assert-false (B011)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B011"]},{"location":"rules/assert-false/#what-it-does","title":"What it does","text":"

        Checks for uses of assert False.

        ","tags":["B011"]},{"location":"rules/assert-false/#why-is-this-bad","title":"Why is this bad?","text":"

        Python removes assert statements when running in optimized mode (python -O), making assert False an unreliable means of raising an AssertionError.

        Instead, raise an AssertionError directly.

        ","tags":["B011"]},{"location":"rules/assert-false/#example","title":"Example","text":"
        assert False\n

        Use instead:

        raise AssertionError\n
        ","tags":["B011"]},{"location":"rules/assert-false/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as changing an assert to a raise will change the behavior of your program when running in optimized mode (python -O).

        ","tags":["B011"]},{"location":"rules/assert-false/#references","title":"References","text":"
        • Python documentation: assert
        ","tags":["B011"]},{"location":"rules/assert-on-string-literal/","title":"assert-on-string-literal (PLW0129)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0129"]},{"location":"rules/assert-on-string-literal/#what-it-does","title":"What it does","text":"

        Checks for assert statements that use a string literal as the first argument.

        ","tags":["PLW0129"]},{"location":"rules/assert-on-string-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        An assert on a non-empty string literal will always pass, while an assert on an empty string literal will always fail.

        ","tags":["PLW0129"]},{"location":"rules/assert-on-string-literal/#example","title":"Example","text":"
        assert \"always true\"\n
        ","tags":["PLW0129"]},{"location":"rules/assert-raises-exception/","title":"assert-raises-exception (B017)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B017"]},{"location":"rules/assert-raises-exception/#what-it-does","title":"What it does","text":"

        Checks for assertRaises and pytest.raises context managers that catch Exception or BaseException.

        ","tags":["B017"]},{"location":"rules/assert-raises-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        These forms catch every Exception, which can lead to tests passing even if, e.g., the code under consideration raises a SyntaxError or IndentationError.

        Either assert for a more specific exception (builtin or custom), or use assertRaisesRegex or pytest.raises(..., match=<REGEX>) respectively.

        ","tags":["B017"]},{"location":"rules/assert-raises-exception/#example","title":"Example","text":"
        self.assertRaises(Exception, foo)\n

        Use instead:

        self.assertRaises(SomeSpecificException, foo)\n
        ","tags":["B017"]},{"location":"rules/assert-tuple/","title":"assert-tuple (F631)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F631"]},{"location":"rules/assert-tuple/#what-it-does","title":"What it does","text":"

        Checks for assert statements that use non-empty tuples as test conditions.

        ","tags":["F631"]},{"location":"rules/assert-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        Non-empty tuples are always True, so an assert statement with a non-empty tuple as its test condition will always pass. This is likely a mistake.

        ","tags":["F631"]},{"location":"rules/assert-tuple/#example","title":"Example","text":"
        assert (some_condition,)\n

        Use instead:

        assert some_condition\n
        ","tags":["F631"]},{"location":"rules/assert-tuple/#references","title":"References","text":"
        • Python documentation: The assert statement
        ","tags":["F631"]},{"location":"rules/assert-with-print-message/","title":"assert-with-print-message (RUF030)","text":"

        Fix is always available.

        ","tags":["RUF030"]},{"location":"rules/assert-with-print-message/#what-it-does","title":"What it does","text":"

        Checks for uses of assert expression, print(message).

        ","tags":["RUF030"]},{"location":"rules/assert-with-print-message/#why-is-this-bad","title":"Why is this bad?","text":"

        If an assert x, y assertion fails, the Python interpreter raises an AssertionError, and the evaluated value of y is used as the contents of that assertion error. The print function always returns None, however, so the evaluated value of a call to print will always be None.

        Using a print call in this context will therefore output the message to stdout, before raising an empty AssertionError(None). Instead, remove the print and pass the message directly as the second expression, allowing stderr to capture the message in a well-formatted context.

        ","tags":["RUF030"]},{"location":"rules/assert-with-print-message/#example","title":"Example","text":"
        assert False, print(\"This is a message\")\n

        Use instead:

        assert False, \"This is a message\"\n
        ","tags":["RUF030"]},{"location":"rules/assert-with-print-message/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as changing the second expression will result in a different AssertionError message being raised, as well as a change in stdout output.

        ","tags":["RUF030"]},{"location":"rules/assert-with-print-message/#references","title":"References","text":"
        • Python documentation: assert
        ","tags":["RUF030"]},{"location":"rules/assert/","title":"assert (S101)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S101"]},{"location":"rules/assert/#what-it-does","title":"What it does","text":"

        Checks for uses of the assert keyword.

        ","tags":["S101"]},{"location":"rules/assert/#why-is-this-bad","title":"Why is this bad?","text":"

        Assertions are removed when Python is run with optimization requested (i.e., when the -O flag is present), which is a common practice in production environments. As such, assertions should not be used for runtime validation of user input or to enforce interface constraints.

        Consider raising a meaningful error instead of using assert.

        ","tags":["S101"]},{"location":"rules/assert/#example","title":"Example","text":"
        assert x > 0, \"Expected positive value.\"\n

        Use instead:

        if not x > 0:\n    raise ValueError(\"Expected positive value.\")\n\n# or even better:\nif x <= 0:\n    raise ValueError(\"Expected positive value.\")\n
        ","tags":["S101"]},{"location":"rules/assignment-default-in-stub/","title":"assignment-default-in-stub (PYI015)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI015"]},{"location":"rules/assignment-default-in-stub/#what-it-does","title":"What it does","text":"

        Checks for assignments in stubs with default values that are not \"simple\" (i.e., int, float, complex, bytes, str, bool, None, ..., or simple container literals).

        ","tags":["PYI015"]},{"location":"rules/assignment-default-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub (.pyi) files exist to define type hints, and are not evaluated at runtime. As such, assignments in stub files should not include values, as they are ignored by type checkers.

        However, the use of such values may be useful for IDEs and other consumers of stub files, and so \"simple\" values may be worth including and are permitted by this rule.

        Instead of including and reproducing a complex value, use ... to indicate that the assignment has a default value, but that the value is non-simple or varies according to the current platform or Python version.

        ","tags":["PYI015"]},{"location":"rules/assignment-default-in-stub/#example","title":"Example","text":"
        foo: str = \"...\"\n

        Use instead:

        foo: str = ...\n
        ","tags":["PYI015"]},{"location":"rules/assignment-default-in-stub/#references","title":"References","text":"
        • flake8-pyi
        ","tags":["PYI015"]},{"location":"rules/assignment-in-assert/","title":"assignment-in-assert (RUF018)","text":"","tags":["RUF018"]},{"location":"rules/assignment-in-assert/#what-it-does","title":"What it does","text":"

        Checks for named assignment expressions (e.g., x := 0) in assert statements.

        ","tags":["RUF018"]},{"location":"rules/assignment-in-assert/#why-is-this-bad","title":"Why is this bad?","text":"

        Named assignment expressions (also known as \"walrus operators\") are used to assign a value to a variable as part of a larger expression.

        Named assignments are syntactically valid in assert statements. However, when the Python interpreter is run under the -O flag, assert statements are not executed. In this case, the named assignment will also be ignored, which may result in unexpected behavior (e.g., undefined variable accesses).

        ","tags":["RUF018"]},{"location":"rules/assignment-in-assert/#example","title":"Example","text":"
        assert (x := 0) == 0\nprint(x)\n

        Use instead:

        x = 0\nassert x == 0\nprint(x)\n

        The rule avoids flagging named expressions that define variables which are only referenced from inside assert statements; the following will not trigger the rule:

        assert (x := y**2) > 42, f\"Expected >42 but got {x}\"\n

        Nor will this:

        assert (x := y**2) > 42\nassert x < 1_000_000\n
        ","tags":["RUF018"]},{"location":"rules/assignment-in-assert/#references","title":"References","text":"
        • Python documentation: -O
        ","tags":["RUF018"]},{"location":"rules/assignment-to-os-environ/","title":"assignment-to-os-environ (B003)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B003"]},{"location":"rules/assignment-to-os-environ/#what-it-does","title":"What it does","text":"

        Checks for assignments to os.environ.

        ","tags":["B003"]},{"location":"rules/assignment-to-os-environ/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, os.environ is a mapping that represents the environment of the current process.

        However, reassigning to os.environ does not clear the environment. Instead, it merely updates the os.environ for the current process. This can lead to unexpected behavior, especially when running the program in a subprocess.

        Instead, use os.environ.clear() to clear the environment, or use the env argument of subprocess.Popen to pass a custom environment to a subprocess.

        ","tags":["B003"]},{"location":"rules/assignment-to-os-environ/#example","title":"Example","text":"
        import os\n\nos.environ = {\"foo\": \"bar\"}\n

        Use instead:

        import os\n\nos.environ.clear()\nos.environ[\"foo\"] = \"bar\"\n
        ","tags":["B003"]},{"location":"rules/assignment-to-os-environ/#references","title":"References","text":"
        • Python documentation: os.environ
        • Python documentation: subprocess.Popen
        ","tags":["B003"]},{"location":"rules/async-busy-wait/","title":"async-busy-wait (ASYNC110)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC110"]},{"location":"rules/async-busy-wait/#what-it-does","title":"What it does","text":"

        Checks for the use of an async sleep function in a while loop.

        ","tags":["ASYNC110"]},{"location":"rules/async-busy-wait/#why-is-this-bad","title":"Why is this bad?","text":"

        Instead of sleeping in a while loop, and waiting for a condition to become true, it's preferable to await on an Event object such as: asyncio.Event, trio.Event, or anyio.Event.

        ","tags":["ASYNC110"]},{"location":"rules/async-busy-wait/#example","title":"Example","text":"
        DONE = False\n\n\nasync def func():\n    while not DONE:\n        await asyncio.sleep(1)\n

        Use instead:

        DONE = asyncio.Event()\n\n\nasync def func():\n    await DONE.wait()\n
        ","tags":["ASYNC110"]},{"location":"rules/async-busy-wait/#references","title":"References","text":"
        • asyncio events
        • anyio events
        • trio events
        ","tags":["ASYNC110"]},{"location":"rules/async-function-with-timeout/","title":"async-function-with-timeout (ASYNC109)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC109"]},{"location":"rules/async-function-with-timeout/#what-it-does","title":"What it does","text":"

        Checks for async function definitions with timeout parameters.

        ","tags":["ASYNC109"]},{"location":"rules/async-function-with-timeout/#why-is-this-bad","title":"Why is this bad?","text":"

        Rather than implementing asynchronous timeout behavior manually, prefer built-in timeout functionality, such as asyncio.timeout, trio.fail_after, or anyio.move_on_after, among others.

        This rule is highly opinionated to enforce a design pattern called \"structured concurrency\" that allows for async functions to be oblivious to timeouts, instead letting callers to handle the logic with a context manager.

        ","tags":["ASYNC109"]},{"location":"rules/async-function-with-timeout/#details","title":"Details","text":"

        This rule attempts to detect which async framework your code is using by analysing the imports in the file it's checking. If it sees an anyio import in your code, it will assume anyio is your framework of choice; if it sees a trio import, it will assume trio; if it sees neither, it will assume asyncio. asyncio.timeout was added in Python 3.11, so if asyncio is detected as the framework being used, this rule will be ignored when your configured target-version is set to less than Python 3.11.

        For functions that wrap asyncio.timeout, trio.fail_after or anyio.move_on_after, false positives from this rule can be avoided by using a different parameter name.

        ","tags":["ASYNC109"]},{"location":"rules/async-function-with-timeout/#example","title":"Example","text":"
        async def long_running_task(timeout): ...\n\n\nasync def main():\n    await long_running_task(timeout=2)\n

        Use instead:

        async def long_running_task(): ...\n\n\nasync def main():\n    async with asyncio.timeout(2):\n        await long_running_task()\n
        ","tags":["ASYNC109"]},{"location":"rules/async-function-with-timeout/#references","title":"References","text":"
        • asyncio timeouts
        • anyio timeouts
        • trio timeouts
        ","tags":["ASYNC109"]},{"location":"rules/async-zero-sleep/","title":"async-zero-sleep (ASYNC115)","text":"

        Derived from the flake8-async linter.

        Fix is always available.

        ","tags":["ASYNC115"]},{"location":"rules/async-zero-sleep/#what-it-does","title":"What it does","text":"

        Checks for uses of trio.sleep(0) or anyio.sleep(0).

        ","tags":["ASYNC115"]},{"location":"rules/async-zero-sleep/#why-is-this-bad","title":"Why is this bad?","text":"

        trio.sleep(0) is equivalent to calling trio.lowlevel.checkpoint(). However, the latter better conveys the intent of the code.

        ","tags":["ASYNC115"]},{"location":"rules/async-zero-sleep/#example","title":"Example","text":"
        import trio\n\n\nasync def func():\n    await trio.sleep(0)\n

        Use instead:

        import trio\n\n\nasync def func():\n    await trio.lowlevel.checkpoint()\n
        ","tags":["ASYNC115"]},{"location":"rules/asyncio-dangling-task/","title":"asyncio-dangling-task (RUF006)","text":"","tags":["RUF006"]},{"location":"rules/asyncio-dangling-task/#what-it-does","title":"What it does","text":"

        Checks for asyncio.create_task and asyncio.ensure_future calls that do not store a reference to the returned result.

        ","tags":["RUF006"]},{"location":"rules/asyncio-dangling-task/#why-is-this-bad","title":"Why is this bad?","text":"

        Per the asyncio documentation, the event loop only retains a weak reference to tasks. If the task returned by asyncio.create_task and asyncio.ensure_future is not stored in a variable, or a collection, or otherwise referenced, it may be garbage collected at any time. This can lead to unexpected and inconsistent behavior, as your tasks may or may not run to completion.

        ","tags":["RUF006"]},{"location":"rules/asyncio-dangling-task/#example","title":"Example","text":"
        import asyncio\n\nfor i in range(10):\n    # This creates a weak reference to the task, which may be garbage\n    # collected at any time.\n    asyncio.create_task(some_coro(param=i))\n

        Use instead:

        import asyncio\n\nbackground_tasks = set()\n\nfor i in range(10):\n    task = asyncio.create_task(some_coro(param=i))\n\n    # Add task to the set. This creates a strong reference.\n    background_tasks.add(task)\n\n    # To prevent keeping references to finished tasks forever,\n    # make each task remove its own reference from the set after\n    # completion:\n    task.add_done_callback(background_tasks.discard)\n
        ","tags":["RUF006"]},{"location":"rules/asyncio-dangling-task/#references","title":"References","text":"
        • The Heisenbug lurking in your async code
        • The Python Standard Library
        ","tags":["RUF006"]},{"location":"rules/avoidable-escaped-quote/","title":"avoidable-escaped-quote (Q003)","text":"

        Derived from the flake8-quotes linter.

        Fix is always available.

        ","tags":["Q003"]},{"location":"rules/avoidable-escaped-quote/#what-it-does","title":"What it does","text":"

        Checks for strings that include escaped quotes, and suggests changing the quote style to avoid the need to escape them.

        ","tags":["Q003"]},{"location":"rules/avoidable-escaped-quote/#why-is-this-bad","title":"Why is this bad?","text":"

        It's preferable to avoid escaped quotes in strings. By changing the outer quote style, you can avoid escaping inner quotes.

        ","tags":["Q003"]},{"location":"rules/avoidable-escaped-quote/#example","title":"Example","text":"
        foo = 'bar\\'s'\n

        Use instead:

        foo = \"bar's\"\n
        ","tags":["Q003"]},{"location":"rules/avoidable-escaped-quote/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter automatically removes unnecessary escapes, making the rule redundant.

        ","tags":["Q003"]},{"location":"rules/await-outside-async/","title":"await-outside-async (PLE1142)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1142"]},{"location":"rules/await-outside-async/#what-it-does","title":"What it does","text":"

        Checks for uses of await outside async functions.

        ","tags":["PLE1142"]},{"location":"rules/await-outside-async/#why-is-this-bad","title":"Why is this bad?","text":"

        Using await outside an async function is a syntax error.

        ","tags":["PLE1142"]},{"location":"rules/await-outside-async/#example","title":"Example","text":"
        import asyncio\n\n\ndef foo():\n    await asyncio.sleep(1)\n

        Use instead:

        import asyncio\n\n\nasync def foo():\n    await asyncio.sleep(1)\n
        ","tags":["PLE1142"]},{"location":"rules/await-outside-async/#notebook-behavior","title":"Notebook behavior","text":"

        As an exception, await is allowed at the top level of a Jupyter notebook (see: autoawait).

        ","tags":["PLE1142"]},{"location":"rules/await-outside-async/#references","title":"References","text":"
        • Python documentation: Await expression
        • PEP 492: Await Expression
        ","tags":["PLE1142"]},{"location":"rules/bad-dunder-method-name/","title":"bad-dunder-method-name (PLW3201)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW3201"]},{"location":"rules/bad-dunder-method-name/#what-it-does","title":"What it does","text":"

        Checks for dunder methods that have no special meaning in Python 3.

        ","tags":["PLW3201"]},{"location":"rules/bad-dunder-method-name/#why-is-this-bad","title":"Why is this bad?","text":"

        Misspelled or no longer supported dunder name methods may cause your code to not function as expected.

        Since dunder methods are associated with customizing the behavior of a class in Python, introducing a dunder method such as __foo__ that diverges from standard Python dunder methods could potentially confuse someone reading the code.

        This rule will detect all methods starting and ending with at least one underscore (e.g., _str_), but ignores known dunder methods (like __init__), as well as methods that are marked with @override.

        Additional dunder methods names can be allowed via the lint.pylint.allow-dunder-method-names setting.

        ","tags":["PLW3201"]},{"location":"rules/bad-dunder-method-name/#example","title":"Example","text":"
        class Foo:\n    def __init_(self): ...\n

        Use instead:

        class Foo:\n    def __init__(self): ...\n
        ","tags":["PLW3201"]},{"location":"rules/bad-dunder-method-name/#options","title":"Options","text":"
        • lint.pylint.allow-dunder-method-names
        ","tags":["PLW3201"]},{"location":"rules/bad-exit-annotation/","title":"bad-exit-annotation (PYI036)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI036"]},{"location":"rules/bad-exit-annotation/#what-it-does","title":"What it does","text":"

        Checks for incorrect function signatures on __exit__ and __aexit__ methods.

        ","tags":["PYI036"]},{"location":"rules/bad-exit-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        Improperly annotated __exit__ and __aexit__ methods can cause unexpected behavior when interacting with type checkers.

        ","tags":["PYI036"]},{"location":"rules/bad-exit-annotation/#example","title":"Example","text":"
        from types import TracebackType\n\nclass Foo:\n    def __exit__(\n        self, typ: BaseException, exc: BaseException, tb: TracebackType\n    ) -> None: ...\n

        Use instead:

        from types import TracebackType\n\nclass Foo:\n    def __exit__(\n        self,\n        typ: type[BaseException] | None,\n        exc: BaseException | None,\n        tb: TracebackType | None,\n    ) -> None: ...\n
        ","tags":["PYI036"]},{"location":"rules/bad-file-permissions/","title":"bad-file-permissions (S103)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S103"]},{"location":"rules/bad-file-permissions/#what-it-does","title":"What it does","text":"

        Checks for files with overly permissive permissions.

        ","tags":["S103"]},{"location":"rules/bad-file-permissions/#why-is-this-bad","title":"Why is this bad?","text":"

        Overly permissive file permissions may allow unintended access and arbitrary code execution.

        ","tags":["S103"]},{"location":"rules/bad-file-permissions/#example","title":"Example","text":"
        import os\n\nos.chmod(\"/etc/secrets.txt\", 0o666)  # rw-rw-rw-\n

        Use instead:

        import os\n\nos.chmod(\"/etc/secrets.txt\", 0o600)  # rw-------\n
        ","tags":["S103"]},{"location":"rules/bad-file-permissions/#references","title":"References","text":"
        • Python documentation: os.chmod
        • Python documentation: stat
        • Common Weakness Enumeration: CWE-732
        ","tags":["S103"]},{"location":"rules/bad-open-mode/","title":"bad-open-mode (PLW1501)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW1501"]},{"location":"rules/bad-open-mode/#what-it-does","title":"What it does","text":"

        Check for an invalid mode argument in open calls.

        ","tags":["PLW1501"]},{"location":"rules/bad-open-mode/#why-is-this-bad","title":"Why is this bad?","text":"

        The open function accepts a mode argument that specifies how the file should be opened (e.g., read-only, write-only, append-only, etc.).

        Python supports a variety of open modes: r, w, a, and x, to control reading, writing, appending, and creating, respectively, along with b (binary mode), + (read and write), and U (universal newlines), the latter of which is only valid alongside r. This rule detects both invalid combinations of modes and invalid characters in the mode string itself.

        ","tags":["PLW1501"]},{"location":"rules/bad-open-mode/#example","title":"Example","text":"
        with open(\"file\", \"rwx\") as f:\n    return f.read()\n

        Use instead:

        with open(\"file\", \"r\") as f:\n    return f.read()\n
        ","tags":["PLW1501"]},{"location":"rules/bad-open-mode/#references","title":"References","text":"
        • Python documentation: open
        ","tags":["PLW1501"]},{"location":"rules/bad-quotes-docstring/","title":"bad-quotes-docstring (Q002)","text":"

        Derived from the flake8-quotes linter.

        Fix is sometimes available.

        ","tags":["Q002"]},{"location":"rules/bad-quotes-docstring/#what-it-does","title":"What it does","text":"

        Checks for docstrings that use single quotes or double quotes, depending on the value of the lint.flake8-quotes.docstring-quotes setting.

        ","tags":["Q002"]},{"location":"rules/bad-quotes-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use either single or double quotes for docstring strings, but be consistent.

        ","tags":["Q002"]},{"location":"rules/bad-quotes-docstring/#example","title":"Example","text":"
        '''\nbar\n'''\n

        Assuming docstring-quotes is set to double, use instead:

        \"\"\"\nbar\n\"\"\"\n
        ","tags":["Q002"]},{"location":"rules/bad-quotes-docstring/#options","title":"Options","text":"
        • lint.flake8-quotes.docstring-quotes
        ","tags":["Q002"]},{"location":"rules/bad-quotes-docstring/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces double quotes for docstrings, making the rule redundant.

        ","tags":["Q002"]},{"location":"rules/bad-quotes-inline-string/","title":"bad-quotes-inline-string (Q000)","text":"

        Derived from the flake8-quotes linter.

        Fix is sometimes available.

        ","tags":["Q000"]},{"location":"rules/bad-quotes-inline-string/#what-it-does","title":"What it does","text":"

        Checks for inline strings that use single quotes or double quotes, depending on the value of the lint.flake8-quotes.inline-quotes option.

        ","tags":["Q000"]},{"location":"rules/bad-quotes-inline-string/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use either single or double quotes for inline strings, but be consistent.

        ","tags":["Q000"]},{"location":"rules/bad-quotes-inline-string/#example","title":"Example","text":"
        foo = 'bar'\n

        Assuming inline-quotes is set to double, use instead:

        foo = \"bar\"\n
        ","tags":["Q000"]},{"location":"rules/bad-quotes-inline-string/#options","title":"Options","text":"
        • lint.flake8-quotes.inline-quotes
        ","tags":["Q000"]},{"location":"rules/bad-quotes-inline-string/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent quotes for inline strings, making the rule redundant.

        ","tags":["Q000"]},{"location":"rules/bad-quotes-multiline-string/","title":"bad-quotes-multiline-string (Q001)","text":"

        Derived from the flake8-quotes linter.

        Fix is always available.

        ","tags":["Q001"]},{"location":"rules/bad-quotes-multiline-string/#what-it-does","title":"What it does","text":"

        Checks for multiline strings that use single quotes or double quotes, depending on the value of the lint.flake8-quotes.multiline-quotes setting.

        ","tags":["Q001"]},{"location":"rules/bad-quotes-multiline-string/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use either single or double quotes for multiline strings, but be consistent.

        ","tags":["Q001"]},{"location":"rules/bad-quotes-multiline-string/#example","title":"Example","text":"
        foo = '''\nbar\n'''\n

        Assuming multiline-quotes is set to double, use instead:

        foo = \"\"\"\nbar\n\"\"\"\n
        ","tags":["Q001"]},{"location":"rules/bad-quotes-multiline-string/#options","title":"Options","text":"
        • lint.flake8-quotes.multiline-quotes
        ","tags":["Q001"]},{"location":"rules/bad-quotes-multiline-string/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces double quotes for multiline strings, making the rule redundant.

        ","tags":["Q001"]},{"location":"rules/bad-staticmethod-argument/","title":"bad-staticmethod-argument (PLW0211)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0211"]},{"location":"rules/bad-staticmethod-argument/#what-it-does","title":"What it does","text":"

        Checks for static methods that use self or cls as their first argument. This rule also applies to __new__ methods, which are implicitly static.

        ","tags":["PLW0211"]},{"location":"rules/bad-staticmethod-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the use of self and cls as the first arguments for instance methods and class methods, respectively. Naming the first argument of a static method as self or cls can be misleading, as static methods do not receive an instance or class reference as their first argument.

        ","tags":["PLW0211"]},{"location":"rules/bad-staticmethod-argument/#example","title":"Example","text":"
        class Wolf:\n    @staticmethod\n    def eat(self):\n        pass\n

        Use instead:

        class Wolf:\n    @staticmethod\n    def eat(sheep):\n        pass\n
        ","tags":["PLW0211"]},{"location":"rules/bad-str-strip-call/","title":"bad-str-strip-call (PLE1310)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1310"]},{"location":"rules/bad-str-strip-call/#what-it-does","title":"What it does","text":"

        Checks duplicate characters in str.strip calls.

        ","tags":["PLE1310"]},{"location":"rules/bad-str-strip-call/#why-is-this-bad","title":"Why is this bad?","text":"

        All characters in str.strip calls are removed from both the leading and trailing ends of the string. Including duplicate characters in the call is redundant and often indicative of a mistake.

        In Python 3.9 and later, you can use str.removeprefix and str.removesuffix to remove an exact prefix or suffix from a string, respectively, which should be preferred when possible.

        ","tags":["PLE1310"]},{"location":"rules/bad-str-strip-call/#example","title":"Example","text":"
        # Evaluates to \"foo\".\n\"bar foo baz\".strip(\"bar baz \")\n

        Use instead:

        # Evaluates to \"foo\".\n\"bar foo baz\".strip(\"abrz \")  # \"foo\"\n

        Or:

        # Evaluates to \"foo\".\n\"bar foo baz\".removeprefix(\"bar \").removesuffix(\" baz\")\n
        ","tags":["PLE1310"]},{"location":"rules/bad-str-strip-call/#options","title":"Options","text":"
        • target-version
        ","tags":["PLE1310"]},{"location":"rules/bad-str-strip-call/#references","title":"References","text":"
        • Python documentation: str.strip
        ","tags":["PLE1310"]},{"location":"rules/bad-string-format-character/","title":"bad-string-format-character (PLE1300)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1300"]},{"location":"rules/bad-string-format-character/#what-it-does","title":"What it does","text":"

        Checks for unsupported format types in format strings.

        ","tags":["PLE1300"]},{"location":"rules/bad-string-format-character/#why-is-this-bad","title":"Why is this bad?","text":"

        An invalid format string character will result in an error at runtime.

        ","tags":["PLE1300"]},{"location":"rules/bad-string-format-character/#example","title":"Example","text":"
        # `z` is not a valid format type.\nprint(\"%z\" % \"1\")\n\nprint(\"{:z}\".format(\"1\"))\n
        ","tags":["PLE1300"]},{"location":"rules/bad-string-format-type/","title":"bad-string-format-type (PLE1307)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1307"]},{"location":"rules/bad-string-format-type/#what-it-does","title":"What it does","text":"

        Checks for mismatched argument types in \"old-style\" format strings.

        ","tags":["PLE1307"]},{"location":"rules/bad-string-format-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The format string is not checked at compile time, so it is easy to introduce bugs by mistyping the format string.

        ","tags":["PLE1307"]},{"location":"rules/bad-string-format-type/#example","title":"Example","text":"
        print(\"%d\" % \"1\")\n

        Use instead:

        print(\"%d\" % 1)\n
        ","tags":["PLE1307"]},{"location":"rules/bad-version-info-comparison/","title":"bad-version-info-comparison (PYI006)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI006"]},{"location":"rules/bad-version-info-comparison/#what-it-does","title":"What it does","text":"

        Checks for uses of comparators other than < and >= for sys.version_info checks. All other comparators, such as >, <=, and ==, are banned.

        ","tags":["PYI006"]},{"location":"rules/bad-version-info-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing sys.version_info with == or <= has unexpected behavior and can lead to bugs.

        For example, sys.version_info > (3, 8, 1) will resolve to True if your Python version is 3.8.1; meanwhile, sys.version_info <= (3, 8) will not resolve to True if your Python version is 3.8.10:

        >>> import sys\n>>> print(sys.version_info)\nsys.version_info(major=3, minor=8, micro=10, releaselevel='final', serial=0)\n>>> print(sys.version_info > (3, 8))\nTrue\n>>> print(sys.version_info == (3, 8))\nFalse\n>>> print(sys.version_info <= (3, 8))\nFalse\n>>> print(sys.version_info in (3, 8))\nFalse\n
        ","tags":["PYI006"]},{"location":"rules/bad-version-info-comparison/#example","title":"Example","text":"
        import sys\n\nif sys.version_info > (3, 8): ...\n

        Use instead:

        import sys\n\nif sys.version_info >= (3, 9): ...\n
        ","tags":["PYI006"]},{"location":"rules/bad-version-info-order/","title":"bad-version-info-order (PYI066)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI066"]},{"location":"rules/bad-version-info-order/#what-it-does","title":"What it does","text":"

        Checks for code that branches on sys.version_info comparisons where branches corresponding to older Python versions come before branches corresponding to newer Python versions.

        ","tags":["PYI066"]},{"location":"rules/bad-version-info-order/#why-is-this-bad","title":"Why is this bad?","text":"

        As a convention, branches that correspond to newer Python versions should come first. This makes it easier to understand the desired behavior, which typically corresponds to the latest Python versions.

        This rule enforces the convention by checking for if tests that compare sys.version_info with < rather than >=.

        By default, this rule only applies to stub files. In preview, it will also flag this anti-pattern in non-stub files.

        ","tags":["PYI066"]},{"location":"rules/bad-version-info-order/#example","title":"Example","text":"
        import sys\n\nif sys.version_info < (3, 10):\n    def read_data(x, *, preserve_order=True): ...\n\nelse:\n    def read_data(x): ...\n

        Use instead:

        if sys.version_info >= (3, 10):\n    def read_data(x): ...\n\nelse:\n    def read_data(x, *, preserve_order=True): ...\n
        ","tags":["PYI066"]},{"location":"rules/banned-api/","title":"banned-api (TID251)","text":"

        Derived from the flake8-tidy-imports linter.

        ","tags":["TID251"]},{"location":"rules/banned-api/#what-it-does","title":"What it does","text":"

        Checks for banned imports.

        ","tags":["TID251"]},{"location":"rules/banned-api/#why-is-this-bad","title":"Why is this bad?","text":"

        Projects may want to ensure that specific modules or module members are not imported or accessed.

        Security or other company policies may be a reason to impose restrictions on importing external Python libraries. In some cases, projects may adopt conventions around the use of certain modules or module members that are not enforceable by the language itself.

        This rule enforces certain import conventions project-wide automatically.

        ","tags":["TID251"]},{"location":"rules/banned-api/#options","title":"Options","text":"
        • lint.flake8-tidy-imports.banned-api
        ","tags":["TID251"]},{"location":"rules/banned-import-alias/","title":"banned-import-alias (ICN002)","text":"

        Derived from the flake8-import-conventions linter.

        ","tags":["ICN002"]},{"location":"rules/banned-import-alias/#what-it-does","title":"What it does","text":"

        Checks for imports that use non-standard naming conventions, like import tensorflow.keras.backend as K.

        ","tags":["ICN002"]},{"location":"rules/banned-import-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Avoid using a non-standard naming convention for imports, and, in particular, choosing import aliases that violate PEP 8.

        For example, aliasing via import tensorflow.keras.backend as K violates the guidance of PEP 8, and is thus avoided in some projects.

        ","tags":["ICN002"]},{"location":"rules/banned-import-alias/#example","title":"Example","text":"
        import tensorflow.keras.backend as K\n

        Use instead:

        import tensorflow as tf\n\ntf.keras.backend\n
        ","tags":["ICN002"]},{"location":"rules/banned-import-alias/#options","title":"Options","text":"
        • lint.flake8-import-conventions.banned-aliases
        ","tags":["ICN002"]},{"location":"rules/banned-import-from/","title":"banned-import-from (ICN003)","text":"

        Derived from the flake8-import-conventions linter.

        ","tags":["ICN003"]},{"location":"rules/banned-import-from/#what-it-does","title":"What it does","text":"

        Checks for member imports that should instead be accessed by importing the module.

        ","tags":["ICN003"]},{"location":"rules/banned-import-from/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use a common convention for imports to make your code more readable and idiomatic.

        For example, it's common to import pandas as pd, and then access members like Series via pd.Series, rather than importing Series directly.

        ","tags":["ICN003"]},{"location":"rules/banned-import-from/#example","title":"Example","text":"
        from pandas import Series\n

        Use instead:

        import pandas as pd\n\npd.Series\n
        ","tags":["ICN003"]},{"location":"rules/banned-import-from/#options","title":"Options","text":"
        • lint.flake8-import-conventions.banned-from
        ","tags":["ICN003"]},{"location":"rules/banned-module-level-imports/","title":"banned-module-level-imports (TID253)","text":"

        Derived from the flake8-tidy-imports linter.

        ","tags":["TID253"]},{"location":"rules/banned-module-level-imports/#what-it-does","title":"What it does","text":"

        Checks for module-level imports that should instead be imported lazily (e.g., within a function definition, or an if TYPE_CHECKING: block, or some other nested context).

        ","tags":["TID253"]},{"location":"rules/banned-module-level-imports/#why-is-this-bad","title":"Why is this bad?","text":"

        Some modules are expensive to import. For example, importing torch or tensorflow can introduce a noticeable delay in the startup time of a Python program.

        In such cases, you may want to enforce that the module is imported lazily as needed, rather than at the top of the file. This could involve inlining the import into the function that uses it, rather than importing it unconditionally, to ensure that the module is only imported when necessary.

        ","tags":["TID253"]},{"location":"rules/banned-module-level-imports/#example","title":"Example","text":"
        import tensorflow as tf\n\n\ndef show_version():\n    print(tf.__version__)\n

        Use instead:

        def show_version():\n    import tensorflow as tf\n\n    print(tf.__version__)\n
        ","tags":["TID253"]},{"location":"rules/banned-module-level-imports/#options","title":"Options","text":"
        • lint.flake8-tidy-imports.banned-module-level-imports
        ","tags":["TID253"]},{"location":"rules/bare-except/","title":"bare-except (E722)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E722"]},{"location":"rules/bare-except/#what-it-does","title":"What it does","text":"

        Checks for bare except catches in try-except statements.

        ","tags":["E722"]},{"location":"rules/bare-except/#why-is-this-bad","title":"Why is this bad?","text":"

        A bare except catches BaseException which includes KeyboardInterrupt, SystemExit, Exception, and others. Catching BaseException can make it hard to interrupt the program (e.g., with Ctrl-C) and can disguise other problems.

        ","tags":["E722"]},{"location":"rules/bare-except/#example","title":"Example","text":"
        try:\n    raise KeyboardInterrupt(\"You probably don't mean to break CTRL-C.\")\nexcept:\n    print(\"But a bare `except` will ignore keyboard interrupts.\")\n

        Use instead:

        try:\n    do_something_that_might_break()\nexcept MoreSpecificException as e:\n    handle_error(e)\n

        If you actually need to catch an unknown error, use Exception which will catch regular program errors but not important system exceptions.

        def run_a_function(some_other_fn):\n    try:\n        some_other_fn()\n    except Exception as e:\n        print(f\"How exceptional! {e}\")\n
        ","tags":["E722"]},{"location":"rules/bare-except/#references","title":"References","text":"
        • Python documentation: Exception hierarchy
        • Google Python Style Guide: \"Exceptions\"
        ","tags":["E722"]},{"location":"rules/batched-without-explicit-strict/","title":"batched-without-explicit-strict (B911)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#what-it-does","title":"What it does","text":"

        Checks for itertools.batched calls without an explicit strict parameter.

        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#why-is-this-bad","title":"Why is this bad?","text":"

        By default, if the length of the iterable is not divisible by the second argument to itertools.batched, the last batch will be shorter than the rest.

        In Python 3.13, a strict parameter was added which allows controlling if the batches must be of uniform length. Pass strict=True to raise a ValueError if the batches are of non-uniform length. Otherwise, pass strict=False to make the intention explicit.

        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#example","title":"Example","text":"
        itertools.batched(iterable, n)\n

        Use instead if the batches must be of uniform length:

        itertools.batched(iterable, n, strict=True)\n

        Or if the batches can be of non-uniform length:

        itertools.batched(iterable, n, strict=False)\n
        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#known-deviations","title":"Known deviations","text":"

        Unlike the upstream B911, this rule will not report infinite iterators (e.g., itertools.cycle(...)).

        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#options","title":"Options","text":"
        • target-version
        ","tags":["B911"]},{"location":"rules/batched-without-explicit-strict/#references","title":"References","text":"
        • Python documentation: batched
        ","tags":["B911"]},{"location":"rules/bidirectional-unicode/","title":"bidirectional-unicode (PLE2502)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE2502"]},{"location":"rules/bidirectional-unicode/#what-it-does","title":"What it does","text":"

        Checks for bidirectional unicode characters.

        ","tags":["PLE2502"]},{"location":"rules/bidirectional-unicode/#why-is-this-bad","title":"Why is this bad?","text":"

        The interaction between bidirectional unicode characters and the surrounding code can be surprising to those that are unfamiliar with right-to-left writing systems.

        In some cases, bidirectional unicode characters can also be used to obfuscate code and introduce or mask security vulnerabilities.

        ","tags":["PLE2502"]},{"location":"rules/bidirectional-unicode/#example","title":"Example","text":"
        s = \"\u05d0\" * 100  #  \"\u05d0\" is assigned\nprint(s)  # prints a 100-character string\n
        ","tags":["PLE2502"]},{"location":"rules/bidirectional-unicode/#references","title":"References","text":"
        • PEP 672: Bidirectional Text
        ","tags":["PLE2502"]},{"location":"rules/binary-op-exception/","title":"binary-op-exception (PLW0711)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0711"]},{"location":"rules/binary-op-exception/#what-it-does","title":"What it does","text":"

        Checks for except clauses that attempt to catch multiple exceptions with a binary operation (and or or).

        ","tags":["PLW0711"]},{"location":"rules/binary-op-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        A binary operation will not catch multiple exceptions. Instead, the binary operation will be evaluated first, and the result of that operation will be caught (for an or operation, this is typically the first exception in the list). This is almost never the desired behavior.

        ","tags":["PLW0711"]},{"location":"rules/binary-op-exception/#example","title":"Example","text":"
        try:\n    pass\nexcept A or B:\n    pass\n

        Use instead:

        try:\n    pass\nexcept (A, B):\n    pass\n
        ","tags":["PLW0711"]},{"location":"rules/bit-count/","title":"bit-count (FURB161)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB161"]},{"location":"rules/bit-count/#what-it-does","title":"What it does","text":"

        Checks for uses of bin(...).count(\"1\") to perform a population count.

        ","tags":["FURB161"]},{"location":"rules/bit-count/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3.10, a bit_count() method was added to the int class, which is more concise and efficient than converting to a binary representation via bin(...).

        ","tags":["FURB161"]},{"location":"rules/bit-count/#example","title":"Example","text":"
        x = bin(123).count(\"1\")\ny = bin(0b1111011).count(\"1\")\n

        Use instead:

        x = (123).bit_count()\ny = 0b1111011.bit_count()\n
        ","tags":["FURB161"]},{"location":"rules/bit-count/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe unless the argument to bin can be inferred as an instance of a type that implements the __index__ and bit_count methods because this can change the exception raised at runtime for an invalid argument.

        ","tags":["FURB161"]},{"location":"rules/bit-count/#options","title":"Options","text":"
        • target-version
        ","tags":["FURB161"]},{"location":"rules/bit-count/#references","title":"References","text":"
        • Python documentation:int.bit_count
        ","tags":["FURB161"]},{"location":"rules/blank-line-after-decorator/","title":"blank-line-after-decorator (E304)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E304"]},{"location":"rules/blank-line-after-decorator/#what-it-does","title":"What it does","text":"

        Checks for extraneous blank line(s) after function decorators.

        ","tags":["E304"]},{"location":"rules/blank-line-after-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        There should be no blank lines between a decorator and the object it is decorating.

        ","tags":["E304"]},{"location":"rules/blank-line-after-decorator/#example","title":"Example","text":"
        class User(object):\n\n    @property\n\n    def name(self):\n        pass\n

        Use instead:

        class User(object):\n\n    @property\n    def name(self):\n        pass\n
        ","tags":["E304"]},{"location":"rules/blank-line-after-decorator/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        ","tags":["E304"]},{"location":"rules/blank-line-after-function/","title":"blank-line-after-function (D202)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D202"]},{"location":"rules/blank-line-after-function/#what-it-does","title":"What it does","text":"

        Checks for docstrings on functions that are separated by one or more blank lines from the function body.

        ","tags":["D202"]},{"location":"rules/blank-line-after-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Remove any blank lines between the function body and the function docstring, for consistency.

        ","tags":["D202"]},{"location":"rules/blank-line-after-function/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n\n    return sum(values) / len(values)\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n    return sum(values) / len(values)\n
        ","tags":["D202"]},{"location":"rules/blank-line-after-function/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D202"]},{"location":"rules/blank-line-before-class/","title":"blank-line-before-class (D211)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D211"]},{"location":"rules/blank-line-before-class/#what-it-does","title":"What it does","text":"

        Checks for docstrings on class definitions that are preceded by a blank line.

        ","tags":["D211"]},{"location":"rules/blank-line-before-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Avoid introducing any blank lines between a class definition and its docstring, for consistency.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the google, numpy, and pep257 conventions.

        For an alternative, see D203.

        ","tags":["D211"]},{"location":"rules/blank-line-before-class/#example","title":"Example","text":"
        class PhotoMetadata:\n\n    \"\"\"Metadata about a photo.\"\"\"\n

        Use instead:

        class PhotoMetadata:\n    \"\"\"Metadata about a photo.\"\"\"\n
        ","tags":["D211"]},{"location":"rules/blank-line-before-class/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D211"]},{"location":"rules/blank-line-before-function/","title":"blank-line-before-function (D201)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D201"]},{"location":"rules/blank-line-before-function/#what-it-does","title":"What it does","text":"

        Checks for docstrings on functions that are separated by one or more blank lines from the function definition.

        ","tags":["D201"]},{"location":"rules/blank-line-before-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Remove any blank lines between the function definition and its docstring, for consistency.

        ","tags":["D201"]},{"location":"rules/blank-line-before-function/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n\n    \"\"\"Return the mean of the given values.\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D201"]},{"location":"rules/blank-line-before-function/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D201"]},{"location":"rules/blank-line-between-methods/","title":"blank-line-between-methods (E301)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E301"]},{"location":"rules/blank-line-between-methods/#what-it-does","title":"What it does","text":"

        Checks for missing blank lines between methods of a class.

        ","tags":["E301"]},{"location":"rules/blank-line-between-methods/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends exactly one blank line between methods of a class.

        ","tags":["E301"]},{"location":"rules/blank-line-between-methods/#example","title":"Example","text":"
        class MyClass(object):\n    def func1():\n        pass\n    def func2():\n        pass\n

        Use instead:

        class MyClass(object):\n    def func1():\n        pass\n\n    def func2():\n        pass\n
        ","tags":["E301"]},{"location":"rules/blank-line-between-methods/#typing-stub-files-pyi","title":"Typing stub files (.pyi)","text":"

        The typing style guide recommends to not use blank lines between methods except to group them. That's why this rule is not enabled in typing stub files.

        ","tags":["E301"]},{"location":"rules/blank-line-between-methods/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        • Typing Style Guide
        ","tags":["E301"]},{"location":"rules/blank-line-with-whitespace/","title":"blank-line-with-whitespace (W293)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["W293"]},{"location":"rules/blank-line-with-whitespace/#what-it-does","title":"What it does","text":"

        Checks for superfluous whitespace in blank lines.

        ","tags":["W293"]},{"location":"rules/blank-line-with-whitespace/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"avoid trailing whitespace anywhere. Because it\u2019s usually invisible, it can be confusing\"

        ","tags":["W293"]},{"location":"rules/blank-line-with-whitespace/#example","title":"Example","text":"
        class Foo(object):\\n    \\n    bang = 12\n

        Use instead:

        class Foo(object):\\n\\n    bang = 12\n
        ","tags":["W293"]},{"location":"rules/blank-lines-after-function-or-class/","title":"blank-lines-after-function-or-class (E305)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E305"]},{"location":"rules/blank-lines-after-function-or-class/#what-it-does","title":"What it does","text":"

        Checks for missing blank lines after the end of function or class.

        ","tags":["E305"]},{"location":"rules/blank-lines-after-function-or-class/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends using blank lines as follows:

        • Two blank lines are expected between functions and classes
        • One blank line is expected between methods of a class.
        ","tags":["E305"]},{"location":"rules/blank-lines-after-function-or-class/#example","title":"Example","text":"
        class User(object):\n    pass\nuser = User()\n

        Use instead:

        class User(object):\n    pass\n\n\nuser = User()\n
        ","tags":["E305"]},{"location":"rules/blank-lines-after-function-or-class/#typing-stub-files-pyi","title":"Typing stub files (.pyi)","text":"

        The typing style guide recommends to not use blank lines between statements except to group them. That's why this rule is not enabled in typing stub files.

        ","tags":["E305"]},{"location":"rules/blank-lines-after-function-or-class/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        • Typing Style Guide
        ","tags":["E305"]},{"location":"rules/blank-lines-before-nested-definition/","title":"blank-lines-before-nested-definition (E306)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E306"]},{"location":"rules/blank-lines-before-nested-definition/#what-it-does","title":"What it does","text":"

        Checks for 1 blank line between nested function or class definitions.

        ","tags":["E306"]},{"location":"rules/blank-lines-before-nested-definition/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends using blank lines as follows:

        • Two blank lines are expected between functions and classes
        • One blank line is expected between methods of a class.
        ","tags":["E306"]},{"location":"rules/blank-lines-before-nested-definition/#example","title":"Example","text":"
        def outer():\n    def inner():\n        pass\n    def inner2():\n        pass\n

        Use instead:

        def outer():\n    def inner():\n        pass\n\n    def inner2():\n        pass\n
        ","tags":["E306"]},{"location":"rules/blank-lines-before-nested-definition/#typing-stub-files-pyi","title":"Typing stub files (.pyi)","text":"

        The typing style guide recommends to not use blank lines between classes and functions except to group them. That's why this rule is not enabled in typing stub files.

        ","tags":["E306"]},{"location":"rules/blank-lines-before-nested-definition/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        • Typing Style Guide
        ","tags":["E306"]},{"location":"rules/blank-lines-between-header-and-content/","title":"blank-lines-between-header-and-content (D412)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D412"]},{"location":"rules/blank-lines-between-header-and-content/#what-it-does","title":"What it does","text":"

        Checks for docstring sections that contain blank lines between a section header and a section body.

        ","tags":["D412"]},{"location":"rules/blank-lines-between-header-and-content/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline docstrings.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. There should be no blank lines between a section header and a section body.

        ","tags":["D412"]},{"location":"rules/blank-lines-between-header-and-content/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D412"]},{"location":"rules/blank-lines-between-header-and-content/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D412"]},{"location":"rules/blank-lines-top-level/","title":"blank-lines-top-level (E302)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#what-it-does","title":"What it does","text":"

        Checks for missing blank lines between top level functions and classes.

        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends exactly two blank lines between top level functions and classes.

        The rule respects the lint.isort.lines-after-imports setting when determining the required number of blank lines between top-level import statements and function or class definitions for compatibility with isort.

        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#example","title":"Example","text":"
        def func1():\n    pass\ndef func2():\n    pass\n

        Use instead:

        def func1():\n    pass\n\n\ndef func2():\n    pass\n
        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#typing-stub-files-pyi","title":"Typing stub files (.pyi)","text":"

        The typing style guide recommends to not use blank lines between classes and functions except to group them. That's why this rule is not enabled in typing stub files.

        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#options","title":"Options","text":"
        • lint.isort.lines-after-imports
        ","tags":["E302"]},{"location":"rules/blank-lines-top-level/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        • Typing Style Guide
        ","tags":["E302"]},{"location":"rules/blanket-noqa/","title":"blanket-noqa (PGH004)","text":"

        Derived from the pygrep-hooks linter.

        Fix is sometimes available.

        ","tags":["PGH004"]},{"location":"rules/blanket-noqa/#what-it-does","title":"What it does","text":"

        Check for noqa annotations that suppress all diagnostics, as opposed to targeting specific diagnostics.

        ","tags":["PGH004"]},{"location":"rules/blanket-noqa/#why-is-this-bad","title":"Why is this bad?","text":"

        Suppressing all diagnostics can hide issues in the code.

        Blanket noqa annotations are also more difficult to interpret and maintain, as the annotation does not clarify which diagnostics are intended to be suppressed.

        ","tags":["PGH004"]},{"location":"rules/blanket-noqa/#example","title":"Example","text":"
        from .base import *  # noqa\n

        Use instead:

        from .base import *  # noqa: F403\n
        ","tags":["PGH004"]},{"location":"rules/blanket-noqa/#fix-safety","title":"Fix safety","text":"

        This rule will attempt to fix blanket noqa annotations that appear to be unintentional. For example, given # noqa F401, the rule will suggest inserting a colon, as in # noqa: F401.

        While modifying noqa comments is generally safe, doing so may introduce additional diagnostics.

        ","tags":["PGH004"]},{"location":"rules/blanket-noqa/#references","title":"References","text":"
        • Ruff documentation
        ","tags":["PGH004"]},{"location":"rules/blanket-type-ignore/","title":"blanket-type-ignore (PGH003)","text":"

        Derived from the pygrep-hooks linter.

        ","tags":["PGH003"]},{"location":"rules/blanket-type-ignore/#what-it-does","title":"What it does","text":"

        Check for type: ignore annotations that suppress all type warnings, as opposed to targeting specific type warnings.

        ","tags":["PGH003"]},{"location":"rules/blanket-type-ignore/#why-is-this-bad","title":"Why is this bad?","text":"

        Suppressing all warnings can hide issues in the code.

        Blanket type: ignore annotations are also more difficult to interpret and maintain, as the annotation does not clarify which warnings are intended to be suppressed.

        ","tags":["PGH003"]},{"location":"rules/blanket-type-ignore/#example","title":"Example","text":"
        from foo import secrets  # type: ignore\n

        Use instead:

        from foo import secrets  # type: ignore[attr-defined]\n
        ","tags":["PGH003"]},{"location":"rules/blanket-type-ignore/#references","title":"References","text":"

        Mypy supports a built-in setting to enforce that all type: ignore annotations include an error code, akin to enabling this rule:

        [tool.mypy]\nenable_error_code = [\"ignore-without-code\"]\n
        ","tags":["PGH003"]},{"location":"rules/blind-except/","title":"blind-except (BLE001)","text":"

        Derived from the flake8-blind-except linter.

        ","tags":["BLE001"]},{"location":"rules/blind-except/#what-it-does","title":"What it does","text":"

        Checks for except clauses that catch all exceptions. This includes bare except, except BaseException and except Exception.

        ","tags":["BLE001"]},{"location":"rules/blind-except/#why-is-this-bad","title":"Why is this bad?","text":"

        Overly broad except clauses can lead to unexpected behavior, such as catching KeyboardInterrupt or SystemExit exceptions that prevent the user from exiting the program.

        Instead of catching all exceptions, catch only those that are expected to be raised in the try block.

        ","tags":["BLE001"]},{"location":"rules/blind-except/#example","title":"Example","text":"
        try:\n    foo()\nexcept BaseException:\n    ...\n

        Use instead:

        try:\n    foo()\nexcept FileNotFoundError:\n    ...\n

        Exceptions that are re-raised will not be flagged, as they're expected to be caught elsewhere:

        try:\n    foo()\nexcept BaseException:\n    raise\n

        Exceptions that are logged via logging.exception() or logging.error() with exc_info enabled will not be flagged, as this is a common pattern for propagating exception traces:

        try:\n    foo()\nexcept BaseException:\n    logging.exception(\"Something went wrong\")\n
        ","tags":["BLE001"]},{"location":"rules/blind-except/#references","title":"References","text":"
        • Python documentation: The try statement
        • Python documentation: Exception hierarchy
        • PEP 8: Programming Recommendations on bare except
        ","tags":["BLE001"]},{"location":"rules/blocking-http-call-in-async-function/","title":"blocking-http-call-in-async-function (ASYNC210)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC210"]},{"location":"rules/blocking-http-call-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not contain blocking HTTP calls.

        ","tags":["ASYNC210"]},{"location":"rules/blocking-http-call-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a blocking HTTP call will block the entire event loop, preventing it from executing other tasks while waiting for the HTTP response, negating the benefits of asynchronous programming.

        Instead of making a blocking HTTP call, use an asynchronous HTTP client library such as aiohttp or httpx.

        ","tags":["ASYNC210"]},{"location":"rules/blocking-http-call-in-async-function/#example","title":"Example","text":"
        async def fetch():\n    urllib.request.urlopen(\"https://example.com/foo/bar\").read()\n

        Use instead:

        async def fetch():\n    async with aiohttp.ClientSession() as session:\n        async with session.get(\"https://example.com/foo/bar\") as resp:\n            ...\n
        ","tags":["ASYNC210"]},{"location":"rules/blocking-open-call-in-async-function/","title":"blocking-open-call-in-async-function (ASYNC230)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC230"]},{"location":"rules/blocking-open-call-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not open files with blocking methods like open.

        ","tags":["ASYNC230"]},{"location":"rules/blocking-open-call-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a blocking call will block the entire event loop, preventing it from executing other tasks while waiting for the call to complete, negating the benefits of asynchronous programming.

        Instead of making a blocking call, use an equivalent asynchronous library or function.

        ","tags":["ASYNC230"]},{"location":"rules/blocking-open-call-in-async-function/#example","title":"Example","text":"
        async def foo():\n    with open(\"bar.txt\") as f:\n        contents = f.read()\n

        Use instead:

        import anyio\n\n\nasync def foo():\n    async with await anyio.open_file(\"bar.txt\") as f:\n        contents = await f.read()\n
        ","tags":["ASYNC230"]},{"location":"rules/blocking-sleep-in-async-function/","title":"blocking-sleep-in-async-function (ASYNC251)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC251"]},{"location":"rules/blocking-sleep-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not call time.sleep.

        ","tags":["ASYNC251"]},{"location":"rules/blocking-sleep-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a time.sleep call will block the entire event loop, preventing it from executing other tasks while waiting for the time.sleep, negating the benefits of asynchronous programming.

        Instead of time.sleep, use asyncio.sleep.

        ","tags":["ASYNC251"]},{"location":"rules/blocking-sleep-in-async-function/#example","title":"Example","text":"
        async def fetch():\n    time.sleep(1)\n

        Use instead:

        async def fetch():\n    await asyncio.sleep(1)\n
        ","tags":["ASYNC251"]},{"location":"rules/boolean-chained-comparison/","title":"boolean-chained-comparison (PLR1716)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLR1716"]},{"location":"rules/boolean-chained-comparison/#what-it-does","title":"What it does","text":"

        Check for chained boolean operations that can be simplified.

        ","tags":["PLR1716"]},{"location":"rules/boolean-chained-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Refactoring the code will improve readability for these cases.

        ","tags":["PLR1716"]},{"location":"rules/boolean-chained-comparison/#example","title":"Example","text":"
        a = int(input())\nb = int(input())\nc = int(input())\nif a < b and b < c:\n    pass\n

        Use instead:

        a = int(input())\nb = int(input())\nc = int(input())\nif a < b < c:\n    pass\n
        ","tags":["PLR1716"]},{"location":"rules/boolean-default-value-positional-argument/","title":"boolean-default-value-positional-argument (FBT002)","text":"

        Derived from the flake8-boolean-trap linter.

        ","tags":["FBT002"]},{"location":"rules/boolean-default-value-positional-argument/#what-it-does","title":"What it does","text":"

        Checks for the use of boolean positional arguments in function definitions, as determined by the presence of a boolean default value.

        ","tags":["FBT002"]},{"location":"rules/boolean-default-value-positional-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling a function with boolean positional arguments is confusing as the meaning of the boolean value is not clear to the caller and to future readers of the code.

        The use of a boolean will also limit the function to only two possible behaviors, which makes the function difficult to extend in the future.

        Instead, consider refactoring into separate implementations for the True and False cases, using an Enum, or making the argument a keyword-only argument, to force callers to be explicit when providing the argument.

        ","tags":["FBT002"]},{"location":"rules/boolean-default-value-positional-argument/#example","title":"Example","text":"
        from math import ceil, floor\n\n\ndef round_number(number, up=True):\n    return ceil(number) if up else floor(number)\n\n\nround_number(1.5, True)  # What does `True` mean?\nround_number(1.5, False)  # What does `False` mean?\n

        Instead, refactor into separate implementations:

        from math import ceil, floor\n\n\ndef round_up(number):\n    return ceil(number)\n\n\ndef round_down(number):\n    return floor(number)\n\n\nround_up(1.5)\nround_down(1.5)\n

        Or, refactor to use an Enum:

        from enum import Enum\n\n\nclass RoundingMethod(Enum):\n    UP = 1\n    DOWN = 2\n\n\ndef round_number(value, method):\n    return ceil(number) if method is RoundingMethod.UP else floor(number)\n\n\nround_number(1.5, RoundingMethod.UP)\nround_number(1.5, RoundingMethod.DOWN)\n

        Or, make the argument a keyword-only argument:

        from math import ceil, floor\n\n\ndef round_number(number, *, up=True):\n    return ceil(number) if up else floor(number)\n\n\nround_number(1.5, up=True)\nround_number(1.5, up=False)\n
        ","tags":["FBT002"]},{"location":"rules/boolean-default-value-positional-argument/#references","title":"References","text":"
        • Python documentation: Calls
        • How to Avoid \u201cThe Boolean Trap\u201d by Adam Johnson
        ","tags":["FBT002"]},{"location":"rules/boolean-positional-value-in-call/","title":"boolean-positional-value-in-call (FBT003)","text":"

        Derived from the flake8-boolean-trap linter.

        ","tags":["FBT003"]},{"location":"rules/boolean-positional-value-in-call/#what-it-does","title":"What it does","text":"

        Checks for boolean positional arguments in function calls.

        Some functions are whitelisted by default. To extend the list of allowed calls configure the lint.flake8-boolean-trap.extend-allowed-calls option.

        ","tags":["FBT003"]},{"location":"rules/boolean-positional-value-in-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling a function with boolean positional arguments is confusing as the meaning of the boolean value is not clear to the caller, and to future readers of the code.

        ","tags":["FBT003"]},{"location":"rules/boolean-positional-value-in-call/#example","title":"Example","text":"
        def func(flag: bool) -> None: ...\n\n\nfunc(True)\n

        Use instead:

        def func(flag: bool) -> None: ...\n\n\nfunc(flag=True)\n
        ","tags":["FBT003"]},{"location":"rules/boolean-positional-value-in-call/#options","title":"Options","text":"
        • lint.flake8-boolean-trap.extend-allowed-calls
        ","tags":["FBT003"]},{"location":"rules/boolean-positional-value-in-call/#references","title":"References","text":"
        • Python documentation: Calls
        • How to Avoid \u201cThe Boolean Trap\u201d by Adam Johnson
        ","tags":["FBT003"]},{"location":"rules/boolean-type-hint-positional-argument/","title":"boolean-type-hint-positional-argument (FBT001)","text":"

        Derived from the flake8-boolean-trap linter.

        ","tags":["FBT001"]},{"location":"rules/boolean-type-hint-positional-argument/#what-it-does","title":"What it does","text":"

        Checks for the use of boolean positional arguments in function definitions, as determined by the presence of a bool type hint.

        ","tags":["FBT001"]},{"location":"rules/boolean-type-hint-positional-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling a function with boolean positional arguments is confusing as the meaning of the boolean value is not clear to the caller and to future readers of the code.

        The use of a boolean will also limit the function to only two possible behaviors, which makes the function difficult to extend in the future.

        Instead, consider refactoring into separate implementations for the True and False cases, using an Enum, or making the argument a keyword-only argument, to force callers to be explicit when providing the argument.

        Dunder methods that define operators are exempt from this rule, as are setters and @override definitions.

        In preview, this rule will also flag annotations that include boolean variants, like bool | int.

        ","tags":["FBT001"]},{"location":"rules/boolean-type-hint-positional-argument/#example","title":"Example","text":"
        from math import ceil, floor\n\n\ndef round_number(number: float, up: bool) -> int:\n    return ceil(number) if up else floor(number)\n\n\nround_number(1.5, True)  # What does `True` mean?\nround_number(1.5, False)  # What does `False` mean?\n

        Instead, refactor into separate implementations:

        from math import ceil, floor\n\n\ndef round_up(number: float) -> int:\n    return ceil(number)\n\n\ndef round_down(number: float) -> int:\n    return floor(number)\n\n\nround_up(1.5)\nround_down(1.5)\n

        Or, refactor to use an Enum:

        from enum import Enum\n\n\nclass RoundingMethod(Enum):\n    UP = 1\n    DOWN = 2\n\n\ndef round_number(value: float, method: RoundingMethod) -> float: ...\n

        Or, make the argument a keyword-only argument:

        from math import ceil, floor\n\n\ndef round_number(number: float, *, up: bool) -> int:\n    return ceil(number) if up else floor(number)\n\n\nround_number(1.5, up=True)\nround_number(1.5, up=False)\n
        ","tags":["FBT001"]},{"location":"rules/boolean-type-hint-positional-argument/#references","title":"References","text":"
        • Python documentation: Calls
        • How to Avoid \u201cThe Boolean Trap\u201d by Adam Johnson
        ","tags":["FBT001"]},{"location":"rules/break-outside-loop/","title":"break-outside-loop (F701)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F701"]},{"location":"rules/break-outside-loop/#what-it-does","title":"What it does","text":"

        Checks for break statements outside of loops.

        ","tags":["F701"]},{"location":"rules/break-outside-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of a break statement outside of a for or while loop will raise a SyntaxError.

        ","tags":["F701"]},{"location":"rules/break-outside-loop/#example","title":"Example","text":"
        def foo():\n    break\n
        ","tags":["F701"]},{"location":"rules/break-outside-loop/#references","title":"References","text":"
        • Python documentation: break
        ","tags":["F701"]},{"location":"rules/builtin-argument-shadowing/","title":"builtin-argument-shadowing (A002)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A002"]},{"location":"rules/builtin-argument-shadowing/#what-it-does","title":"What it does","text":"

        Checks for function arguments that use the same names as builtins.

        ","tags":["A002"]},{"location":"rules/builtin-argument-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a builtin name for the name of an argument increases the difficulty of reading and maintaining the code, and can cause non-obvious errors, as readers may mistake the argument for the builtin and vice versa.

        Builtins can be marked as exceptions to this rule via the lint.flake8-builtins.ignorelist configuration option.

        ","tags":["A002"]},{"location":"rules/builtin-argument-shadowing/#example","title":"Example","text":"
        def remove_duplicates(list, list2):\n    result = set()\n    for value in list:\n        result.add(value)\n    for value in list2:\n        result.add(value)\n    return list(result)  # TypeError: 'list' object is not callable\n

        Use instead:

        def remove_duplicates(list1, list2):\n    result = set()\n    for value in list1:\n        result.add(value)\n    for value in list2:\n        result.add(value)\n    return list(result)\n
        ","tags":["A002"]},{"location":"rules/builtin-argument-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.ignorelist
        ","tags":["A002"]},{"location":"rules/builtin-argument-shadowing/#references","title":"References","text":"
        • Is it bad practice to use a built-in function name as an attribute or method identifier?
        • Why is it a bad idea to name a variable id in Python?
        ","tags":["A002"]},{"location":"rules/builtin-attribute-shadowing/","title":"builtin-attribute-shadowing (A003)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A003"]},{"location":"rules/builtin-attribute-shadowing/#what-it-does","title":"What it does","text":"

        Checks for class attributes and methods that use the same names as Python builtins.

        ","tags":["A003"]},{"location":"rules/builtin-attribute-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a builtin name for the name of an attribute increases the difficulty of reading and maintaining the code, and can cause non-obvious errors, as readers may mistake the attribute for the builtin and vice versa.

        Since methods and class attributes typically cannot be referenced directly from outside the class scope, this rule only applies to those methods and attributes that both shadow a builtin and are referenced from within the class scope, as in the following example, where the list[int] return type annotation resolves to the list method, rather than the builtin:

        class Class:\n    @staticmethod\n    def list() -> None:\n        pass\n\n    @staticmethod\n    def repeat(value: int, times: int) -> list[int]:\n        return [value] * times\n

        Builtins can be marked as exceptions to this rule via the lint.flake8-builtins.ignorelist configuration option, or converted to the appropriate dunder method. Methods decorated with @typing.override or @typing_extensions.override are also ignored.

        ","tags":["A003"]},{"location":"rules/builtin-attribute-shadowing/#example","title":"Example","text":"
        class Class:\n    @staticmethod\n    def list() -> None:\n        pass\n\n    @staticmethod\n    def repeat(value: int, times: int) -> list[int]:\n        return [value] * times\n
        ","tags":["A003"]},{"location":"rules/builtin-attribute-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.ignorelist
        ","tags":["A003"]},{"location":"rules/builtin-import-shadowing/","title":"builtin-import-shadowing (A004)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A004"]},{"location":"rules/builtin-import-shadowing/#what-it-does","title":"What it does","text":"

        Checks for imports that use the same names as builtins.

        ","tags":["A004"]},{"location":"rules/builtin-import-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a builtin for the name of an import increases the difficulty of reading and maintaining the code, and can cause non-obvious errors, as readers may mistake the variable for the builtin and vice versa.

        Builtins can be marked as exceptions to this rule via the lint.flake8-builtins.ignorelist configuration option.

        ","tags":["A004"]},{"location":"rules/builtin-import-shadowing/#example","title":"Example","text":"
        from rich import print\n\nprint(\"Some message\")\n

        Use instead:

        from rich import print as rich_print\n\nrich_print(\"Some message\")\n

        or:

        import rich\n\nrich.print(\"Some message\")\n
        ","tags":["A004"]},{"location":"rules/builtin-import-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.ignorelist
        • target-version
        ","tags":["A004"]},{"location":"rules/builtin-lambda-argument-shadowing/","title":"builtin-lambda-argument-shadowing (A006)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A006"]},{"location":"rules/builtin-lambda-argument-shadowing/#what-it-does","title":"What it does","text":"

        Checks for lambda arguments that use the same names as Python builtins.

        ","tags":["A006"]},{"location":"rules/builtin-lambda-argument-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a builtin name for the name of a lambda argument increases the difficulty of reading and maintaining the code and can cause non-obvious errors. Readers may mistake the variable for the builtin, and vice versa.

        Builtins can be marked as exceptions to this rule via the lint.flake8-builtins.ignorelist configuration option.

        ","tags":["A006"]},{"location":"rules/builtin-lambda-argument-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.ignorelist
        ","tags":["A006"]},{"location":"rules/builtin-open/","title":"builtin-open (PTH123)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH123"]},{"location":"rules/builtin-open/#what-it-does","title":"What it does","text":"

        Checks for uses of the open() builtin.

        ","tags":["PTH123"]},{"location":"rules/builtin-open/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation. When possible, using Path object methods such as Path.open() can improve readability over the open builtin.

        ","tags":["PTH123"]},{"location":"rules/builtin-open/#examples","title":"Examples","text":"
        with open(\"f1.py\", \"wb\") as fp:\n    ...\n

        Use instead:

        from pathlib import Path\n\nwith Path(\"f1.py\").open(\"wb\") as fp:\n    ...\n
        ","tags":["PTH123"]},{"location":"rules/builtin-open/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than working directly with strings, especially on older versions of Python.

        ","tags":["PTH123"]},{"location":"rules/builtin-open/#references","title":"References","text":"
        • Python documentation: Path.open
        • Python documentation: open
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH123"]},{"location":"rules/builtin-variable-shadowing/","title":"builtin-variable-shadowing (A001)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A001"]},{"location":"rules/builtin-variable-shadowing/#what-it-does","title":"What it does","text":"

        Checks for variable (and function) assignments that use the same names as builtins.

        ","tags":["A001"]},{"location":"rules/builtin-variable-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a builtin name for the name of a variable increases the difficulty of reading and maintaining the code, and can cause non-obvious errors, as readers may mistake the variable for the builtin and vice versa.

        Builtins can be marked as exceptions to this rule via the lint.flake8-builtins.ignorelist configuration option.

        ","tags":["A001"]},{"location":"rules/builtin-variable-shadowing/#example","title":"Example","text":"
        def find_max(list_of_lists):\n    max = 0\n    for flat_list in list_of_lists:\n        for value in flat_list:\n            max = max(max, value)  # TypeError: 'int' object is not callable\n    return max\n

        Use instead:

        def find_max(list_of_lists):\n    result = 0\n    for flat_list in list_of_lists:\n        for value in flat_list:\n            result = max(result, value)\n    return result\n
        ","tags":["A001"]},{"location":"rules/builtin-variable-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.ignorelist
        ","tags":["A001"]},{"location":"rules/builtin-variable-shadowing/#references","title":"References","text":"
        • Why is it a bad idea to name a variable id in Python?
        ","tags":["A001"]},{"location":"rules/byte-string-usage/","title":"byte-string-usage (PYI057)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI057"]},{"location":"rules/byte-string-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of typing.ByteString or collections.abc.ByteString.

        ","tags":["PYI057"]},{"location":"rules/byte-string-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        ByteString has been deprecated since Python 3.9 and will be removed in Python 3.14. The Python documentation recommends using either collections.abc.Buffer (or the typing_extensions backport on Python \\<3.12) or a union like bytes | bytearray | memoryview instead.

        ","tags":["PYI057"]},{"location":"rules/byte-string-usage/#example","title":"Example","text":"
        from typing import ByteString\n

        Use instead:

        from collections.abc import Buffer\n
        ","tags":["PYI057"]},{"location":"rules/byte-string-usage/#references","title":"References","text":"
        • Python documentation: The ByteString type
        ","tags":["PYI057"]},{"location":"rules/cached-instance-method/","title":"cached-instance-method (B019)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B019"]},{"location":"rules/cached-instance-method/#what-it-does","title":"What it does","text":"

        Checks for uses of the functools.lru_cache and functools.cache decorators on methods.

        ","tags":["B019"]},{"location":"rules/cached-instance-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Using the functools.lru_cache and functools.cache decorators on methods can lead to memory leaks, as the global cache will retain a reference to the instance, preventing it from being garbage collected.

        Instead, refactor the method to depend only on its arguments and not on the instance of the class, or use the @lru_cache decorator on a function outside of the class.

        This rule ignores instance methods on enumeration classes, as enum members are singletons.

        ","tags":["B019"]},{"location":"rules/cached-instance-method/#example","title":"Example","text":"
        from functools import lru_cache\n\n\ndef square(x: int) -> int:\n    return x * x\n\n\nclass Number:\n    value: int\n\n    @lru_cache\n    def squared(self):\n        return square(self.value)\n

        Use instead:

        from functools import lru_cache\n\n\n@lru_cache\ndef square(x: int) -> int:\n    return x * x\n\n\nclass Number:\n    value: int\n\n    def squared(self):\n        return square(self.value)\n
        ","tags":["B019"]},{"location":"rules/cached-instance-method/#references","title":"References","text":"
        • Python documentation: functools.lru_cache
        • Python documentation: functools.cache
        • don't lru_cache methods!
        ","tags":["B019"]},{"location":"rules/call-date-fromtimestamp/","title":"call-date-fromtimestamp (DTZ012)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ012"]},{"location":"rules/call-date-fromtimestamp/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.date.fromtimestamp().

        ","tags":["DTZ012"]},{"location":"rules/call-date-fromtimestamp/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.date.fromtimestamp(ts) returns a naive datetime object. Instead, use datetime.datetime.fromtimestamp(ts, tz=...) to create a timezone-aware object.

        ","tags":["DTZ012"]},{"location":"rules/call-date-fromtimestamp/#example","title":"Example","text":"
        import datetime\n\ndatetime.date.fromtimestamp(946684800)\n

        Use instead:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.timezone.utc)\n

        Or, for Python 3.11 and later:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.UTC)\n
        ","tags":["DTZ012"]},{"location":"rules/call-date-fromtimestamp/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ012"]},{"location":"rules/call-date-today/","title":"call-date-today (DTZ011)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ011"]},{"location":"rules/call-date-today/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.date.today().

        ","tags":["DTZ011"]},{"location":"rules/call-date-today/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.date.today returns a naive datetime object. Instead, use datetime.datetime.now(tz=...).date() to create a timezone-aware object.

        ","tags":["DTZ011"]},{"location":"rules/call-date-today/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.today()\n

        Use instead:

        import datetime\n\ndatetime.datetime.now(tz=datetime.timezone.utc).date()\n

        Or, for Python 3.11 and later:

        import datetime\n\ndatetime.datetime.now(tz=datetime.UTC).date()\n
        ","tags":["DTZ011"]},{"location":"rules/call-date-today/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ011"]},{"location":"rules/call-datetime-fromtimestamp/","title":"call-datetime-fromtimestamp (DTZ006)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ006"]},{"location":"rules/call-datetime-fromtimestamp/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.datetime.fromtimestamp() that do not specify a timezone.

        ","tags":["DTZ006"]},{"location":"rules/call-datetime-fromtimestamp/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.datetime.fromtimestamp(ts) or datetime.datetime.fromtimestampe(ts, tz=None) returns a naive datetime object. Instead, use datetime.datetime.fromtimestamp(ts, tz=<timezone>) to create a timezone-aware object.

        ","tags":["DTZ006"]},{"location":"rules/call-datetime-fromtimestamp/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.fromtimestamp(946684800)\n

        Use instead:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.timezone.utc)\n

        Or, on Python 3.11 and later:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.UTC)\n
        ","tags":["DTZ006"]},{"location":"rules/call-datetime-fromtimestamp/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ006"]},{"location":"rules/call-datetime-now-without-tzinfo/","title":"call-datetime-now-without-tzinfo (DTZ005)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ005"]},{"location":"rules/call-datetime-now-without-tzinfo/#what-it-does","title":"What it does","text":"

        Checks for usages of datetime.datetime.now() that do not specify a timezone.

        ","tags":["DTZ005"]},{"location":"rules/call-datetime-now-without-tzinfo/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.datetime.now() or datetime.datetime.now(tz=None) returns a naive datetime object. Instead, use datetime.datetime.now(tz=<timezone>) to create a timezone-aware object.

        ","tags":["DTZ005"]},{"location":"rules/call-datetime-now-without-tzinfo/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.now()\n

        Use instead:

        import datetime\n\ndatetime.datetime.now(tz=datetime.timezone.utc)\n

        Or, for Python 3.11 and later:

        import datetime\n\ndatetime.datetime.now(tz=datetime.UTC)\n
        ","tags":["DTZ005"]},{"location":"rules/call-datetime-now-without-tzinfo/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ005"]},{"location":"rules/call-datetime-strptime-without-zone/","title":"call-datetime-strptime-without-zone (DTZ007)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ007"]},{"location":"rules/call-datetime-strptime-without-zone/#what-it-does","title":"What it does","text":"

        Checks for uses of datetime.datetime.strptime() that lead to naive datetime objects.

        ","tags":["DTZ007"]},{"location":"rules/call-datetime-strptime-without-zone/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.datetime.strptime() without %z returns a naive datetime object. Follow it with .replace(tzinfo=<timezone>) or .astimezone().

        ","tags":["DTZ007"]},{"location":"rules/call-datetime-strptime-without-zone/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.strptime(\"2022/01/31\", \"%Y/%m/%d\")\n

        Instead, use .replace(tzinfo=<timezone>):

        import datetime\n\ndatetime.datetime.strptime(\"2022/01/31\", \"%Y/%m/%d\").replace(\n    tzinfo=datetime.timezone.utc\n)\n

        Or, use .astimezone():

        import datetime\n\ndatetime.datetime.strptime(\"2022/01/31\", \"%Y/%m/%d\").astimezone(datetime.timezone.utc)\n

        On Python 3.11 and later, datetime.timezone.utc can be replaced with datetime.UTC.

        ","tags":["DTZ007"]},{"location":"rules/call-datetime-strptime-without-zone/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        • Python documentation: strftime() and strptime() Behavior
        ","tags":["DTZ007"]},{"location":"rules/call-datetime-today/","title":"call-datetime-today (DTZ002)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ002"]},{"location":"rules/call-datetime-today/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.datetime.today().

        ","tags":["DTZ002"]},{"location":"rules/call-datetime-today/#why-is-this-bad","title":"Why is this bad?","text":"

        datetime objects are \"naive\" by default, in that they do not include timezone information. \"Naive\" objects are easy to understand, but ignore some aspects of reality, which can lead to subtle bugs. Timezone-aware datetime objects are preferred, as they represent a specific moment in time, unlike \"naive\" objects.

        datetime.datetime.today() creates a \"naive\" object; instead, use datetime.datetime.now(tz=...) to create a timezone-aware object.

        ","tags":["DTZ002"]},{"location":"rules/call-datetime-today/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.today()\n

        Use instead:

        import datetime\n\ndatetime.datetime.now(tz=datetime.timezone.utc)\n

        Or, for Python 3.11 and later:

        import datetime\n\ndatetime.datetime.now(tz=datetime.UTC)\n
        ","tags":["DTZ002"]},{"location":"rules/call-datetime-utcfromtimestamp/","title":"call-datetime-utcfromtimestamp (DTZ004)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ004"]},{"location":"rules/call-datetime-utcfromtimestamp/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.datetime.utcfromtimestamp().

        ","tags":["DTZ004"]},{"location":"rules/call-datetime-utcfromtimestamp/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.datetime.utcfromtimestamp() returns a naive datetime object; instead, use datetime.datetime.fromtimestamp(ts, tz=...) to create a timezone-aware object.

        ","tags":["DTZ004"]},{"location":"rules/call-datetime-utcfromtimestamp/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.utcfromtimestamp(946684800)\n

        Use instead:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.timezone.utc)\n

        Or, on Python 3.11 and later:

        import datetime\n\ndatetime.datetime.fromtimestamp(946684800, tz=datetime.UTC)\n
        ","tags":["DTZ004"]},{"location":"rules/call-datetime-utcfromtimestamp/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ004"]},{"location":"rules/call-datetime-utcnow/","title":"call-datetime-utcnow (DTZ003)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ003"]},{"location":"rules/call-datetime-utcnow/#what-it-does","title":"What it does","text":"

        Checks for usage of datetime.datetime.utcnow().

        ","tags":["DTZ003"]},{"location":"rules/call-datetime-utcnow/#why-is-this-bad","title":"Why is this bad?","text":"

        Python datetime objects can be naive or timezone-aware. While an aware object represents a specific moment in time, a naive object does not contain enough information to unambiguously locate itself relative to other datetime objects. Since this can lead to errors, it is recommended to always use timezone-aware objects.

        datetime.datetime.utcnow() returns a naive datetime object; instead, use datetime.datetime.now(tz=...) to create a timezone-aware object.

        ","tags":["DTZ003"]},{"location":"rules/call-datetime-utcnow/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime.utcnow()\n

        Use instead:

        import datetime\n\ndatetime.datetime.now(tz=datetime.timezone.utc)\n

        Or, for Python 3.11 and later:

        import datetime\n\ndatetime.datetime.now(tz=datetime.UTC)\n
        ","tags":["DTZ003"]},{"location":"rules/call-datetime-utcnow/#references","title":"References","text":"
        • Python documentation: Aware and Naive Objects
        ","tags":["DTZ003"]},{"location":"rules/call-datetime-without-tzinfo/","title":"call-datetime-without-tzinfo (DTZ001)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ001"]},{"location":"rules/call-datetime-without-tzinfo/#what-it-does","title":"What it does","text":"

        Checks for datetime instantiations that do not specify a timezone.

        ","tags":["DTZ001"]},{"location":"rules/call-datetime-without-tzinfo/#why-is-this-bad","title":"Why is this bad?","text":"

        datetime objects are \"naive\" by default, in that they do not include timezone information. \"Naive\" objects are easy to understand, but ignore some aspects of reality, which can lead to subtle bugs. Timezone-aware datetime objects are preferred, as they represent a specific moment in time, unlike \"naive\" objects.

        By providing a non-None value for tzinfo, a datetime can be made timezone-aware.

        ","tags":["DTZ001"]},{"location":"rules/call-datetime-without-tzinfo/#example","title":"Example","text":"
        import datetime\n\ndatetime.datetime(2000, 1, 1, 0, 0, 0)\n

        Use instead:

        import datetime\n\ndatetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)\n

        Or, on Python 3.11 and later:

        import datetime\n\ndatetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=datetime.UTC)\n
        ","tags":["DTZ001"]},{"location":"rules/call-with-shell-equals-true/","title":"call-with-shell-equals-true (S604)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S604"]},{"location":"rules/call-with-shell-equals-true/#what-it-does","title":"What it does","text":"

        Checks for method calls that set the shell parameter to true or another truthy value when invoking a subprocess.

        ","tags":["S604"]},{"location":"rules/call-with-shell-equals-true/#why-is-this-bad","title":"Why is this bad?","text":"

        Setting the shell parameter to true or another truthy value when invoking a subprocess can introduce security vulnerabilities, as it allows shell metacharacters and whitespace to be passed to child processes, potentially leading to shell injection attacks.

        It is recommended to avoid using shell=True unless absolutely necessary and, when used, to ensure that all inputs are properly sanitized and quoted to prevent such vulnerabilities.

        ","tags":["S604"]},{"location":"rules/call-with-shell-equals-true/#known-problems","title":"Known problems","text":"

        Prone to false positives as it is triggered on any function call with a shell=True parameter.

        ","tags":["S604"]},{"location":"rules/call-with-shell-equals-true/#example","title":"Example","text":"
        import subprocess\n\nuser_input = input(\"Enter a command: \")\nsubprocess.run(user_input, shell=True)\n
        ","tags":["S604"]},{"location":"rules/call-with-shell-equals-true/#references","title":"References","text":"
        • Python documentation: Security Considerations
        ","tags":["S604"]},{"location":"rules/camelcase-imported-as-acronym/","title":"camelcase-imported-as-acronym (N817)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N817"]},{"location":"rules/camelcase-imported-as-acronym/#what-it-does","title":"What it does","text":"

        Checks for CamelCase imports that are aliased as acronyms.

        ","tags":["N817"]},{"location":"rules/camelcase-imported-as-acronym/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends naming conventions for classes, functions, constants, and more. The use of inconsistent naming styles between import and alias names may lead readers to expect an import to be of another type (e.g., confuse a Python class with a constant).

        Import aliases should thus follow the same naming style as the member being imported.

        Note that this rule is distinct from camelcase-imported-as-constant to accommodate selective enforcement.

        Also note that import aliases following an import convention according to the lint.flake8-import-conventions.aliases option are allowed.

        ","tags":["N817"]},{"location":"rules/camelcase-imported-as-acronym/#example","title":"Example","text":"
        from example import MyClassName as MCN\n

        Use instead:

        from example import MyClassName\n
        ","tags":["N817"]},{"location":"rules/camelcase-imported-as-acronym/#options","title":"Options","text":"
        • lint.flake8-import-conventions.aliases
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N817"]},{"location":"rules/camelcase-imported-as-constant/","title":"camelcase-imported-as-constant (N814)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-constant/#what-it-does","title":"What it does","text":"

        Checks for CamelCase imports that are aliased to constant-style names.

        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends naming conventions for classes, functions, constants, and more. The use of inconsistent naming styles between import and alias names may lead readers to expect an import to be of another type (e.g., confuse a Python class with a constant).

        Import aliases should thus follow the same naming style as the member being imported.

        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-constant/#example","title":"Example","text":"
        from example import MyClassName as MY_CLASS_NAME\n

        Use instead:

        from example import MyClassName\n
        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-constant/#note","title":"Note","text":"

        Identifiers consisting of a single uppercase character are ambiguous under the rules of PEP 8, which specifies CamelCase for classes and ALL_CAPS_SNAKE_CASE for constants. Without a second character, it is not possible to reliably guess whether the identifier is intended to be part of a CamelCase string for a class or an ALL_CAPS_SNAKE_CASE string for a constant, since both conventions will produce the same output when given a single input character. Therefore, this lint rule does not apply to cases where the alias for the imported identifier consists of a single uppercase character.

        A common example of a single uppercase character being used for a class name can be found in Django's django.db.models.Q class.

        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-constant/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N814"]},{"location":"rules/camelcase-imported-as-lowercase/","title":"camelcase-imported-as-lowercase (N813)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N813"]},{"location":"rules/camelcase-imported-as-lowercase/#what-it-does","title":"What it does","text":"

        Checks for CamelCase imports that are aliased to lowercase names.

        ","tags":["N813"]},{"location":"rules/camelcase-imported-as-lowercase/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends naming conventions for classes, functions, constants, and more. The use of inconsistent naming styles between import and alias names may lead readers to expect an import to be of another type (e.g., confuse a Python class with a constant).

        Import aliases should thus follow the same naming style as the member being imported.

        ","tags":["N813"]},{"location":"rules/camelcase-imported-as-lowercase/#example","title":"Example","text":"
        from example import MyClassName as myclassname\n

        Use instead:

        from example import MyClassName\n
        ","tags":["N813"]},{"location":"rules/camelcase-imported-as-lowercase/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N813"]},{"location":"rules/cancel-scope-no-checkpoint/","title":"cancel-scope-no-checkpoint (ASYNC100)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC100"]},{"location":"rules/cancel-scope-no-checkpoint/#what-it-does","title":"What it does","text":"

        Checks for timeout context managers which do not contain a checkpoint.

        For the purposes of this check, yield is considered a checkpoint, since checkpoints may occur in the caller to which we yield.

        ","tags":["ASYNC100"]},{"location":"rules/cancel-scope-no-checkpoint/#why-is-this-bad","title":"Why is this bad?","text":"

        Some asynchronous context managers, such as asyncio.timeout and trio.move_on_after, have no effect unless they contain a checkpoint. The use of such context managers without an await, async with or async for statement is likely a mistake.

        ","tags":["ASYNC100"]},{"location":"rules/cancel-scope-no-checkpoint/#example","title":"Example","text":"
        async def func():\n    async with asyncio.timeout(2):\n        do_something()\n

        Use instead:

        async def func():\n    async with asyncio.timeout(2):\n        do_something()\n        await awaitable()\n
        ","tags":["ASYNC100"]},{"location":"rules/cancel-scope-no-checkpoint/#references","title":"References","text":"
        • asyncio timeouts
        • anyio timeouts
        • trio timeouts
        ","tags":["ASYNC100"]},{"location":"rules/check-and-remove-from-set/","title":"check-and-remove-from-set (FURB132)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB132"]},{"location":"rules/check-and-remove-from-set/#what-it-does","title":"What it does","text":"

        Checks for uses of set.remove that can be replaced with set.discard.

        ","tags":["FURB132"]},{"location":"rules/check-and-remove-from-set/#why-is-this-bad","title":"Why is this bad?","text":"

        If an element should be removed from a set if it is present, it is more succinct and idiomatic to use discard.

        ","tags":["FURB132"]},{"location":"rules/check-and-remove-from-set/#known-problems","title":"Known problems","text":"

        This rule is prone to false negatives due to type inference limitations, as it will only detect sets that are instantiated as literals or annotated with a type annotation.

        ","tags":["FURB132"]},{"location":"rules/check-and-remove-from-set/#example","title":"Example","text":"
        nums = {123, 456}\n\nif 123 in nums:\n    nums.remove(123)\n

        Use instead:

        nums = {123, 456}\n\nnums.discard(123)\n
        ","tags":["FURB132"]},{"location":"rules/check-and-remove-from-set/#references","title":"References","text":"
        • Python documentation: set.discard()
        ","tags":["FURB132"]},{"location":"rules/class-as-data-structure/","title":"class-as-data-structure (B903)","text":"

        Derived from the flake8-bugbear linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["B903"]},{"location":"rules/class-as-data-structure/#what-it-does","title":"What it does","text":"

        Checks for classes that only have a public __init__ method, without base classes and decorators.

        ","tags":["B903"]},{"location":"rules/class-as-data-structure/#why-is-this-bad","title":"Why is this bad?","text":"

        Classes with just an __init__ are possibly better off being a dataclass or a namedtuple, which have less boilerplate.

        ","tags":["B903"]},{"location":"rules/class-as-data-structure/#example","title":"Example","text":"
        class Point:\n    def __init__(self, x: float, y: float):\n        self.x = x\n        self.y = y\n

        Use instead:

        from dataclasses import dataclass\n\n\n@dataclass\nclass Point:\n    x: float\n    y: float\n
        ","tags":["B903"]},{"location":"rules/class-with-mixed-type-vars/","title":"class-with-mixed-type-vars (RUF053)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF053"]},{"location":"rules/class-with-mixed-type-vars/#what-it-does","title":"What it does","text":"

        Checks for classes that have PEP 695 while also inheriting from typing.Generic or typing_extensions.Generic.

        ","tags":["RUF053"]},{"location":"rules/class-with-mixed-type-vars/#why-is-this-bad","title":"Why is this bad?","text":"

        Such classes cause errors at runtime:

        from typing import Generic, TypeVar\n\nU = TypeVar(\"U\")\n\n# TypeError: Cannot inherit from Generic[...] multiple times.\nclass C[T](Generic[U]): ...\n
        ","tags":["RUF053"]},{"location":"rules/class-with-mixed-type-vars/#example","title":"Example","text":"
        from typing import Generic, ParamSpec, TypeVar, TypeVarTuple\n\nU = TypeVar(\"U\")\nP = ParamSpec(\"P\")\nTs = TypeVarTuple(\"Ts\")\n\n\nclass C[T](Generic[U, P, *Ts]): ...\n

        Use instead:

        class C[T, U, **P, *Ts]: ...\n
        ","tags":["RUF053"]},{"location":"rules/class-with-mixed-type-vars/#fix-safety","title":"Fix safety","text":"

        As the fix changes runtime behaviour, it is always marked as unsafe. Additionally, comments within the fix range will not be preserved.

        ","tags":["RUF053"]},{"location":"rules/class-with-mixed-type-vars/#references","title":"References","text":"
        • Python documentation: User-defined generic types
        • Python documentation: type parameter lists
        • PEP 695 - Type Parameter Syntax
        ","tags":["RUF053"]},{"location":"rules/collapsible-else-if/","title":"collapsible-else-if (PLR5501)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLR5501"]},{"location":"rules/collapsible-else-if/#what-it-does","title":"What it does","text":"

        Checks for else blocks that consist of a single if statement.

        ","tags":["PLR5501"]},{"location":"rules/collapsible-else-if/#why-is-this-bad","title":"Why is this bad?","text":"

        If an else block contains a single if statement, it can be collapsed into an elif, thus reducing the indentation level.

        ","tags":["PLR5501"]},{"location":"rules/collapsible-else-if/#example","title":"Example","text":"
        def check_sign(value: int) -> None:\n    if value > 0:\n        print(\"Number is positive.\")\n    else:\n        if value < 0:\n            print(\"Number is negative.\")\n        else:\n            print(\"Number is zero.\")\n

        Use instead:

        def check_sign(value: int) -> None:\n    if value > 0:\n        print(\"Number is positive.\")\n    elif value < 0:\n        print(\"Number is negative.\")\n    else:\n        print(\"Number is zero.\")\n
        ","tags":["PLR5501"]},{"location":"rules/collapsible-else-if/#references","title":"References","text":"
        • Python documentation: if Statements
        ","tags":["PLR5501"]},{"location":"rules/collapsible-if/","title":"collapsible-if (SIM102)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM102"]},{"location":"rules/collapsible-if/#what-it-does","title":"What it does","text":"

        Checks for nested if statements that can be collapsed into a single if statement.

        ","tags":["SIM102"]},{"location":"rules/collapsible-if/#why-is-this-bad","title":"Why is this bad?","text":"

        Nesting if statements leads to deeper indentation and makes code harder to read. Instead, combine the conditions into a single if statement with an and operator.

        ","tags":["SIM102"]},{"location":"rules/collapsible-if/#example","title":"Example","text":"
        if foo:\n    if bar:\n        ...\n

        Use instead:

        if foo and bar:\n    ...\n
        ","tags":["SIM102"]},{"location":"rules/collapsible-if/#references","title":"References","text":"
        • Python documentation: The if statement
        • Python documentation: Boolean operations
        ","tags":["SIM102"]},{"location":"rules/collection-literal-concatenation/","title":"collection-literal-concatenation (RUF005)","text":"

        Fix is sometimes available.

        ","tags":["RUF005"]},{"location":"rules/collection-literal-concatenation/#what-it-does","title":"What it does","text":"

        Checks for uses of the + operator to concatenate collections.

        ","tags":["RUF005"]},{"location":"rules/collection-literal-concatenation/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the + operator can be used to concatenate collections (e.g., x + y to concatenate the lists x and y).

        However, collections can be concatenated more efficiently using the unpacking operator (e.g., [*x, *y] to concatenate x and y).

        Prefer the unpacking operator to concatenate collections, as it is more readable and flexible. The * operator can unpack any iterable, whereas + operates only on particular sequences which, in many cases, must be of the same type.

        ","tags":["RUF005"]},{"location":"rules/collection-literal-concatenation/#example","title":"Example","text":"
        foo = [2, 3, 4]\nbar = [1] + foo + [5, 6]\n

        Use instead:

        foo = [2, 3, 4]\nbar = [1, *foo, 5, 6]\n
        ","tags":["RUF005"]},{"location":"rules/collection-literal-concatenation/#fix-safety","title":"Fix safety","text":"

        The fix is always marked as unsafe because the + operator uses the __add__ magic method and *-unpacking uses the __iter__ magic method. Both of these could have custom implementations, causing the fix to change program behaviour.

        ","tags":["RUF005"]},{"location":"rules/collection-literal-concatenation/#references","title":"References","text":"
        • PEP 448 \u2013 Additional Unpacking Generalizations
        • Python documentation: Sequence Types \u2014 list, tuple, range
        ","tags":["RUF005"]},{"location":"rules/collections-named-tuple/","title":"collections-named-tuple (PYI024)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI024"]},{"location":"rules/collections-named-tuple/#what-it-does","title":"What it does","text":"

        Checks for uses of collections.namedtuple in stub files.

        ","tags":["PYI024"]},{"location":"rules/collections-named-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        typing.NamedTuple is the \"typed version\" of collections.namedtuple.

        Inheriting from typing.NamedTuple creates a custom tuple subclass in the same way as using the collections.namedtuple factory function. However, using typing.NamedTuple allows you to provide a type annotation for each field in the class. This means that type checkers will have more information to work with, and will be able to analyze your code more precisely.

        ","tags":["PYI024"]},{"location":"rules/collections-named-tuple/#example","title":"Example","text":"
        from collections import namedtuple\n\nperson = namedtuple(\"Person\", [\"name\", \"age\"])\n

        Use instead:

        from typing import NamedTuple\n\nclass Person(NamedTuple):\n    name: str\n    age: int\n
        ","tags":["PYI024"]},{"location":"rules/commented-out-code/","title":"commented-out-code (ERA001)","text":"

        Derived from the eradicate linter.

        ","tags":["ERA001"]},{"location":"rules/commented-out-code/#what-it-does","title":"What it does","text":"

        Checks for commented-out Python code.

        ","tags":["ERA001"]},{"location":"rules/commented-out-code/#why-is-this-bad","title":"Why is this bad?","text":"

        Commented-out code is dead code, and is often included inadvertently. It should be removed.

        ","tags":["ERA001"]},{"location":"rules/commented-out-code/#known-problems","title":"Known problems","text":"

        Prone to false positives when checking comments that resemble Python code, but are not actually Python code (#4845).

        ","tags":["ERA001"]},{"location":"rules/commented-out-code/#example","title":"Example","text":"
        # print(\"Hello, world!\")\n
        ","tags":["ERA001"]},{"location":"rules/commented-out-code/#options","title":"Options","text":"
        • lint.task-tags
        ","tags":["ERA001"]},{"location":"rules/compare-to-empty-string/","title":"compare-to-empty-string (PLC1901)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLC1901"]},{"location":"rules/compare-to-empty-string/#what-it-does","title":"What it does","text":"

        Checks for comparisons to empty strings.

        ","tags":["PLC1901"]},{"location":"rules/compare-to-empty-string/#why-is-this-bad","title":"Why is this bad?","text":"

        An empty string is falsy, so it is unnecessary to compare it to \"\". If the value can be something else Python considers falsy, such as None, 0, or another empty container, then the code is not equivalent.

        ","tags":["PLC1901"]},{"location":"rules/compare-to-empty-string/#known-problems","title":"Known problems","text":"

        High false positive rate, as the check is context-insensitive and does not consider the type of the variable being compared (#4282).

        ","tags":["PLC1901"]},{"location":"rules/compare-to-empty-string/#example","title":"Example","text":"
        x: str = ...\n\nif x == \"\":\n    print(\"x is empty\")\n

        Use instead:

        x: str = ...\n\nif not x:\n    print(\"x is empty\")\n
        ","tags":["PLC1901"]},{"location":"rules/compare-to-empty-string/#references","title":"References","text":"
        • Python documentation: Truth Value Testing
        ","tags":["PLC1901"]},{"location":"rules/compare-with-tuple/","title":"compare-with-tuple (SIM109)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM109"]},{"location":"rules/compare-with-tuple/#what-it-does","title":"What it does","text":"

        Checks for boolean expressions that contain multiple equality comparisons to the same value.

        ","tags":["SIM109"]},{"location":"rules/compare-with-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        To check if an object is equal to any one of multiple values, it's more concise to use the in operator with a tuple of values.

        ","tags":["SIM109"]},{"location":"rules/compare-with-tuple/#example","title":"Example","text":"
        if foo == x or foo == y:\n    ...\n

        Use instead:

        if foo in (x, y):\n    ...\n
        ","tags":["SIM109"]},{"location":"rules/compare-with-tuple/#references","title":"References","text":"
        • Python documentation: Membership test operations
        ","tags":["SIM109"]},{"location":"rules/comparison-of-constant/","title":"comparison-of-constant (PLR0133)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0133"]},{"location":"rules/comparison-of-constant/#what-it-does","title":"What it does","text":"

        Checks for comparisons between constants.

        ","tags":["PLR0133"]},{"location":"rules/comparison-of-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing two constants will always resolve to the same value, so the comparison is redundant. Instead, the expression should be replaced with the result of the comparison.

        ","tags":["PLR0133"]},{"location":"rules/comparison-of-constant/#example","title":"Example","text":"
        foo = 1 == 1\n

        Use instead:

        foo = True\n
        ","tags":["PLR0133"]},{"location":"rules/comparison-of-constant/#references","title":"References","text":"
        • Python documentation: Comparisons
        ","tags":["PLR0133"]},{"location":"rules/comparison-with-itself/","title":"comparison-with-itself (PLR0124)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0124"]},{"location":"rules/comparison-with-itself/#what-it-does","title":"What it does","text":"

        Checks for operations that compare a name to itself.

        ","tags":["PLR0124"]},{"location":"rules/comparison-with-itself/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing a name to itself always results in the same value, and is likely a mistake.

        ","tags":["PLR0124"]},{"location":"rules/comparison-with-itself/#example","title":"Example","text":"
        foo == foo\n

        In some cases, self-comparisons are used to determine whether a float is NaN. Instead, prefer math.isnan:

        import math\n\nmath.isnan(foo)\n
        ","tags":["PLR0124"]},{"location":"rules/comparison-with-itself/#references","title":"References","text":"
        • Python documentation: Comparisons
        ","tags":["PLR0124"]},{"location":"rules/complex-assignment-in-stub/","title":"complex-assignment-in-stub (PYI017)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI017"]},{"location":"rules/complex-assignment-in-stub/#what-it-does","title":"What it does","text":"

        Checks for assignments with multiple or non-name targets in stub files.

        ","tags":["PYI017"]},{"location":"rules/complex-assignment-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        In general, stub files should be thought of as \"data files\" for a type checker, and are not intended to be executed. As such, it's useful to enforce that only a subset of Python syntax is allowed in a stub file, to ensure that everything in the stub is unambiguous for the type checker.

        The need to perform multi-assignment, or assignment to a non-name target, likely indicates a misunderstanding of how stub files are intended to be used.

        ","tags":["PYI017"]},{"location":"rules/complex-assignment-in-stub/#example","title":"Example","text":"
        from typing import TypeAlias\n\na = b = int\n\nclass Klass: ...\n\nKlass.X: TypeAlias = int\n

        Use instead:

        from typing import TypeAlias\n\na: TypeAlias = int\nb: TypeAlias = int\n\nclass Klass:\n    X: TypeAlias = int\n
        ","tags":["PYI017"]},{"location":"rules/complex-if-statement-in-stub/","title":"complex-if-statement-in-stub (PYI002)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI002"]},{"location":"rules/complex-if-statement-in-stub/#what-it-does","title":"What it does","text":"

        Checks for if statements with complex conditionals in stubs.

        ","tags":["PYI002"]},{"location":"rules/complex-if-statement-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Type checkers understand simple conditionals to express variations between different Python versions and platforms. However, complex tests may not be understood by a type checker, leading to incorrect inferences when they analyze your code.

        ","tags":["PYI002"]},{"location":"rules/complex-if-statement-in-stub/#example","title":"Example","text":"
        import sys\n\nif (3, 10) <= sys.version_info < (3, 12): ...\n

        Use instead:

        import sys\n\nif sys.version_info >= (3, 10) and sys.version_info < (3, 12): ...\n
        ","tags":["PYI002"]},{"location":"rules/complex-if-statement-in-stub/#references","title":"References","text":"
        • Typing documentation: Version and platform checking
        ","tags":["PYI002"]},{"location":"rules/complex-structure/","title":"complex-structure (C901)","text":"

        Derived from the mccabe linter.

        ","tags":["C901"]},{"location":"rules/complex-structure/#what-it-does","title":"What it does","text":"

        Checks for functions with a high McCabe complexity.

        ","tags":["C901"]},{"location":"rules/complex-structure/#why-is-this-bad","title":"Why is this bad?","text":"

        The McCabe complexity of a function is a measure of the complexity of the control flow graph of the function. It is calculated by adding one to the number of decision points in the function. A decision point is a place in the code where the program has a choice of two or more paths to follow.

        Functions with a high complexity are hard to understand and maintain.

        ","tags":["C901"]},{"location":"rules/complex-structure/#example","title":"Example","text":"
        def foo(a, b, c):\n    if a:\n        if b:\n            if c:\n                return 1\n            else:\n                return 2\n        else:\n            return 3\n    else:\n        return 4\n

        Use instead:

        def foo(a, b, c):\n    if not a:\n        return 4\n    if not b:\n        return 3\n    if not c:\n        return 2\n    return 1\n
        ","tags":["C901"]},{"location":"rules/complex-structure/#options","title":"Options","text":"
        • lint.mccabe.max-complexity
        ","tags":["C901"]},{"location":"rules/constant-imported-as-non-constant/","title":"constant-imported-as-non-constant (N811)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N811"]},{"location":"rules/constant-imported-as-non-constant/#what-it-does","title":"What it does","text":"

        Checks for constant imports that are aliased to non-constant-style names.

        ","tags":["N811"]},{"location":"rules/constant-imported-as-non-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends naming conventions for classes, functions, constants, and more. The use of inconsistent naming styles between import and alias names may lead readers to expect an import to be of another type (e.g., confuse a Python class with a constant).

        Import aliases should thus follow the same naming style as the member being imported.

        ","tags":["N811"]},{"location":"rules/constant-imported-as-non-constant/#example","title":"Example","text":"
        from example import CONSTANT_VALUE as ConstantValue\n

        Use instead:

        from example import CONSTANT_VALUE\n
        ","tags":["N811"]},{"location":"rules/constant-imported-as-non-constant/#note","title":"Note","text":"

        Identifiers consisting of a single uppercase character are ambiguous under the rules of PEP 8, which specifies CamelCase for classes and ALL_CAPS_SNAKE_CASE for constants. Without a second character, it is not possible to reliably guess whether the identifier is intended to be part of a CamelCase string for a class or an ALL_CAPS_SNAKE_CASE string for a constant, since both conventions will produce the same output when given a single input character. Therefore, this lint rule does not apply to cases where the imported identifier consists of a single uppercase character.

        A common example of a single uppercase character being used for a class name can be found in Django's django.db.models.Q class.

        ","tags":["N811"]},{"location":"rules/constant-imported-as-non-constant/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N811"]},{"location":"rules/continue-in-finally/","title":"continue-in-finally (PLE0116)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0116"]},{"location":"rules/continue-in-finally/#what-it-does","title":"What it does","text":"

        Checks for continue statements inside finally

        ","tags":["PLE0116"]},{"location":"rules/continue-in-finally/#why-is-this-bad","title":"Why is this bad?","text":"

        continue statements were not allowed within finally clauses prior to Python 3.8. Using a continue statement within a finally clause can cause a SyntaxError.

        ","tags":["PLE0116"]},{"location":"rules/continue-in-finally/#example","title":"Example","text":"
        while True:\n    try:\n        pass\n    finally:\n        continue\n

        Use instead:

        while True:\n    try:\n        pass\n    except Exception:\n        pass\n    else:\n        continue\n
        ","tags":["PLE0116"]},{"location":"rules/continue-in-finally/#options","title":"Options","text":"
        • target-version
        ","tags":["PLE0116"]},{"location":"rules/continue-outside-loop/","title":"continue-outside-loop (F702)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F702"]},{"location":"rules/continue-outside-loop/#what-it-does","title":"What it does","text":"

        Checks for continue statements outside of loops.

        ","tags":["F702"]},{"location":"rules/continue-outside-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of a continue statement outside of a for or while loop will raise a SyntaxError.

        ","tags":["F702"]},{"location":"rules/continue-outside-loop/#example","title":"Example","text":"
        def foo():\n    continue  # SyntaxError\n
        ","tags":["F702"]},{"location":"rules/continue-outside-loop/#references","title":"References","text":"
        • Python documentation: continue
        ","tags":["F702"]},{"location":"rules/convert-named-tuple-functional-to-class/","title":"convert-named-tuple-functional-to-class (UP014)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP014"]},{"location":"rules/convert-named-tuple-functional-to-class/#what-it-does","title":"What it does","text":"

        Checks for NamedTuple declarations that use functional syntax.

        ","tags":["UP014"]},{"location":"rules/convert-named-tuple-functional-to-class/#why-is-this-bad","title":"Why is this bad?","text":"

        NamedTuple subclasses can be defined either through a functional syntax (Foo = NamedTuple(...)) or a class syntax (class Foo(NamedTuple): ...).

        The class syntax is more readable and generally preferred over the functional syntax, which exists primarily for backwards compatibility with collections.namedtuple.

        ","tags":["UP014"]},{"location":"rules/convert-named-tuple-functional-to-class/#example","title":"Example","text":"
        from typing import NamedTuple\n\nFoo = NamedTuple(\"Foo\", [(\"a\", int), (\"b\", str)])\n

        Use instead:

        from typing import NamedTuple\n\n\nclass Foo(NamedTuple):\n    a: int\n    b: str\n
        ","tags":["UP014"]},{"location":"rules/convert-named-tuple-functional-to-class/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe if there are any comments within the range of the NamedTuple definition, as these will be dropped by the autofix.

        ","tags":["UP014"]},{"location":"rules/convert-named-tuple-functional-to-class/#references","title":"References","text":"
        • Python documentation: typing.NamedTuple
        ","tags":["UP014"]},{"location":"rules/convert-typed-dict-functional-to-class/","title":"convert-typed-dict-functional-to-class (UP013)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP013"]},{"location":"rules/convert-typed-dict-functional-to-class/#what-it-does","title":"What it does","text":"

        Checks for TypedDict declarations that use functional syntax.

        ","tags":["UP013"]},{"location":"rules/convert-typed-dict-functional-to-class/#why-is-this-bad","title":"Why is this bad?","text":"

        TypedDict types can be defined either through a functional syntax (Foo = TypedDict(...)) or a class syntax (class Foo(TypedDict): ...).

        The class syntax is more readable and generally preferred over the functional syntax.

        Nonetheless, there are some situations in which it is impossible to use the class-based syntax. This rule will not apply to those cases. Namely, it is impossible to use the class-based syntax if any TypedDict fields are:

        • Not valid python identifiers (for example, @x)
        • Python keywords such as in
        • Private names such as __id that would undergo name mangling at runtime if the class-based syntax was used
        • Dunder names such as __int__ that can confuse type checkers if they're used with the class-based syntax.
        ","tags":["UP013"]},{"location":"rules/convert-typed-dict-functional-to-class/#example","title":"Example","text":"
        from typing import TypedDict\n\nFoo = TypedDict(\"Foo\", {\"a\": int, \"b\": str})\n

        Use instead:

        from typing import TypedDict\n\n\nclass Foo(TypedDict):\n    a: int\n    b: str\n
        ","tags":["UP013"]},{"location":"rules/convert-typed-dict-functional-to-class/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe if there are any comments within the range of the TypedDict definition, as these will be dropped by the autofix.

        ","tags":["UP013"]},{"location":"rules/convert-typed-dict-functional-to-class/#references","title":"References","text":"
        • Python documentation: typing.TypedDict
        ","tags":["UP013"]},{"location":"rules/create-subprocess-in-async-function/","title":"create-subprocess-in-async-function (ASYNC220)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC220"]},{"location":"rules/create-subprocess-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not create subprocesses with blocking methods.

        ","tags":["ASYNC220"]},{"location":"rules/create-subprocess-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a blocking call will block the entire event loop, preventing it from executing other tasks while waiting for the call to complete, negating the benefits of asynchronous programming.

        Instead of making a blocking call, use an equivalent asynchronous library or function, like trio.run_process() or anyio.run_process().

        ","tags":["ASYNC220"]},{"location":"rules/create-subprocess-in-async-function/#example","title":"Example","text":"
        async def foo():\n    os.popen(cmd)\n

        Use instead:

        async def foo():\n    asyncio.create_subprocess_shell(cmd)\n
        ","tags":["ASYNC220"]},{"location":"rules/custom-type-var-for-self/","title":"custom-type-var-for-self (PYI019)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#what-it-does","title":"What it does","text":"

        Checks for methods that use custom TypeVars in their annotations when they could use Self instead.

        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#why-is-this-bad","title":"Why is this bad?","text":"

        While the semantics are often identical, using Self is more intuitive and succinct (per PEP 673) than a custom TypeVar. For example, the use of Self will typically allow for the omission of type parameters on the self and cls arguments.

        This check currently applies to instance methods that return self, class methods that return an instance of cls, class methods that return cls, and __new__ methods.

        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#example","title":"Example","text":"
        from typing import TypeVar\n\n_S = TypeVar(\"_S\", bound=\"Foo\")\n\nclass Foo:\n    def __new__(cls: type[_S], *args: str, **kwargs: int) -> _S: ...\n    def foo(self: _S, arg: bytes) -> _S: ...\n    @classmethod\n    def bar(cls: type[_S], arg: int) -> _S: ...\n

        Use instead:

        from typing import Self\n\nclass Foo:\n    def __new__(cls, *args: str, **kwargs: int) -> Self: ...\n    def foo(self, arg: bytes) -> Self: ...\n    @classmethod\n    def bar(cls, arg: int) -> Self: ...\n
        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#fix-behaviour-and-safety","title":"Fix behaviour and safety","text":"

        The fix replaces all references to the custom type variable in the method's header and body with references to Self. The fix also adds an import of Self if neither Self nor typing is already imported in the module. If your target-version setting is set to Python 3.11 or newer, the fix imports Self from the standard-library typing module; otherwise, the fix imports Self from the third-party typing_extensions backport package.

        If the custom type variable is a PEP-695-style TypeVar, the fix also removes the TypeVar declaration from the method's type parameter list. However, if the type variable is an old-style TypeVar, the declaration of the type variable will not be removed by this rule's fix, as the type variable could still be used by other functions, methods or classes. See unused-private-type-var for a rule that will clean up unused private type variables.

        The fix is only marked as unsafe if there is the possibility that it might delete a comment from your code.

        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for Python versions before 3.11, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["PYI019"]},{"location":"rules/custom-type-var-for-self/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["PYI019"]},{"location":"rules/dataclass-enum/","title":"dataclass-enum (RUF049)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF049"]},{"location":"rules/dataclass-enum/#what-it-does","title":"What it does","text":"

        Checks for enum classes which are also decorated with @dataclass.

        ","tags":["RUF049"]},{"location":"rules/dataclass-enum/#why-is-this-bad","title":"Why is this bad?","text":"

        Decorating an enum with @dataclass() does not cause any errors at runtime, but may cause erroneous results:

        @dataclass\nclass E(Enum):\n    A = 1\n    B = 2\n\nprint(E.A == E.B)  # True\n
        ","tags":["RUF049"]},{"location":"rules/dataclass-enum/#example","title":"Example","text":"
        from dataclasses import dataclass\nfrom enum import Enum\n\n\n@dataclass\nclass E(Enum): ...\n

        Use instead:

        from enum import Enum\n\n\nclass E(Enum): ...\n
        ","tags":["RUF049"]},{"location":"rules/dataclass-enum/#references","title":"References","text":"
        • Python documentation: Enum HOWTO \u00a7 Dataclass support
        ","tags":["RUF049"]},{"location":"rules/datetime-min-max/","title":"datetime-min-max (DTZ901)","text":"

        Derived from the flake8-datetimez linter.

        ","tags":["DTZ901"]},{"location":"rules/datetime-min-max/#what-it-does","title":"What it does","text":"

        Checks for uses of datetime.datetime.min and datetime.datetime.max.

        ","tags":["DTZ901"]},{"location":"rules/datetime-min-max/#why-is-this-bad","title":"Why is this bad?","text":"

        datetime.min and datetime.max are non-timezone-aware datetime objects.

        As such, operations on datetime.min and datetime.max may behave unexpectedly, as in:

        # Timezone: UTC-14\ndatetime.min.timestamp()  # ValueError: year 0 is out of range\ndatetime.max.timestamp()  # ValueError: year 10000 is out of range\n
        ","tags":["DTZ901"]},{"location":"rules/datetime-min-max/#example","title":"Example","text":"
        datetime.max\n

        Use instead:

        datetime.max.replace(tzinfo=datetime.UTC)\n
        ","tags":["DTZ901"]},{"location":"rules/datetime-timezone-utc/","title":"datetime-timezone-utc (UP017)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP017"]},{"location":"rules/datetime-timezone-utc/#what-it-does","title":"What it does","text":"

        Checks for uses of datetime.timezone.utc.

        ","tags":["UP017"]},{"location":"rules/datetime-timezone-utc/#why-is-this-bad","title":"Why is this bad?","text":"

        As of Python 3.11, datetime.UTC is an alias for datetime.timezone.utc. The alias is more readable and generally preferred over the full path.

        ","tags":["UP017"]},{"location":"rules/datetime-timezone-utc/#example","title":"Example","text":"
        import datetime\n\ndatetime.timezone.utc\n

        Use instead:

        import datetime\n\ndatetime.UTC\n
        ","tags":["UP017"]},{"location":"rules/datetime-timezone-utc/#options","title":"Options","text":"
        • target-version
        ","tags":["UP017"]},{"location":"rules/datetime-timezone-utc/#references","title":"References","text":"
        • Python documentation: datetime.UTC
        ","tags":["UP017"]},{"location":"rules/debugger/","title":"debugger (T100)","text":"

        Derived from the flake8-debugger linter.

        ","tags":["T100"]},{"location":"rules/debugger/#what-it-does","title":"What it does","text":"

        Checks for the presence of debugger calls and imports.

        ","tags":["T100"]},{"location":"rules/debugger/#why-is-this-bad","title":"Why is this bad?","text":"

        Debugger calls and imports should be used for debugging purposes only. The presence of a debugger call or import in production code is likely a mistake and may cause unintended behavior, such as exposing sensitive information or causing the program to hang.

        Instead, consider using a logging library to log information about the program's state, and writing tests to verify that the program behaves as expected.

        ","tags":["T100"]},{"location":"rules/debugger/#example","title":"Example","text":"
        def foo():\n    breakpoint()\n
        ","tags":["T100"]},{"location":"rules/debugger/#references","title":"References","text":"
        • Python documentation: pdb \u2014 The Python Debugger
        • Python documentation: logging \u2014 Logging facility for Python
        ","tags":["T100"]},{"location":"rules/decimal-from-float-literal/","title":"decimal-from-float-literal (RUF032)","text":"

        Fix is always available.

        ","tags":["RUF032"]},{"location":"rules/decimal-from-float-literal/#what-it-does","title":"What it does","text":"

        Checks for Decimal calls passing a float literal.

        ","tags":["RUF032"]},{"location":"rules/decimal-from-float-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        Float literals have limited precision that can lead to unexpected results. The Decimal class is designed to handle numbers with fixed-point precision, so a string literal should be used instead.

        ","tags":["RUF032"]},{"location":"rules/decimal-from-float-literal/#example","title":"Example","text":"
        num = Decimal(1.2345)\n

        Use instead:

        num = Decimal(\"1.2345\")\n
        ","tags":["RUF032"]},{"location":"rules/decimal-from-float-literal/#fix-safety","title":"Fix Safety","text":"

        This rule's fix is marked as unsafe because it changes the underlying value of the Decimal instance that is constructed. This can lead to unexpected behavior if your program relies on the previous value (whether deliberately or not).

        ","tags":["RUF032"]},{"location":"rules/default-except-not-last/","title":"default-except-not-last (F707)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F707"]},{"location":"rules/default-except-not-last/#what-it-does","title":"What it does","text":"

        Checks for except blocks that handle all exceptions, but are not the last except block in a try statement.

        ","tags":["F707"]},{"location":"rules/default-except-not-last/#why-is-this-bad","title":"Why is this bad?","text":"

        When an exception is raised within a try block, the except blocks are evaluated in order, and the first matching block is executed. If an except block handles all exceptions, but isn't the last block, Python will raise a SyntaxError, as the following blocks would never be executed.

        ","tags":["F707"]},{"location":"rules/default-except-not-last/#example","title":"Example","text":"
        def reciprocal(n):\n    try:\n        reciprocal = 1 / n\n    except:\n        print(\"An exception occurred.\")\n    except ZeroDivisionError:\n        print(\"Cannot divide by zero.\")\n    else:\n        return reciprocal\n

        Use instead:

        def reciprocal(n):\n    try:\n        reciprocal = 1 / n\n    except ZeroDivisionError:\n        print(\"Cannot divide by zero.\")\n    except:\n        print(\"An exception occurred.\")\n    else:\n        return reciprocal\n
        ","tags":["F707"]},{"location":"rules/default-except-not-last/#references","title":"References","text":"
        • Python documentation: except clause
        ","tags":["F707"]},{"location":"rules/default-factory-kwarg/","title":"default-factory-kwarg (RUF026)","text":"

        Fix is sometimes available.

        ","tags":["RUF026"]},{"location":"rules/default-factory-kwarg/#what-it-does","title":"What it does","text":"

        Checks for incorrect usages of default_factory as a keyword argument when initializing a defaultdict.

        ","tags":["RUF026"]},{"location":"rules/default-factory-kwarg/#why-is-this-bad","title":"Why is this bad?","text":"

        The defaultdict constructor accepts a callable as its first argument. For example, it's common to initialize a defaultdict with int or list via defaultdict(int) or defaultdict(list), to create a dictionary that returns 0 or [] respectively when a key is missing.

        The default factory must be provided as a positional argument, as all keyword arguments to defaultdict are interpreted as initial entries in the dictionary. For example, defaultdict(foo=1, bar=2) will create a dictionary with {\"foo\": 1, \"bar\": 2} as its initial entries.

        As such, defaultdict(default_factory=list) will create a dictionary with {\"default_factory\": list} as its initial entry, instead of a dictionary that returns [] when a key is missing. Specifying a default_factory keyword argument is almost always a mistake, and one that type checkers can't reliably detect.

        ","tags":["RUF026"]},{"location":"rules/default-factory-kwarg/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as converting default_factory from a keyword to a positional argument will change the behavior of the code, even if the keyword argument was used erroneously.

        ","tags":["RUF026"]},{"location":"rules/default-factory-kwarg/#example","title":"Example","text":"
        defaultdict(default_factory=int)\ndefaultdict(default_factory=list)\n

        Use instead:

        defaultdict(int)\ndefaultdict(list)\n
        ","tags":["RUF026"]},{"location":"rules/delete-full-slice/","title":"delete-full-slice (FURB131)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB131"]},{"location":"rules/delete-full-slice/#what-it-does","title":"What it does","text":"

        Checks for del statements that delete the entire slice of a list or dictionary.

        ","tags":["FURB131"]},{"location":"rules/delete-full-slice/#why-is-this-bad","title":"Why is this bad?","text":"

        It is faster and more succinct to remove all items via the clear() method.

        ","tags":["FURB131"]},{"location":"rules/delete-full-slice/#known-problems","title":"Known problems","text":"

        This rule is prone to false negatives due to type inference limitations, as it will only detect lists and dictionaries that are instantiated as literals or annotated with a type annotation.

        ","tags":["FURB131"]},{"location":"rules/delete-full-slice/#example","title":"Example","text":"
        names = {\"key\": \"value\"}\nnums = [1, 2, 3]\n\ndel names[:]\ndel nums[:]\n

        Use instead:

        names = {\"key\": \"value\"}\nnums = [1, 2, 3]\n\nnames.clear()\nnums.clear()\n
        ","tags":["FURB131"]},{"location":"rules/delete-full-slice/#references","title":"References","text":"
        • Python documentation: Mutable Sequence Types
        • Python documentation: dict.clear()
        ","tags":["FURB131"]},{"location":"rules/deprecated-c-element-tree/","title":"deprecated-c-element-tree (UP023)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP023"]},{"location":"rules/deprecated-c-element-tree/#what-it-does","title":"What it does","text":"

        Checks for uses of the xml.etree.cElementTree module.

        ","tags":["UP023"]},{"location":"rules/deprecated-c-element-tree/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3.3, xml.etree.cElementTree was deprecated in favor of xml.etree.ElementTree.

        ","tags":["UP023"]},{"location":"rules/deprecated-c-element-tree/#example","title":"Example","text":"
        from xml.etree import cElementTree\n

        Use instead:

        from xml.etree import ElementTree\n
        ","tags":["UP023"]},{"location":"rules/deprecated-c-element-tree/#references","title":"References","text":"
        • Python documentation: xml.etree.ElementTree
        ","tags":["UP023"]},{"location":"rules/deprecated-import/","title":"deprecated-import (UP035)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP035"]},{"location":"rules/deprecated-import/#what-it-does","title":"What it does","text":"

        Checks for uses of deprecated imports based on the minimum supported Python version.

        ","tags":["UP035"]},{"location":"rules/deprecated-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Deprecated imports may be removed in future versions of Python, and should be replaced with their new equivalents.

        Note that, in some cases, it may be preferable to continue importing members from typing_extensions even after they're added to the Python standard library, as typing_extensions can backport bugfixes and optimizations from later Python versions. This rule thus avoids flagging imports from typing_extensions in such cases.

        ","tags":["UP035"]},{"location":"rules/deprecated-import/#example","title":"Example","text":"
        from collections import Sequence\n

        Use instead:

        from collections.abc import Sequence\n
        ","tags":["UP035"]},{"location":"rules/deprecated-log-warn/","title":"deprecated-log-warn (PGH002)","text":"

        Derived from the pygrep-hooks linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        Fix is sometimes available.

        ","tags":["PGH002"]},{"location":"rules/deprecated-log-warn/#removed","title":"Removed","text":"

        This rule is identical to G010 which should be used instead.

        ","tags":["PGH002"]},{"location":"rules/deprecated-log-warn/#what-it-does","title":"What it does","text":"

        Check for usages of the deprecated warn method from the logging module.

        ","tags":["PGH002"]},{"location":"rules/deprecated-log-warn/#why-is-this-bad","title":"Why is this bad?","text":"

        The warn method is deprecated. Use warning instead.

        ","tags":["PGH002"]},{"location":"rules/deprecated-log-warn/#example","title":"Example","text":"
        import logging\n\n\ndef foo():\n    logging.warn(\"Something happened\")\n

        Use instead:

        import logging\n\n\ndef foo():\n    logging.warning(\"Something happened\")\n
        ","tags":["PGH002"]},{"location":"rules/deprecated-log-warn/#references","title":"References","text":"
        • Python documentation: logger.Logger.warning
        ","tags":["PGH002"]},{"location":"rules/deprecated-mock-import/","title":"deprecated-mock-import (UP026)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP026"]},{"location":"rules/deprecated-mock-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the mock module that should be replaced with unittest.mock.

        ","tags":["UP026"]},{"location":"rules/deprecated-mock-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3.3, mock has been a part of the standard library as unittest.mock. The mock package is deprecated; use unittest.mock instead.

        ","tags":["UP026"]},{"location":"rules/deprecated-mock-import/#example","title":"Example","text":"
        import mock\n

        Use instead:

        from unittest import mock\n
        ","tags":["UP026"]},{"location":"rules/deprecated-mock-import/#references","title":"References","text":"
        • Python documentation: unittest.mock
        • PyPI: mock
        ","tags":["UP026"]},{"location":"rules/deprecated-unittest-alias/","title":"deprecated-unittest-alias (UP005)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP005"]},{"location":"rules/deprecated-unittest-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of deprecated methods from the unittest module.

        ","tags":["UP005"]},{"location":"rules/deprecated-unittest-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        The unittest module has deprecated aliases for some of its methods. The deprecated aliases were removed in Python 3.12. Instead of aliases, use their non-deprecated counterparts.

        ","tags":["UP005"]},{"location":"rules/deprecated-unittest-alias/#example","title":"Example","text":"
        from unittest import TestCase\n\n\nclass SomeTest(TestCase):\n    def test_something(self):\n        self.assertEquals(1, 1)\n

        Use instead:

        from unittest import TestCase\n\n\nclass SomeTest(TestCase):\n    def test_something(self):\n        self.assertEqual(1, 1)\n
        ","tags":["UP005"]},{"location":"rules/deprecated-unittest-alias/#references","title":"References","text":"
        • Python 3.11 documentation: Deprecated aliases
        ","tags":["UP005"]},{"location":"rules/dict-get-with-none-default/","title":"dict-get-with-none-default (SIM910)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM910"]},{"location":"rules/dict-get-with-none-default/#what-it-does","title":"What it does","text":"

        Checks for dict.get() calls that pass None as the default value.

        ","tags":["SIM910"]},{"location":"rules/dict-get-with-none-default/#why-is-this-bad","title":"Why is this bad?","text":"

        None is the default value for dict.get(), so it is redundant to pass it explicitly.

        ","tags":["SIM910"]},{"location":"rules/dict-get-with-none-default/#example","title":"Example","text":"
        ages = {\"Tom\": 23, \"Maria\": 23, \"Dog\": 11}\nage = ages.get(\"Cat\", None)\n

        Use instead:

        ages = {\"Tom\": 23, \"Maria\": 23, \"Dog\": 11}\nage = ages.get(\"Cat\")\n
        ","tags":["SIM910"]},{"location":"rules/dict-get-with-none-default/#references","title":"References","text":"
        • Python documentation: dict.get
        ","tags":["SIM910"]},{"location":"rules/dict-index-missing-items/","title":"dict-index-missing-items (PLC0206)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC0206"]},{"location":"rules/dict-index-missing-items/#what-it-does","title":"What it does","text":"

        Checks for dictionary iterations that extract the dictionary value via explicit indexing, instead of using .items().

        ","tags":["PLC0206"]},{"location":"rules/dict-index-missing-items/#why-is-this-bad","title":"Why is this bad?","text":"

        Iterating over a dictionary with .items() is semantically clearer and more efficient than extracting the value with the key.

        ","tags":["PLC0206"]},{"location":"rules/dict-index-missing-items/#example","title":"Example","text":"
        ORCHESTRA = {\n    \"violin\": \"strings\",\n    \"oboe\": \"woodwind\",\n    \"tuba\": \"brass\",\n    \"gong\": \"percussion\",\n}\n\nfor instrument in ORCHESTRA:\n    print(f\"{instrument}: {ORCHESTRA[instrument]}\")\n

        Use instead:

        ORCHESTRA = {\n    \"violin\": \"strings\",\n    \"oboe\": \"woodwind\",\n    \"tuba\": \"brass\",\n    \"gong\": \"percussion\",\n}\n\nfor instrument, section in ORCHESTRA.items():\n    print(f\"{instrument}: {section}\")\n
        ","tags":["PLC0206"]},{"location":"rules/dict-iter-missing-items/","title":"dict-iter-missing-items (PLE1141)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLE1141"]},{"location":"rules/dict-iter-missing-items/#what-it-does","title":"What it does","text":"

        Checks for dictionary unpacking in a for loop without calling .items().

        ","tags":["PLE1141"]},{"location":"rules/dict-iter-missing-items/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over a dictionary in a for loop, if a dictionary is unpacked without calling .items(), it could lead to a runtime error if the keys are not a tuple of two elements.

        It is likely that you're looking for an iteration over (key, value) pairs which can only be achieved when calling .items().

        ","tags":["PLE1141"]},{"location":"rules/dict-iter-missing-items/#example","title":"Example","text":"
        data = {\"Paris\": 2_165_423, \"New York City\": 8_804_190, \"Tokyo\": 13_988_129}\n\nfor city, population in data:\n    print(f\"{city} has population {population}.\")\n

        Use instead:

        data = {\"Paris\": 2_165_423, \"New York City\": 8_804_190, \"Tokyo\": 13_988_129}\n\nfor city, population in data.items():\n    print(f\"{city} has population {population}.\")\n
        ","tags":["PLE1141"]},{"location":"rules/dict-iter-missing-items/#known-problems","title":"Known problems","text":"

        If the dictionary key is a tuple, e.g.:

        d = {(1, 2): 3, (3, 4): 5}\nfor x, y in d:\n    print(x, y)\n

        The tuple key is unpacked into x and y instead of the key and values. This means that the suggested fix of using d.items() would result in different runtime behavior. Ruff cannot consistently infer the type of a dictionary's keys.

        ","tags":["PLE1141"]},{"location":"rules/dict-iter-missing-items/#fix-safety","title":"Fix safety","text":"

        Due to the known problem with tuple keys, this fix is unsafe.

        ","tags":["PLE1141"]},{"location":"rules/direct-logger-instantiation/","title":"direct-logger-instantiation (LOG001)","text":"

        Derived from the flake8-logging linter.

        Fix is sometimes available.

        ","tags":["LOG001"]},{"location":"rules/direct-logger-instantiation/#what-it-does","title":"What it does","text":"

        Checks for direct instantiation of logging.Logger, as opposed to using logging.getLogger().

        ","tags":["LOG001"]},{"location":"rules/direct-logger-instantiation/#why-is-this-bad","title":"Why is this bad?","text":"

        The Logger Objects documentation states that:

        Note that Loggers should NEVER be instantiated directly, but always through the module-level function logging.getLogger(name).

        If a logger is directly instantiated, it won't be added to the logger tree, and will bypass all configuration. Messages logged to it will only be sent to the \"handler of last resort\", skipping any filtering or formatting.

        ","tags":["LOG001"]},{"location":"rules/direct-logger-instantiation/#example","title":"Example","text":"
        import logging\n\nlogger = logging.Logger(__name__)\n

        Use instead:

        import logging\n\nlogger = logging.getLogger(__name__)\n
        ","tags":["LOG001"]},{"location":"rules/django-all-with-model-form/","title":"django-all-with-model-form (DJ007)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ007"]},{"location":"rules/django-all-with-model-form/#what-it-does","title":"What it does","text":"

        Checks for the use of fields = \"__all__\" in Django ModelForm classes.

        ","tags":["DJ007"]},{"location":"rules/django-all-with-model-form/#why-is-this-bad","title":"Why is this bad?","text":"

        If a ModelForm includes the fields = \"__all__\" attribute, any new field that is added to the model will automatically be exposed for modification.

        ","tags":["DJ007"]},{"location":"rules/django-all-with-model-form/#example","title":"Example","text":"
        from django.forms import ModelForm\n\n\nclass PostForm(ModelForm):\n    class Meta:\n        model = Post\n        fields = \"__all__\"\n

        Use instead:

        from django.forms import ModelForm\n\n\nclass PostForm(ModelForm):\n    class Meta:\n        model = Post\n        fields = [\"title\", \"content\"]\n
        ","tags":["DJ007"]},{"location":"rules/django-exclude-with-model-form/","title":"django-exclude-with-model-form (DJ006)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ006"]},{"location":"rules/django-exclude-with-model-form/#what-it-does","title":"What it does","text":"

        Checks for the use of exclude in Django ModelForm classes.

        ","tags":["DJ006"]},{"location":"rules/django-exclude-with-model-form/#why-is-this-bad","title":"Why is this bad?","text":"

        If a ModelForm includes the exclude attribute, any new field that is added to the model will automatically be exposed for modification.

        ","tags":["DJ006"]},{"location":"rules/django-exclude-with-model-form/#example","title":"Example","text":"
        from django.forms import ModelForm\n\n\nclass PostForm(ModelForm):\n    class Meta:\n        model = Post\n        exclude = [\"author\"]\n

        Use instead:

        from django.forms import ModelForm\n\n\nclass PostForm(ModelForm):\n    class Meta:\n        model = Post\n        fields = [\"title\", \"content\"]\n
        ","tags":["DJ006"]},{"location":"rules/django-extra/","title":"django-extra (S610)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S610"]},{"location":"rules/django-extra/#what-it-does","title":"What it does","text":"

        Checks for uses of Django's extra function where one or more arguments passed are not literal expressions.

        ","tags":["S610"]},{"location":"rules/django-extra/#why-is-this-bad","title":"Why is this bad?","text":"

        Django's extra function can be used to execute arbitrary SQL queries, which can in turn lead to SQL injection vulnerabilities.

        ","tags":["S610"]},{"location":"rules/django-extra/#example","title":"Example","text":"
        from django.contrib.auth.models import User\n\n# String interpolation creates a security loophole that could be used\n# for SQL injection:\nUser.objects.all().extra(select={\"test\": \"%secure\" % \"nos\"})\n

        Use instead:

        from django.contrib.auth.models import User\n\n# SQL injection is impossible if all arguments are literal expressions:\nUser.objects.all().extra(select={\"test\": \"secure\"})\n
        ","tags":["S610"]},{"location":"rules/django-extra/#references","title":"References","text":"
        • Django documentation: SQL injection protection
        • Common Weakness Enumeration: CWE-89
        ","tags":["S610"]},{"location":"rules/django-locals-in-render-function/","title":"django-locals-in-render-function (DJ003)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ003"]},{"location":"rules/django-locals-in-render-function/#what-it-does","title":"What it does","text":"

        Checks for the use of locals() in render functions.

        ","tags":["DJ003"]},{"location":"rules/django-locals-in-render-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Using locals() can expose internal variables or other unintentional data to the rendered template.

        ","tags":["DJ003"]},{"location":"rules/django-locals-in-render-function/#example","title":"Example","text":"
        from django.shortcuts import render\n\n\ndef index(request):\n    posts = Post.objects.all()\n    return render(request, \"app/index.html\", locals())\n

        Use instead:

        from django.shortcuts import render\n\n\ndef index(request):\n    posts = Post.objects.all()\n    context = {\"posts\": posts}\n    return render(request, \"app/index.html\", context)\n
        ","tags":["DJ003"]},{"location":"rules/django-model-without-dunder-str/","title":"django-model-without-dunder-str (DJ008)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ008"]},{"location":"rules/django-model-without-dunder-str/#what-it-does","title":"What it does","text":"

        Checks that a __str__ method is defined in Django models.

        ","tags":["DJ008"]},{"location":"rules/django-model-without-dunder-str/#why-is-this-bad","title":"Why is this bad?","text":"

        Django models should define a __str__ method to return a string representation of the model instance, as Django calls this method to display the object in the Django Admin and elsewhere.

        Models without a __str__ method will display a non-meaningful representation of the object in the Django Admin.

        ","tags":["DJ008"]},{"location":"rules/django-model-without-dunder-str/#example","title":"Example","text":"
        from django.db import models\n\n\nclass MyModel(models.Model):\n    field = models.CharField(max_length=255)\n

        Use instead:

        from django.db import models\n\n\nclass MyModel(models.Model):\n    field = models.CharField(max_length=255)\n\n    def __str__(self):\n        return f\"{self.field}\"\n
        ","tags":["DJ008"]},{"location":"rules/django-non-leading-receiver-decorator/","title":"django-non-leading-receiver-decorator (DJ013)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ013"]},{"location":"rules/django-non-leading-receiver-decorator/#what-it-does","title":"What it does","text":"

        Checks that Django's @receiver decorator is listed first, prior to any other decorators.

        ","tags":["DJ013"]},{"location":"rules/django-non-leading-receiver-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        Django's @receiver decorator is special in that it does not return a wrapped function. Rather, @receiver connects the decorated function to a signal. If any other decorators are listed before @receiver, the decorated function will not be connected to the signal.

        ","tags":["DJ013"]},{"location":"rules/django-non-leading-receiver-decorator/#example","title":"Example","text":"
        from django.dispatch import receiver\nfrom django.db.models.signals import post_save\n\n\n@transaction.atomic\n@receiver(post_save, sender=MyModel)\ndef my_handler(sender, instance, created, **kwargs):\n    pass\n

        Use instead:

        from django.dispatch import receiver\nfrom django.db.models.signals import post_save\n\n\n@receiver(post_save, sender=MyModel)\n@transaction.atomic\ndef my_handler(sender, instance, created, **kwargs):\n    pass\n
        ","tags":["DJ013"]},{"location":"rules/django-nullable-model-string-field/","title":"django-nullable-model-string-field (DJ001)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ001"]},{"location":"rules/django-nullable-model-string-field/#what-it-does","title":"What it does","text":"

        Checks nullable string-based fields (like CharField and TextField) in Django models.

        ","tags":["DJ001"]},{"location":"rules/django-nullable-model-string-field/#why-is-this-bad","title":"Why is this bad?","text":"

        If a string-based field is nullable, then your model will have two possible representations for \"no data\": None and the empty string. This can lead to confusion, as clients of the API have to check for both None and the empty string when trying to determine if the field has data.

        The Django convention is to use the empty string in lieu of None for string-based fields.

        ","tags":["DJ001"]},{"location":"rules/django-nullable-model-string-field/#example","title":"Example","text":"
        from django.db import models\n\n\nclass MyModel(models.Model):\n    field = models.CharField(max_length=255, null=True)\n

        Use instead:

        from django.db import models\n\n\nclass MyModel(models.Model):\n    field = models.CharField(max_length=255, default=\"\")\n
        ","tags":["DJ001"]},{"location":"rules/django-raw-sql/","title":"django-raw-sql (S611)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S611"]},{"location":"rules/django-raw-sql/#what-it-does","title":"What it does","text":"

        Checks for uses of Django's RawSQL function.

        ","tags":["S611"]},{"location":"rules/django-raw-sql/#why-is-this-bad","title":"Why is this bad?","text":"

        Django's RawSQL function can be used to execute arbitrary SQL queries, which can in turn lead to SQL injection vulnerabilities.

        ","tags":["S611"]},{"location":"rules/django-raw-sql/#example","title":"Example","text":"
        from django.db.models.expressions import RawSQL\nfrom django.contrib.auth.models import User\n\nUser.objects.annotate(val=RawSQL(\"%s\" % input_param, []))\n
        ","tags":["S611"]},{"location":"rules/django-raw-sql/#references","title":"References","text":"
        • Django documentation: SQL injection protection
        • Common Weakness Enumeration: CWE-89
        ","tags":["S611"]},{"location":"rules/django-unordered-body-content-in-model/","title":"django-unordered-body-content-in-model (DJ012)","text":"

        Derived from the flake8-django linter.

        ","tags":["DJ012"]},{"location":"rules/django-unordered-body-content-in-model/#what-it-does","title":"What it does","text":"

        Checks for the order of Model's inner classes, methods, and fields as per the Django Style Guide.

        ","tags":["DJ012"]},{"location":"rules/django-unordered-body-content-in-model/#why-is-this-bad","title":"Why is this bad?","text":"

        The Django Style Guide specifies that the order of Model inner classes, attributes and methods should be as follows:

        1. All database fields
        2. Custom manager attributes
        3. class Meta
        4. def __str__()
        5. def save()
        6. def get_absolute_url()
        7. Any custom methods
        ","tags":["DJ012"]},{"location":"rules/django-unordered-body-content-in-model/#example","title":"Example","text":"
        from django.db import models\n\n\nclass StrBeforeFieldModel(models.Model):\n    class Meta:\n        verbose_name = \"test\"\n        verbose_name_plural = \"tests\"\n\n    def __str__(self):\n        return \"foobar\"\n\n    first_name = models.CharField(max_length=32)\n    last_name = models.CharField(max_length=40)\n

        Use instead:

        from django.db import models\n\n\nclass StrBeforeFieldModel(models.Model):\n    first_name = models.CharField(max_length=32)\n    last_name = models.CharField(max_length=40)\n\n    class Meta:\n        verbose_name = \"test\"\n        verbose_name_plural = \"tests\"\n\n    def __str__(self):\n        return \"foobar\"\n
        ","tags":["DJ012"]},{"location":"rules/doc-line-too-long/","title":"doc-line-too-long (W505)","text":"

        Derived from the pycodestyle linter.

        ","tags":["W505"]},{"location":"rules/doc-line-too-long/#what-it-does","title":"What it does","text":"

        Checks for doc lines that exceed the specified maximum character length.

        ","tags":["W505"]},{"location":"rules/doc-line-too-long/#why-is-this-bad","title":"Why is this bad?","text":"

        For flowing long blocks of text (docstrings or comments), overlong lines can hurt readability. PEP 8, for example, recommends that such lines be limited to 72 characters, while this rule enforces the limit specified by the lint.pycodestyle.max-doc-length setting. (If no value is provided, this rule will be ignored, even if it's added to your --select list.)

        In the context of this rule, a \"doc line\" is defined as a line consisting of either a standalone comment or a standalone string, like a docstring.

        In the interest of pragmatism, this rule makes a few exceptions when determining whether a line is overlong. Namely, it:

        1. Ignores lines that consist of a single \"word\" (i.e., without any whitespace between its characters).
        2. Ignores lines that end with a URL, as long as the URL starts before the line-length threshold.
        3. Ignores line that end with a pragma comment (e.g., # type: ignore or # noqa), as long as the pragma comment starts before the line-length threshold. That is, a line will not be flagged as overlong if a pragma comment causes it to exceed the line length. (This behavior aligns with that of the Ruff formatter.)

        If lint.pycodestyle.ignore-overlong-task-comments is true, this rule will also ignore comments that start with any of the specified lint.task-tags (e.g., # TODO:).

        ","tags":["W505"]},{"location":"rules/doc-line-too-long/#example","title":"Example","text":"
        def function(x):\n    \"\"\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis auctor purus ut ex fermentum, at maximus est hendrerit.\"\"\"\n

        Use instead:

        def function(x):\n    \"\"\"\n    Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n    Duis auctor purus ut ex fermentum, at maximus est hendrerit.\n    \"\"\"\n
        ","tags":["W505"]},{"location":"rules/doc-line-too-long/#error-suppression","title":"Error suppression","text":"

        Hint: when suppressing W505 errors within multi-line strings (like docstrings), the noqa directive should come at the end of the string (after the closing triple quote), and will apply to the entire string, like so:

        \"\"\"Lorem ipsum dolor sit amet.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.\n\"\"\"  # noqa: W505\n
        ","tags":["W505"]},{"location":"rules/doc-line-too-long/#options","title":"Options","text":"
        • lint.task-tags
        • lint.pycodestyle.max-doc-length
        • lint.pycodestyle.ignore-overlong-task-comments
        ","tags":["W505"]},{"location":"rules/docstring-extraneous-exception/","title":"docstring-extraneous-exception (DOC502)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC502"]},{"location":"rules/docstring-extraneous-exception/#what-it-does","title":"What it does","text":"

        Checks for function docstrings that state that exceptions could be raised even though they are not directly raised in the function body.

        ","tags":["DOC502"]},{"location":"rules/docstring-extraneous-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Some conventions prefer non-explicit exceptions be omitted from the docstring.

        This rule is not enforced for abstract methods. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC502"]},{"location":"rules/docstring-extraneous-exception/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        ZeroDivisionError: Divided by zero.\n    \"\"\"\n    return distance / time\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n    \"\"\"\n    return distance / time\n
        ","tags":["DOC502"]},{"location":"rules/docstring-extraneous-exception/#known-issues","title":"Known issues","text":"

        It may often be desirable to document all exceptions that a function could possibly raise, even those which are not explicitly raised using raise statements in the function body.

        ","tags":["DOC502"]},{"location":"rules/docstring-extraneous-returns/","title":"docstring-extraneous-returns (DOC202)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC202"]},{"location":"rules/docstring-extraneous-returns/#what-it-does","title":"What it does","text":"

        Checks for function docstrings with unnecessary \"Returns\" sections.

        ","tags":["DOC202"]},{"location":"rules/docstring-extraneous-returns/#why-is-this-bad","title":"Why is this bad?","text":"

        A function without an explicit return statement should not have a \"Returns\" section in its docstring.

        This rule is not enforced for abstract methods. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC202"]},{"location":"rules/docstring-extraneous-returns/#example","title":"Example","text":"
        def say_hello(n: int) -> None:\n    \"\"\"Says hello to the user.\n\n    Args:\n        n: Number of times to say hello.\n\n    Returns:\n        Doesn't return anything.\n    \"\"\"\n    for _ in range(n):\n        print(\"Hello!\")\n

        Use instead:

        def say_hello(n: int) -> None:\n    \"\"\"Says hello to the user.\n\n    Args:\n        n: Number of times to say hello.\n    \"\"\"\n    for _ in range(n):\n        print(\"Hello!\")\n
        ","tags":["DOC202"]},{"location":"rules/docstring-extraneous-yields/","title":"docstring-extraneous-yields (DOC403)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC403"]},{"location":"rules/docstring-extraneous-yields/#what-it-does","title":"What it does","text":"

        Checks for function docstrings with unnecessary \"Yields\" sections.

        ","tags":["DOC403"]},{"location":"rules/docstring-extraneous-yields/#why-is-this-bad","title":"Why is this bad?","text":"

        A function that doesn't yield anything should not have a \"Yields\" section in its docstring.

        This rule is not enforced for abstract methods. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC403"]},{"location":"rules/docstring-extraneous-yields/#example","title":"Example","text":"
        def say_hello(n: int) -> None:\n    \"\"\"Says hello to the user.\n\n    Args:\n        n: Number of times to say hello.\n\n    Yields:\n        Doesn't yield anything.\n    \"\"\"\n    for _ in range(n):\n        print(\"Hello!\")\n

        Use instead:

        def say_hello(n: int) -> None:\n    \"\"\"Says hello to the user.\n\n    Args:\n        n: Number of times to say hello.\n    \"\"\"\n    for _ in range(n):\n        print(\"Hello!\")\n
        ","tags":["DOC403"]},{"location":"rules/docstring-in-stub/","title":"docstring-in-stub (PYI021)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI021"]},{"location":"rules/docstring-in-stub/#what-it-does","title":"What it does","text":"

        Checks for the presence of docstrings in stub files.

        ","tags":["PYI021"]},{"location":"rules/docstring-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files should omit docstrings, as they're intended to provide type hints, rather than documentation.

        ","tags":["PYI021"]},{"location":"rules/docstring-in-stub/#example","title":"Example","text":"
        def func(param: int) -> str:\n    \"\"\"This is a docstring.\"\"\"\n    ...\n

        Use instead:

        def func(param: int) -> str: ...\n
        ","tags":["PYI021"]},{"location":"rules/docstring-missing-exception/","title":"docstring-missing-exception (DOC501)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC501"]},{"location":"rules/docstring-missing-exception/#what-it-does","title":"What it does","text":"

        Checks for function docstrings that do not document all explicitly raised exceptions.

        ","tags":["DOC501"]},{"location":"rules/docstring-missing-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        A function should document all exceptions that are directly raised in some circumstances. Failing to document an exception that could be raised can be misleading to users and/or a sign of incomplete documentation.

        This rule is not enforced for abstract methods. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC501"]},{"location":"rules/docstring-missing-exception/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["DOC501"]},{"location":"rules/docstring-missing-returns/","title":"docstring-missing-returns (DOC201)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC201"]},{"location":"rules/docstring-missing-returns/#what-it-does","title":"What it does","text":"

        Checks for functions with return statements that do not have \"Returns\" sections in their docstrings.

        ","tags":["DOC201"]},{"location":"rules/docstring-missing-returns/#why-is-this-bad","title":"Why is this bad?","text":"

        A missing \"Returns\" section is a sign of incomplete documentation.

        This rule is not enforced for abstract methods or functions that only return None. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC201"]},{"location":"rules/docstring-missing-returns/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n    \"\"\"\n    return distance / time\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n    \"\"\"\n    return distance / time\n
        ","tags":["DOC201"]},{"location":"rules/docstring-missing-yields/","title":"docstring-missing-yields (DOC402)","text":"

        Derived from the pydoclint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["DOC402"]},{"location":"rules/docstring-missing-yields/#what-it-does","title":"What it does","text":"

        Checks for functions with yield statements that do not have \"Yields\" sections in their docstrings.

        ","tags":["DOC402"]},{"location":"rules/docstring-missing-yields/#why-is-this-bad","title":"Why is this bad?","text":"

        A missing \"Yields\" section is a sign of incomplete documentation.

        This rule is not enforced for abstract methods or functions that only yield None. It is also ignored for \"stub functions\": functions where the body only consists of pass, ..., raise NotImplementedError, or similar.

        ","tags":["DOC402"]},{"location":"rules/docstring-missing-yields/#example","title":"Example","text":"
        def count_to_n(n: int) -> int:\n    \"\"\"Generate integers up to *n*.\n\n    Args:\n        n: The number at which to stop counting.\n    \"\"\"\n    for i in range(1, n + 1):\n        yield i\n

        Use instead:

        def count_to_n(n: int) -> int:\n    \"\"\"Generate integers up to *n*.\n\n    Args:\n        n: The number at which to stop counting.\n\n    Yields:\n        int: The number we're at in the count.\n    \"\"\"\n    for i in range(1, n + 1):\n        yield i\n
        ","tags":["DOC402"]},{"location":"rules/docstring-starts-with-this/","title":"docstring-starts-with-this (D404)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D404"]},{"location":"rules/docstring-starts-with-this/#what-it-does","title":"What it does","text":"

        Checks for docstrings that start with This.

        ","tags":["D404"]},{"location":"rules/docstring-starts-with-this/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that the first line of a docstring be written in the imperative mood, for consistency.

        Hint: to rewrite the docstring in the imperative, phrase the first line as if it were a command.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the numpy convention,, and disabled when using the google and pep257 conventions.

        ","tags":["D404"]},{"location":"rules/docstring-starts-with-this/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"This function returns the mean of the given values.\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D404"]},{"location":"rules/docstring-starts-with-this/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D404"]},{"location":"rules/docstring-starts-with-this/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        ","tags":["D404"]},{"location":"rules/docstring-tab-indentation/","title":"docstring-tab-indentation (D206)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D206"]},{"location":"rules/docstring-tab-indentation/#what-it-does","title":"What it does","text":"

        Checks for docstrings that are indented with tabs.

        ","tags":["D206"]},{"location":"rules/docstring-tab-indentation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends using spaces over tabs for indentation.

        ","tags":["D206"]},{"location":"rules/docstring-tab-indentation/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D206"]},{"location":"rules/docstring-tab-indentation/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        The rule is also incompatible with the formatter when using format.indent-style=\"tab\".

        ","tags":["D206"]},{"location":"rules/docstring-tab-indentation/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D206"]},{"location":"rules/dot-format-in-exception/","title":"dot-format-in-exception (EM103)","text":"

        Derived from the flake8-errmsg linter.

        Fix is sometimes available.

        ","tags":["EM103"]},{"location":"rules/dot-format-in-exception/#what-it-does","title":"What it does","text":"

        Checks for the use of .format calls on string literals in exception constructors.

        ","tags":["EM103"]},{"location":"rules/dot-format-in-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Python includes the raise in the default traceback (and formatters like Rich and IPython do too).

        By using a .format call, the error message will be duplicated in the traceback, which can make the traceback less readable.

        ","tags":["EM103"]},{"location":"rules/dot-format-in-exception/#example","title":"Example","text":"

        Given:

        sub = \"Some value\"\nraise RuntimeError(\"'{}' is incorrect\".format(sub))\n

        Python will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 2, in <module>\n    raise RuntimeError(\"'{}' is incorrect\".format(sub))\nRuntimeError: 'Some value' is incorrect\n

        Instead, assign the string to a variable:

        sub = \"Some value\"\nmsg = \"'{}' is incorrect\".format(sub)\nraise RuntimeError(msg)\n

        Which will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 3, in <module>\n    raise RuntimeError(msg)\nRuntimeError: 'Some value' is incorrect\n
        ","tags":["EM103"]},{"location":"rules/double-negation/","title":"double-negation (SIM208)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM208"]},{"location":"rules/double-negation/#what-it-does","title":"What it does","text":"

        Checks for double negations (i.e., multiple not operators).

        ","tags":["SIM208"]},{"location":"rules/double-negation/#why-is-this-bad","title":"Why is this bad?","text":"

        A double negation is redundant and less readable than omitting the not operators entirely.

        ","tags":["SIM208"]},{"location":"rules/double-negation/#example","title":"Example","text":"
        not (not a)\n

        Use instead:

        a\n
        ","tags":["SIM208"]},{"location":"rules/double-negation/#references","title":"References","text":"
        • Python documentation: Comparisons
        ","tags":["SIM208"]},{"location":"rules/dunder-function-name/","title":"dunder-function-name (N807)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N807"]},{"location":"rules/dunder-function-name/#what-it-does","title":"What it does","text":"

        Checks for functions with \"dunder\" names (that is, names with two leading and trailing underscores) that are not documented.

        ","tags":["N807"]},{"location":"rules/dunder-function-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that only documented \"dunder\" methods are used:

        ...\"magic\" objects or attributes that live in user-controlled namespaces. E.g. __init__, __import__ or __file__. Never invent such names; only use them as documented.

        ","tags":["N807"]},{"location":"rules/dunder-function-name/#example","title":"Example","text":"
        def __my_function__():\n    pass\n

        Use instead:

        def my_function():\n    pass\n
        ","tags":["N807"]},{"location":"rules/dunder-function-name/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N807"]},{"location":"rules/duplicate-bases/","title":"duplicate-bases (PLE0241)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE0241"]},{"location":"rules/duplicate-bases/#what-it-does","title":"What it does","text":"

        Checks for duplicate base classes in class definitions.

        ","tags":["PLE0241"]},{"location":"rules/duplicate-bases/#why-is-this-bad","title":"Why is this bad?","text":"

        Including duplicate base classes will raise a TypeError at runtime.

        ","tags":["PLE0241"]},{"location":"rules/duplicate-bases/#example","title":"Example","text":"
        class Foo:\n    pass\n\n\nclass Bar(Foo, Foo):\n    pass\n

        Use instead:

        class Foo:\n    pass\n\n\nclass Bar(Foo):\n    pass\n
        ","tags":["PLE0241"]},{"location":"rules/duplicate-bases/#references","title":"References","text":"
        • Python documentation: Class definitions
        ","tags":["PLE0241"]},{"location":"rules/duplicate-class-field-definition/","title":"duplicate-class-field-definition (PIE794)","text":"

        Derived from the flake8-pie linter.

        Fix is always available.

        ","tags":["PIE794"]},{"location":"rules/duplicate-class-field-definition/#what-it-does","title":"What it does","text":"

        Checks for duplicate field definitions in classes.

        ","tags":["PIE794"]},{"location":"rules/duplicate-class-field-definition/#why-is-this-bad","title":"Why is this bad?","text":"

        Defining a field multiple times in a class body is redundant and likely a mistake.

        ","tags":["PIE794"]},{"location":"rules/duplicate-class-field-definition/#example","title":"Example","text":"
        class Person:\n    name = Tom\n    ...\n    name = Ben\n

        Use instead:

        class Person:\n    name = Tom\n    ...\n
        ","tags":["PIE794"]},{"location":"rules/duplicate-handler-exception/","title":"duplicate-handler-exception (B014)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B014"]},{"location":"rules/duplicate-handler-exception/#what-it-does","title":"What it does","text":"

        Checks for exception handlers that catch duplicate exceptions.

        ","tags":["B014"]},{"location":"rules/duplicate-handler-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Including the same exception multiple times in the same handler is redundant, as the first exception will catch the exception, making the second exception unreachable. The same applies to exception hierarchies, as a handler for a parent exception (like Exception) will also catch child exceptions (like ValueError).

        ","tags":["B014"]},{"location":"rules/duplicate-handler-exception/#example","title":"Example","text":"
        try:\n    ...\nexcept (Exception, ValueError):  # `Exception` includes `ValueError`.\n    ...\n

        Use instead:

        try:\n    ...\nexcept Exception:\n    ...\n
        ","tags":["B014"]},{"location":"rules/duplicate-handler-exception/#references","title":"References","text":"
        • Python documentation: except clause
        • Python documentation: Exception hierarchy
        ","tags":["B014"]},{"location":"rules/duplicate-isinstance-call/","title":"duplicate-isinstance-call (SIM101)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM101"]},{"location":"rules/duplicate-isinstance-call/#what-it-does","title":"What it does","text":"

        Checks for multiple isinstance calls on the same target.

        ","tags":["SIM101"]},{"location":"rules/duplicate-isinstance-call/#why-is-this-bad","title":"Why is this bad?","text":"

        To check if an object is an instance of any one of multiple types or classes, it is unnecessary to use multiple isinstance calls, as the second argument of the isinstance built-in function accepts a tuple of types and classes.

        Using a single isinstance call implements the same behavior with more concise code and clearer intent.

        ","tags":["SIM101"]},{"location":"rules/duplicate-isinstance-call/#example","title":"Example","text":"
        if isinstance(obj, int) or isinstance(obj, float):\n    pass\n

        Use instead:

        if isinstance(obj, (int, float)):\n    pass\n
        ","tags":["SIM101"]},{"location":"rules/duplicate-isinstance-call/#references","title":"References","text":"
        • Python documentation: isinstance
        ","tags":["SIM101"]},{"location":"rules/duplicate-literal-member/","title":"duplicate-literal-member (PYI062)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI062"]},{"location":"rules/duplicate-literal-member/#what-it-does","title":"What it does","text":"

        Checks for duplicate members in a typing.Literal[] slice.

        ","tags":["PYI062"]},{"location":"rules/duplicate-literal-member/#why-is-this-bad","title":"Why is this bad?","text":"

        Duplicate literal members are redundant and should be removed.

        ","tags":["PYI062"]},{"location":"rules/duplicate-literal-member/#example","title":"Example","text":"
        foo: Literal[\"a\", \"b\", \"a\"]\n

        Use instead:

        foo: Literal[\"a\", \"b\"]\n
        ","tags":["PYI062"]},{"location":"rules/duplicate-literal-member/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the type annotation contains comments.

        Note that while the fix may flatten nested literals into a single top-level literal, the semantics of the annotation will remain unchanged.

        ","tags":["PYI062"]},{"location":"rules/duplicate-literal-member/#references","title":"References","text":"
        • Python documentation: typing.Literal
        ","tags":["PYI062"]},{"location":"rules/duplicate-try-block-exception/","title":"duplicate-try-block-exception (B025)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B025"]},{"location":"rules/duplicate-try-block-exception/#what-it-does","title":"What it does","text":"

        Checks for try-except blocks with duplicate exception handlers.

        ","tags":["B025"]},{"location":"rules/duplicate-try-block-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Duplicate exception handlers are redundant, as the first handler will catch the exception, making the second handler unreachable.

        ","tags":["B025"]},{"location":"rules/duplicate-try-block-exception/#example","title":"Example","text":"
        try:\n    ...\nexcept ValueError:\n    ...\nexcept ValueError:\n    ...\n

        Use instead:

        try:\n    ...\nexcept ValueError:\n    ...\n
        ","tags":["B025"]},{"location":"rules/duplicate-try-block-exception/#references","title":"References","text":"
        • Python documentation: except clause
        ","tags":["B025"]},{"location":"rules/duplicate-union-member/","title":"duplicate-union-member (PYI016)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI016"]},{"location":"rules/duplicate-union-member/#what-it-does","title":"What it does","text":"

        Checks for duplicate union members.

        ","tags":["PYI016"]},{"location":"rules/duplicate-union-member/#why-is-this-bad","title":"Why is this bad?","text":"

        Duplicate union members are redundant and should be removed.

        ","tags":["PYI016"]},{"location":"rules/duplicate-union-member/#example","title":"Example","text":"
        foo: str | str\n

        Use instead:

        foo: str\n
        ","tags":["PYI016"]},{"location":"rules/duplicate-union-member/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe unless the union contains comments.

        For nested union, the fix will flatten type expressions into a single top-level union.

        ","tags":["PYI016"]},{"location":"rules/duplicate-union-member/#references","title":"References","text":"
        • Python documentation: typing.Union
        ","tags":["PYI016"]},{"location":"rules/duplicate-value/","title":"duplicate-value (B033)","text":"

        Derived from the flake8-bugbear linter.

        Fix is sometimes available.

        ","tags":["B033"]},{"location":"rules/duplicate-value/#what-it-does","title":"What it does","text":"

        Checks for set literals that contain duplicate items.

        ","tags":["B033"]},{"location":"rules/duplicate-value/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, sets are unordered collections of unique elements. Including a duplicate item in a set literal is redundant, as the duplicate item will be replaced with a single item at runtime.

        ","tags":["B033"]},{"location":"rules/duplicate-value/#example","title":"Example","text":"
        {1, 2, 3, 1}\n

        Use instead:

        {1, 2, 3}\n
        ","tags":["B033"]},{"location":"rules/ellipsis-in-non-empty-class-body/","title":"ellipsis-in-non-empty-class-body (PYI013)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI013"]},{"location":"rules/ellipsis-in-non-empty-class-body/#what-it-does","title":"What it does","text":"

        Removes ellipses (...) in otherwise non-empty class bodies.

        ","tags":["PYI013"]},{"location":"rules/ellipsis-in-non-empty-class-body/#why-is-this-bad","title":"Why is this bad?","text":"

        An ellipsis in a class body is only necessary if the class body is otherwise empty. If the class body is non-empty, then the ellipsis is redundant.

        ","tags":["PYI013"]},{"location":"rules/ellipsis-in-non-empty-class-body/#example","title":"Example","text":"
        class Foo:\n    ...\n    value: int\n

        Use instead:

        class Foo:\n    value: int\n
        ","tags":["PYI013"]},{"location":"rules/empty-comment/","title":"empty-comment (PLR2044)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLR2044"]},{"location":"rules/empty-comment/#what-it-does","title":"What it does","text":"

        Checks for a # symbol appearing on a line not followed by an actual comment.

        ","tags":["PLR2044"]},{"location":"rules/empty-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Empty comments don't provide any clarity to the code, and just add clutter. Either add a comment or delete the empty comment.

        ","tags":["PLR2044"]},{"location":"rules/empty-comment/#example","title":"Example","text":"
        class Foo:  #\n    pass\n

        Use instead:

        class Foo:\n    pass\n
        ","tags":["PLR2044"]},{"location":"rules/empty-comment/#references","title":"References","text":"
        • Pylint documentation
        ","tags":["PLR2044"]},{"location":"rules/empty-docstring-section/","title":"empty-docstring-section (D414)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D414"]},{"location":"rules/empty-docstring-section/#what-it-does","title":"What it does","text":"

        Checks for docstrings with empty sections.

        ","tags":["D414"]},{"location":"rules/empty-docstring-section/#why-is-this-bad","title":"Why is this bad?","text":"

        An empty section in a multiline docstring likely indicates an unfinished or incomplete docstring.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. Each section body should be non-empty; empty sections should either have content added to them, or be removed entirely.

        ","tags":["D414"]},{"location":"rules/empty-docstring-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D414"]},{"location":"rules/empty-docstring-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Guide
        ","tags":["D414"]},{"location":"rules/empty-docstring/","title":"empty-docstring (D419)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D419"]},{"location":"rules/empty-docstring/#what-it-does","title":"What it does","text":"

        Checks for empty docstrings.

        ","tags":["D419"]},{"location":"rules/empty-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        An empty docstring is indicative of incomplete documentation. It should either be removed or replaced with a meaningful docstring.

        ","tags":["D419"]},{"location":"rules/empty-docstring/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D419"]},{"location":"rules/empty-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D419"]},{"location":"rules/empty-method-without-abstract-decorator/","title":"empty-method-without-abstract-decorator (B027)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B027"]},{"location":"rules/empty-method-without-abstract-decorator/#what-it-does","title":"What it does","text":"

        Checks for empty methods in abstract base classes without an abstract decorator.

        ","tags":["B027"]},{"location":"rules/empty-method-without-abstract-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        Empty methods in abstract base classes without an abstract decorator may be be indicative of a mistake. If the method is meant to be abstract, add an @abstractmethod decorator to the method.

        ","tags":["B027"]},{"location":"rules/empty-method-without-abstract-decorator/#example","title":"Example","text":"
        from abc import ABC\n\n\nclass Foo(ABC):\n    def method(self): ...\n

        Use instead:

        from abc import ABC, abstractmethod\n\n\nclass Foo(ABC):\n    @abstractmethod\n    def method(self): ...\n
        ","tags":["B027"]},{"location":"rules/empty-method-without-abstract-decorator/#references","title":"References","text":"
        • Python documentation: abc
        ","tags":["B027"]},{"location":"rules/empty-type-checking-block/","title":"empty-type-checking-block (TC005)","text":"

        Derived from the flake8-type-checking linter.

        Fix is always available.

        ","tags":["TC005"]},{"location":"rules/empty-type-checking-block/#what-it-does","title":"What it does","text":"

        Checks for an empty type-checking block.

        ","tags":["TC005"]},{"location":"rules/empty-type-checking-block/#why-is-this-bad","title":"Why is this bad?","text":"

        The type-checking block does not do anything and should be removed to avoid confusion.

        ","tags":["TC005"]},{"location":"rules/empty-type-checking-block/#example","title":"Example","text":"
        from typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    pass\n\nprint(\"Hello, world!\")\n

        Use instead:

        print(\"Hello, world!\")\n
        ","tags":["TC005"]},{"location":"rules/empty-type-checking-block/#references","title":"References","text":"
        • PEP 563: Runtime annotation resolution and TYPE_CHECKING
        ","tags":["TC005"]},{"location":"rules/enumerate-for-loop/","title":"enumerate-for-loop (SIM113)","text":"

        Derived from the flake8-simplify linter.

        ","tags":["SIM113"]},{"location":"rules/enumerate-for-loop/#what-it-does","title":"What it does","text":"

        Checks for for loops with explicit loop-index variables that can be replaced with enumerate().

        ","tags":["SIM113"]},{"location":"rules/enumerate-for-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over a sequence, it's often desirable to keep track of the index of each element alongside the element itself. Prefer the enumerate builtin over manually incrementing a counter variable within the loop, as enumerate is more concise and idiomatic.

        ","tags":["SIM113"]},{"location":"rules/enumerate-for-loop/#example","title":"Example","text":"
        fruits = [\"apple\", \"banana\", \"cherry\"]\nfor fruit in fruits:\n    print(f\"{i + 1}. {fruit}\")\n    i += 1\n

        Use instead:

        fruits = [\"apple\", \"banana\", \"cherry\"]\nfor i, fruit in enumerate(fruits):\n    print(f\"{i + 1}. {fruit}\")\n
        ","tags":["SIM113"]},{"location":"rules/enumerate-for-loop/#references","title":"References","text":"
        • Python documentation: enumerate
        ","tags":["SIM113"]},{"location":"rules/eq-without-hash/","title":"eq-without-hash (PLW1641)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW1641"]},{"location":"rules/eq-without-hash/#what-it-does","title":"What it does","text":"

        Checks for classes that implement __eq__ but not __hash__.

        ","tags":["PLW1641"]},{"location":"rules/eq-without-hash/#why-is-this-bad","title":"Why is this bad?","text":"

        A class that implements __eq__ but not __hash__ will have its hash method implicitly set to None, regardless of if a super class defines __hash__. This will cause the class to be unhashable, will in turn cause issues when using the class as a key in a dictionary or a member of a set.

        ","tags":["PLW1641"]},{"location":"rules/eq-without-hash/#example","title":"Example","text":"
        class Person:\n    def __init__(self):\n        self.name = \"monty\"\n\n    def __eq__(self, other):\n        return isinstance(other, Person) and other.name == self.name\n

        Use instead:

        class Person:\n    def __init__(self):\n        self.name = \"monty\"\n\n    def __eq__(self, other):\n        return isinstance(other, Person) and other.name == self.name\n\n    def __hash__(self):\n        return hash(self.name)\n

        This issue is particularly tricky with inheritance. Even if a parent class correctly implements both __eq__ and __hash__, overriding __eq__ in a child class without also implementing __hash__ will make the child class unhashable:

        class Person:\n    def __init__(self):\n        self.name = \"monty\"\n\n    def __eq__(self, other):\n        return isinstance(other, Person) and other.name == self.name\n\n    def __hash__(self):\n        return hash(self.name)\n\n\nclass Developer(Person):\n    def __init__(self):\n        super().__init__()\n        self.language = \"python\"\n\n    def __eq__(self, other):\n        return (\n            super().__eq__(other)\n            and isinstance(other, Developer)\n            and self.language == other.language\n        )\n\n\nhash(Developer())  # TypeError: unhashable type: 'Developer'\n

        One way to fix this is to retain the implementation of __hash__ from the parent class:

        class Developer(Person):\n    def __init__(self):\n        super().__init__()\n        self.language = \"python\"\n\n    def __eq__(self, other):\n        return (\n            super().__eq__(other)\n            and isinstance(other, Developer)\n            and self.language == other.language\n        )\n\n    __hash__ = Person.__hash__\n
        ","tags":["PLW1641"]},{"location":"rules/eq-without-hash/#references","title":"References","text":"
        • Python documentation: object.__hash__
        • Python glossary: hashable
        ","tags":["PLW1641"]},{"location":"rules/error-instead-of-exception/","title":"error-instead-of-exception (TRY400)","text":"

        Derived from the tryceratops linter.

        Fix is sometimes available.

        ","tags":["TRY400"]},{"location":"rules/error-instead-of-exception/#what-it-does","title":"What it does","text":"

        Checks for uses of logging.error instead of logging.exception when logging an exception.

        ","tags":["TRY400"]},{"location":"rules/error-instead-of-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        logging.exception logs the exception and the traceback, while logging.error only logs the exception. The former is more appropriate when logging an exception, as the traceback is often useful for debugging.

        ","tags":["TRY400"]},{"location":"rules/error-instead-of-exception/#example","title":"Example","text":"
        import logging\n\n\ndef func():\n    try:\n        raise NotImplementedError\n    except NotImplementedError:\n        logging.error(\"Exception occurred\")\n

        Use instead:

        import logging\n\n\ndef func():\n    try:\n        raise NotImplementedError\n    except NotImplementedError:\n        logging.exception(\"Exception occurred\")\n
        ","tags":["TRY400"]},{"location":"rules/error-instead-of-exception/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe when run against logging.error calls, but unsafe when marked against other logger-like calls (e.g., logger.error), since the rule is prone to false positives when detecting logger-like calls outside of the logging module.

        ","tags":["TRY400"]},{"location":"rules/error-instead-of-exception/#references","title":"References","text":"
        • Python documentation: logging.exception
        ","tags":["TRY400"]},{"location":"rules/error-suffix-on-exception-name/","title":"error-suffix-on-exception-name (N818)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N818"]},{"location":"rules/error-suffix-on-exception-name/#what-it-does","title":"What it does","text":"

        Checks for custom exception definitions that omit the Error suffix.

        ","tags":["N818"]},{"location":"rules/error-suffix-on-exception-name/#why-is-this-bad","title":"Why is this bad?","text":"

        The Error suffix is recommended by PEP 8:

        Because exceptions should be classes, the class naming convention applies here. However, you should use the suffix \"Error\" on your exception names (if the exception actually is an error).

        ","tags":["N818"]},{"location":"rules/error-suffix-on-exception-name/#example","title":"Example","text":"
        class Validation(Exception): ...\n

        Use instead:

        class ValidationError(Exception): ...\n
        ","tags":["N818"]},{"location":"rules/error-suffix-on-exception-name/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N818"]},{"location":"rules/escape-sequence-in-docstring/","title":"escape-sequence-in-docstring (D301)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D301"]},{"location":"rules/escape-sequence-in-docstring/#what-it-does","title":"What it does","text":"

        Checks for docstrings that include backslashes, but are not defined as raw string literals.

        ","tags":["D301"]},{"location":"rules/escape-sequence-in-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, backslashes are typically used to escape characters in strings. In raw strings (those prefixed with an r), however, backslashes are treated as literal characters.

        PEP 257 recommends the use of raw strings (i.e., r\"\"\"raw triple double quotes\"\"\") for docstrings that include backslashes. The use of a raw string ensures that any backslashes are treated as literal characters, and not as escape sequences, which avoids confusion.

        ","tags":["D301"]},{"location":"rules/escape-sequence-in-docstring/#example","title":"Example","text":"
        def foobar():\n    \"\"\"Docstring for foo\\bar.\"\"\"\n\n\nfoobar.__doc__  # \"Docstring for foar.\"\n

        Use instead:

        def foobar():\n    r\"\"\"Docstring for foo\\bar.\"\"\"\n\n\nfoobar.__doc__  # \"Docstring for foo\\bar.\"\n
        ","tags":["D301"]},{"location":"rules/escape-sequence-in-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • Python documentation: String and Bytes literals
        ","tags":["D301"]},{"location":"rules/eval/","title":"eval (PGH001)","text":"

        Derived from the pygrep-hooks linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["PGH001"]},{"location":"rules/eval/#removed","title":"Removed","text":"

        This rule is identical to S307 which should be used instead.

        ","tags":["PGH001"]},{"location":"rules/eval/#what-it-does","title":"What it does","text":"

        Checks for uses of the builtin eval() function.

        ","tags":["PGH001"]},{"location":"rules/eval/#why-is-this-bad","title":"Why is this bad?","text":"

        The eval() function is insecure as it enables arbitrary code execution.

        ","tags":["PGH001"]},{"location":"rules/eval/#example","title":"Example","text":"
        def foo():\n    x = eval(input(\"Enter a number: \"))\n    ...\n

        Use instead:

        def foo():\n    x = input(\"Enter a number: \")\n    ...\n
        ","tags":["PGH001"]},{"location":"rules/eval/#references","title":"References","text":"
        • Python documentation: eval
        • Eval really is dangerous by Ned Batchelder
        ","tags":["PGH001"]},{"location":"rules/exc-info-outside-except-handler/","title":"exc-info-outside-except-handler (LOG014)","text":"

        Derived from the flake8-logging linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["LOG014"]},{"location":"rules/exc-info-outside-except-handler/#what-it-does","title":"What it does","text":"

        Checks for logging calls with exc_info= outside exception handlers.

        ","tags":["LOG014"]},{"location":"rules/exc-info-outside-except-handler/#why-is-this-bad","title":"Why is this bad?","text":"

        Using exc_info=True outside of an exception handler attaches None as the exception information, leading to confusing messages:

        >>> logging.warning(\"Uh oh\", exc_info=True)\nWARNING:root:Uh oh\nNoneType: None\n
        ","tags":["LOG014"]},{"location":"rules/exc-info-outside-except-handler/#example","title":"Example","text":"
        import logging\n\n\nlogging.warning(\"Foobar\", exc_info=True)\n

        Use instead:

        import logging\n\n\nlogging.warning(\"Foobar\")\n
        ","tags":["LOG014"]},{"location":"rules/exc-info-outside-except-handler/#fix-safety","title":"Fix safety","text":"

        The fix is always marked as unsafe, as it changes runtime behavior.

        ","tags":["LOG014"]},{"location":"rules/except-with-empty-tuple/","title":"except-with-empty-tuple (B029)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B029"]},{"location":"rules/except-with-empty-tuple/#what-it-does","title":"What it does","text":"

        Checks for exception handlers that catch an empty tuple.

        ","tags":["B029"]},{"location":"rules/except-with-empty-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        An exception handler that catches an empty tuple will not catch anything, and is indicative of a mistake. Instead, add exceptions to the except clause.

        ","tags":["B029"]},{"location":"rules/except-with-empty-tuple/#example","title":"Example","text":"
        try:\n    1 / 0\nexcept ():\n    ...\n

        Use instead:

        try:\n    1 / 0\nexcept ZeroDivisionError:\n    ...\n
        ","tags":["B029"]},{"location":"rules/except-with-empty-tuple/#references","title":"References","text":"
        • Python documentation: except clause
        ","tags":["B029"]},{"location":"rules/except-with-non-exception-classes/","title":"except-with-non-exception-classes (B030)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B030"]},{"location":"rules/except-with-non-exception-classes/#what-it-does","title":"What it does","text":"

        Checks for exception handlers that catch non-exception classes.

        ","tags":["B030"]},{"location":"rules/except-with-non-exception-classes/#why-is-this-bad","title":"Why is this bad?","text":"

        Catching classes that do not inherit from BaseException will raise a TypeError.

        ","tags":["B030"]},{"location":"rules/except-with-non-exception-classes/#example","title":"Example","text":"
        try:\n    1 / 0\nexcept 1:\n    ...\n

        Use instead:

        try:\n    1 / 0\nexcept ZeroDivisionError:\n    ...\n
        ","tags":["B030"]},{"location":"rules/except-with-non-exception-classes/#references","title":"References","text":"
        • Python documentation: except clause
        • Python documentation: Built-in Exceptions
        ","tags":["B030"]},{"location":"rules/exception-without-exc-info/","title":"exception-without-exc-info (LOG007)","text":"

        Derived from the flake8-logging linter.

        ","tags":["LOG007"]},{"location":"rules/exception-without-exc-info/#what-it-does","title":"What it does","text":"

        Checks for uses of logging.exception() with exc_info set to False.

        ","tags":["LOG007"]},{"location":"rules/exception-without-exc-info/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging.exception() method captures the exception automatically, but accepts an optional exc_info argument to override this behavior. Setting exc_info to False disables the automatic capture of the exception and stack trace.

        Instead of setting exc_info to False, prefer logging.error(), which has equivalent behavior to logging.exception() with exc_info set to False, but is clearer in intent.

        ","tags":["LOG007"]},{"location":"rules/exception-without-exc-info/#example","title":"Example","text":"
        logging.exception(\"...\", exc_info=False)\n

        Use instead:

        logging.error(\"...\")\n
        ","tags":["LOG007"]},{"location":"rules/exec-builtin/","title":"exec-builtin (S102)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S102"]},{"location":"rules/exec-builtin/#what-it-does","title":"What it does","text":"

        Checks for uses of the builtin exec function.

        ","tags":["S102"]},{"location":"rules/exec-builtin/#why-is-this-bad","title":"Why is this bad?","text":"

        The exec() function is insecure as it allows for arbitrary code execution.

        ","tags":["S102"]},{"location":"rules/exec-builtin/#example","title":"Example","text":"
        exec(\"print('Hello World')\")\n
        ","tags":["S102"]},{"location":"rules/exec-builtin/#references","title":"References","text":"
        • Python documentation: exec
        • Common Weakness Enumeration: CWE-78
        ","tags":["S102"]},{"location":"rules/explicit-f-string-type-conversion/","title":"explicit-f-string-type-conversion (RUF010)","text":"

        Fix is always available.

        ","tags":["RUF010"]},{"location":"rules/explicit-f-string-type-conversion/#what-it-does","title":"What it does","text":"

        Checks for uses of str(), repr(), and ascii() as explicit type conversions within f-strings.

        ","tags":["RUF010"]},{"location":"rules/explicit-f-string-type-conversion/#why-is-this-bad","title":"Why is this bad?","text":"

        f-strings support dedicated conversion flags for these types, which are more succinct and idiomatic.

        Note that, in many cases, calling str() within an f-string is unnecessary and can be removed entirely, as the value will be converted to a string automatically, the notable exception being for classes that implement a custom __format__ method.

        ","tags":["RUF010"]},{"location":"rules/explicit-f-string-type-conversion/#example","title":"Example","text":"
        a = \"some string\"\nf\"{repr(a)}\"\n

        Use instead:

        a = \"some string\"\nf\"{a!r}\"\n
        ","tags":["RUF010"]},{"location":"rules/explicit-string-concatenation/","title":"explicit-string-concatenation (ISC003)","text":"

        Derived from the flake8-implicit-str-concat linter.

        ","tags":["ISC003"]},{"location":"rules/explicit-string-concatenation/#what-it-does","title":"What it does","text":"

        Checks for string literals that are explicitly concatenated (using the + operator).

        ","tags":["ISC003"]},{"location":"rules/explicit-string-concatenation/#why-is-this-bad","title":"Why is this bad?","text":"

        For string literals that wrap across multiple lines, implicit string concatenation within parentheses is preferred over explicit concatenation using the + operator, as the former is more readable.

        ","tags":["ISC003"]},{"location":"rules/explicit-string-concatenation/#example","title":"Example","text":"
        z = (\n    \"The quick brown fox jumps over the lazy \"\n    + \"dog\"\n)\n

        Use instead:

        z = (\n    \"The quick brown fox jumps over the lazy \"\n    \"dog\"\n)\n
        ","tags":["ISC003"]},{"location":"rules/expr-and-false/","title":"expr-and-false (SIM223)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM223"]},{"location":"rules/expr-and-false/#what-it-does","title":"What it does","text":"

        Checks for and expressions that contain falsey values.

        ","tags":["SIM223"]},{"location":"rules/expr-and-false/#why-is-this-bad","title":"Why is this bad?","text":"

        If the expression is used as a condition, it can be replaced in-full with False.

        In other cases, the expression can be short-circuited to the first falsey value.

        By using False (or the first falsey value), the code is more concise and easier to understand, since it no longer contains redundant conditions.

        ","tags":["SIM223"]},{"location":"rules/expr-and-false/#example","title":"Example","text":"
        if x and [] and y:\n    pass\n\na = x and [] and y\n

        Use instead:

        if False:\n    pass\n\na = x and []\n
        ","tags":["SIM223"]},{"location":"rules/expr-and-not-expr/","title":"expr-and-not-expr (SIM220)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM220"]},{"location":"rules/expr-and-not-expr/#what-it-does","title":"What it does","text":"

        Checks for and expressions that include both an expression and its negation.

        ","tags":["SIM220"]},{"location":"rules/expr-and-not-expr/#why-is-this-bad","title":"Why is this bad?","text":"

        An and expression that includes both an expression and its negation will always evaluate to False.

        ","tags":["SIM220"]},{"location":"rules/expr-and-not-expr/#example","title":"Example","text":"
        x and not x\n
        ","tags":["SIM220"]},{"location":"rules/expr-and-not-expr/#references","title":"References","text":"
        • Python documentation: Boolean operations
        ","tags":["SIM220"]},{"location":"rules/expr-or-not-expr/","title":"expr-or-not-expr (SIM221)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM221"]},{"location":"rules/expr-or-not-expr/#what-it-does","title":"What it does","text":"

        Checks for or expressions that include both an expression and its negation.

        ","tags":["SIM221"]},{"location":"rules/expr-or-not-expr/#why-is-this-bad","title":"Why is this bad?","text":"

        An or expression that includes both an expression and its negation will always evaluate to True.

        ","tags":["SIM221"]},{"location":"rules/expr-or-not-expr/#example","title":"Example","text":"
        x or not x\n
        ","tags":["SIM221"]},{"location":"rules/expr-or-not-expr/#references","title":"References","text":"
        • Python documentation: Boolean operations
        ","tags":["SIM221"]},{"location":"rules/expr-or-true/","title":"expr-or-true (SIM222)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM222"]},{"location":"rules/expr-or-true/#what-it-does","title":"What it does","text":"

        Checks for or expressions that contain truthy values.

        ","tags":["SIM222"]},{"location":"rules/expr-or-true/#why-is-this-bad","title":"Why is this bad?","text":"

        If the expression is used as a condition, it can be replaced in-full with True.

        In other cases, the expression can be short-circuited to the first truthy value.

        By using True (or the first truthy value), the code is more concise and easier to understand, since it no longer contains redundant conditions.

        ","tags":["SIM222"]},{"location":"rules/expr-or-true/#example","title":"Example","text":"
        if x or [1] or y:\n    pass\n\na = x or [1] or y\n

        Use instead:

        if True:\n    pass\n\na = x or [1]\n
        ","tags":["SIM222"]},{"location":"rules/expressions-in-star-assignment/","title":"expressions-in-star-assignment (F621)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F621"]},{"location":"rules/expressions-in-star-assignment/#what-it-does","title":"What it does","text":"

        Checks for the use of too many expressions in starred assignment statements.

        ","tags":["F621"]},{"location":"rules/expressions-in-star-assignment/#why-is-this-bad","title":"Why is this bad?","text":"

        In assignment statements, starred expressions can be used to unpack iterables.

        In Python 3, no more than 1 \\<< 8 assignments are allowed before a starred expression, and no more than 1 \\<< 24 expressions are allowed after a starred expression.

        ","tags":["F621"]},{"location":"rules/expressions-in-star-assignment/#references","title":"References","text":"
        • PEP 3132 \u2013 Extended Iterable Unpacking
        ","tags":["F621"]},{"location":"rules/extraneous-parentheses/","title":"extraneous-parentheses (UP034)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP034"]},{"location":"rules/extraneous-parentheses/#what-it-does","title":"What it does","text":"

        Checks for extraneous parentheses.

        ","tags":["UP034"]},{"location":"rules/extraneous-parentheses/#why-is-this-bad","title":"Why is this bad?","text":"

        Extraneous parentheses are redundant, and can be removed to improve readability while retaining identical semantics.

        ","tags":["UP034"]},{"location":"rules/extraneous-parentheses/#example","title":"Example","text":"
        print((\"Hello, world\"))\n

        Use instead:

        print(\"Hello, world\")\n
        ","tags":["UP034"]},{"location":"rules/f-string-docstring/","title":"f-string-docstring (B021)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B021"]},{"location":"rules/f-string-docstring/#what-it-does","title":"What it does","text":"

        Checks for docstrings that are written via f-strings.

        ","tags":["B021"]},{"location":"rules/f-string-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        Python will interpret the f-string as a joined string, rather than as a docstring. As such, the \"docstring\" will not be accessible via the __doc__ attribute, nor will it be picked up by any automated documentation tooling.

        ","tags":["B021"]},{"location":"rules/f-string-docstring/#example","title":"Example","text":"
        def foo():\n    f\"\"\"Not a docstring.\"\"\"\n

        Use instead:

        def foo():\n    \"\"\"A docstring.\"\"\"\n
        ","tags":["B021"]},{"location":"rules/f-string-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • Python documentation: Formatted string literals
        ","tags":["B021"]},{"location":"rules/f-string-in-exception/","title":"f-string-in-exception (EM102)","text":"

        Derived from the flake8-errmsg linter.

        Fix is sometimes available.

        ","tags":["EM102"]},{"location":"rules/f-string-in-exception/#what-it-does","title":"What it does","text":"

        Checks for the use of f-strings in exception constructors.

        ","tags":["EM102"]},{"location":"rules/f-string-in-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Python includes the raise in the default traceback (and formatters like Rich and IPython do too).

        By using an f-string, the error message will be duplicated in the traceback, which can make the traceback less readable.

        ","tags":["EM102"]},{"location":"rules/f-string-in-exception/#example","title":"Example","text":"

        Given:

        sub = \"Some value\"\nraise RuntimeError(f\"{sub!r} is incorrect\")\n

        Python will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 2, in <module>\n    raise RuntimeError(f\"{sub!r} is incorrect\")\nRuntimeError: 'Some value' is incorrect\n

        Instead, assign the string to a variable:

        sub = \"Some value\"\nmsg = f\"{sub!r} is incorrect\"\nraise RuntimeError(msg)\n

        Which will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 3, in <module>\n    raise RuntimeError(msg)\nRuntimeError: 'Some value' is incorrect\n
        ","tags":["EM102"]},{"location":"rules/f-string-in-get-text-func-call/","title":"f-string-in-get-text-func-call (INT001)","text":"

        Derived from the flake8-gettext linter.

        ","tags":["INT001"]},{"location":"rules/f-string-in-get-text-func-call/#what-it-does","title":"What it does","text":"

        Checks for f-strings in gettext function calls.

        ","tags":["INT001"]},{"location":"rules/f-string-in-get-text-func-call/#why-is-this-bad","title":"Why is this bad?","text":"

        In the gettext API, the gettext function (often aliased to _) returns a translation of its input argument by looking it up in a translation catalog.

        Calling gettext with an f-string as its argument can cause unexpected behavior. Since the f-string is resolved before the function call, the translation catalog will look up the formatted string, rather than the f-string template.

        Instead, format the value returned by the function call, rather than its argument.

        ","tags":["INT001"]},{"location":"rules/f-string-in-get-text-func-call/#example","title":"Example","text":"
        from gettext import gettext as _\n\nname = \"Maria\"\n_(f\"Hello, {name}!\")  # Looks for \"Hello, Maria!\".\n

        Use instead:

        from gettext import gettext as _\n\nname = \"Maria\"\n_(\"Hello, %s!\") % name  # Looks for \"Hello, %s!\".\n
        ","tags":["INT001"]},{"location":"rules/f-string-in-get-text-func-call/#references","title":"References","text":"
        • Python documentation: gettext \u2014 Multilingual internationalization services
        ","tags":["INT001"]},{"location":"rules/f-string-missing-placeholders/","title":"f-string-missing-placeholders (F541)","text":"

        Derived from the Pyflakes linter.

        Fix is always available.

        ","tags":["F541"]},{"location":"rules/f-string-missing-placeholders/#what-it-does","title":"What it does","text":"

        Checks for f-strings that do not contain any placeholder expressions.

        ","tags":["F541"]},{"location":"rules/f-string-missing-placeholders/#why-is-this-bad","title":"Why is this bad?","text":"

        f-strings are a convenient way to format strings, but they are not necessary if there are no placeholder expressions to format. In this case, a regular string should be used instead, as an f-string without placeholders can be confusing for readers, who may expect such a placeholder to be present.

        An f-string without any placeholders could also indicate that the author forgot to add a placeholder expression.

        ","tags":["F541"]},{"location":"rules/f-string-missing-placeholders/#example","title":"Example","text":"
        f\"Hello, world!\"\n

        Use instead:

        \"Hello, world!\"\n

        Note: to maintain compatibility with PyFlakes, this rule only flags f-strings that are part of an implicit concatenation if none of the f-string segments contain placeholder expressions.

        For example:

        # Will not be flagged.\n(\n    f\"Hello,\"\n    f\" {name}!\"\n)\n\n# Will be flagged.\n(\n    f\"Hello,\"\n    f\" World!\"\n)\n

        See #10885 for more.

        ","tags":["F541"]},{"location":"rules/f-string-missing-placeholders/#references","title":"References","text":"
        • PEP 498 \u2013 Literal String Interpolation
        ","tags":["F541"]},{"location":"rules/f-string-number-format/","title":"f-string-number-format (FURB116)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB116"]},{"location":"rules/f-string-number-format/#what-it-does","title":"What it does","text":"

        Checks for uses of bin(...)[2:] (or hex, or oct) to convert an integer into a string.

        ","tags":["FURB116"]},{"location":"rules/f-string-number-format/#why-is-this-bad","title":"Why is this bad?","text":"

        When converting an integer to a baseless binary, hexadecimal, or octal string, using f-strings is more concise and readable than using the bin, hex, or oct functions followed by a slice.

        ","tags":["FURB116"]},{"location":"rules/f-string-number-format/#example","title":"Example","text":"
        print(bin(1337)[2:])\n

        Use instead:

        print(f\"{1337:b}\")\n
        ","tags":["FURB116"]},{"location":"rules/f-string-number-format/#fix-safety","title":"Fix safety","text":"

        The fix is only marked as safe for integer literals, all other cases are display-only, as they may change the runtime behaviour of the program or introduce syntax errors.

        ","tags":["FURB116"]},{"location":"rules/f-string/","title":"f-string (UP032)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP032"]},{"location":"rules/f-string/#what-it-does","title":"What it does","text":"

        Checks for str.format calls that can be replaced with f-strings.

        ","tags":["UP032"]},{"location":"rules/f-string/#why-is-this-bad","title":"Why is this bad?","text":"

        f-strings are more readable and generally preferred over str.format calls.

        ","tags":["UP032"]},{"location":"rules/f-string/#example","title":"Example","text":"
        \"{}\".format(foo)\n

        Use instead:

        f\"{foo}\"\n
        ","tags":["UP032"]},{"location":"rules/f-string/#references","title":"References","text":"
        • Python documentation: f-strings
        ","tags":["UP032"]},{"location":"rules/falsy-dict-get-fallback/","title":"falsy-dict-get-fallback (RUF056)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF056"]},{"location":"rules/falsy-dict-get-fallback/#what-it-does","title":"What it does","text":"

        Checks for dict.get(key, falsy_value) calls in boolean test positions.

        ","tags":["RUF056"]},{"location":"rules/falsy-dict-get-fallback/#why-is-this-bad","title":"Why is this bad?","text":"

        The default fallback None is already falsy.

        ","tags":["RUF056"]},{"location":"rules/falsy-dict-get-fallback/#example","title":"Example","text":"
        if dict.get(key, False):\n    ...\n

        Use instead:

        if dict.get(key):\n    ...\n
        ","tags":["RUF056"]},{"location":"rules/falsy-dict-get-fallback/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the dict.get() call contains comments between arguments.

        ","tags":["RUF056"]},{"location":"rules/fast-api-non-annotated-dependency/","title":"fast-api-non-annotated-dependency (FAST002)","text":"

        Derived from the FastAPI linter.

        Fix is sometimes available.

        ","tags":["FAST002"]},{"location":"rules/fast-api-non-annotated-dependency/#what-it-does","title":"What it does","text":"

        Identifies FastAPI routes with deprecated uses of Depends or similar.

        ","tags":["FAST002"]},{"location":"rules/fast-api-non-annotated-dependency/#why-is-this-bad","title":"Why is this bad?","text":"

        The FastAPI documentation recommends the use of typing.Annotated for defining route dependencies and parameters, rather than using Depends, Query or similar as a default value for a parameter. Using this approach everywhere helps ensure consistency and clarity in defining dependencies and parameters.

        Annotated was added to the typing module in Python 3.9; however, the third-party typing_extensions package provides a backport that can be used on older versions of Python.

        ","tags":["FAST002"]},{"location":"rules/fast-api-non-annotated-dependency/#example","title":"Example","text":"
        from fastapi import Depends, FastAPI\n\napp = FastAPI()\n\n\nasync def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):\n    return {\"q\": q, \"skip\": skip, \"limit\": limit}\n\n\n@app.get(\"/items/\")\nasync def read_items(commons: dict = Depends(common_parameters)):\n    return commons\n

        Use instead:

        from typing import Annotated\n\nfrom fastapi import Depends, FastAPI\n\napp = FastAPI()\n\n\nasync def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):\n    return {\"q\": q, \"skip\": skip, \"limit\": limit}\n\n\n@app.get(\"/items/\")\nasync def read_items(commons: Annotated[dict, Depends(common_parameters)]):\n    return commons\n
        ","tags":["FAST002"]},{"location":"rules/fast-api-non-annotated-dependency/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for Python versions before 3.9, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["FAST002"]},{"location":"rules/fast-api-non-annotated-dependency/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["FAST002"]},{"location":"rules/fast-api-redundant-response-model/","title":"fast-api-redundant-response-model (FAST001)","text":"

        Derived from the FastAPI linter.

        Fix is always available.

        ","tags":["FAST001"]},{"location":"rules/fast-api-redundant-response-model/#what-it-does","title":"What it does","text":"

        Checks for FastAPI routes that use the optional response_model parameter with the same type as the return type.

        ","tags":["FAST001"]},{"location":"rules/fast-api-redundant-response-model/#why-is-this-bad","title":"Why is this bad?","text":"

        FastAPI routes automatically infer the response model type from the return type, so specifying it explicitly is redundant.

        The response_model parameter is used to override the default response model type. For example, response_model can be used to specify that a non-serializable response type should instead be serialized via an alternative type.

        For more information, see the FastAPI documentation.

        ","tags":["FAST001"]},{"location":"rules/fast-api-redundant-response-model/#example","title":"Example","text":"
        from fastapi import FastAPI\nfrom pydantic import BaseModel\n\napp = FastAPI()\n\n\nclass Item(BaseModel):\n    name: str\n\n\n@app.post(\"/items/\", response_model=Item)\nasync def create_item(item: Item) -> Item:\n    return item\n

        Use instead:

        from fastapi import FastAPI\nfrom pydantic import BaseModel\n\napp = FastAPI()\n\n\nclass Item(BaseModel):\n    name: str\n\n\n@app.post(\"/items/\")\nasync def create_item(item: Item) -> Item:\n    return item\n
        ","tags":["FAST001"]},{"location":"rules/fast-api-unused-path-parameter/","title":"fast-api-unused-path-parameter (FAST003)","text":"

        Derived from the FastAPI linter.

        Fix is sometimes available.

        ","tags":["FAST003"]},{"location":"rules/fast-api-unused-path-parameter/#what-it-does","title":"What it does","text":"

        Identifies FastAPI routes that declare path parameters in the route path that are not included in the function signature.

        ","tags":["FAST003"]},{"location":"rules/fast-api-unused-path-parameter/#why-is-this-bad","title":"Why is this bad?","text":"

        Path parameters are used to extract values from the URL path.

        If a path parameter is declared in the route path but not in the function signature, it will not be accessible in the function body, which is likely a mistake.

        If a path parameter is declared in the route path, but as a positional-only argument in the function signature, it will also not be accessible in the function body, as FastAPI will not inject the parameter.

        ","tags":["FAST003"]},{"location":"rules/fast-api-unused-path-parameter/#known-problems","title":"Known problems","text":"

        If the path parameter is not a valid Python identifier (e.g., user-id, as opposed to user_id), FastAPI will normalize it. However, this rule simply ignores such path parameters, as FastAPI's normalization behavior is undocumented.

        ","tags":["FAST003"]},{"location":"rules/fast-api-unused-path-parameter/#example","title":"Example","text":"
        from fastapi import FastAPI\n\napp = FastAPI()\n\n\n@app.get(\"/things/{thing_id}\")\nasync def read_thing(query: str): ...\n

        Use instead:

        from fastapi import FastAPI\n\napp = FastAPI()\n\n\n@app.get(\"/things/{thing_id}\")\nasync def read_thing(thing_id: int, query: str): ...\n
        ","tags":["FAST003"]},{"location":"rules/fast-api-unused-path-parameter/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as modifying a function signature can change the behavior of the code.

        ","tags":["FAST003"]},{"location":"rules/first-word-uncapitalized/","title":"first-word-uncapitalized (D403)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D403"]},{"location":"rules/first-word-uncapitalized/#what-it-does","title":"What it does","text":"

        Checks for docstrings that do not start with a capital letter.

        ","tags":["D403"]},{"location":"rules/first-word-uncapitalized/#why-is-this-bad","title":"Why is this bad?","text":"

        The first non-whitespace character in a docstring should be capitalized for grammatical correctness and consistency.

        ","tags":["D403"]},{"location":"rules/first-word-uncapitalized/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"return the mean of the given values.\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D403"]},{"location":"rules/first-word-uncapitalized/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D403"]},{"location":"rules/flask-debug-true/","title":"flask-debug-true (S201)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S201"]},{"location":"rules/flask-debug-true/#what-it-does","title":"What it does","text":"

        Checks for uses of debug=True in Flask.

        ","tags":["S201"]},{"location":"rules/flask-debug-true/#why-is-this-bad","title":"Why is this bad?","text":"

        Enabling debug mode shows an interactive debugger in the browser if an error occurs, and allows running arbitrary Python code from the browser. This could leak sensitive information, or allow an attacker to run arbitrary code.

        ","tags":["S201"]},{"location":"rules/flask-debug-true/#example","title":"Example","text":"
        import flask\n\napp = Flask()\n\napp.run(debug=True)\n

        Use instead:

        import flask\n\napp = Flask()\n\napp.run(debug=os.environ[\"ENV\"] == \"dev\")\n
        ","tags":["S201"]},{"location":"rules/flask-debug-true/#references","title":"References","text":"
        • Flask documentation: Debug Mode
        ","tags":["S201"]},{"location":"rules/for-loop-set-mutations/","title":"for-loop-set-mutations (FURB142)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB142"]},{"location":"rules/for-loop-set-mutations/#what-it-does","title":"What it does","text":"

        Checks for code that updates a set with the contents of an iterable by using a for loop to call .add() or .discard() on each element separately.

        ","tags":["FURB142"]},{"location":"rules/for-loop-set-mutations/#why-is-this-bad","title":"Why is this bad?","text":"

        When adding or removing a batch of elements to or from a set, it's more idiomatic to use a single method call rather than adding or removing elements one by one.

        ","tags":["FURB142"]},{"location":"rules/for-loop-set-mutations/#example","title":"Example","text":"
        s = set()\n\nfor x in (1, 2, 3):\n    s.add(x)\n\nfor x in (1, 2, 3):\n    s.discard(x)\n

        Use instead:

        s = set()\n\ns.update((1, 2, 3))\ns.difference_update((1, 2, 3))\n
        ","tags":["FURB142"]},{"location":"rules/for-loop-set-mutations/#fix-safety","title":"Fix safety","text":"

        The fix will be marked as unsafe if applying the fix would delete any comments. Otherwise, it is marked as safe.

        ","tags":["FURB142"]},{"location":"rules/for-loop-set-mutations/#references","title":"References","text":"
        • Python documentation: set
        ","tags":["FURB142"]},{"location":"rules/for-loop-writes/","title":"for-loop-writes (FURB122)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB122"]},{"location":"rules/for-loop-writes/#what-it-does","title":"What it does","text":"

        Checks for the use of IOBase.write in a for loop.

        ","tags":["FURB122"]},{"location":"rules/for-loop-writes/#why-is-this-bad","title":"Why is this bad?","text":"

        When writing a batch of elements, it's more idiomatic to use a single method call to IOBase.writelines, rather than write elements one by one.

        ","tags":["FURB122"]},{"location":"rules/for-loop-writes/#example","title":"Example","text":"
        with Path(\"file\").open(\"w\") as f:\n    for line in lines:\n        f.write(line)\n\nwith Path(\"file\").open(\"wb\") as f:\n    for line in lines:\n        f.write(line.encode())\n

        Use instead:

        with Path(\"file\").open(\"w\") as f:\n    f.writelines(lines)\n\nwith Path(\"file\").open(\"wb\") as f:\n    f.writelines(line.encode() for line in lines)\n
        ","tags":["FURB122"]},{"location":"rules/for-loop-writes/#references","title":"References","text":"
        • Python documentation: io.IOBase.writelines
        ","tags":["FURB122"]},{"location":"rules/format-in-get-text-func-call/","title":"format-in-get-text-func-call (INT002)","text":"

        Derived from the flake8-gettext linter.

        ","tags":["INT002"]},{"location":"rules/format-in-get-text-func-call/#what-it-does","title":"What it does","text":"

        Checks for str.format calls in gettext function calls.

        ","tags":["INT002"]},{"location":"rules/format-in-get-text-func-call/#why-is-this-bad","title":"Why is this bad?","text":"

        In the gettext API, the gettext function (often aliased to _) returns a translation of its input argument by looking it up in a translation catalog.

        Calling gettext with a formatted string as its argument can cause unexpected behavior. Since the formatted string is resolved before the function call, the translation catalog will look up the formatted string, rather than the str.format-style template.

        Instead, format the value returned by the function call, rather than its argument.

        ","tags":["INT002"]},{"location":"rules/format-in-get-text-func-call/#example","title":"Example","text":"
        from gettext import gettext as _\n\nname = \"Maria\"\n_(\"Hello, {}!\".format(name))  # Looks for \"Hello, Maria!\".\n

        Use instead:

        from gettext import gettext as _\n\nname = \"Maria\"\n_(\"Hello, %s!\") % name  # Looks for \"Hello, %s!\".\n
        ","tags":["INT002"]},{"location":"rules/format-in-get-text-func-call/#references","title":"References","text":"
        • Python documentation: gettext \u2014 Multilingual internationalization services
        ","tags":["INT002"]},{"location":"rules/format-literals/","title":"format-literals (UP030)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP030"]},{"location":"rules/format-literals/#what-it-does","title":"What it does","text":"

        Checks for unnecessary positional indices in format strings.

        ","tags":["UP030"]},{"location":"rules/format-literals/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3.1 and later, format strings can use implicit positional references. For example, \"{0}, {1}\".format(\"Hello\", \"World\") can be rewritten as \"{}, {}\".format(\"Hello\", \"World\").

        If the positional indices appear exactly in-order, they can be omitted in favor of automatic indices to improve readability.

        ","tags":["UP030"]},{"location":"rules/format-literals/#example","title":"Example","text":"
        \"{0}, {1}\".format(\"Hello\", \"World\")  # \"Hello, World\"\n

        Use instead:

        \"{}, {}\".format(\"Hello\", \"World\")  # \"Hello, World\"\n

        This fix is marked as unsafe because:

        • Comments attached to arguments are not moved, which can cause comments to mismatch the actual arguments.
        • If arguments have side effects (e.g., print), reordering may change program behavior.
        ","tags":["UP030"]},{"location":"rules/format-literals/#references","title":"References","text":"
        • Python documentation: Format String Syntax
        • Python documentation: str.format
        ","tags":["UP030"]},{"location":"rules/forward-annotation-syntax-error/","title":"forward-annotation-syntax-error (F722)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F722"]},{"location":"rules/forward-annotation-syntax-error/#what-it-does","title":"What it does","text":"

        Checks for forward annotations that include invalid syntax.

        ","tags":["F722"]},{"location":"rules/forward-annotation-syntax-error/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, type annotations can be quoted as strings literals to enable references to types that have not yet been defined, known as \"forward references\".

        However, these quoted annotations must be valid Python expressions. The use of invalid syntax in a quoted annotation won't raise a SyntaxError, but will instead raise an error when type checking is performed.

        ","tags":["F722"]},{"location":"rules/forward-annotation-syntax-error/#example","title":"Example","text":"
        def foo() -> \"/\": ...\n
        ","tags":["F722"]},{"location":"rules/forward-annotation-syntax-error/#references","title":"References","text":"
        • PEP 563 \u2013 Postponed Evaluation of Annotations
        ","tags":["F722"]},{"location":"rules/fromisoformat-replace-z/","title":"fromisoformat-replace-z (FURB162)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB162"]},{"location":"rules/fromisoformat-replace-z/#what-it-does","title":"What it does","text":"

        Checks for datetime.fromisoformat() calls where the only argument is an inline replacement of Z with a zero offset timezone.

        ","tags":["FURB162"]},{"location":"rules/fromisoformat-replace-z/#why-is-this-bad","title":"Why is this bad?","text":"

        On Python 3.11 and later, datetime.fromisoformat() can handle most ISO 8601 formats including ones affixed with Z, so such an operation is unnecessary.

        More information on unsupported formats can be found in the official documentation.

        ","tags":["FURB162"]},{"location":"rules/fromisoformat-replace-z/#example","title":"Example","text":"
        from datetime import datetime\n\n\ndate = \"2025-01-01T00:00:00Z\"\n\ndatetime.fromisoformat(date.replace(\"Z\", \"+00:00\"))\ndatetime.fromisoformat(date[:-1] + \"-00\")\ndatetime.fromisoformat(date.strip(\"Z\", \"-0000\"))\ndatetime.fromisoformat(date.rstrip(\"Z\", \"-00:00\"))\n

        Use instead:

        from datetime import datetime\n\n\ndate = \"2025-01-01T00:00:00Z\"\n\ndatetime.fromisoformat(date)\n
        ","tags":["FURB162"]},{"location":"rules/fromisoformat-replace-z/#fix-safety","title":"Fix safety","text":"

        The fix is always marked as unsafe, as it might change the program's behaviour.

        For example, working code might become non-working:

        d = \"Z2025-01-01T00:00:00Z\"  # Note the leading `Z`\n\ndatetime.fromisoformat(d.strip(\"Z\") + \"+00:00\")  # Fine\ndatetime.fromisoformat(d)  # Runtime error\n
        ","tags":["FURB162"]},{"location":"rules/fromisoformat-replace-z/#references","title":"References","text":"
        • What\u2019s New In Python 3.11 \u00a7 datetime
        • fromisoformat
        ","tags":["FURB162"]},{"location":"rules/function-call-in-dataclass-default-argument/","title":"function-call-in-dataclass-default-argument (RUF009)","text":"","tags":["RUF009"]},{"location":"rules/function-call-in-dataclass-default-argument/#what-it-does","title":"What it does","text":"

        Checks for function calls in dataclass attribute defaults.

        ","tags":["RUF009"]},{"location":"rules/function-call-in-dataclass-default-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Function calls are only performed once, at definition time. The returned value is then reused by all instances of the dataclass. This can lead to unexpected behavior when the function call returns a mutable object, as changes to the object will be shared across all instances.

        If a field needs to be initialized with a mutable object, use the field(default_factory=...) pattern.

        Attributes whose default arguments are NewType calls where the original type is immutable are ignored.

        ","tags":["RUF009"]},{"location":"rules/function-call-in-dataclass-default-argument/#example","title":"Example","text":"
        from dataclasses import dataclass\n\n\ndef simple_list() -> list[int]:\n    return [1, 2, 3, 4]\n\n\n@dataclass\nclass A:\n    mutable_default: list[int] = simple_list()\n

        Use instead:

        from dataclasses import dataclass, field\n\n\ndef creating_list() -> list[int]:\n    return [1, 2, 3, 4]\n\n\n@dataclass\nclass A:\n    mutable_default: list[int] = field(default_factory=creating_list)\n
        ","tags":["RUF009"]},{"location":"rules/function-call-in-dataclass-default-argument/#options","title":"Options","text":"
        • lint.flake8-bugbear.extend-immutable-calls
        ","tags":["RUF009"]},{"location":"rules/function-call-in-default-argument/","title":"function-call-in-default-argument (B008)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B008"]},{"location":"rules/function-call-in-default-argument/#what-it-does","title":"What it does","text":"

        Checks for function calls in default function arguments.

        ","tags":["B008"]},{"location":"rules/function-call-in-default-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Any function call that's used in a default argument will only be performed once, at definition time. The returned value will then be reused by all calls to the function, which can lead to unexpected behaviour.

        Parameters with immutable type annotations will be ignored by this rule. Those whose default arguments are NewType calls where the original type is immutable are also ignored.

        Calls and types outside of the standard library can be marked as an exception to this rule with the lint.flake8-bugbear.extend-immutable-calls configuration option.

        ","tags":["B008"]},{"location":"rules/function-call-in-default-argument/#example","title":"Example","text":"
        def create_list() -> list[int]:\n    return [1, 2, 3]\n\n\ndef mutable_default(arg: list[int] = create_list()) -> list[int]:\n    arg.append(4)\n    return arg\n

        Use instead:

        def better(arg: list[int] | None = None) -> list[int]:\n    if arg is None:\n        arg = create_list()\n\n    arg.append(4)\n    return arg\n

        If the use of a singleton is intentional, assign the result call to a module-level variable, and use that variable in the default argument:

        ERROR = ValueError(\"Hosts weren't successfully added\")\n\n\ndef add_host(error: Exception = ERROR) -> None: ...\n
        ","tags":["B008"]},{"location":"rules/function-call-in-default-argument/#options","title":"Options","text":"
        • lint.flake8-bugbear.extend-immutable-calls
        ","tags":["B008"]},{"location":"rules/function-uses-loop-variable/","title":"function-uses-loop-variable (B023)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B023"]},{"location":"rules/function-uses-loop-variable/#what-it-does","title":"What it does","text":"

        Checks for function definitions that use a loop variable.

        ","tags":["B023"]},{"location":"rules/function-uses-loop-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        The loop variable is not bound in the function definition, so it will always have the value it had in the last iteration when the function is called.

        Instead, consider using a default argument to bind the loop variable at function definition time. Or, use functools.partial.

        ","tags":["B023"]},{"location":"rules/function-uses-loop-variable/#example","title":"Example","text":"
        adders = [lambda x: x + i for i in range(3)]\nvalues = [adder(1) for adder in adders]  # [3, 3, 3]\n

        Use instead:

        adders = [lambda x, i=i: x + i for i in range(3)]\nvalues = [adder(1) for adder in adders]  # [1, 2, 3]\n

        Or:

        from functools import partial\n\nadders = [partial(lambda x, i: x + i, i=i) for i in range(3)]\nvalues = [adder(1) for adder in adders]  # [1, 2, 3]\n
        ","tags":["B023"]},{"location":"rules/function-uses-loop-variable/#references","title":"References","text":"
        • The Hitchhiker's Guide to Python: Late Binding Closures
        • Python documentation: functools.partial
        ","tags":["B023"]},{"location":"rules/future-annotations-in-stub/","title":"future-annotations-in-stub (PYI044)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI044"]},{"location":"rules/future-annotations-in-stub/#what-it-does","title":"What it does","text":"

        Checks for the presence of the from __future__ import annotations import statement in stub files.

        ","tags":["PYI044"]},{"location":"rules/future-annotations-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files natively support forward references in all contexts, as stubs are never executed at runtime. (They should be thought of as \"data files\" for type checkers.) As such, the from __future__ import annotations import statement has no effect and should be omitted.

        ","tags":["PYI044"]},{"location":"rules/future-annotations-in-stub/#references","title":"References","text":"
        • Static Typing with Python: Type Stubs
        ","tags":["PYI044"]},{"location":"rules/future-feature-not-defined/","title":"future-feature-not-defined (F407)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F407"]},{"location":"rules/future-feature-not-defined/#what-it-does","title":"What it does","text":"

        Checks for __future__ imports that are not defined in the current Python version.

        ","tags":["F407"]},{"location":"rules/future-feature-not-defined/#why-is-this-bad","title":"Why is this bad?","text":"

        Importing undefined or unsupported members from the __future__ module is a SyntaxError.

        ","tags":["F407"]},{"location":"rules/future-feature-not-defined/#references","title":"References","text":"
        • Python documentation: __future__
        ","tags":["F407"]},{"location":"rules/future-required-type-annotation/","title":"future-required-type-annotation (FA102)","text":"

        Derived from the flake8-future-annotations linter.

        Fix is always available.

        ","tags":["FA102"]},{"location":"rules/future-required-type-annotation/#what-it-does","title":"What it does","text":"

        Checks for uses of PEP 585- and PEP 604-style type annotations in Python modules that lack the required from __future__ import annotations import for compatibility with older Python versions.

        ","tags":["FA102"]},{"location":"rules/future-required-type-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        Using PEP 585 and PEP 604 style annotations without a from __future__ import annotations import will cause runtime errors on Python versions prior to 3.9 and 3.10, respectively.

        By adding the __future__ import, the interpreter will no longer interpret annotations at evaluation time, making the code compatible with both past and future Python versions.

        This rule respects the target-version setting. For example, if your project targets Python 3.10 and above, adding from __future__ import annotations does not impact your ability to leverage PEP 604-style unions (e.g., to convert Optional[str] to str | None). As such, this rule will only flag such usages if your project targets Python 3.9 or below.

        ","tags":["FA102"]},{"location":"rules/future-required-type-annotation/#example","title":"Example","text":"
        def func(obj: dict[str, int | None]) -> None: ...\n

        Use instead:

        from __future__ import annotations\n\n\ndef func(obj: dict[str, int | None]) -> None: ...\n
        ","tags":["FA102"]},{"location":"rules/future-required-type-annotation/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as adding from __future__ import annotations may change the semantics of the program.

        ","tags":["FA102"]},{"location":"rules/future-required-type-annotation/#options","title":"Options","text":"
        • target-version
        ","tags":["FA102"]},{"location":"rules/future-rewritable-type-annotation/","title":"future-rewritable-type-annotation (FA100)","text":"

        Derived from the flake8-future-annotations linter.

        ","tags":["FA100"]},{"location":"rules/future-rewritable-type-annotation/#what-it-does","title":"What it does","text":"

        Checks for missing from __future__ import annotations imports upon detecting type annotations that can be written more succinctly under PEP 563.

        ","tags":["FA100"]},{"location":"rules/future-rewritable-type-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 585 enabled the use of a number of convenient type annotations, such as list[str] instead of List[str]. However, these annotations are only available on Python 3.9 and higher, unless the from __future__ import annotations import is present.

        Similarly, PEP 604 enabled the use of the | operator for unions, such as str | None instead of Optional[str]. However, these annotations are only available on Python 3.10 and higher, unless the from __future__ import annotations import is present.

        By adding the __future__ import, the pyupgrade rules can automatically migrate existing code to use the new syntax, even for older Python versions. This rule thus pairs well with pyupgrade and with Ruff's pyupgrade rules.

        This rule respects the target-version setting. For example, if your project targets Python 3.10 and above, adding from __future__ import annotations does not impact your ability to leverage PEP 604-style unions (e.g., to convert Optional[str] to str | None). As such, this rule will only flag such usages if your project targets Python 3.9 or below.

        ","tags":["FA100"]},{"location":"rules/future-rewritable-type-annotation/#example","title":"Example","text":"
        from typing import List, Dict, Optional\n\n\ndef func(obj: Dict[str, Optional[int]]) -> None: ...\n

        Use instead:

        from __future__ import annotations\n\nfrom typing import List, Dict, Optional\n\n\ndef func(obj: Dict[str, Optional[int]]) -> None: ...\n

        After running the additional pyupgrade rules:

        from __future__ import annotations\n\n\ndef func(obj: dict[str, int | None]) -> None: ...\n
        ","tags":["FA100"]},{"location":"rules/future-rewritable-type-annotation/#options","title":"Options","text":"
        • target-version
        ","tags":["FA100"]},{"location":"rules/generator-return-from-iter-method/","title":"generator-return-from-iter-method (PYI058)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI058"]},{"location":"rules/generator-return-from-iter-method/#what-it-does","title":"What it does","text":"

        Checks for simple __iter__ methods that return Generator, and for simple __aiter__ methods that return AsyncGenerator.

        ","tags":["PYI058"]},{"location":"rules/generator-return-from-iter-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Using (Async)Iterator for these methods is simpler and more elegant. More importantly, it also reflects the fact that the precise kind of iterator returned from an __iter__ method is usually an implementation detail that could change at any time. Type annotations help define a contract for a function; implementation details should not leak into that contract.

        For example:

        from collections.abc import AsyncGenerator, Generator\nfrom typing import Any\n\n\nclass CustomIterator:\n    def __iter__(self) -> Generator:\n        yield from range(42)\n\n\nclass CustomIterator2:\n    def __iter__(self) -> Generator[str, Any, None]:\n        yield from \"abcdefg\"\n

        Use instead:

        from collections.abc import Iterator\n\n\nclass CustomIterator:\n    def __iter__(self) -> Iterator:\n        yield from range(42)\n\n\nclass CustomIterator2:\n    def __iter__(self) -> Iterator[str]:\n        yield from \"abdefg\"\n
        ","tags":["PYI058"]},{"location":"rules/generator-return-from-iter-method/#fix-safety","title":"Fix safety","text":"

        This rule tries hard to avoid false-positive errors, and the rule's fix should always be safe for .pyi stub files. However, there is a slightly higher chance that a false positive might be emitted by this rule when applied to runtime Python (.py files). As such, the fix is marked as unsafe for any __iter__ or __aiter__ method in a .py file that has more than two statements (including docstrings) in its body.

        ","tags":["PYI058"]},{"location":"rules/generic-not-last-base-class/","title":"generic-not-last-base-class (PYI059)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PYI059"]},{"location":"rules/generic-not-last-base-class/#what-it-does","title":"What it does","text":"

        Checks for classes inheriting from typing.Generic[] where Generic[] is not the last base class in the bases tuple.

        ","tags":["PYI059"]},{"location":"rules/generic-not-last-base-class/#why-is-this-bad","title":"Why is this bad?","text":"

        If Generic[] is not the final class in the bases tuple, unexpected behaviour can occur at runtime (See this CPython issue for an example). The rule is also applied to stub files, but, unlike at runtime, in stubs it is purely enforced for stylistic consistency.

        For example:

        class LinkedList(Generic[T], Sized):\n    def push(self, item: T) -> None:\n        self._items.append(item)\n\nclass MyMapping(\n    Generic[K, V],\n    Iterable[Tuple[K, V]],\n    Container[Tuple[K, V]],\n):\n    ...\n

        Use instead:

        class LinkedList(Sized, Generic[T]):\n    def push(self, item: T) -> None:\n        self._items.append(item)\n\nclass MyMapping(\n    Iterable[Tuple[K, V]],\n    Container[Tuple[K, V]],\n    Generic[K, V],\n):\n    ...\n
        ","tags":["PYI059"]},{"location":"rules/generic-not-last-base-class/#references","title":"References","text":"
        • typing.Generic documentation
        ","tags":["PYI059"]},{"location":"rules/get-attr-with-constant/","title":"get-attr-with-constant (B009)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B009"]},{"location":"rules/get-attr-with-constant/#what-it-does","title":"What it does","text":"

        Checks for uses of getattr that take a constant attribute value as an argument (e.g., getattr(obj, \"foo\")).

        ","tags":["B009"]},{"location":"rules/get-attr-with-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        getattr is used to access attributes dynamically. If the attribute is defined as a constant, it is no safer than a typical property access. When possible, prefer property access over getattr calls, as the former is more concise and idiomatic.

        ","tags":["B009"]},{"location":"rules/get-attr-with-constant/#example","title":"Example","text":"
        getattr(obj, \"foo\")\n

        Use instead:

        obj.foo\n
        ","tags":["B009"]},{"location":"rules/get-attr-with-constant/#references","title":"References","text":"
        • Python documentation: getattr
        ","tags":["B009"]},{"location":"rules/glob/","title":"glob (PTH207)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH207"]},{"location":"rules/glob/#what-it-does","title":"What it does","text":"

        Checks for the use of glob.glob() and glob.iglob().

        ","tags":["PTH207"]},{"location":"rules/glob/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os and glob.

        When possible, using Path object methods such as Path.glob() can improve readability over their low-level counterparts (e.g., glob.glob()).

        Note that glob.glob() and Path.glob() are not exact equivalents:

        glob-module functions Path.glob() Hidden files Hidden files are excluded by default. On Python 3.11+, the include_hidden keyword can be used to include hidden directories. Includes hidden files by default. Eagerness glob.iglob() returns a lazy iterator. Under the hood, glob.glob() simply converts the iterator to a list. Path.glob() returns a lazy iterator. Working directory glob.glob() and glob.iglob() take a root_dir keyword to set the current working directory. Path.rglob() can be used to return the relative path. Globstar (**) The recursive flag must be set to True for the ** pattern to match any files and zero or more directories, subdirectories, and symbolic links. The ** pattern in Path.glob() means \"this directory and all subdirectories, recursively\". In other words, it enables recursive globbing.","tags":["PTH207"]},{"location":"rules/glob/#example","title":"Example","text":"
        import glob\nimport os\n\nglob.glob(os.path.join(\"my_path\", \"requirements*.txt\"))\n

        Use instead:

        from pathlib import Path\n\nPath(\"my_path\").glob(\"requirements*.txt\")\n
        ","tags":["PTH207"]},{"location":"rules/glob/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH207"]},{"location":"rules/glob/#references","title":"References","text":"
        • Python documentation: Path.glob
        • Python documentation: Path.rglob
        • Python documentation: glob.glob
        • Python documentation: glob.iglob
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH207"]},{"location":"rules/global-at-module-level/","title":"global-at-module-level (PLW0604)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0604"]},{"location":"rules/global-at-module-level/#what-it-does","title":"What it does","text":"

        Checks for uses of the global keyword at the module level.

        ","tags":["PLW0604"]},{"location":"rules/global-at-module-level/#why-is-this-bad","title":"Why is this bad?","text":"

        The global keyword is used within functions to indicate that a name refers to a global variable, rather than a local variable.

        At the module level, all names are global by default, so the global keyword is redundant.

        ","tags":["PLW0604"]},{"location":"rules/global-statement/","title":"global-statement (PLW0603)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0603"]},{"location":"rules/global-statement/#what-it-does","title":"What it does","text":"

        Checks for the use of global statements to update identifiers.

        ","tags":["PLW0603"]},{"location":"rules/global-statement/#why-is-this-bad","title":"Why is this bad?","text":"

        Pylint discourages the use of global variables as global mutable state is a common source of bugs and confusing behavior.

        ","tags":["PLW0603"]},{"location":"rules/global-statement/#example","title":"Example","text":"
        var = 1\n\n\ndef foo():\n    global var  # [global-statement]\n    var = 10\n    print(var)\n\n\nfoo()\nprint(var)\n

        Use instead:

        var = 1\n\n\ndef foo():\n    var = 10\n    print(var)\n    return var\n\n\nvar = foo()\nprint(var)\n
        ","tags":["PLW0603"]},{"location":"rules/global-variable-not-assigned/","title":"global-variable-not-assigned (PLW0602)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0602"]},{"location":"rules/global-variable-not-assigned/#what-it-does","title":"What it does","text":"

        Checks for global variables that are not assigned a value in the current scope.

        ","tags":["PLW0602"]},{"location":"rules/global-variable-not-assigned/#why-is-this-bad","title":"Why is this bad?","text":"

        The global keyword allows an inner scope to modify a variable declared in the outer scope. If the variable is not modified within the inner scope, there is no need to use global.

        ","tags":["PLW0602"]},{"location":"rules/global-variable-not-assigned/#example","title":"Example","text":"
        DEBUG = True\n\n\ndef foo():\n    global DEBUG\n    if DEBUG:\n        print(\"foo() called\")\n    ...\n

        Use instead:

        DEBUG = True\n\n\ndef foo():\n    if DEBUG:\n        print(\"foo() called\")\n    ...\n
        ","tags":["PLW0602"]},{"location":"rules/global-variable-not-assigned/#references","title":"References","text":"
        • Python documentation: The global statement
        ","tags":["PLW0602"]},{"location":"rules/hardcoded-bind-all-interfaces/","title":"hardcoded-bind-all-interfaces (S104)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S104"]},{"location":"rules/hardcoded-bind-all-interfaces/#what-it-does","title":"What it does","text":"

        Checks for hardcoded bindings to all network interfaces (0.0.0.0).

        ","tags":["S104"]},{"location":"rules/hardcoded-bind-all-interfaces/#why-is-this-bad","title":"Why is this bad?","text":"

        Binding to all network interfaces is insecure as it allows access from unintended interfaces, which may be poorly secured or unauthorized.

        Instead, bind to specific interfaces.

        ","tags":["S104"]},{"location":"rules/hardcoded-bind-all-interfaces/#example","title":"Example","text":"
        ALLOWED_HOSTS = [\"0.0.0.0\"]\n

        Use instead:

        ALLOWED_HOSTS = [\"127.0.0.1\", \"localhost\"]\n
        ","tags":["S104"]},{"location":"rules/hardcoded-bind-all-interfaces/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-200
        ","tags":["S104"]},{"location":"rules/hardcoded-password-default/","title":"hardcoded-password-default (S107)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S107"]},{"location":"rules/hardcoded-password-default/#what-it-does","title":"What it does","text":"

        Checks for potential uses of hardcoded passwords in function argument defaults.

        ","tags":["S107"]},{"location":"rules/hardcoded-password-default/#why-is-this-bad","title":"Why is this bad?","text":"

        Including a hardcoded password in source code is a security risk, as an attacker could discover the password and use it to gain unauthorized access.

        Instead, store passwords and other secrets in configuration files, environment variables, or other sources that are excluded from version control.

        ","tags":["S107"]},{"location":"rules/hardcoded-password-default/#example","title":"Example","text":"
        def connect_to_server(password=\"hunter2\"): ...\n

        Use instead:

        import os\n\n\ndef connect_to_server(password=os.environ[\"PASSWORD\"]): ...\n
        ","tags":["S107"]},{"location":"rules/hardcoded-password-default/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-259
        ","tags":["S107"]},{"location":"rules/hardcoded-password-func-arg/","title":"hardcoded-password-func-arg (S106)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S106"]},{"location":"rules/hardcoded-password-func-arg/#what-it-does","title":"What it does","text":"

        Checks for potential uses of hardcoded passwords in function calls.

        ","tags":["S106"]},{"location":"rules/hardcoded-password-func-arg/#why-is-this-bad","title":"Why is this bad?","text":"

        Including a hardcoded password in source code is a security risk, as an attacker could discover the password and use it to gain unauthorized access.

        Instead, store passwords and other secrets in configuration files, environment variables, or other sources that are excluded from version control.

        ","tags":["S106"]},{"location":"rules/hardcoded-password-func-arg/#example","title":"Example","text":"
        connect_to_server(password=\"hunter2\")\n

        Use instead:

        import os\n\nconnect_to_server(password=os.environ[\"PASSWORD\"])\n
        ","tags":["S106"]},{"location":"rules/hardcoded-password-func-arg/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-259
        ","tags":["S106"]},{"location":"rules/hardcoded-password-string/","title":"hardcoded-password-string (S105)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S105"]},{"location":"rules/hardcoded-password-string/#what-it-does","title":"What it does","text":"

        Checks for potential uses of hardcoded passwords in strings.

        ","tags":["S105"]},{"location":"rules/hardcoded-password-string/#why-is-this-bad","title":"Why is this bad?","text":"

        Including a hardcoded password in source code is a security risk, as an attacker could discover the password and use it to gain unauthorized access.

        Instead, store passwords and other secrets in configuration files, environment variables, or other sources that are excluded from version control.

        ","tags":["S105"]},{"location":"rules/hardcoded-password-string/#example","title":"Example","text":"
        SECRET_KEY = \"hunter2\"\n

        Use instead:

        import os\n\nSECRET_KEY = os.environ[\"SECRET_KEY\"]\n
        ","tags":["S105"]},{"location":"rules/hardcoded-password-string/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-259
        ","tags":["S105"]},{"location":"rules/hardcoded-sql-expression/","title":"hardcoded-sql-expression (S608)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S608"]},{"location":"rules/hardcoded-sql-expression/#what-it-does","title":"What it does","text":"

        Checks for strings that resemble SQL statements involved in some form string building operation.

        ","tags":["S608"]},{"location":"rules/hardcoded-sql-expression/#why-is-this-bad","title":"Why is this bad?","text":"

        SQL injection is a common attack vector for web applications. Directly interpolating user input into SQL statements should always be avoided. Instead, favor parameterized queries, in which the SQL statement is provided separately from its parameters, as supported by psycopg3 and other database drivers and ORMs.

        ","tags":["S608"]},{"location":"rules/hardcoded-sql-expression/#example","title":"Example","text":"
        query = \"DELETE FROM foo WHERE id = '%s'\" % identifier\n
        ","tags":["S608"]},{"location":"rules/hardcoded-sql-expression/#references","title":"References","text":"
        • B608: Test for SQL injection
        • psycopg3: Server-side binding
        ","tags":["S608"]},{"location":"rules/hardcoded-string-charset/","title":"hardcoded-string-charset (FURB156)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB156"]},{"location":"rules/hardcoded-string-charset/#what-it-does","title":"What it does","text":"

        Checks for uses of hardcoded charsets, which are defined in Python string module.

        ","tags":["FURB156"]},{"location":"rules/hardcoded-string-charset/#why-is-this-bad","title":"Why is this bad?","text":"

        Usage of named charsets from the standard library is more readable and less error-prone.

        ","tags":["FURB156"]},{"location":"rules/hardcoded-string-charset/#example","title":"Example","text":"
        x = \"0123456789\"\ny in \"abcdefghijklmnopqrstuvwxyz\"\n

        Use instead

        import string\n\nx = string.digits\ny in string.ascii_lowercase\n
        ","tags":["FURB156"]},{"location":"rules/hardcoded-string-charset/#references","title":"References","text":"
        • Python documentation: String constants
        ","tags":["FURB156"]},{"location":"rules/hardcoded-temp-file/","title":"hardcoded-temp-file (S108)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S108"]},{"location":"rules/hardcoded-temp-file/#what-it-does","title":"What it does","text":"

        Checks for the use of hardcoded temporary file or directory paths.

        ","tags":["S108"]},{"location":"rules/hardcoded-temp-file/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of hardcoded paths for temporary files can be insecure. If an attacker discovers the location of a hardcoded path, they can replace the contents of the file or directory with a malicious payload.

        Other programs may also read or write contents to these hardcoded paths, causing unexpected behavior.

        ","tags":["S108"]},{"location":"rules/hardcoded-temp-file/#example","title":"Example","text":"
        with open(\"/tmp/foo.txt\", \"w\") as file:\n    ...\n

        Use instead:

        import tempfile\n\nwith tempfile.NamedTemporaryFile() as file:\n    ...\n
        ","tags":["S108"]},{"location":"rules/hardcoded-temp-file/#options","title":"Options","text":"
        • lint.flake8-bandit.hardcoded-tmp-directory
        • lint.flake8-bandit.hardcoded-tmp-directory-extend
        ","tags":["S108"]},{"location":"rules/hardcoded-temp-file/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-377
        • Common Weakness Enumeration: CWE-379
        • Python documentation: tempfile
        ","tags":["S108"]},{"location":"rules/hashlib-digest-hex/","title":"hashlib-digest-hex (FURB181)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB181"]},{"location":"rules/hashlib-digest-hex/#what-it-does","title":"What it does","text":"

        Checks for the use of .digest().hex() on a hashlib hash, like sha512.

        ","tags":["FURB181"]},{"location":"rules/hashlib-digest-hex/#why-is-this-bad","title":"Why is this bad?","text":"

        When generating a hex digest from a hash, it's preferable to use the .hexdigest() method, rather than calling .digest() and then .hex(), as the former is more concise and readable.

        ","tags":["FURB181"]},{"location":"rules/hashlib-digest-hex/#example","title":"Example","text":"
        from hashlib import sha512\n\nhashed = sha512(b\"some data\").digest().hex()\n

        Use instead:

        from hashlib import sha512\n\nhashed = sha512(b\"some data\").hexdigest()\n
        ","tags":["FURB181"]},{"location":"rules/hashlib-digest-hex/#references","title":"References","text":"
        • Python documentation: hashlib
        ","tags":["FURB181"]},{"location":"rules/hashlib-insecure-hash-function/","title":"hashlib-insecure-hash-function (S324)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S324"]},{"location":"rules/hashlib-insecure-hash-function/#what-it-does","title":"What it does","text":"

        Checks for uses of weak or broken cryptographic hash functions in hashlib and crypt libraries.

        ","tags":["S324"]},{"location":"rules/hashlib-insecure-hash-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Weak or broken cryptographic hash functions may be susceptible to collision attacks (where two different inputs produce the same hash) or pre-image attacks (where an attacker can find an input that produces a given hash). This can lead to security vulnerabilities in applications that rely on these hash functions.

        Avoid using weak or broken cryptographic hash functions in security contexts. Instead, use a known secure hash function such as SHA256.

        ","tags":["S324"]},{"location":"rules/hashlib-insecure-hash-function/#example","title":"Example","text":"
        import hashlib\n\n\ndef certificate_is_valid(certificate: bytes, known_hash: str) -> bool:\n    hash = hashlib.md5(certificate).hexdigest()\n    return hash == known_hash\n

        Use instead:

        import hashlib\n\n\ndef certificate_is_valid(certificate: bytes, known_hash: str) -> bool:\n    hash = hashlib.sha256(certificate).hexdigest()\n    return hash == known_hash\n

        or add usedforsecurity=False if the hashing algorithm is not used in a security context, e.g. as a non-cryptographic one-way compression function:

        import hashlib\n\n\ndef certificate_is_valid(certificate: bytes, known_hash: str) -> bool:\n    hash = hashlib.md5(certificate, usedforsecurity=False).hexdigest()\n    return hash == known_hash\n
        ","tags":["S324"]},{"location":"rules/hashlib-insecure-hash-function/#references","title":"References","text":"
        • Python documentation: hashlib \u2014 Secure hashes and message digests
        • Python documentation: crypt \u2014 Function to check Unix passwords
        • Python documentation: FIPS - FIPS compliant hashlib implementation
        • Common Weakness Enumeration: CWE-327
        • Common Weakness Enumeration: CWE-328
        • Common Weakness Enumeration: CWE-916
        ","tags":["S324"]},{"location":"rules/if-else-block-instead-of-dict-get/","title":"if-else-block-instead-of-dict-get (SIM401)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM401"]},{"location":"rules/if-else-block-instead-of-dict-get/#what-it-does","title":"What it does","text":"

        Checks for if statements that can be replaced with dict.get calls.

        ","tags":["SIM401"]},{"location":"rules/if-else-block-instead-of-dict-get/#why-is-this-bad","title":"Why is this bad?","text":"

        dict.get() calls can be used to replace if statements that assign a value to a variable in both branches, falling back to a default value if the key is not found. When possible, using dict.get is more concise and more idiomatic.

        Under preview mode, this rule will also suggest replacing if-else expressions with dict.get calls.

        ","tags":["SIM401"]},{"location":"rules/if-else-block-instead-of-dict-get/#example","title":"Example","text":"
        if \"bar\" in foo:\n    value = foo[\"bar\"]\nelse:\n    value = 0\n

        Use instead:

        value = foo.get(\"bar\", 0)\n

        If preview mode is enabled:

        value = foo[\"bar\"] if \"bar\" in foo else 0\n

        Use instead:

        value = foo.get(\"bar\", 0)\n
        ","tags":["SIM401"]},{"location":"rules/if-else-block-instead-of-dict-get/#references","title":"References","text":"
        • Python documentation: Mapping Types
        ","tags":["SIM401"]},{"location":"rules/if-else-block-instead-of-dict-lookup/","title":"if-else-block-instead-of-dict-lookup (SIM116)","text":"

        Derived from the flake8-simplify linter.

        ","tags":["SIM116"]},{"location":"rules/if-else-block-instead-of-dict-lookup/#what-it-does","title":"What it does","text":"

        Checks for three or more consecutive if-statements with direct returns

        ","tags":["SIM116"]},{"location":"rules/if-else-block-instead-of-dict-lookup/#why-is-this-bad","title":"Why is this bad?","text":"

        These can be simplified by using a dictionary

        ","tags":["SIM116"]},{"location":"rules/if-else-block-instead-of-dict-lookup/#example","title":"Example","text":"
        if x == 1:\n    return \"Hello\"\nelif x == 2:\n    return \"Goodbye\"\nelse:\n    return \"Goodnight\"\n

        Use instead:

        return {1: \"Hello\", 2: \"Goodbye\"}.get(x, \"Goodnight\")\n
        ","tags":["SIM116"]},{"location":"rules/if-else-block-instead-of-if-exp/","title":"if-else-block-instead-of-if-exp (SIM108)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM108"]},{"location":"rules/if-else-block-instead-of-if-exp/#what-it-does","title":"What it does","text":"

        Check for if-else-blocks that can be replaced with a ternary operator. Moreover, in preview, check if these ternary expressions can be further simplified to binary expressions.

        ","tags":["SIM108"]},{"location":"rules/if-else-block-instead-of-if-exp/#why-is-this-bad","title":"Why is this bad?","text":"

        if-else-blocks that assign a value to a variable in both branches can be expressed more concisely by using a ternary or binary operator.

        ","tags":["SIM108"]},{"location":"rules/if-else-block-instead-of-if-exp/#example","title":"Example","text":"
        if foo:\n    bar = x\nelse:\n    bar = y\n

        Use instead:

        bar = x if foo else y\n

        Or, in preview:

        if cond:\n    z = cond\nelse:\n    z = other_cond\n

        Use instead:

        z = cond or other_cond\n
        ","tags":["SIM108"]},{"location":"rules/if-else-block-instead-of-if-exp/#known-issues","title":"Known issues","text":"

        This is an opinionated style rule that may not always be to everyone's taste, especially for code that makes use of complex if conditions. Ternary operators can also make it harder to measure code coverage with tools that use line profiling.

        ","tags":["SIM108"]},{"location":"rules/if-else-block-instead-of-if-exp/#references","title":"References","text":"
        • Python documentation: Conditional expressions
        ","tags":["SIM108"]},{"location":"rules/if-exp-instead-of-or-operator/","title":"if-exp-instead-of-or-operator (FURB110)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB110"]},{"location":"rules/if-exp-instead-of-or-operator/#what-it-does","title":"What it does","text":"

        Checks for ternary if expressions that can be replaced with the or operator.

        ","tags":["FURB110"]},{"location":"rules/if-exp-instead-of-or-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        Ternary if expressions are more verbose than or expressions while providing the same functionality.

        ","tags":["FURB110"]},{"location":"rules/if-exp-instead-of-or-operator/#example","title":"Example","text":"
        z = x if x else y\n

        Use instead:

        z = x or y\n
        ","tags":["FURB110"]},{"location":"rules/if-exp-instead-of-or-operator/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe in the event that the body of the if expression contains side effects.

        For example, foo will be called twice in foo() if foo() else bar() (assuming foo() returns a truthy value), but only once in foo() or bar().

        ","tags":["FURB110"]},{"location":"rules/if-expr-min-max/","title":"if-expr-min-max (FURB136)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB136"]},{"location":"rules/if-expr-min-max/#what-it-does","title":"What it does","text":"

        Checks for if expressions that can be replaced with min() or max() calls.

        ","tags":["FURB136"]},{"location":"rules/if-expr-min-max/#why-is-this-bad","title":"Why is this bad?","text":"

        An if expression that selects the lesser or greater of two sub-expressions can be replaced with a min() or max() call respectively. When possible, prefer min() and max(), as they're more concise and readable than the equivalent if expression.

        ","tags":["FURB136"]},{"location":"rules/if-expr-min-max/#example","title":"Example","text":"
        highest_score = score1 if score1 > score2 else score2\n

        Use instead:

        highest_score = max(score2, score1)\n
        ","tags":["FURB136"]},{"location":"rules/if-expr-min-max/#references","title":"References","text":"
        • Python documentation: min
        • Python documentation: max
        ","tags":["FURB136"]},{"location":"rules/if-expr-with-false-true/","title":"if-expr-with-false-true (SIM211)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM211"]},{"location":"rules/if-expr-with-false-true/#what-it-does","title":"What it does","text":"

        Checks for if expressions that can be replaced by negating a given condition.

        ","tags":["SIM211"]},{"location":"rules/if-expr-with-false-true/#why-is-this-bad","title":"Why is this bad?","text":"

        if expressions that evaluate to False for a truthy condition and True for a falsey condition can be replaced with not operators, which are more concise and readable.

        ","tags":["SIM211"]},{"location":"rules/if-expr-with-false-true/#example","title":"Example","text":"
        False if a else True\n

        Use instead:

        not a\n
        ","tags":["SIM211"]},{"location":"rules/if-expr-with-false-true/#references","title":"References","text":"
        • Python documentation: Truth Value Testing
        ","tags":["SIM211"]},{"location":"rules/if-expr-with-true-false/","title":"if-expr-with-true-false (SIM210)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM210"]},{"location":"rules/if-expr-with-true-false/#what-it-does","title":"What it does","text":"

        Checks for if expressions that can be replaced with bool() calls.

        ","tags":["SIM210"]},{"location":"rules/if-expr-with-true-false/#why-is-this-bad","title":"Why is this bad?","text":"

        if expressions that evaluate to True for a truthy condition an False for a falsey condition can be replaced with bool() calls, which are more concise and readable.

        ","tags":["SIM210"]},{"location":"rules/if-expr-with-true-false/#example","title":"Example","text":"
        True if a else False\n

        Use instead:

        bool(a)\n
        ","tags":["SIM210"]},{"location":"rules/if-expr-with-true-false/#fix-safety","title":"Fix safety","text":"

        This fix is marked as unsafe because it may change the program\u2019s behavior if the condition does not return a proper Boolean. While the fix will try to wrap non-boolean values in a call to bool, custom implementations of comparison functions like __eq__ can avoid the bool call and still lead to altered behavior. Moreover, the fix may remove comments.

        ","tags":["SIM210"]},{"location":"rules/if-expr-with-true-false/#references","title":"References","text":"
        • Python documentation: Truth Value Testing
        ","tags":["SIM210"]},{"location":"rules/if-expr-with-twisted-arms/","title":"if-expr-with-twisted-arms (SIM212)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM212"]},{"location":"rules/if-expr-with-twisted-arms/#what-it-does","title":"What it does","text":"

        Checks for if expressions that check against a negated condition.

        ","tags":["SIM212"]},{"location":"rules/if-expr-with-twisted-arms/#why-is-this-bad","title":"Why is this bad?","text":"

        if expressions that check against a negated condition are more difficult to read than if expressions that check against the condition directly.

        ","tags":["SIM212"]},{"location":"rules/if-expr-with-twisted-arms/#example","title":"Example","text":"
        b if not a else a\n

        Use instead:

        a if a else b\n
        ","tags":["SIM212"]},{"location":"rules/if-expr-with-twisted-arms/#references","title":"References","text":"
        • Python documentation: Truth Value Testing
        ","tags":["SIM212"]},{"location":"rules/if-key-in-dict-del/","title":"if-key-in-dict-del (RUF051)","text":"

        Fix is always available.

        ","tags":["RUF051"]},{"location":"rules/if-key-in-dict-del/#what-it-does","title":"What it does","text":"

        Checks for if key in dictionary: del dictionary[key].

        ","tags":["RUF051"]},{"location":"rules/if-key-in-dict-del/#why-is-this-bad","title":"Why is this bad?","text":"

        To remove a key-value pair from a dictionary, it's more concise to use .pop(..., None).

        ","tags":["RUF051"]},{"location":"rules/if-key-in-dict-del/#example","title":"Example","text":"
        if key in dictionary:\n    del dictionary[key]\n

        Use instead:

        dictionary.pop(key, None)\n
        ","tags":["RUF051"]},{"location":"rules/if-key-in-dict-del/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the if statement contains comments.

        ","tags":["RUF051"]},{"location":"rules/if-stmt-min-max/","title":"if-stmt-min-max (PLR1730)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLR1730"]},{"location":"rules/if-stmt-min-max/#what-it-does","title":"What it does","text":"

        Checks for if statements that can be replaced with min() or max() calls.

        ","tags":["PLR1730"]},{"location":"rules/if-stmt-min-max/#why-is-this-bad","title":"Why is this bad?","text":"

        An if statement that selects the lesser or greater of two sub-expressions can be replaced with a min() or max() call respectively. Where possible, prefer min() and max(), as they're more concise and readable than the equivalent if statements.

        ","tags":["PLR1730"]},{"location":"rules/if-stmt-min-max/#example","title":"Example","text":"
        if score > highest_score:\n    highest_score = score\n

        Use instead:

        highest_score = max(highest_score, score)\n
        ","tags":["PLR1730"]},{"location":"rules/if-stmt-min-max/#fix-safety","title":"Fix safety","text":"

        This fix is marked unsafe if it would delete any comments within the replacement range.

        An example to illustrate where comments are preserved and where they are not:

        a, b = 0, 10\n\nif a >= b: # deleted comment\n    # deleted comment\n    a = b # preserved comment\n
        ","tags":["PLR1730"]},{"location":"rules/if-stmt-min-max/#references","title":"References","text":"
        • Python documentation: max
        • Python documentation: min
        ","tags":["PLR1730"]},{"location":"rules/if-tuple/","title":"if-tuple (F634)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F634"]},{"location":"rules/if-tuple/#what-it-does","title":"What it does","text":"

        Checks for if statements that use non-empty tuples as test conditions.

        ","tags":["F634"]},{"location":"rules/if-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        Non-empty tuples are always True, so an if statement with a non-empty tuple as its test condition will always pass. This is likely a mistake.

        ","tags":["F634"]},{"location":"rules/if-tuple/#example","title":"Example","text":"
        if (False,):\n    print(\"This will always run\")\n

        Use instead:

        if False:\n    print(\"This will never run\")\n
        ","tags":["F634"]},{"location":"rules/if-tuple/#references","title":"References","text":"
        • Python documentation: The if statement
        ","tags":["F634"]},{"location":"rules/if-with-same-arms/","title":"if-with-same-arms (SIM114)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM114"]},{"location":"rules/if-with-same-arms/#what-it-does","title":"What it does","text":"

        Checks for if branches with identical arm bodies.

        ","tags":["SIM114"]},{"location":"rules/if-with-same-arms/#why-is-this-bad","title":"Why is this bad?","text":"

        If multiple arms of an if statement have the same body, using or better signals the intent of the statement.

        ","tags":["SIM114"]},{"location":"rules/if-with-same-arms/#example","title":"Example","text":"
        if x == 1:\n    print(\"Hello\")\nelif x == 2:\n    print(\"Hello\")\n

        Use instead:

        if x == 1 or x == 2:\n    print(\"Hello\")\n
        ","tags":["SIM114"]},{"location":"rules/implicit-class-var-in-dataclass/","title":"implicit-class-var-in-dataclass (RUF045)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF045"]},{"location":"rules/implicit-class-var-in-dataclass/#what-it-does","title":"What it does","text":"

        Checks for implicit class variables in dataclasses.

        Variables matching the lint.dummy-variable-rgx are excluded from this rule.

        ","tags":["RUF045"]},{"location":"rules/implicit-class-var-in-dataclass/#why-is-this-bad","title":"Why is this bad?","text":"

        Class variables are shared between all instances of that class. In dataclasses, fields with no annotations at all are implicitly considered class variables, and a TypeError is raised if a user attempts to initialize an instance of the class with this field.

        @dataclass\nclass C:\n    a = 1\n    b: str = \"\"\n\nC(a = 42)  # TypeError: C.__init__() got an unexpected keyword argument 'a'\n
        ","tags":["RUF045"]},{"location":"rules/implicit-class-var-in-dataclass/#example","title":"Example","text":"
        @dataclass\nclass C:\n    a = 1\n

        Use instead:

        from typing import ClassVar\n\n\n@dataclass\nclass C:\n    a: ClassVar[int] = 1\n
        ","tags":["RUF045"]},{"location":"rules/implicit-class-var-in-dataclass/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["RUF045"]},{"location":"rules/implicit-cwd/","title":"implicit-cwd (FURB177)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB177"]},{"location":"rules/implicit-cwd/#what-it-does","title":"What it does","text":"

        Checks for current-directory lookups using Path().resolve().

        ","tags":["FURB177"]},{"location":"rules/implicit-cwd/#why-is-this-bad","title":"Why is this bad?","text":"

        When looking up the current directory, prefer Path.cwd() over Path().resolve(), as Path.cwd() is more explicit in its intent.

        ","tags":["FURB177"]},{"location":"rules/implicit-cwd/#example","title":"Example","text":"
        cwd = Path().resolve()\n

        Use instead:

        cwd = Path.cwd()\n
        ","tags":["FURB177"]},{"location":"rules/implicit-cwd/#references","title":"References","text":"
        • Python documentation: Path.cwd
        ","tags":["FURB177"]},{"location":"rules/implicit-namespace-package/","title":"implicit-namespace-package (INP001)","text":"

        Derived from the flake8-no-pep420 linter.

        ","tags":["INP001"]},{"location":"rules/implicit-namespace-package/#what-it-does","title":"What it does","text":"

        Checks for packages that are missing an __init__.py file.

        ","tags":["INP001"]},{"location":"rules/implicit-namespace-package/#why-is-this-bad","title":"Why is this bad?","text":"

        Python packages are directories that contain a file named __init__.py. The existence of this file indicates that the directory is a Python package, and so it can be imported the same way a module can be imported.

        Directories that lack an __init__.py file can still be imported, but they're indicative of a special kind of package, known as a \"namespace package\" (see: PEP 420). Namespace packages are less widely used, so a package that lacks an __init__.py file is typically meant to be a regular package, and the absence of the __init__.py file is probably an oversight.

        ","tags":["INP001"]},{"location":"rules/implicit-namespace-package/#options","title":"Options","text":"
        • namespace-packages
        ","tags":["INP001"]},{"location":"rules/implicit-optional/","title":"implicit-optional (RUF013)","text":"

        Fix is sometimes available.

        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#what-it-does","title":"What it does","text":"

        Checks for the use of implicit Optional in type annotations when the default parameter value is None.

        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#why-is-this-bad","title":"Why is this bad?","text":"

        Implicit Optional is prohibited by PEP 484. It is confusing and inconsistent with the rest of the type system.

        It's recommended to use Optional[T] instead. For Python 3.10 and later, you can also use T | None.

        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#example","title":"Example","text":"
        def foo(arg: int = None):\n    pass\n

        Use instead:

        from typing import Optional\n\n\ndef foo(arg: Optional[int] = None):\n    pass\n

        Or, for Python 3.10 and later:

        def foo(arg: int | None = None):\n    pass\n

        If you want to use the | operator in Python 3.9 and earlier, you can use future imports:

        from __future__ import annotations\n\n\ndef foo(arg: int | None = None):\n    pass\n
        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#limitations","title":"Limitations","text":"

        Type aliases are not supported and could result in false negatives. For example, the following code will not be flagged:

        Text = str | bytes\n\n\ndef foo(arg: Text = None):\n    pass\n
        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#options","title":"Options","text":"
        • target-version
        ","tags":["RUF013"]},{"location":"rules/implicit-optional/#fix-safety","title":"Fix safety","text":"

        This fix is always marked as unsafe because it can change the behavior of code that relies on type hints, and it assumes the default value is always appropriate\u2014which might not be the case.

        ","tags":["RUF013"]},{"location":"rules/implicit-return-value/","title":"implicit-return-value (RET502)","text":"

        Derived from the flake8-return linter.

        Fix is always available.

        ","tags":["RET502"]},{"location":"rules/implicit-return-value/#what-it-does","title":"What it does","text":"

        Checks for the presence of a return statement with no explicit value, for functions that return non-None values elsewhere.

        ","tags":["RET502"]},{"location":"rules/implicit-return-value/#why-is-this-bad","title":"Why is this bad?","text":"

        Including a return statement with no explicit value can cause confusion when other return statements in the function return non-None values. Python implicitly assumes return None if no other return value is present. Adding an explicit return None can make the code more readable by clarifying intent.

        ","tags":["RET502"]},{"location":"rules/implicit-return-value/#example","title":"Example","text":"
        def foo(bar):\n    if not bar:\n        return\n    return 1\n

        Use instead:

        def foo(bar):\n    if not bar:\n        return None\n    return 1\n
        ","tags":["RET502"]},{"location":"rules/implicit-return/","title":"implicit-return (RET503)","text":"

        Derived from the flake8-return linter.

        Fix is always available.

        ","tags":["RET503"]},{"location":"rules/implicit-return/#what-it-does","title":"What it does","text":"

        Checks for missing explicit return statements at the end of functions that can return non-None values.

        ","tags":["RET503"]},{"location":"rules/implicit-return/#why-is-this-bad","title":"Why is this bad?","text":"

        The lack of an explicit return statement at the end of a function that can return non-None values can cause confusion. Python implicitly returns None if no other return value is present. Adding an explicit return None can make the code more readable by clarifying intent.

        ","tags":["RET503"]},{"location":"rules/implicit-return/#example","title":"Example","text":"
        def foo(bar):\n    if not bar:\n        return 1\n

        Use instead:

        def foo(bar):\n    if not bar:\n        return 1\n    return None\n
        ","tags":["RET503"]},{"location":"rules/import-outside-top-level/","title":"import-outside-top-level (PLC0415)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLC0415"]},{"location":"rules/import-outside-top-level/#what-it-does","title":"What it does","text":"

        Checks for import statements outside of a module's top-level scope, such as within a function or class definition.

        ","tags":["PLC0415"]},{"location":"rules/import-outside-top-level/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends placing imports not only at the top-level of a module, but at the very top of the file, \"just after any module comments and docstrings, and before module globals and constants.\"

        import statements have effects that are global in scope; defining them at the top level has a number of benefits. For example, it makes it easier to identify the dependencies of a module, and ensures that any invalid imports are caught regardless of whether a specific function is called or class is instantiated.

        An import statement would typically be placed within a function only to avoid a circular dependency, to defer a costly module load, or to avoid loading a dependency altogether in a certain runtime environment.

        ","tags":["PLC0415"]},{"location":"rules/import-outside-top-level/#example","title":"Example","text":"
        def print_python_version():\n    import platform\n\n    print(python.python_version())\n

        Use instead:

        import platform\n\n\ndef print_python_version():\n    print(python.python_version())\n
        ","tags":["PLC0415"]},{"location":"rules/import-private-name/","title":"import-private-name (PLC2701)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#what-it-does","title":"What it does","text":"

        Checks for import statements that import a private name (a name starting with an underscore _) from another module.

        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 states that names starting with an underscore are private. Thus, they are not intended to be used outside of the module in which they are defined.

        Further, as private imports are not considered part of the public API, they are prone to unexpected changes, especially outside of semantic versioning.

        Instead, consider using the public API of the module.

        This rule ignores private name imports that are exclusively used in type annotations. Ideally, types would be public; however, this is not always possible when using third-party libraries.

        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#known-problems","title":"Known problems","text":"

        Does not ignore private name imports from within the module that defines the private name if the module is defined with PEP 420 namespace packages (i.e., directories that omit the __init__.py file). Namespace packages must be configured via the namespace-packages setting.

        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#example","title":"Example","text":"
        from foo import _bar\n
        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#options","title":"Options","text":"
        • namespace-packages
        ","tags":["PLC2701"]},{"location":"rules/import-private-name/#references","title":"References","text":"
        • PEP 8: Naming Conventions
        • Semantic Versioning
        ","tags":["PLC2701"]},{"location":"rules/import-self/","title":"import-self (PLW0406)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0406"]},{"location":"rules/import-self/#what-it-does","title":"What it does","text":"

        Checks for import statements that import the current module.

        ","tags":["PLW0406"]},{"location":"rules/import-self/#why-is-this-bad","title":"Why is this bad?","text":"

        Importing a module from itself is a circular dependency and results in an ImportError exception.

        ","tags":["PLW0406"]},{"location":"rules/import-self/#example","title":"Example","text":"
        # file: this_file.py\nfrom this_file import foo\n\n\ndef foo(): ...\n
        ","tags":["PLW0406"]},{"location":"rules/import-shadowed-by-loop-var/","title":"import-shadowed-by-loop-var (F402)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F402"]},{"location":"rules/import-shadowed-by-loop-var/#what-it-does","title":"What it does","text":"

        Checks for import bindings that are shadowed by loop variables.

        ","tags":["F402"]},{"location":"rules/import-shadowed-by-loop-var/#why-is-this-bad","title":"Why is this bad?","text":"

        Shadowing an import with loop variables makes the code harder to read and reason about, as the identify of the imported binding is no longer clear. It's also often indicative of a mistake, as it's unlikely that the loop variable is intended to be used as the imported binding.

        Consider using a different name for the loop variable.

        ","tags":["F402"]},{"location":"rules/import-shadowed-by-loop-var/#example","title":"Example","text":"
        from os import path\n\nfor path in files:\n    print(path)\n

        Use instead:

        from os import path\n\n\nfor filename in files:\n    print(filename)\n
        ","tags":["F402"]},{"location":"rules/in-dict-keys/","title":"in-dict-keys (SIM118)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM118"]},{"location":"rules/in-dict-keys/#what-it-does","title":"What it does","text":"

        Checks for key-existence checks against dict.keys() calls.

        ","tags":["SIM118"]},{"location":"rules/in-dict-keys/#why-is-this-bad","title":"Why is this bad?","text":"

        When checking for the existence of a key in a given dictionary, using key in dict is more readable and efficient than key in dict.keys(), while having the same semantics.

        ","tags":["SIM118"]},{"location":"rules/in-dict-keys/#example","title":"Example","text":"
        key in foo.keys()\n

        Use instead:

        key in foo\n
        ","tags":["SIM118"]},{"location":"rules/in-dict-keys/#fix-safety","title":"Fix safety","text":"

        Given key in obj.keys(), obj could be a dictionary, or it could be another type that defines a .keys() method. In the latter case, removing the .keys() attribute could lead to a runtime error. The fix is marked as safe when the type of obj is known to be a dictionary; otherwise, it is marked as unsafe.

        ","tags":["SIM118"]},{"location":"rules/in-dict-keys/#references","title":"References","text":"
        • Python documentation: Mapping Types
        ","tags":["SIM118"]},{"location":"rules/in-empty-collection/","title":"in-empty-collection (RUF060)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF060"]},{"location":"rules/in-empty-collection/#what-it-does","title":"What it does","text":"

        Checks for membership tests on empty collections (such as list, tuple, set or dict).

        ","tags":["RUF060"]},{"location":"rules/in-empty-collection/#why-is-this-bad","title":"Why is this bad?","text":"

        If the collection is always empty, the check is unnecessary, and can be removed.

        ","tags":["RUF060"]},{"location":"rules/in-empty-collection/#example","title":"Example","text":"
        if 1 not in set():\n    print(\"got it!\")\n

        Use instead:

        print(\"got it!\")\n
        ","tags":["RUF060"]},{"location":"rules/incorrect-blank-line-after-class/","title":"incorrect-blank-line-after-class (D204)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-after-class/#what-it-does","title":"What it does","text":"

        Checks for class methods that are not separated from the class's docstring by a blank line.

        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-after-class/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends the use of a blank line to separate a class's docstring from its methods.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the numpy and pep257 conventions, and disabled when using the google convention.

        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-after-class/#example","title":"Example","text":"
        class PhotoMetadata:\n    \"\"\"Metadata about a photo.\"\"\"\n    def __init__(self, file: Path):\n        ...\n

        Use instead:

        class PhotoMetadata:\n    \"\"\"Metadata about a photo.\"\"\"\n\n    def __init__(self, file: Path):\n        ...\n
        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-after-class/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-after-class/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D204"]},{"location":"rules/incorrect-blank-line-before-class/","title":"incorrect-blank-line-before-class (D203)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D203"]},{"location":"rules/incorrect-blank-line-before-class/#what-it-does","title":"What it does","text":"

        Checks for docstrings on class definitions that are not preceded by a blank line.

        ","tags":["D203"]},{"location":"rules/incorrect-blank-line-before-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Use a blank line to separate the docstring from the class definition, for consistency.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is disabled when using the google, numpy, and pep257 conventions.

        For an alternative, see D211.

        ","tags":["D203"]},{"location":"rules/incorrect-blank-line-before-class/#example","title":"Example","text":"
        class PhotoMetadata:\n    \"\"\"Metadata about a photo.\"\"\"\n

        Use instead:

        class PhotoMetadata:\n\n    \"\"\"Metadata about a photo.\"\"\"\n
        ","tags":["D203"]},{"location":"rules/incorrect-blank-line-before-class/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D203"]},{"location":"rules/incorrect-dict-iterator/","title":"incorrect-dict-iterator (PERF102)","text":"

        Derived from the Perflint linter.

        Fix is always available.

        ","tags":["PERF102"]},{"location":"rules/incorrect-dict-iterator/#what-it-does","title":"What it does","text":"

        Checks for uses of dict.items() that discard either the key or the value when iterating over the dictionary.

        ","tags":["PERF102"]},{"location":"rules/incorrect-dict-iterator/#why-is-this-bad","title":"Why is this bad?","text":"

        If you only need the keys or values of a dictionary, you should use dict.keys() or dict.values() respectively, instead of dict.items(). These specialized methods are more efficient than dict.items(), as they avoid allocating tuples for every item in the dictionary. They also communicate the intent of the code more clearly.

        Note that, as with all perflint rules, this is only intended as a micro-optimization, and will have a negligible impact on performance in most cases.

        ","tags":["PERF102"]},{"location":"rules/incorrect-dict-iterator/#example","title":"Example","text":"
        obj = {\"a\": 1, \"b\": 2}\nfor key, value in obj.items():\n    print(value)\n

        Use instead:

        obj = {\"a\": 1, \"b\": 2}\nfor value in obj.values():\n    print(value)\n
        ","tags":["PERF102"]},{"location":"rules/incorrect-dict-iterator/#fix-safety","title":"Fix safety","text":"

        The fix does not perform any type analysis and, as such, may suggest an incorrect fix if the object in question does not duck-type as a mapping (e.g., if it is missing a .keys() or .values() method, or if those methods behave differently than they do on standard mapping types).

        ","tags":["PERF102"]},{"location":"rules/incorrectly-parenthesized-tuple-in-subscript/","title":"incorrectly-parenthesized-tuple-in-subscript (RUF031)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF031"]},{"location":"rules/incorrectly-parenthesized-tuple-in-subscript/#what-it-does","title":"What it does","text":"

        Checks for consistent style regarding whether nonempty tuples in subscripts are parenthesized.

        The exact nature of this violation depends on the setting lint.ruff.parenthesize-tuple-in-subscript. By default, the use of parentheses is considered a violation.

        This rule is not applied inside \"typing contexts\" (type annotations, type aliases and subscripted class bases), as these have their own specific conventions around them.

        ","tags":["RUF031"]},{"location":"rules/incorrectly-parenthesized-tuple-in-subscript/#why-is-this-bad","title":"Why is this bad?","text":"

        It is good to be consistent and, depending on the codebase, one or the other convention may be preferred.

        ","tags":["RUF031"]},{"location":"rules/incorrectly-parenthesized-tuple-in-subscript/#example","title":"Example","text":"
        directions = {(0, 1): \"North\", (1, 0): \"East\", (0, -1): \"South\", (-1, 0): \"West\"}\ndirections[(0, 1)]\n

        Use instead (with default setting):

        directions = {(0, 1): \"North\", (1, 0): \"East\", (0, -1): \"South\", (-1, 0): \"West\"}\ndirections[0, 1]\n
        ","tags":["RUF031"]},{"location":"rules/incorrectly-parenthesized-tuple-in-subscript/#options","title":"Options","text":"
        • lint.ruff.parenthesize-tuple-in-subscript
        ","tags":["RUF031"]},{"location":"rules/indentation-with-invalid-multiple-comment/","title":"indentation-with-invalid-multiple-comment (E114)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple-comment/#what-it-does","title":"What it does","text":"

        Checks for indentation of comments with a non-multiple of 4 spaces.

        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, 4 spaces per indentation level should be preferred.

        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple-comment/#example","title":"Example","text":"
        if True:\n   # a = 1\n

        Use instead:

        if True:\n    # a = 1\n
        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple-comment/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        The rule is also incompatible with the formatter when using indent-width with a value other than 4.

        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple-comment/#options","title":"Options","text":"
        • indent-width
        ","tags":["E114"]},{"location":"rules/indentation-with-invalid-multiple/","title":"indentation-with-invalid-multiple (E111)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E111"]},{"location":"rules/indentation-with-invalid-multiple/#what-it-does","title":"What it does","text":"

        Checks for indentation with a non-multiple of 4 spaces.

        ","tags":["E111"]},{"location":"rules/indentation-with-invalid-multiple/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, 4 spaces per indentation level should be preferred.

        ","tags":["E111"]},{"location":"rules/indentation-with-invalid-multiple/#example","title":"Example","text":"
        if True:\n   a = 1\n

        Use instead:

        if True:\n    a = 1\n
        ","tags":["E111"]},{"location":"rules/indentation-with-invalid-multiple/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        The rule is also incompatible with the formatter when using indent-width with a value other than 4.

        ","tags":["E111"]},{"location":"rules/indentation-with-invalid-multiple/#options","title":"Options","text":"
        • indent-width
        ","tags":["E111"]},{"location":"rules/indented-form-feed/","title":"indented-form-feed (RUF054)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF054"]},{"location":"rules/indented-form-feed/#what-it-does","title":"What it does","text":"

        Checks for form feed characters preceded by either a space or a tab.

        ","tags":["RUF054"]},{"location":"rules/indented-form-feed/#why-is-this-bad","title":"Why is this bad?","text":"

        The language reference states:

        A formfeed character may be present at the start of the line; it will be ignored for the indentation calculations above. Formfeed characters occurring elsewhere in the leading whitespace have an undefined effect (for instance, they may reset the space count to zero).

        ","tags":["RUF054"]},{"location":"rules/indented-form-feed/#example","title":"Example","text":"
        if foo():\\n    \\fbar()\n

        Use instead:

        if foo():\\n    bar()\n
        ","tags":["RUF054"]},{"location":"rules/int-on-sliced-str/","title":"int-on-sliced-str (FURB166)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB166"]},{"location":"rules/int-on-sliced-str/#what-it-does","title":"What it does","text":"

        Checks for uses of int with an explicit base in which a string expression is stripped of its leading prefix (i.e., 0b, 0o, or 0x).

        ","tags":["FURB166"]},{"location":"rules/int-on-sliced-str/#why-is-this-bad","title":"Why is this bad?","text":"

        Given an integer string with a prefix (e.g., 0xABC), Python can automatically determine the base of the integer by the prefix without needing to specify it explicitly.

        Instead of int(num[2:], 16), use int(num, 0), which will automatically deduce the base based on the prefix.

        ","tags":["FURB166"]},{"location":"rules/int-on-sliced-str/#example","title":"Example","text":"
        num = \"0xABC\"\n\nif num.startswith(\"0b\"):\n    i = int(num[2:], 2)\nelif num.startswith(\"0o\"):\n    i = int(num[2:], 8)\nelif num.startswith(\"0x\"):\n    i = int(num[2:], 16)\n\nprint(i)\n

        Use instead:

        num = \"0xABC\"\n\ni = int(num, 0)\n\nprint(i)\n
        ","tags":["FURB166"]},{"location":"rules/int-on-sliced-str/#fix-safety","title":"Fix safety","text":"

        The rule's fix is marked as unsafe, as Ruff cannot guarantee that the argument to int will remain valid when its base is included in the function call.

        ","tags":["FURB166"]},{"location":"rules/int-on-sliced-str/#references","title":"References","text":"
        • Python documentation: int
        ","tags":["FURB166"]},{"location":"rules/invalid-all-format/","title":"invalid-all-format (PLE0605)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0605"]},{"location":"rules/invalid-all-format/#what-it-does","title":"What it does","text":"

        Checks for invalid assignments to __all__.

        ","tags":["PLE0605"]},{"location":"rules/invalid-all-format/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, __all__ should contain a sequence of strings that represent the names of all \"public\" symbols exported by a module.

        Assigning anything other than a tuple or list of strings to __all__ is invalid.

        ","tags":["PLE0605"]},{"location":"rules/invalid-all-format/#example","title":"Example","text":"
        __all__ = \"Foo\"\n

        Use instead:

        __all__ = (\"Foo\",)\n
        ","tags":["PLE0605"]},{"location":"rules/invalid-all-format/#references","title":"References","text":"
        • Python documentation: The import statement
        ","tags":["PLE0605"]},{"location":"rules/invalid-all-object/","title":"invalid-all-object (PLE0604)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0604"]},{"location":"rules/invalid-all-object/#what-it-does","title":"What it does","text":"

        Checks for the inclusion of invalid objects in __all__.

        ","tags":["PLE0604"]},{"location":"rules/invalid-all-object/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, __all__ should contain a sequence of strings that represent the names of all \"public\" symbols exported by a module.

        Assigning anything other than a tuple or list of strings to __all__ is invalid.

        ","tags":["PLE0604"]},{"location":"rules/invalid-all-object/#example","title":"Example","text":"
        __all__ = [Foo, 1, None]\n

        Use instead:

        __all__ = [\"Foo\", \"Bar\", \"Baz\"]\n
        ","tags":["PLE0604"]},{"location":"rules/invalid-all-object/#references","title":"References","text":"
        • Python documentation: The import statement
        ","tags":["PLE0604"]},{"location":"rules/invalid-argument-name/","title":"invalid-argument-name (N803)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N803"]},{"location":"rules/invalid-argument-name/#what-it-does","title":"What it does","text":"

        Checks for argument names that do not follow the snake_case convention.

        ","tags":["N803"]},{"location":"rules/invalid-argument-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that function names should be lower case and separated by underscores (also known as snake_case).

        Function names should be lowercase, with words separated by underscores as necessary to improve readability.

        Variable names follow the same convention as function names.

        mixedCase is allowed only in contexts where that\u2019s already the prevailing style (e.g. threading.py), to retain backwards compatibility.

        Methods decorated with @typing.override are ignored.

        ","tags":["N803"]},{"location":"rules/invalid-argument-name/#example","title":"Example","text":"
        def my_function(A, myArg):\n    pass\n

        Use instead:

        def my_function(a, my_arg):\n    pass\n
        ","tags":["N803"]},{"location":"rules/invalid-argument-name/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N803"]},{"location":"rules/invalid-assert-message-literal-argument/","title":"invalid-assert-message-literal-argument (RUF040)","text":"","tags":["RUF040"]},{"location":"rules/invalid-assert-message-literal-argument/#what-it-does","title":"What it does","text":"

        Checks for invalid use of literals in assert message arguments.

        ","tags":["RUF040"]},{"location":"rules/invalid-assert-message-literal-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An assert message which is a non-string literal was likely intended to be used in a comparison assertion, rather than as a message.

        ","tags":["RUF040"]},{"location":"rules/invalid-assert-message-literal-argument/#example","title":"Example","text":"
        fruits = [\"apples\", \"plums\", \"pears\"]\nfruits.filter(lambda fruit: fruit.startwith(\"p\"))\nassert len(fruits), 2  # True unless the list is empty\n

        Use instead:

        fruits = [\"apples\", \"plums\", \"pears\"]\nfruits.filter(lambda fruit: fruit.startwith(\"p\"))\nassert len(fruits) == 2\n
        ","tags":["RUF040"]},{"location":"rules/invalid-bool-return-type/","title":"invalid-bool-return-type (PLE0304)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLE0304"]},{"location":"rules/invalid-bool-return-type/#what-it-does","title":"What it does","text":"

        Checks for __bool__ implementations that return a type other than bool.

        ","tags":["PLE0304"]},{"location":"rules/invalid-bool-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __bool__ method should return a bool object. Returning a different type may cause unexpected behavior.

        ","tags":["PLE0304"]},{"location":"rules/invalid-bool-return-type/#example","title":"Example","text":"
        class Foo:\n    def __bool__(self):\n        return 2\n

        Use instead:

        class Foo:\n    def __bool__(self):\n        return True\n
        ","tags":["PLE0304"]},{"location":"rules/invalid-bool-return-type/#references","title":"References","text":"
        • Python documentation: The __bool__ method
        ","tags":["PLE0304"]},{"location":"rules/invalid-bytes-return-type/","title":"invalid-bytes-return-type (PLE0308)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0308"]},{"location":"rules/invalid-bytes-return-type/#what-it-does","title":"What it does","text":"

        Checks for __bytes__ implementations that return types other than bytes.

        ","tags":["PLE0308"]},{"location":"rules/invalid-bytes-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __bytes__ method should return a bytes object. Returning a different type may cause unexpected behavior.

        ","tags":["PLE0308"]},{"location":"rules/invalid-bytes-return-type/#example","title":"Example","text":"
        class Foo:\n    def __bytes__(self):\n        return 2\n

        Use instead:

        class Foo:\n    def __bytes__(self):\n        return b\"2\"\n
        ","tags":["PLE0308"]},{"location":"rules/invalid-bytes-return-type/#references","title":"References","text":"
        • Python documentation: The __bytes__ method
        ","tags":["PLE0308"]},{"location":"rules/invalid-character-backspace/","title":"invalid-character-backspace (PLE2510)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE2510"]},{"location":"rules/invalid-character-backspace/#what-it-does","title":"What it does","text":"

        Checks for strings that contain the control character BS.

        ","tags":["PLE2510"]},{"location":"rules/invalid-character-backspace/#why-is-this-bad","title":"Why is this bad?","text":"

        Control characters are displayed differently by different text editors and terminals.

        By using the \\b sequence in lieu of the BS control character, the string will contain the same value, but will render visibly in all editors.

        ","tags":["PLE2510"]},{"location":"rules/invalid-character-backspace/#example","title":"Example","text":"
        x = \"\"\n

        Use instead:

        x = \"\\b\"\n
        ","tags":["PLE2510"]},{"location":"rules/invalid-character-esc/","title":"invalid-character-esc (PLE2513)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE2513"]},{"location":"rules/invalid-character-esc/#what-it-does","title":"What it does","text":"

        Checks for strings that contain the raw control character ESC.

        ","tags":["PLE2513"]},{"location":"rules/invalid-character-esc/#why-is-this-bad","title":"Why is this bad?","text":"

        Control characters are displayed differently by different text editors and terminals.

        By using the \\x1B sequence in lieu of the SUB control character, the string will contain the same value, but will render visibly in all editors.

        ","tags":["PLE2513"]},{"location":"rules/invalid-character-esc/#example","title":"Example","text":"
        x = \"\"\n

        Use instead:

        x = \"\\x1b\"\n
        ","tags":["PLE2513"]},{"location":"rules/invalid-character-nul/","title":"invalid-character-nul (PLE2514)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE2514"]},{"location":"rules/invalid-character-nul/#what-it-does","title":"What it does","text":"

        Checks for strings that contain the raw control character NUL (0 byte).

        ","tags":["PLE2514"]},{"location":"rules/invalid-character-nul/#why-is-this-bad","title":"Why is this bad?","text":"

        Control characters are displayed differently by different text editors and terminals.

        By using the \\0 sequence in lieu of the NUL control character, the string will contain the same value, but will render visibly in all editors.

        ","tags":["PLE2514"]},{"location":"rules/invalid-character-nul/#example","title":"Example","text":"
        x = \"\"\n

        Use instead:

        x = \"\\0\"\n
        ","tags":["PLE2514"]},{"location":"rules/invalid-character-sub/","title":"invalid-character-sub (PLE2512)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE2512"]},{"location":"rules/invalid-character-sub/#what-it-does","title":"What it does","text":"

        Checks for strings that contain the raw control character SUB.

        ","tags":["PLE2512"]},{"location":"rules/invalid-character-sub/#why-is-this-bad","title":"Why is this bad?","text":"

        Control characters are displayed differently by different text editors and terminals.

        By using the \\x1A sequence in lieu of the SUB control character, the string will contain the same value, but will render visibly in all editors.

        ","tags":["PLE2512"]},{"location":"rules/invalid-character-sub/#example","title":"Example","text":"
        x = \"\"\n

        Use instead:

        x = \"\\x1a\"\n
        ","tags":["PLE2512"]},{"location":"rules/invalid-character-zero-width-space/","title":"invalid-character-zero-width-space (PLE2515)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE2515"]},{"location":"rules/invalid-character-zero-width-space/#what-it-does","title":"What it does","text":"

        Checks for strings that contain the zero width space character.

        ","tags":["PLE2515"]},{"location":"rules/invalid-character-zero-width-space/#why-is-this-bad","title":"Why is this bad?","text":"

        This character is rendered invisibly in some text editors and terminals.

        By using the \\u200B sequence, the string will contain the same value, but will render visibly in all editors.

        ","tags":["PLE2515"]},{"location":"rules/invalid-character-zero-width-space/#example","title":"Example","text":"
        x = \"Dear Sir/Madam\"\n

        Use instead:

        x = \"Dear Sir\\u200b/\\u200bMadam\"  # zero width space\n
        ","tags":["PLE2515"]},{"location":"rules/invalid-class-name/","title":"invalid-class-name (N801)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N801"]},{"location":"rules/invalid-class-name/#what-it-does","title":"What it does","text":"

        Checks for class names that do not follow the CamelCase convention.

        ","tags":["N801"]},{"location":"rules/invalid-class-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the use of the CapWords (or CamelCase) convention for class names:

        Class names should normally use the CapWords convention.

        The naming convention for functions may be used instead in cases where the interface is documented and used primarily as a callable.

        Note that there is a separate convention for builtin names: most builtin names are single words (or two words run together), with the CapWords convention used only for exception names and builtin constants.

        ","tags":["N801"]},{"location":"rules/invalid-class-name/#example","title":"Example","text":"
        class my_class:\n    pass\n

        Use instead:

        class MyClass:\n    pass\n
        ","tags":["N801"]},{"location":"rules/invalid-class-name/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N801"]},{"location":"rules/invalid-envvar-default/","title":"invalid-envvar-default (PLW1508)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW1508"]},{"location":"rules/invalid-envvar-default/#what-it-does","title":"What it does","text":"

        Checks for os.getenv calls with invalid default values.

        ","tags":["PLW1508"]},{"location":"rules/invalid-envvar-default/#why-is-this-bad","title":"Why is this bad?","text":"

        If an environment variable is set, os.getenv will return its value as a string. If the environment variable is not set, os.getenv will return None, or the default value if one is provided.

        If the default value is not a string or None, then it will be inconsistent with the return type of os.getenv, which can lead to confusing behavior.

        ","tags":["PLW1508"]},{"location":"rules/invalid-envvar-default/#example","title":"Example","text":"
        import os\n\nint(os.getenv(\"FOO\", 1))\n

        Use instead:

        import os\n\nint(os.getenv(\"FOO\", \"1\"))\n
        ","tags":["PLW1508"]},{"location":"rules/invalid-envvar-value/","title":"invalid-envvar-value (PLE1507)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1507"]},{"location":"rules/invalid-envvar-value/#what-it-does","title":"What it does","text":"

        Checks for os.getenv calls with an invalid key argument.

        ","tags":["PLE1507"]},{"location":"rules/invalid-envvar-value/#why-is-this-bad","title":"Why is this bad?","text":"

        os.getenv only supports strings as the first argument (key).

        If the provided argument is not a string, os.getenv will throw a TypeError at runtime.

        ","tags":["PLE1507"]},{"location":"rules/invalid-envvar-value/#example","title":"Example","text":"
        os.getenv(1)\n

        Use instead:

        os.getenv(\"1\")\n
        ","tags":["PLE1507"]},{"location":"rules/invalid-escape-sequence/","title":"invalid-escape-sequence (W605)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["W605"]},{"location":"rules/invalid-escape-sequence/#what-it-does","title":"What it does","text":"

        Checks for invalid escape sequences.

        ","tags":["W605"]},{"location":"rules/invalid-escape-sequence/#why-is-this-bad","title":"Why is this bad?","text":"

        Invalid escape sequences are deprecated in Python 3.6.

        ","tags":["W605"]},{"location":"rules/invalid-escape-sequence/#example","title":"Example","text":"
        regex = \"\\.png$\"\n

        Use instead:

        regex = r\"\\.png$\"\n

        Or, if the string already contains a valid escape sequence:

        value = \"new line\\nand invalid escape \\_ here\"\n

        Use instead:

        value = \"new line\\nand invalid escape \\\\_ here\"\n
        ","tags":["W605"]},{"location":"rules/invalid-escape-sequence/#references","title":"References","text":"
        • Python documentation: String and Bytes literals
        ","tags":["W605"]},{"location":"rules/invalid-first-argument-name-for-class-method/","title":"invalid-first-argument-name-for-class-method (N804)","text":"

        Derived from the pep8-naming linter.

        Fix is sometimes available.

        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-class-method/#what-it-does","title":"What it does","text":"

        Checks for class methods that use a name other than cls for their first argument.

        The method __new__ is exempted from this check and the corresponding violation is caught by bad-staticmethod-argument.

        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-class-method/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the use of cls as the first argument for all class methods:

        Always use cls for the first argument to class methods.

        If a function argument\u2019s name clashes with a reserved keyword, it is generally better to append a single trailing underscore rather than use an abbreviation or spelling corruption. Thus class_ is better than clss. (Perhaps better is to avoid such clashes by using a synonym.)

        Names can be excluded from this rule using the lint.pep8-naming.ignore-names or lint.pep8-naming.extend-ignore-names configuration options. For example, to allow the use of klass as the first argument to class methods, set the lint.pep8-naming.extend-ignore-names option to [\"klass\"].

        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-class-method/#example","title":"Example","text":"
        class Example:\n    @classmethod\n    def function(self, data): ...\n

        Use instead:

        class Example:\n    @classmethod\n    def function(cls, data): ...\n
        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-class-method/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as renaming a method parameter can change the behavior of the program.

        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-class-method/#options","title":"Options","text":"
        • lint.pep8-naming.classmethod-decorators
        • lint.pep8-naming.staticmethod-decorators
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N804"]},{"location":"rules/invalid-first-argument-name-for-method/","title":"invalid-first-argument-name-for-method (N805)","text":"

        Derived from the pep8-naming linter.

        Fix is sometimes available.

        ","tags":["N805"]},{"location":"rules/invalid-first-argument-name-for-method/#what-it-does","title":"What it does","text":"

        Checks for instance methods that use a name other than self for their first argument.

        ","tags":["N805"]},{"location":"rules/invalid-first-argument-name-for-method/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the use of self as first argument for all instance methods:

        Always use self for the first argument to instance methods.

        If a function argument\u2019s name clashes with a reserved keyword, it is generally better to append a single trailing underscore rather than use an abbreviation or spelling corruption. Thus class_ is better than clss. (Perhaps better is to avoid such clashes by using a synonym.)

        Names can be excluded from this rule using the lint.pep8-naming.ignore-names or lint.pep8-naming.extend-ignore-names configuration options. For example, to allow the use of this as the first argument to instance methods, set the lint.pep8-naming.extend-ignore-names option to [\"this\"].

        ","tags":["N805"]},{"location":"rules/invalid-first-argument-name-for-method/#example","title":"Example","text":"
        class Example:\n    def function(cls, data): ...\n

        Use instead:

        class Example:\n    def function(self, data): ...\n
        ","tags":["N805"]},{"location":"rules/invalid-first-argument-name-for-method/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as renaming a method parameter can change the behavior of the program.

        ","tags":["N805"]},{"location":"rules/invalid-first-argument-name-for-method/#options","title":"Options","text":"
        • lint.pep8-naming.classmethod-decorators
        • lint.pep8-naming.staticmethod-decorators
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N805"]},{"location":"rules/invalid-formatter-suppression-comment/","title":"invalid-formatter-suppression-comment (RUF028)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF028"]},{"location":"rules/invalid-formatter-suppression-comment/#what-it-does","title":"What it does","text":"

        Checks for formatter suppression comments that are ineffective or incompatible with Ruff's formatter.

        ","tags":["RUF028"]},{"location":"rules/invalid-formatter-suppression-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Suppression comments that do not actually prevent formatting could cause unintended changes when the formatter is run.

        ","tags":["RUF028"]},{"location":"rules/invalid-formatter-suppression-comment/#example","title":"Example","text":"

        In the following example, all suppression comments would cause a rule violation.

        def decorator():\n    pass\n\n\n@decorator\n# fmt: off\ndef example():\n    if True:\n        # fmt: skip\n        expression = [\n            # fmt: off\n            1,\n            2,\n        ]\n        # yapf: disable\n    # fmt: on\n    # yapf: enable\n
        ","tags":["RUF028"]},{"location":"rules/invalid-formatter-suppression-comment/#fix-safety","title":"Fix safety","text":"

        This fix is always marked as unsafe because it deletes the invalid suppression comment, rather than trying to move it to a valid position, which the user more likely intended.

        ","tags":["RUF028"]},{"location":"rules/invalid-function-name/","title":"invalid-function-name (N802)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N802"]},{"location":"rules/invalid-function-name/#what-it-does","title":"What it does","text":"

        Checks for functions names that do not follow the snake_case naming convention.

        ","tags":["N802"]},{"location":"rules/invalid-function-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that function names follow snake_case:

        Function names should be lowercase, with words separated by underscores as necessary to improve readability. mixedCase is allowed only in contexts where that\u2019s already the prevailing style (e.g. threading.py), to retain backwards compatibility.

        Names can be excluded from this rule using the lint.pep8-naming.ignore-names or lint.pep8-naming.extend-ignore-names configuration options. For example, to ignore all functions starting with test_ from this rule, set the lint.pep8-naming.extend-ignore-names option to [\"test_*\"].

        ","tags":["N802"]},{"location":"rules/invalid-function-name/#example","title":"Example","text":"
        def myFunction():\n    pass\n

        Use instead:

        def my_function():\n    pass\n
        ","tags":["N802"]},{"location":"rules/invalid-function-name/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N802"]},{"location":"rules/invalid-get-logger-argument/","title":"invalid-get-logger-argument (LOG002)","text":"

        Derived from the flake8-logging linter.

        Fix is sometimes available.

        ","tags":["LOG002"]},{"location":"rules/invalid-get-logger-argument/#what-it-does","title":"What it does","text":"

        Checks for any usage of __cached__ and __file__ as an argument to logging.getLogger().

        ","tags":["LOG002"]},{"location":"rules/invalid-get-logger-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging documentation recommends this pattern:

        logging.getLogger(__name__)\n

        Here, __name__ is the fully qualified module name, such as foo.bar, which is the intended format for logger names.

        This rule detects probably-mistaken usage of similar module-level dunder constants:

        • __cached__ - the pathname of the module's compiled version, such as foo/__pycache__/bar.cpython-311.pyc.
        • __file__ - the pathname of the module, such as foo/bar.py.
        ","tags":["LOG002"]},{"location":"rules/invalid-get-logger-argument/#example","title":"Example","text":"
        import logging\n\nlogger = logging.getLogger(__file__)\n

        Use instead:

        import logging\n\nlogger = logging.getLogger(__name__)\n
        ","tags":["LOG002"]},{"location":"rules/invalid-hash-return-type/","title":"invalid-hash-return-type (PLE0309)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0309"]},{"location":"rules/invalid-hash-return-type/#what-it-does","title":"What it does","text":"

        Checks for __hash__ implementations that return non-integer values.

        ","tags":["PLE0309"]},{"location":"rules/invalid-hash-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __hash__ method should return an integer. Returning a different type may cause unexpected behavior.

        Note: bool is a subclass of int, so it's technically valid for __hash__ to return True or False. However, for consistency with other rules, Ruff will still emit a diagnostic when __hash__ returns a bool.

        ","tags":["PLE0309"]},{"location":"rules/invalid-hash-return-type/#example","title":"Example","text":"
        class Foo:\n    def __hash__(self):\n        return \"2\"\n

        Use instead:

        class Foo:\n    def __hash__(self):\n        return 2\n
        ","tags":["PLE0309"]},{"location":"rules/invalid-hash-return-type/#references","title":"References","text":"
        • Python documentation: The __hash__ method
        ","tags":["PLE0309"]},{"location":"rules/invalid-index-return-type/","title":"invalid-index-return-type (PLE0305)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0305"]},{"location":"rules/invalid-index-return-type/#what-it-does","title":"What it does","text":"

        Checks for __index__ implementations that return non-integer values.

        ","tags":["PLE0305"]},{"location":"rules/invalid-index-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __index__ method should return an integer. Returning a different type may cause unexpected behavior.

        Note: bool is a subclass of int, so it's technically valid for __index__ to return True or False. However, a DeprecationWarning (DeprecationWarning: __index__ returned non-int (type bool)) for such cases was already introduced, thus this is a conscious difference between the original pylint rule and the current ruff implementation.

        ","tags":["PLE0305"]},{"location":"rules/invalid-index-return-type/#example","title":"Example","text":"
        class Foo:\n    def __index__(self):\n        return \"2\"\n

        Use instead:

        class Foo:\n    def __index__(self):\n        return 2\n
        ","tags":["PLE0305"]},{"location":"rules/invalid-index-return-type/#references","title":"References","text":"
        • Python documentation: The __index__ method
        ","tags":["PLE0305"]},{"location":"rules/invalid-index-type/","title":"invalid-index-type (RUF016)","text":"","tags":["RUF016"]},{"location":"rules/invalid-index-type/#what-it-does","title":"What it does","text":"

        Checks for indexed access to lists, strings, tuples, bytes, and comprehensions using a type other than an integer or slice.

        ","tags":["RUF016"]},{"location":"rules/invalid-index-type/#why-is-this-bad","title":"Why is this bad?","text":"

        Only integers or slices can be used as indices to these types. Using other types will result in a TypeError at runtime and a SyntaxWarning at import time.

        ","tags":["RUF016"]},{"location":"rules/invalid-index-type/#example","title":"Example","text":"
        var = [1, 2, 3][\"x\"]\n

        Use instead:

        var = [1, 2, 3][0]\n
        ","tags":["RUF016"]},{"location":"rules/invalid-length-return-type/","title":"invalid-length-return-type (PLE0303)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0303"]},{"location":"rules/invalid-length-return-type/#what-it-does","title":"What it does","text":"

        Checks for __len__ implementations that return values that are not non-negative integers.

        ","tags":["PLE0303"]},{"location":"rules/invalid-length-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __len__ method should return a non-negative integer. Returning a different value may cause unexpected behavior.

        Note: bool is a subclass of int, so it's technically valid for __len__ to return True or False. However, for consistency with other rules, Ruff will still emit a diagnostic when __len__ returns a bool.

        ","tags":["PLE0303"]},{"location":"rules/invalid-length-return-type/#example","title":"Example","text":"
        class Foo:\n    def __len__(self):\n        return \"2\"\n

        Use instead:

        class Foo:\n    def __len__(self):\n        return 2\n
        ","tags":["PLE0303"]},{"location":"rules/invalid-length-return-type/#references","title":"References","text":"
        • Python documentation: The __len__ method
        ","tags":["PLE0303"]},{"location":"rules/invalid-mock-access/","title":"invalid-mock-access (PGH005)","text":"

        Derived from the pygrep-hooks linter.

        ","tags":["PGH005"]},{"location":"rules/invalid-mock-access/#what-it-does","title":"What it does","text":"

        Checks for common mistakes when using mock objects.

        ","tags":["PGH005"]},{"location":"rules/invalid-mock-access/#why-is-this-bad","title":"Why is this bad?","text":"

        The mock module exposes an assertion API that can be used to verify that mock objects undergo expected interactions. This rule checks for common mistakes when using this API.

        For example, it checks for mock attribute accesses that should be replaced with mock method calls.

        ","tags":["PGH005"]},{"location":"rules/invalid-mock-access/#example","title":"Example","text":"
        my_mock.assert_called\n

        Use instead:

        my_mock.assert_called()\n
        ","tags":["PGH005"]},{"location":"rules/invalid-module-name/","title":"invalid-module-name (N999)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N999"]},{"location":"rules/invalid-module-name/#what-it-does","title":"What it does","text":"

        Checks for module names that do not follow the snake_case naming convention or are otherwise invalid.

        ","tags":["N999"]},{"location":"rules/invalid-module-name/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the use of the snake_case naming convention for module names:

        Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.

        When an extension module written in C or C++ has an accompanying Python module that provides a higher level (e.g. more object-oriented) interface, the C/C++ module has a leading underscore (e.g. _socket).

        Further, in order for Python modules to be importable, they must be valid identifiers. As such, they cannot start with a digit, or collide with hard keywords, like import or class.

        ","tags":["N999"]},{"location":"rules/invalid-module-name/#example","title":"Example","text":"
        • Instead of example-module-name or example module name, use example_module_name.
        • Instead of ExampleModule, use example_module.
        ","tags":["N999"]},{"location":"rules/invalid-pathlib-with-suffix/","title":"invalid-pathlib-with-suffix (PTH210)","text":"

        Derived from the flake8-use-pathlib linter.

        Fix is sometimes available.

        ","tags":["PTH210"]},{"location":"rules/invalid-pathlib-with-suffix/#what-it-does","title":"What it does","text":"

        Checks for pathlib.Path.with_suffix() calls where the given suffix does not have a leading dot or the given suffix is a single dot \".\".

        ","tags":["PTH210"]},{"location":"rules/invalid-pathlib-with-suffix/#why-is-this-bad","title":"Why is this bad?","text":"

        Path.with_suffix() will raise an error at runtime if the given suffix is not prefixed with a dot or it is a single dot \".\".

        ","tags":["PTH210"]},{"location":"rules/invalid-pathlib-with-suffix/#example","title":"Example","text":"
        path.with_suffix(\"py\")\n

        Use instead:

        path.with_suffix(\".py\")\n
        ","tags":["PTH210"]},{"location":"rules/invalid-pathlib-with-suffix/#known-problems","title":"Known problems","text":"

        This rule is likely to have false negatives, as Ruff can only emit the lint if it can say for sure that a binding refers to a Path object at runtime. Due to type inference limitations, Ruff is currently only confident about this if it can see that the binding originates from a function parameter annotated with Path or from a direct assignment to a Path() constructor call.

        ","tags":["PTH210"]},{"location":"rules/invalid-pathlib-with-suffix/#fix-safety","title":"Fix safety","text":"

        The fix for this rule adds a leading period to the string passed to the with_suffix() call. This fix is marked as unsafe, as it changes runtime behaviour: the call would previously always have raised an exception, but no longer will.

        Moreover, it's impossible to determine if this is the correct fix for a given situation (it's possible that the string was correct but was being passed to the wrong method entirely, for example).

        No fix is offered if the suffix \".\" is given, since the intent is unclear.

        ","tags":["PTH210"]},{"location":"rules/invalid-print-syntax/","title":"invalid-print-syntax (F633)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F633"]},{"location":"rules/invalid-print-syntax/#what-it-does","title":"What it does","text":"

        Checks for print statements that use the >> syntax.

        ","tags":["F633"]},{"location":"rules/invalid-print-syntax/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 2, the print statement can be used with the >> syntax to print to a file-like object. This print >> sys.stderr syntax no longer exists in Python 3, where print is only a function, not a statement.

        Instead, use the file keyword argument to the print function, the sys.stderr.write function, or the logging module.

        ","tags":["F633"]},{"location":"rules/invalid-print-syntax/#example","title":"Example","text":"
        from __future__ import print_function\nimport sys\n\nprint >> sys.stderr, \"Hello, world!\"\n

        Use instead:

        print(\"Hello, world!\", file=sys.stderr)\n

        Or:

        import sys\n\nsys.stderr.write(\"Hello, world!\\n\")\n

        Or:

        import logging\n\nlogging.error(\"Hello, world!\")\n
        ","tags":["F633"]},{"location":"rules/invalid-print-syntax/#references","title":"References","text":"
        • Python documentation: print
        ","tags":["F633"]},{"location":"rules/invalid-pyproject-toml/","title":"invalid-pyproject-toml (RUF200)","text":"","tags":["RUF200"]},{"location":"rules/invalid-pyproject-toml/#what-it-does","title":"What it does","text":"

        Checks for any pyproject.toml that does not conform to the schema from the relevant PEPs.

        ","tags":["RUF200"]},{"location":"rules/invalid-pyproject-toml/#why-is-this-bad","title":"Why is this bad?","text":"

        Your project may contain invalid metadata or configuration without you noticing

        ","tags":["RUF200"]},{"location":"rules/invalid-pyproject-toml/#example","title":"Example","text":"
        [project]\nname = \"crab\"\nversion = \"1.0.0\"\nauthors = [\"Ferris the Crab <ferris@example.org>\"]\n

        Use instead:

        [project]\nname = \"crab\"\nversion = \"1.0.0\"\nauthors = [\n  { name = \"Ferris the Crab\", email = \"ferris@example.org\" }\n]\n
        ","tags":["RUF200"]},{"location":"rules/invalid-pyproject-toml/#references","title":"References","text":"
        • Specification of [project] in pyproject.toml
        • Specification of [build-system] in pyproject.toml
        • Draft but implemented license declaration extensions
        ","tags":["RUF200"]},{"location":"rules/invalid-rule-code/","title":"invalid-rule-code (RUF102)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF102"]},{"location":"rules/invalid-rule-code/#what-it-does","title":"What it does","text":"

        Checks for noqa codes that are invalid.

        ","tags":["RUF102"]},{"location":"rules/invalid-rule-code/#why-is-this-bad","title":"Why is this bad?","text":"

        Invalid rule codes serve no purpose and may indicate outdated code suppressions.

        ","tags":["RUF102"]},{"location":"rules/invalid-rule-code/#example","title":"Example","text":"
        import os  # noqa: XYZ999\n

        Use instead:

        import os\n

        Or if there are still valid codes needed:

        import os  # noqa: E402\n
        ","tags":["RUF102"]},{"location":"rules/invalid-rule-code/#options","title":"Options","text":"
        • lint.external
        ","tags":["RUF102"]},{"location":"rules/invalid-str-return-type/","title":"invalid-str-return-type (PLE0307)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0307"]},{"location":"rules/invalid-str-return-type/#what-it-does","title":"What it does","text":"

        Checks for __str__ implementations that return a type other than str.

        ","tags":["PLE0307"]},{"location":"rules/invalid-str-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The __str__ method should return a str object. Returning a different type may cause unexpected behavior.

        ","tags":["PLE0307"]},{"location":"rules/invalid-str-return-type/#example","title":"Example","text":"
        class Foo:\n    def __str__(self):\n        return True\n

        Use instead:

        class Foo:\n    def __str__(self):\n        return \"Foo\"\n
        ","tags":["PLE0307"]},{"location":"rules/invalid-str-return-type/#references","title":"References","text":"
        • Python documentation: The __str__ method
        ","tags":["PLE0307"]},{"location":"rules/invalid-todo-capitalization/","title":"invalid-todo-capitalization (TD006)","text":"

        Derived from the flake8-todos linter.

        Fix is always available.

        ","tags":["TD006"]},{"location":"rules/invalid-todo-capitalization/#what-it-does","title":"What it does","text":"

        Checks that a \"TODO\" tag is properly capitalized (i.e., that the tag is uppercase).

        ","tags":["TD006"]},{"location":"rules/invalid-todo-capitalization/#why-is-this-bad","title":"Why is this bad?","text":"

        Capitalizing the \"TODO\" in a TODO comment is a convention that makes it easier for future readers to identify TODOs.

        ","tags":["TD006"]},{"location":"rules/invalid-todo-capitalization/#example","title":"Example","text":"
        # todo(charlie): capitalize this\n

        Use instead:

        # TODO(charlie): this is capitalized\n
        ","tags":["TD006"]},{"location":"rules/invalid-todo-tag/","title":"invalid-todo-tag (TD001)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD001"]},{"location":"rules/invalid-todo-tag/#what-it-does","title":"What it does","text":"

        Checks that a TODO comment is labelled with \"TODO\".

        ","tags":["TD001"]},{"location":"rules/invalid-todo-tag/#why-is-this-bad","title":"Why is this bad?","text":"

        Ambiguous tags reduce code visibility and can lead to dangling TODOs. For example, if a comment is tagged with \"FIXME\" rather than \"TODO\", it may be overlooked by future readers.

        Note that this rule will only flag \"FIXME\" and \"XXX\" tags as incorrect.

        ","tags":["TD001"]},{"location":"rules/invalid-todo-tag/#example","title":"Example","text":"
        # FIXME(ruff): this should get fixed!\n

        Use instead:

        # TODO(ruff): this is now fixed!\n
        ","tags":["TD001"]},{"location":"rules/io-error/","title":"io-error (E902)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E902"]},{"location":"rules/io-error/#what-it-does","title":"What it does","text":"

        This is not a regular diagnostic; instead, it's raised when a file cannot be read from disk.

        ","tags":["E902"]},{"location":"rules/io-error/#why-is-this-bad","title":"Why is this bad?","text":"

        An IOError indicates an error in the development setup. For example, the user may not have permissions to read a given file, or the filesystem may contain a broken symlink.

        ","tags":["E902"]},{"location":"rules/io-error/#example","title":"Example","text":"

        On Linux or macOS:

        $ echo 'print(\"hello world!\")' > a.py\n$ chmod 000 a.py\n$ ruff a.py\na.py:1:1: E902 Permission denied (os error 13)\nFound 1 error.\n
        ","tags":["E902"]},{"location":"rules/io-error/#references","title":"References","text":"
        • UNIX Permissions introduction
        • Command Line Basics: Symbolic Links
        ","tags":["E902"]},{"location":"rules/is-literal/","title":"is-literal (F632)","text":"

        Derived from the Pyflakes linter.

        Fix is always available.

        ","tags":["F632"]},{"location":"rules/is-literal/#what-it-does","title":"What it does","text":"

        Checks for is and is not comparisons against literals, like integers, strings, or lists.

        ","tags":["F632"]},{"location":"rules/is-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        The is and is not comparators operate on identity, in that they check whether two objects are the same object. If the objects are not the same object, the comparison will always be False. Using is and is not with constant literals often works \"by accident\", but are not guaranteed to produce the expected result.

        As of Python 3.8, using is and is not with constant literals will produce a SyntaxWarning.

        This rule will also flag is and is not comparisons against non-constant literals, like lists, sets, and dictionaries. While such comparisons will not raise a SyntaxWarning, they are still likely to be incorrect, as they will compare the identities of the objects instead of their values, which will always evaluate to False.

        Instead, use == and != to compare literals, which will compare the values of the objects instead of their identities.

        ","tags":["F632"]},{"location":"rules/is-literal/#example","title":"Example","text":"
        x = 200\nif x is 200:\n    print(\"It's 200!\")\n

        Use instead:

        x = 200\nif x == 200:\n    print(\"It's 200!\")\n
        ","tags":["F632"]},{"location":"rules/is-literal/#references","title":"References","text":"
        • Python documentation: Identity comparisons
        • Python documentation: Value comparisons
        • Why does Python log a SyntaxWarning for \u2018is\u2019 with literals? by Adam Johnson
        ","tags":["F632"]},{"location":"rules/isinstance-type-none/","title":"isinstance-type-none (FURB168)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB168"]},{"location":"rules/isinstance-type-none/#what-it-does","title":"What it does","text":"

        Checks for uses of isinstance that check if an object is of type None.

        ","tags":["FURB168"]},{"location":"rules/isinstance-type-none/#why-is-this-bad","title":"Why is this bad?","text":"

        There is only ever one instance of None, so it is more efficient and readable to use the is operator to check if an object is None.

        ","tags":["FURB168"]},{"location":"rules/isinstance-type-none/#example","title":"Example","text":"
        isinstance(obj, type(None))\n

        Use instead:

        obj is None\n
        ","tags":["FURB168"]},{"location":"rules/isinstance-type-none/#fix-safety","title":"Fix safety","text":"

        The fix will be marked as unsafe if there are any comments within the call.

        ","tags":["FURB168"]},{"location":"rules/isinstance-type-none/#references","title":"References","text":"
        • Python documentation: isinstance
        • Python documentation: None
        • Python documentation: type
        • Python documentation: Identity comparisons
        ","tags":["FURB168"]},{"location":"rules/iter-method-return-iterable/","title":"iter-method-return-iterable (PYI045)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI045"]},{"location":"rules/iter-method-return-iterable/#what-it-does","title":"What it does","text":"

        Checks for __iter__ methods in stubs that return Iterable[T] instead of an Iterator[T].

        ","tags":["PYI045"]},{"location":"rules/iter-method-return-iterable/#why-is-this-bad","title":"Why is this bad?","text":"

        __iter__ methods should always should return an Iterator of some kind, not an Iterable.

        In Python, an Iterable is an object that has an __iter__ method; an Iterator is an object that has __iter__ and __next__ methods. All __iter__ methods are expected to return Iterators. Type checkers may not always recognize an object as being iterable if its __iter__ method does not return an Iterator.

        Every Iterator is an Iterable, but not every Iterable is an Iterator. For example, list is an Iterable, but not an Iterator; you can obtain an iterator over a list's elements by passing the list to iter():

        >>> import collections.abc\n>>> x = [42]\n>>> isinstance(x, collections.abc.Iterable)\nTrue\n>>> isinstance(x, collections.abc.Iterator)\nFalse\n>>> next(x)\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: 'list' object is not an iterator\n>>> y = iter(x)\n>>> isinstance(y, collections.abc.Iterable)\nTrue\n>>> isinstance(y, collections.abc.Iterator)\nTrue\n>>> next(y)\n42\n

        Using Iterable rather than Iterator as a return type for an __iter__ methods would imply that you would not necessarily be able to call next() on the returned object, violating the expectations of the interface.

        ","tags":["PYI045"]},{"location":"rules/iter-method-return-iterable/#example","title":"Example","text":"
        import collections.abc\n\n\nclass Klass:\n    def __iter__(self) -> collections.abc.Iterable[str]: ...\n

        Use instead:

        import collections.abc\n\n\nclass Klass:\n    def __iter__(self) -> collections.abc.Iterator[str]: ...\n
        ","tags":["PYI045"]},{"location":"rules/iteration-over-set/","title":"iteration-over-set (PLC0208)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLC0208"]},{"location":"rules/iteration-over-set/#what-it-does","title":"What it does","text":"

        Checks for iteration over a set literal where each element in the set is itself a literal value.

        ","tags":["PLC0208"]},{"location":"rules/iteration-over-set/#why-is-this-bad","title":"Why is this bad?","text":"

        Iterating over a set is less efficient than iterating over a sequence type, like list or tuple.

        ","tags":["PLC0208"]},{"location":"rules/iteration-over-set/#example","title":"Example","text":"
        for number in {1, 2, 3}:\n    ...\n

        Use instead:

        for number in (1, 2, 3):\n    ...\n
        ","tags":["PLC0208"]},{"location":"rules/iteration-over-set/#references","title":"References","text":"
        • Python documentation: set
        ","tags":["PLC0208"]},{"location":"rules/jinja2-autoescape-false/","title":"jinja2-autoescape-false (S701)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S701"]},{"location":"rules/jinja2-autoescape-false/#what-it-does","title":"What it does","text":"

        Checks for jinja2 templates that use autoescape=False.

        ","tags":["S701"]},{"location":"rules/jinja2-autoescape-false/#why-is-this-bad","title":"Why is this bad?","text":"

        jinja2 templates that use autoescape=False are vulnerable to cross-site scripting (XSS) attacks that allow attackers to execute arbitrary JavaScript.

        By default, jinja2 sets autoescape to False, so it is important to set autoescape=True or use the select_autoescape function to mitigate XSS vulnerabilities.

        ","tags":["S701"]},{"location":"rules/jinja2-autoescape-false/#example","title":"Example","text":"
        import jinja2\n\njinja2.Environment(loader=jinja2.FileSystemLoader(\".\"))\n

        Use instead:

        import jinja2\n\njinja2.Environment(loader=jinja2.FileSystemLoader(\".\"), autoescape=True)\n
        ","tags":["S701"]},{"location":"rules/jinja2-autoescape-false/#references","title":"References","text":"
        • Jinja documentation: API
        • Common Weakness Enumeration: CWE-94
        ","tags":["S701"]},{"location":"rules/jump-statement-in-finally/","title":"jump-statement-in-finally (B012)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B012"]},{"location":"rules/jump-statement-in-finally/#what-it-does","title":"What it does","text":"

        Checks for break, continue, and return statements in finally blocks.

        ","tags":["B012"]},{"location":"rules/jump-statement-in-finally/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of break, continue, and return statements in finally blocks can cause exceptions to be silenced.

        finally blocks execute regardless of whether an exception is raised. If a break, continue, or return statement is reached in a finally block, any exception raised in the try or except blocks will be silenced.

        ","tags":["B012"]},{"location":"rules/jump-statement-in-finally/#example","title":"Example","text":"
        def speed(distance, time):\n    try:\n        return distance / time\n    except ZeroDivisionError:\n        raise ValueError(\"Time cannot be zero\")\n    finally:\n        return 299792458  # `ValueError` is silenced\n

        Use instead:

        def speed(distance, time):\n    try:\n        return distance / time\n    except ZeroDivisionError:\n        raise ValueError(\"Time cannot be zero\")\n
        ","tags":["B012"]},{"location":"rules/jump-statement-in-finally/#references","title":"References","text":"
        • Python documentation: The try statement
        ","tags":["B012"]},{"location":"rules/lambda-assignment/","title":"lambda-assignment (E731)","text":"

        Derived from the pycodestyle linter.

        Fix is sometimes available.

        ","tags":["E731"]},{"location":"rules/lambda-assignment/#what-it-does","title":"What it does","text":"

        Checks for lambda expressions which are assigned to a variable.

        ","tags":["E731"]},{"location":"rules/lambda-assignment/#why-is-this-bad","title":"Why is this bad?","text":"

        Per PEP 8, you should \"Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier.\"

        Using a def statement leads to better tracebacks, and the assignment itself negates the primary benefit of using a lambda expression (i.e., that it can be embedded inside another expression).

        ","tags":["E731"]},{"location":"rules/lambda-assignment/#example","title":"Example","text":"
        f = lambda x: 2 * x\n

        Use instead:

        def f(x):\n    return 2 * x\n
        ","tags":["E731"]},{"location":"rules/late-future-import/","title":"late-future-import (F404)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F404"]},{"location":"rules/late-future-import/#what-it-does","title":"What it does","text":"

        Checks for __future__ imports that are not located at the beginning of a file.

        ","tags":["F404"]},{"location":"rules/late-future-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Imports from __future__ must be placed the beginning of the file, before any other statements (apart from docstrings). The use of __future__ imports elsewhere is invalid and will result in a SyntaxError.

        ","tags":["F404"]},{"location":"rules/late-future-import/#example","title":"Example","text":"
        from pathlib import Path\n\nfrom __future__ import annotations\n

        Use instead:

        from __future__ import annotations\n\nfrom pathlib import Path\n
        ","tags":["F404"]},{"location":"rules/late-future-import/#references","title":"References","text":"
        • Python documentation: Future statements
        ","tags":["F404"]},{"location":"rules/len-test/","title":"len-test (PLC1802)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLC1802"]},{"location":"rules/len-test/#what-it-does","title":"What it does","text":"

        Checks for len calls on sequences in a boolean test context.

        ","tags":["PLC1802"]},{"location":"rules/len-test/#why-is-this-bad","title":"Why is this bad?","text":"

        Empty sequences are considered false in a boolean context. You can either remove the call to len or compare the length against a scalar.

        ","tags":["PLC1802"]},{"location":"rules/len-test/#example","title":"Example","text":"
        fruits = [\"orange\", \"apple\"]\nvegetables = []\n\nif len(fruits):\n    print(fruits)\n\nif not len(vegetables):\n    print(vegetables)\n

        Use instead:

        fruits = [\"orange\", \"apple\"]\nvegetables = []\n\nif fruits:\n    print(fruits)\n\nif not vegetables:\n    print(vegetables)\n
        ","tags":["PLC1802"]},{"location":"rules/len-test/#references","title":"References","text":"

        PEP 8: Programming Recommendations

        ","tags":["PLC1802"]},{"location":"rules/line-contains-fixme/","title":"line-contains-fixme (FIX001)","text":"

        Derived from the flake8-fixme linter.

        ","tags":["FIX001"]},{"location":"rules/line-contains-fixme/#what-it-does","title":"What it does","text":"

        Checks for \"FIXME\" comments.

        ","tags":["FIX001"]},{"location":"rules/line-contains-fixme/#why-is-this-bad","title":"Why is this bad?","text":"

        \"FIXME\" comments are used to describe an issue that should be resolved (usually, a bug or unexpected behavior).

        Consider resolving the issue before deploying the code.

        Note that if you use \"FIXME\" comments as a form of documentation, this rule may not be appropriate for your project.

        ","tags":["FIX001"]},{"location":"rules/line-contains-fixme/#example","title":"Example","text":"
        def speed(distance, time):\n    return distance / time  # FIXME: Raises ZeroDivisionError for time = 0.\n
        ","tags":["FIX001"]},{"location":"rules/line-contains-hack/","title":"line-contains-hack (FIX004)","text":"

        Derived from the flake8-fixme linter.

        ","tags":["FIX004"]},{"location":"rules/line-contains-hack/#what-it-does","title":"What it does","text":"

        Checks for \"HACK\" comments.

        ","tags":["FIX004"]},{"location":"rules/line-contains-hack/#why-is-this-bad","title":"Why is this bad?","text":"

        \"HACK\" comments are used to describe an issue that should be resolved (usually, a suboptimal solution or temporary workaround).

        Consider resolving the issue before deploying the code.

        Note that if you use \"HACK\" comments as a form of documentation, this rule may not be appropriate for your project.

        ","tags":["FIX004"]},{"location":"rules/line-contains-hack/#example","title":"Example","text":"
        import os\n\n\ndef running_windows():  # HACK: Use platform module instead.\n    try:\n        os.mkdir(\"C:\\\\Windows\\\\System32\\\\\")\n    except FileExistsError:\n        return True\n    else:\n        os.rmdir(\"C:\\\\Windows\\\\System32\\\\\")\n        return False\n
        ","tags":["FIX004"]},{"location":"rules/line-contains-todo/","title":"line-contains-todo (FIX002)","text":"

        Derived from the flake8-fixme linter.

        ","tags":["FIX002"]},{"location":"rules/line-contains-todo/#what-it-does","title":"What it does","text":"

        Checks for \"TODO\" comments.

        ","tags":["FIX002"]},{"location":"rules/line-contains-todo/#why-is-this-bad","title":"Why is this bad?","text":"

        \"TODO\" comments are used to describe an issue that should be resolved (usually, a missing feature, optimization, or refactoring opportunity).

        Consider resolving the issue before deploying the code.

        Note that if you use \"TODO\" comments as a form of documentation (e.g., to provide context for future work), this rule may not be appropriate for your project.

        ","tags":["FIX002"]},{"location":"rules/line-contains-todo/#example","title":"Example","text":"
        def greet(name):\n    return f\"Hello, {name}!\"  # TODO: Add support for custom greetings.\n
        ","tags":["FIX002"]},{"location":"rules/line-contains-xxx/","title":"line-contains-xxx (FIX003)","text":"

        Derived from the flake8-fixme linter.

        ","tags":["FIX003"]},{"location":"rules/line-contains-xxx/#what-it-does","title":"What it does","text":"

        Checks for \"XXX\" comments.

        ","tags":["FIX003"]},{"location":"rules/line-contains-xxx/#why-is-this-bad","title":"Why is this bad?","text":"

        \"XXX\" comments are used to describe an issue that should be resolved.

        Consider resolving the issue before deploying the code, or, at minimum, using a more descriptive comment tag (e.g, \"TODO\").

        ","tags":["FIX003"]},{"location":"rules/line-contains-xxx/#example","title":"Example","text":"
        def speed(distance, time):\n    return distance / time  # XXX: Raises ZeroDivisionError for time = 0.\n
        ","tags":["FIX003"]},{"location":"rules/line-too-long/","title":"line-too-long (E501)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E501"]},{"location":"rules/line-too-long/#what-it-does","title":"What it does","text":"

        Checks for lines that exceed the specified maximum character length.

        ","tags":["E501"]},{"location":"rules/line-too-long/#why-is-this-bad","title":"Why is this bad?","text":"

        Overlong lines can hurt readability. PEP 8, for example, recommends limiting lines to 79 characters. By default, this rule enforces a limit of 88 characters for compatibility with Black and the Ruff formatter, though that limit is configurable via the line-length setting.

        In the interest of pragmatism, this rule makes a few exceptions when determining whether a line is overlong. Namely, it:

        1. Ignores lines that consist of a single \"word\" (i.e., without any whitespace between its characters).
        2. Ignores lines that end with a URL, as long as the URL starts before the line-length threshold.
        3. Ignores line that end with a pragma comment (e.g., # type: ignore or # noqa), as long as the pragma comment starts before the line-length threshold. That is, a line will not be flagged as overlong if a pragma comment causes it to exceed the line length. (This behavior aligns with that of the Ruff formatter.)
        4. Ignores SPDX license identifiers and copyright notices (e.g., # SPDX-License-Identifier: MIT), which are machine-readable and should not wrap over multiple lines.

        If lint.pycodestyle.ignore-overlong-task-comments is true, this rule will also ignore comments that start with any of the specified lint.task-tags (e.g., # TODO:).

        ","tags":["E501"]},{"location":"rules/line-too-long/#example","title":"Example","text":"
        my_function(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10)\n

        Use instead:

        my_function(\n    param1, param2, param3, param4, param5,\n    param6, param7, param8, param9, param10\n)\n
        ","tags":["E501"]},{"location":"rules/line-too-long/#error-suppression","title":"Error suppression","text":"

        Hint: when suppressing E501 errors within multi-line strings (like docstrings), the noqa directive should come at the end of the string (after the closing triple quote), and will apply to the entire string, like so:

        \"\"\"Lorem ipsum dolor sit amet.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.\n\"\"\"  # noqa: E501\n
        ","tags":["E501"]},{"location":"rules/line-too-long/#options","title":"Options","text":"
        • line-length
        • lint.task-tags
        • lint.pycodestyle.ignore-overlong-task-comments
        • lint.pycodestyle.max-line-length
        ","tags":["E501"]},{"location":"rules/list-reverse-copy/","title":"list-reverse-copy (FURB187)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB187"]},{"location":"rules/list-reverse-copy/#what-it-does","title":"What it does","text":"

        Checks for list reversals that can be performed in-place in lieu of creating a new list.

        ","tags":["FURB187"]},{"location":"rules/list-reverse-copy/#why-is-this-bad","title":"Why is this bad?","text":"

        When reversing a list, it's more efficient to use the in-place method .reverse() instead of creating a new list, if the original list is no longer needed.

        ","tags":["FURB187"]},{"location":"rules/list-reverse-copy/#example","title":"Example","text":"
        l = [1, 2, 3]\nl = reversed(l)\n\nl = [1, 2, 3]\nl = list(reversed(l))\n\nl = [1, 2, 3]\nl = l[::-1]\n

        Use instead:

        l = [1, 2, 3]\nl.reverse()\n
        ","tags":["FURB187"]},{"location":"rules/list-reverse-copy/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as calling .reverse() on a list will mutate the list in-place, unlike reversed, which creates a new list and leaves the original list unchanged.

        If the list is referenced elsewhere, this could lead to unexpected behavior.

        ","tags":["FURB187"]},{"location":"rules/list-reverse-copy/#references","title":"References","text":"
        • Python documentation: More on Lists
        ","tags":["FURB187"]},{"location":"rules/literal-membership/","title":"literal-membership (PLR6201)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR6201"]},{"location":"rules/literal-membership/#what-it-does","title":"What it does","text":"

        Checks for membership tests on list and tuple literals.

        ","tags":["PLR6201"]},{"location":"rules/literal-membership/#why-is-this-bad","title":"Why is this bad?","text":"

        When testing for membership in a static sequence, prefer a set literal over a list or tuple, as Python optimizes set membership tests.

        ","tags":["PLR6201"]},{"location":"rules/literal-membership/#example","title":"Example","text":"
        1 in [1, 2, 3]\n

        Use instead:

        1 in {1, 2, 3}\n
        ","tags":["PLR6201"]},{"location":"rules/literal-membership/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as the use of a set literal will error at runtime if the sequence contains unhashable elements (like lists or dictionaries). While Ruff will attempt to infer the hashability of the elements, it may not always be able to do so.

        ","tags":["PLR6201"]},{"location":"rules/literal-membership/#references","title":"References","text":"
        • What\u2019s New In Python 3.2
        ","tags":["PLR6201"]},{"location":"rules/load-before-global-declaration/","title":"load-before-global-declaration (PLE0118)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0118"]},{"location":"rules/load-before-global-declaration/#what-it-does","title":"What it does","text":"

        Checks for uses of names that are declared as global prior to the relevant global declaration.

        ","tags":["PLE0118"]},{"location":"rules/load-before-global-declaration/#why-is-this-bad","title":"Why is this bad?","text":"

        The global declaration applies to the entire scope. Using a name that's declared as global in a given scope prior to the relevant global declaration is a SyntaxError.

        ","tags":["PLE0118"]},{"location":"rules/load-before-global-declaration/#example","title":"Example","text":"
        counter = 1\n\n\ndef increment():\n    print(f\"Adding 1 to {counter}\")\n    global counter\n    counter += 1\n

        Use instead:

        counter = 1\n\n\ndef increment():\n    global counter\n    print(f\"Adding 1 to {counter}\")\n    counter += 1\n
        ","tags":["PLE0118"]},{"location":"rules/load-before-global-declaration/#references","title":"References","text":"
        • Python documentation: The global statement
        ","tags":["PLE0118"]},{"location":"rules/log-exception-outside-except-handler/","title":"log-exception-outside-except-handler (LOG004)","text":"

        Derived from the flake8-logging linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["LOG004"]},{"location":"rules/log-exception-outside-except-handler/#what-it-does","title":"What it does","text":"

        Checks for .exception() logging calls outside of exception handlers.

        ","tags":["LOG004"]},{"location":"rules/log-exception-outside-except-handler/#why-is-this-bad","title":"Why is this bad?","text":"

        The documentation states:

        This function should only be called from an exception handler.

        Calling .exception() outside of an exception handler attaches None as exception information, leading to confusing messages:

        >>> logging.exception(\"example\")\nERROR:root:example\nNoneType: None\n
        ","tags":["LOG004"]},{"location":"rules/log-exception-outside-except-handler/#example","title":"Example","text":"
        import logging\n\nlogging.exception(\"Foobar\")\n

        Use instead:

        import logging\n\nlogging.error(\"Foobar\")\n
        ","tags":["LOG004"]},{"location":"rules/log-exception-outside-except-handler/#fix-safety","title":"Fix safety","text":"

        The fix, if available, will always be marked as unsafe, as it changes runtime behavior.

        ","tags":["LOG004"]},{"location":"rules/logging-config-insecure-listen/","title":"logging-config-insecure-listen (S612)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S612"]},{"location":"rules/logging-config-insecure-listen/#what-it-does","title":"What it does","text":"

        Checks for insecure logging.config.listen calls.

        ","tags":["S612"]},{"location":"rules/logging-config-insecure-listen/#why-is-this-bad","title":"Why is this bad?","text":"

        logging.config.listen starts a server that listens for logging configuration requests. This is insecure, as parts of the configuration are passed to the built-in eval function, which can be used to execute arbitrary code.

        ","tags":["S612"]},{"location":"rules/logging-config-insecure-listen/#example","title":"Example","text":"
        import logging\n\nlogging.config.listen(9999)\n
        ","tags":["S612"]},{"location":"rules/logging-config-insecure-listen/#references","title":"References","text":"
        • Python documentation: logging.config.listen()
        ","tags":["S612"]},{"location":"rules/logging-exc-info/","title":"logging-exc-info (G201)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G201"]},{"location":"rules/logging-exc-info/#what-it-does","title":"What it does","text":"

        Checks for uses of logging.error that pass exc_info=True.

        ","tags":["G201"]},{"location":"rules/logging-exc-info/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling logging.error with exc_info=True is equivalent to calling logging.exception. Using logging.exception is more concise, more readable, and conveys the intent of the logging statement more clearly.

        ","tags":["G201"]},{"location":"rules/logging-exc-info/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G201"]},{"location":"rules/logging-exc-info/#example","title":"Example","text":"
        import logging\n\ntry:\n    ...\nexcept ValueError:\n    logging.error(\"Exception occurred\", exc_info=True)\n

        Use instead:

        import logging\n\ntry:\n    ...\nexcept ValueError:\n    logging.exception(\"Exception occurred\")\n
        ","tags":["G201"]},{"location":"rules/logging-exc-info/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G201"]},{"location":"rules/logging-exc-info/#references","title":"References","text":"
        • Python documentation: logging.exception
        • Python documentation: exception
        • Python documentation: logging.error
        • Python documentation: error
        ","tags":["G201"]},{"location":"rules/logging-extra-attr-clash/","title":"logging-extra-attr-clash (G101)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#what-it-does","title":"What it does","text":"

        Checks for extra keywords in logging statements that clash with LogRecord attributes.

        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging module provides a mechanism for passing additional values to be logged using the extra keyword argument. These values are then passed to the LogRecord constructor.

        Providing a value via extra that clashes with one of the attributes of the LogRecord constructor will raise a KeyError when the LogRecord is constructed.

        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#example","title":"Example","text":"
        import logging\n\nlogging.basicConfig(format=\"%(name) - %(message)s\", level=logging.INFO)\n\nusername = \"Maria\"\n\nlogging.info(\"Something happened\", extra=dict(name=username))\n

        Use instead:

        import logging\n\nlogging.basicConfig(format=\"%(user_id)s - %(message)s\", level=logging.INFO)\n\nusername = \"Maria\"\n\nlogging.info(\"Something happened\", extra=dict(user_id=username))\n
        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G101"]},{"location":"rules/logging-extra-attr-clash/#references","title":"References","text":"
        • Python documentation: LogRecord attributes
        ","tags":["G101"]},{"location":"rules/logging-f-string/","title":"logging-f-string (G004)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G004"]},{"location":"rules/logging-f-string/#what-it-does","title":"What it does","text":"

        Checks for uses of f-strings to format logging messages.

        ","tags":["G004"]},{"location":"rules/logging-f-string/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging module provides a mechanism for passing additional values to be logged using the extra keyword argument. This is more consistent, more efficient, and less error-prone than formatting the string directly.

        Using f-strings to format a logging message requires that Python eagerly format the string, even if the logging statement is never executed (e.g., if the log level is above the level of the logging statement), whereas using the extra keyword argument defers formatting until required.

        Additionally, the use of extra will ensure that the values are made available to all handlers, which can then be configured to log the values in a consistent manner.

        As an alternative to extra, passing values as arguments to the logging method can also be used to defer string formatting until required.

        ","tags":["G004"]},{"location":"rules/logging-f-string/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G004"]},{"location":"rules/logging-f-string/#example","title":"Example","text":"
        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(f\"{user} - Something happened\")\n

        Use instead:

        import logging\n\nlogging.basicConfig(format=\"%(user_id)s - %(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"Something happened\", extra=dict(user_id=user))\n

        Or:

        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"%s - Something happened\", user)\n
        ","tags":["G004"]},{"location":"rules/logging-f-string/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G004"]},{"location":"rules/logging-f-string/#references","title":"References","text":"
        • Python documentation: logging
        • Python documentation: Optimization
        ","tags":["G004"]},{"location":"rules/logging-percent-format/","title":"logging-percent-format (G002)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G002"]},{"location":"rules/logging-percent-format/#what-it-does","title":"What it does","text":"

        Checks for uses of printf-style format strings to format logging messages.

        ","tags":["G002"]},{"location":"rules/logging-percent-format/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging module provides a mechanism for passing additional values to be logged using the extra keyword argument. This is more consistent, more efficient, and less error-prone than formatting the string directly.

        Using printf-style format strings to format a logging message requires that Python eagerly format the string, even if the logging statement is never executed (e.g., if the log level is above the level of the logging statement), whereas using the extra keyword argument defers formatting until required.

        Additionally, the use of extra will ensure that the values are made available to all handlers, which can then be configured to log the values in a consistent manner.

        As an alternative to extra, passing values as arguments to the logging method can also be used to defer string formatting until required.

        ","tags":["G002"]},{"location":"rules/logging-percent-format/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G002"]},{"location":"rules/logging-percent-format/#example","title":"Example","text":"
        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"%s - Something happened\" % user)\n

        Use instead:

        import logging\n\nlogging.basicConfig(format=\"%(user_id)s - %(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"Something happened\", extra=dict(user_id=user))\n

        Or:

        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"%s - Something happened\", user)\n
        ","tags":["G002"]},{"location":"rules/logging-percent-format/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G002"]},{"location":"rules/logging-percent-format/#references","title":"References","text":"
        • Python documentation: logging
        • Python documentation: Optimization
        ","tags":["G002"]},{"location":"rules/logging-redundant-exc-info/","title":"logging-redundant-exc-info (G202)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#what-it-does","title":"What it does","text":"

        Checks for redundant exc_info keyword arguments in logging statements.

        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#why-is-this-bad","title":"Why is this bad?","text":"

        exc_info is True by default for logging.exception, and False by default for logging.error.

        Passing exc_info=True to logging.exception calls is redundant, as is passing exc_info=False to logging.error calls.

        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#example","title":"Example","text":"
        import logging\n\ntry:\n    ...\nexcept ValueError:\n    logging.exception(\"Exception occurred\", exc_info=True)\n

        Use instead:

        import logging\n\ntry:\n    ...\nexcept ValueError:\n    logging.exception(\"Exception occurred\")\n
        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G202"]},{"location":"rules/logging-redundant-exc-info/#references","title":"References","text":"
        • Python documentation: logging.exception
        • Python documentation: exception
        • Python documentation: logging.error
        • Python documentation: error
        ","tags":["G202"]},{"location":"rules/logging-string-concat/","title":"logging-string-concat (G003)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G003"]},{"location":"rules/logging-string-concat/#what-it-does","title":"What it does","text":"

        Checks for uses string concatenation via the + operator to format logging messages.

        ","tags":["G003"]},{"location":"rules/logging-string-concat/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging module provides a mechanism for passing additional values to be logged using the extra keyword argument. This is more consistent, more efficient, and less error-prone than formatting the string directly.

        Using concatenation to format a logging message requires that Python eagerly format the string, even if the logging statement is never executed (e.g., if the log level is above the level of the logging statement), whereas using the extra keyword argument defers formatting until required.

        Additionally, the use of extra will ensure that the values are made available to all handlers, which can then be configured to log the values in a consistent manner.

        As an alternative to extra, passing values as arguments to the logging method can also be used to defer string formatting until required.

        ","tags":["G003"]},{"location":"rules/logging-string-concat/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G003"]},{"location":"rules/logging-string-concat/#example","title":"Example","text":"
        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(user + \" - Something happened\")\n

        Use instead:

        import logging\n\nlogging.basicConfig(format=\"%(user_id)s - %(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"Something happened\", extra=dict(user_id=user))\n

        Or:

        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"%s - Something happened\", user)\n
        ","tags":["G003"]},{"location":"rules/logging-string-concat/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G003"]},{"location":"rules/logging-string-concat/#references","title":"References","text":"
        • Python documentation: logging
        • Python documentation: Optimization
        ","tags":["G003"]},{"location":"rules/logging-string-format/","title":"logging-string-format (G001)","text":"

        Derived from the flake8-logging-format linter.

        ","tags":["G001"]},{"location":"rules/logging-string-format/#what-it-does","title":"What it does","text":"

        Checks for uses of str.format to format logging messages.

        ","tags":["G001"]},{"location":"rules/logging-string-format/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging module provides a mechanism for passing additional values to be logged using the extra keyword argument. This is more consistent, more efficient, and less error-prone than formatting the string directly.

        Using str.format to format a logging message requires that Python eagerly format the string, even if the logging statement is never executed (e.g., if the log level is above the level of the logging statement), whereas using the extra keyword argument defers formatting until required.

        Additionally, the use of extra will ensure that the values are made available to all handlers, which can then be configured to log the values in a consistent manner.

        As an alternative to extra, passing values as arguments to the logging method can also be used to defer string formatting until required.

        ","tags":["G001"]},{"location":"rules/logging-string-format/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G001"]},{"location":"rules/logging-string-format/#example","title":"Example","text":"
        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"{} - Something happened\".format(user))\n

        Use instead:

        import logging\n\nlogging.basicConfig(format=\"%(user_id)s - %(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"Something happened\", extra={\"user_id\": user})\n

        Or:

        import logging\n\nlogging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n\nuser = \"Maria\"\n\nlogging.info(\"%s - Something happened\", user)\n
        ","tags":["G001"]},{"location":"rules/logging-string-format/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G001"]},{"location":"rules/logging-string-format/#references","title":"References","text":"
        • Python documentation: logging
        • Python documentation: Optimization
        ","tags":["G001"]},{"location":"rules/logging-too-few-args/","title":"logging-too-few-args (PLE1206)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1206"]},{"location":"rules/logging-too-few-args/#what-it-does","title":"What it does","text":"

        Checks for too few positional arguments for a logging format string.

        ","tags":["PLE1206"]},{"location":"rules/logging-too-few-args/#why-is-this-bad","title":"Why is this bad?","text":"

        A TypeError will be raised if the statement is run.

        ","tags":["PLE1206"]},{"location":"rules/logging-too-few-args/#example","title":"Example","text":"
        import logging\n\ntry:\n    function()\nexcept Exception as e:\n    logging.error(\"%s error occurred: %s\", e)\n    raise\n

        Use instead:

        import logging\n\ntry:\n    function()\nexcept Exception as e:\n    logging.error(\"%s error occurred: %s\", type(e), e)\n    raise\n
        ","tags":["PLE1206"]},{"location":"rules/logging-too-many-args/","title":"logging-too-many-args (PLE1205)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1205"]},{"location":"rules/logging-too-many-args/#what-it-does","title":"What it does","text":"

        Checks for too many positional arguments for a logging format string.

        ","tags":["PLE1205"]},{"location":"rules/logging-too-many-args/#why-is-this-bad","title":"Why is this bad?","text":"

        A TypeError will be raised if the statement is run.

        ","tags":["PLE1205"]},{"location":"rules/logging-too-many-args/#example","title":"Example","text":"
        import logging\n\ntry:\n    function()\nexcept Exception as e:\n    logging.error(\"Error occurred: %s\", type(e), e)\n    raise\n

        Use instead:

        import logging\n\ntry:\n    function()\nexcept Exception as e:\n    logging.error(\"%s error occurred: %s\", type(e), e)\n    raise\n
        ","tags":["PLE1205"]},{"location":"rules/logging-warn/","title":"logging-warn (G010)","text":"

        Derived from the flake8-logging-format linter.

        Fix is always available.

        ","tags":["G010"]},{"location":"rules/logging-warn/#what-it-does","title":"What it does","text":"

        Checks for uses of logging.warn and logging.Logger.warn.

        ","tags":["G010"]},{"location":"rules/logging-warn/#why-is-this-bad","title":"Why is this bad?","text":"

        logging.warn and logging.Logger.warn are deprecated in favor of logging.warning and logging.Logger.warning, which are functionally equivalent.

        ","tags":["G010"]},{"location":"rules/logging-warn/#known-problems","title":"Known problems","text":"

        This rule detects uses of the logging module via a heuristic. Specifically, it matches against:

        • Uses of the logging module itself (e.g., import logging; logging.info(...)).
        • Uses of flask.current_app.logger (e.g., from flask import current_app; current_app.logger.info(...)).
        • Objects whose name starts with log or ends with logger or logging, when used in the same file in which they are defined (e.g., logger = logging.getLogger(); logger.info(...)).
        • Imported objects marked as loggers via the lint.logger-objects setting, which can be used to enforce these rules against shared logger objects (e.g., from module import logger; logger.info(...), when lint.logger-objects is set to [\"module.logger\"]).
        ","tags":["G010"]},{"location":"rules/logging-warn/#example","title":"Example","text":"
        import logging\n\nlogging.warn(\"Something happened\")\n

        Use instead:

        import logging\n\nlogging.warning(\"Something happened\")\n
        ","tags":["G010"]},{"location":"rules/logging-warn/#options","title":"Options","text":"
        • lint.logger-objects
        ","tags":["G010"]},{"location":"rules/logging-warn/#references","title":"References","text":"
        • Python documentation: logging.warning
        • Python documentation: logging.Logger.warning
        ","tags":["G010"]},{"location":"rules/long-sleep-not-forever/","title":"long-sleep-not-forever (ASYNC116)","text":"

        Derived from the flake8-async linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["ASYNC116"]},{"location":"rules/long-sleep-not-forever/#what-it-does","title":"What it does","text":"

        Checks for uses of trio.sleep() or anyio.sleep() with a delay greater than 24 hours.

        ","tags":["ASYNC116"]},{"location":"rules/long-sleep-not-forever/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling sleep() with a delay greater than 24 hours is usually intended to sleep indefinitely. Instead of using a large delay, trio.sleep_forever() or anyio.sleep_forever() better conveys the intent.

        ","tags":["ASYNC116"]},{"location":"rules/long-sleep-not-forever/#example","title":"Example","text":"
        import trio\n\n\nasync def func():\n    await trio.sleep(86401)\n

        Use instead:

        import trio\n\n\nasync def func():\n    await trio.sleep_forever()\n
        ","tags":["ASYNC116"]},{"location":"rules/long-sleep-not-forever/#fix-safety","title":"Fix safety","text":"

        This fix is marked as unsafe as it changes program behavior.

        ","tags":["ASYNC116"]},{"location":"rules/loop-iterator-mutation/","title":"loop-iterator-mutation (B909)","text":"

        Derived from the flake8-bugbear linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["B909"]},{"location":"rules/loop-iterator-mutation/#what-it-does","title":"What it does","text":"

        Checks for mutations to an iterable during a loop iteration.

        ","tags":["B909"]},{"location":"rules/loop-iterator-mutation/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over an iterable, mutating the iterable can lead to unexpected behavior, like skipping elements or infinite loops.

        ","tags":["B909"]},{"location":"rules/loop-iterator-mutation/#example","title":"Example","text":"
        items = [1, 2, 3]\n\nfor item in items:\n    print(item)\n\n    # Create an infinite loop by appending to the list.\n    items.append(item)\n
        ","tags":["B909"]},{"location":"rules/loop-iterator-mutation/#references","title":"References","text":"
        • Python documentation: Mutable Sequence Types
        ","tags":["B909"]},{"location":"rules/loop-variable-overrides-iterator/","title":"loop-variable-overrides-iterator (B020)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B020"]},{"location":"rules/loop-variable-overrides-iterator/#what-it-does","title":"What it does","text":"

        Checks for loop control variables that override the loop iterable.

        ","tags":["B020"]},{"location":"rules/loop-variable-overrides-iterator/#why-is-this-bad","title":"Why is this bad?","text":"

        Loop control variables should not override the loop iterable, as this can lead to confusing behavior.

        Instead, use a distinct variable name for any loop control variables.

        ","tags":["B020"]},{"location":"rules/loop-variable-overrides-iterator/#example","title":"Example","text":"
        items = [1, 2, 3]\n\nfor items in items:\n    print(items)\n

        Use instead:

        items = [1, 2, 3]\n\nfor item in items:\n    print(item)\n
        ","tags":["B020"]},{"location":"rules/loop-variable-overrides-iterator/#references","title":"References","text":"
        • Python documentation: The for statement
        ","tags":["B020"]},{"location":"rules/lowercase-imported-as-non-lowercase/","title":"lowercase-imported-as-non-lowercase (N812)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N812"]},{"location":"rules/lowercase-imported-as-non-lowercase/#what-it-does","title":"What it does","text":"

        Checks for lowercase imports that are aliased to non-lowercase names.

        ","tags":["N812"]},{"location":"rules/lowercase-imported-as-non-lowercase/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends naming conventions for classes, functions, constants, and more. The use of inconsistent naming styles between import and alias names may lead readers to expect an import to be of another type (e.g., confuse a Python class with a constant).

        Import aliases should thus follow the same naming style as the member being imported.

        ","tags":["N812"]},{"location":"rules/lowercase-imported-as-non-lowercase/#example","title":"Example","text":"
        from example import myclassname as MyClassName\n

        Use instead:

        from example import myclassname\n
        ","tags":["N812"]},{"location":"rules/lowercase-imported-as-non-lowercase/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N812"]},{"location":"rules/lru-cache-with-maxsize-none/","title":"lru-cache-with-maxsize-none (UP033)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP033"]},{"location":"rules/lru-cache-with-maxsize-none/#what-it-does","title":"What it does","text":"

        Checks for uses of functools.lru_cache that set maxsize=None.

        ","tags":["UP033"]},{"location":"rules/lru-cache-with-maxsize-none/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3.9, functools.cache can be used as a drop-in replacement for functools.lru_cache(maxsize=None). When possible, prefer functools.cache as it is more readable and idiomatic.

        ","tags":["UP033"]},{"location":"rules/lru-cache-with-maxsize-none/#example","title":"Example","text":"
        import functools\n\n\n@functools.lru_cache(maxsize=None)\ndef foo(): ...\n

        Use instead:

        import functools\n\n\n@functools.cache\ndef foo(): ...\n
        ","tags":["UP033"]},{"location":"rules/lru-cache-with-maxsize-none/#options","title":"Options","text":"
        • target-version
        ","tags":["UP033"]},{"location":"rules/lru-cache-with-maxsize-none/#references","title":"References","text":"
        • Python documentation: @functools.cache
        ","tags":["UP033"]},{"location":"rules/lru-cache-without-parameters/","title":"lru-cache-without-parameters (UP011)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP011"]},{"location":"rules/lru-cache-without-parameters/#what-it-does","title":"What it does","text":"

        Checks for unnecessary parentheses on functools.lru_cache decorators.

        ","tags":["UP011"]},{"location":"rules/lru-cache-without-parameters/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3.8, functools.lru_cache can be used as a decorator without trailing parentheses, as long as no arguments are passed to it.

        ","tags":["UP011"]},{"location":"rules/lru-cache-without-parameters/#example","title":"Example","text":"
        import functools\n\n\n@functools.lru_cache()\ndef foo(): ...\n

        Use instead:

        import functools\n\n\n@functools.lru_cache\ndef foo(): ...\n
        ","tags":["UP011"]},{"location":"rules/lru-cache-without-parameters/#options","title":"Options","text":"
        • target-version
        ","tags":["UP011"]},{"location":"rules/lru-cache-without-parameters/#references","title":"References","text":"
        • Python documentation: @functools.lru_cache
        • Let lru_cache be used as a decorator with no arguments
        ","tags":["UP011"]},{"location":"rules/magic-value-comparison/","title":"magic-value-comparison (PLR2004)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR2004"]},{"location":"rules/magic-value-comparison/#what-it-does","title":"What it does","text":"

        Checks for the use of unnamed numerical constants (\"magic\") values in comparisons.

        ","tags":["PLR2004"]},{"location":"rules/magic-value-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of \"magic\" values can make code harder to read and maintain, as readers will have to infer the meaning of the value from the context. Such values are discouraged by PEP 8.

        For convenience, this rule excludes a variety of common values from the \"magic\" value definition, such as 0, 1, \"\", and \"__main__\".

        ","tags":["PLR2004"]},{"location":"rules/magic-value-comparison/#example","title":"Example","text":"
        def apply_discount(price: float) -> float:\n    if price <= 100:\n        return price / 2\n    else:\n        return price\n

        Use instead:

        MAX_DISCOUNT = 100\n\n\ndef apply_discount(price: float) -> float:\n    if price <= MAX_DISCOUNT:\n        return price / 2\n    else:\n        return price\n
        ","tags":["PLR2004"]},{"location":"rules/magic-value-comparison/#options","title":"Options","text":"
        • lint.pylint.allow-magic-value-types
        ","tags":["PLR2004"]},{"location":"rules/mako-templates/","title":"mako-templates (S702)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S702"]},{"location":"rules/mako-templates/#what-it-does","title":"What it does","text":"

        Checks for uses of the mako templates.

        ","tags":["S702"]},{"location":"rules/mako-templates/#why-is-this-bad","title":"Why is this bad?","text":"

        Mako templates allow HTML and JavaScript rendering by default, and are inherently open to XSS attacks. Ensure variables in all templates are properly sanitized via the n, h or x flags (depending on context). For example, to HTML escape the variable data, use ${ data |h }.

        ","tags":["S702"]},{"location":"rules/mako-templates/#example","title":"Example","text":"
        from mako.template import Template\n\nTemplate(\"hello\")\n

        Use instead:

        from mako.template import Template\n\nTemplate(\"hello |h\")\n
        ","tags":["S702"]},{"location":"rules/mako-templates/#references","title":"References","text":"
        • Mako documentation
        • OpenStack security: Cross site scripting XSS
        • Common Weakness Enumeration: CWE-80
        ","tags":["S702"]},{"location":"rules/manual-dict-comprehension/","title":"manual-dict-comprehension (PERF403)","text":"

        Derived from the Perflint linter.

        Fix is sometimes available.

        ","tags":["PERF403"]},{"location":"rules/manual-dict-comprehension/#what-it-does","title":"What it does","text":"

        Checks for for loops that can be replaced by a dictionary comprehension.

        ","tags":["PERF403"]},{"location":"rules/manual-dict-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        When creating or extending a dictionary in a for-loop, prefer a dictionary comprehension. Comprehensions are more readable and more performant.

        For example, when comparing {x: x for x in list(range(1000))} to the for loop version, the comprehension is ~10% faster on Python 3.11.

        Note that, as with all perflint rules, this is only intended as a micro-optimization, and will have a negligible impact on performance in most cases.

        ","tags":["PERF403"]},{"location":"rules/manual-dict-comprehension/#example","title":"Example","text":"
        pairs = ((\"a\", 1), (\"b\", 2))\nresult = {}\nfor x, y in pairs:\n    if y % 2:\n        result[x] = y\n

        Use instead:

        pairs = ((\"a\", 1), (\"b\", 2))\nresult = {x: y for x, y in pairs if y % 2}\n

        If you're appending to an existing dictionary, use the update method instead:

        pairs = ((\"a\", 1), (\"b\", 2))\nresult.update({x: y for x, y in pairs if y % 2})\n
        ","tags":["PERF403"]},{"location":"rules/manual-from-import/","title":"manual-from-import (PLR0402)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLR0402"]},{"location":"rules/manual-from-import/#what-it-does","title":"What it does","text":"

        Checks for submodule imports that are aliased to the submodule name.

        ","tags":["PLR0402"]},{"location":"rules/manual-from-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using the from keyword to import the submodule is more concise and readable.

        ","tags":["PLR0402"]},{"location":"rules/manual-from-import/#example","title":"Example","text":"
        import concurrent.futures as futures\n

        Use instead:

        from concurrent import futures\n
        ","tags":["PLR0402"]},{"location":"rules/manual-from-import/#references","title":"References","text":"
        • Python documentation: Submodules
        ","tags":["PLR0402"]},{"location":"rules/manual-list-comprehension/","title":"manual-list-comprehension (PERF401)","text":"

        Derived from the Perflint linter.

        Fix is sometimes available.

        ","tags":["PERF401"]},{"location":"rules/manual-list-comprehension/#what-it-does","title":"What it does","text":"

        Checks for for loops that can be replaced by a list comprehension.

        ","tags":["PERF401"]},{"location":"rules/manual-list-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        When creating a transformed list from an existing list using a for-loop, prefer a list comprehension. List comprehensions are more readable and more performant.

        Using the below as an example, the list comprehension is ~10% faster on Python 3.11, and ~25% faster on Python 3.10.

        Note that, as with all perflint rules, this is only intended as a micro-optimization, and will have a negligible impact on performance in most cases.

        ","tags":["PERF401"]},{"location":"rules/manual-list-comprehension/#example","title":"Example","text":"
        original = list(range(10000))\nfiltered = []\nfor i in original:\n    if i % 2:\n        filtered.append(i)\n

        Use instead:

        original = list(range(10000))\nfiltered = [x for x in original if x % 2]\n

        If you're appending to an existing list, use the extend method instead:

        original = list(range(10000))\nfiltered.extend(x for x in original if x % 2)\n

        Take care that if the original for-loop uses an assignment expression as a conditional, such as if match:=re.match(\"\\d+\",\"123\"), then the corresponding comprehension must wrap the assignment expression in parentheses to avoid a syntax error.

        ","tags":["PERF401"]},{"location":"rules/manual-list-copy/","title":"manual-list-copy (PERF402)","text":"

        Derived from the Perflint linter.

        ","tags":["PERF402"]},{"location":"rules/manual-list-copy/#what-it-does","title":"What it does","text":"

        Checks for for loops that can be replaced by a making a copy of a list.

        ","tags":["PERF402"]},{"location":"rules/manual-list-copy/#why-is-this-bad","title":"Why is this bad?","text":"

        When creating a copy of an existing list using a for-loop, prefer list or list.copy instead. Making a direct copy is more readable and more performant.

        Using the below as an example, the list-based copy is ~2x faster on Python 3.11.

        Note that, as with all perflint rules, this is only intended as a micro-optimization, and will have a negligible impact on performance in most cases.

        ","tags":["PERF402"]},{"location":"rules/manual-list-copy/#example","title":"Example","text":"
        original = list(range(10000))\nfiltered = []\nfor i in original:\n    filtered.append(i)\n

        Use instead:

        original = list(range(10000))\nfiltered = list(original)\n
        ","tags":["PERF402"]},{"location":"rules/map-int-version-parsing/","title":"map-int-version-parsing (RUF048)","text":"","tags":["RUF048"]},{"location":"rules/map-int-version-parsing/#what-it-does","title":"What it does","text":"

        Checks for calls of the form map(int, __version__.split(\".\")).

        ","tags":["RUF048"]},{"location":"rules/map-int-version-parsing/#why-is-this-bad","title":"Why is this bad?","text":"

        __version__ does not always contain integral-like elements.

        import matplotlib  # `__version__ == \"3.9.1.post-1\"` in our environment\n\n# ValueError: invalid literal for int() with base 10: 'post1'\ntuple(map(int, matplotlib.__version__.split(\".\")))\n

        See also Version specifiers | Packaging spec.

        ","tags":["RUF048"]},{"location":"rules/map-int-version-parsing/#example","title":"Example","text":"
        tuple(map(int, matplotlib.__version__.split(\".\")))\n

        Use instead:

        import packaging.version as version\n\nversion.parse(matplotlib.__version__)\n
        ","tags":["RUF048"]},{"location":"rules/math-constant/","title":"math-constant (FURB152)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB152"]},{"location":"rules/math-constant/#what-it-does","title":"What it does","text":"

        Checks for literals that are similar to constants in math module.

        ","tags":["FURB152"]},{"location":"rules/math-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        Hard-coding mathematical constants like \u03c0 increases code duplication, reduces readability, and may lead to a lack of precision.

        ","tags":["FURB152"]},{"location":"rules/math-constant/#example","title":"Example","text":"
        A = 3.141592 * r**2\n

        Use instead:

        A = math.pi * r**2\n
        ","tags":["FURB152"]},{"location":"rules/math-constant/#references","title":"References","text":"
        • Python documentation: math constants
        ","tags":["FURB152"]},{"location":"rules/meta-class-abc-meta/","title":"meta-class-abc-meta (FURB180)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB180"]},{"location":"rules/meta-class-abc-meta/#what-it-does","title":"What it does","text":"

        Checks for uses of metaclass=abc.ABCMeta to define abstract base classes (ABCs).

        ","tags":["FURB180"]},{"location":"rules/meta-class-abc-meta/#why-is-this-bad","title":"Why is this bad?","text":"

        Instead of class C(metaclass=abc.ABCMeta): ..., use class C(ABC): ... to define an abstract base class. Inheriting from the ABC wrapper class is semantically identical to setting metaclass=abc.ABCMeta, but more succinct.

        ","tags":["FURB180"]},{"location":"rules/meta-class-abc-meta/#example","title":"Example","text":"
        class C(metaclass=ABCMeta):\n    pass\n

        Use instead:

        class C(ABC):\n    pass\n
        ","tags":["FURB180"]},{"location":"rules/meta-class-abc-meta/#references","title":"References","text":"
        • Python documentation: abc.ABC
        • Python documentation: abc.ABCMeta
        ","tags":["FURB180"]},{"location":"rules/mismatched-section-underline-length/","title":"mismatched-section-underline-length (D409)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D409"]},{"location":"rules/mismatched-section-underline-length/#what-it-does","title":"What it does","text":"

        Checks for section underlines in docstrings that do not match the length of the corresponding section header.

        ","tags":["D409"]},{"location":"rules/mismatched-section-underline-length/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline numpy-style docstrings, and helps prevent incorrect syntax in docstrings using reStructuredText.

        Multiline numpy-style docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section has a section header and a section body, and there should be a series of underline characters in the line following the header. The length of the underline should exactly match the length of the section header.

        This rule enforces a consistent style for multiline numpy-style docstrings with sections. If your docstring uses reStructuredText, the rule also helps protect against incorrect reStructuredText syntax, which would cause errors if you tried to use a tool such as Sphinx to generate documentation from the docstring.

        This rule is enabled when using the numpy convention, and disabled when using the google or pep257 conventions.

        ","tags":["D409"]},{"location":"rules/mismatched-section-underline-length/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ---\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    ---\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ---\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D409"]},{"location":"rules/mismatched-section-underline-length/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D409"]},{"location":"rules/mismatched-section-underline-length/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D409"]},{"location":"rules/misplaced-bare-raise/","title":"misplaced-bare-raise (PLE0704)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0704"]},{"location":"rules/misplaced-bare-raise/#what-it-does","title":"What it does","text":"

        Checks for bare raise statements outside of exception handlers.

        ","tags":["PLE0704"]},{"location":"rules/misplaced-bare-raise/#why-is-this-bad","title":"Why is this bad?","text":"

        A bare raise statement without an exception object will re-raise the last exception that was active in the current scope, and is typically used within an exception handler to re-raise the caught exception.

        If a bare raise is used outside of an exception handler, it will generate an error due to the lack of an active exception.

        Note that a bare raise within a finally block will work in some cases (namely, when the exception is raised within the try block), but should be avoided as it can lead to confusing behavior.

        ","tags":["PLE0704"]},{"location":"rules/misplaced-bare-raise/#example","title":"Example","text":"
        from typing import Any\n\n\ndef is_some(obj: Any) -> bool:\n    if obj is None:\n        raise\n

        Use instead:

        from typing import Any\n\n\ndef is_some(obj: Any) -> bool:\n    if obj is None:\n        raise ValueError(\"`obj` cannot be `None`\")\n
        ","tags":["PLE0704"]},{"location":"rules/missing-blank-line-after-last-section/","title":"missing-blank-line-after-last-section (D413)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-last-section/#what-it-does","title":"What it does","text":"

        Checks for missing blank lines after the last section of a multiline docstring.

        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-last-section/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline docstrings.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, the rule is disabled when using the google, numpy, and pep257 conventions.

        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-last-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-last-section/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-last-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D413"]},{"location":"rules/missing-blank-line-after-summary/","title":"missing-blank-line-after-summary (D205)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D205"]},{"location":"rules/missing-blank-line-after-summary/#what-it-does","title":"What it does","text":"

        Checks for docstring summary lines that are not separated from the docstring description by one blank line.

        ","tags":["D205"]},{"location":"rules/missing-blank-line-after-summary/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that multi-line docstrings consist of \"a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description.\"

        ","tags":["D205"]},{"location":"rules/missing-blank-line-after-summary/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n    Sort the list in ascending order and return a copy of the\n    result using the bubble sort algorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the\n    result using the bubble sort algorithm.\n    \"\"\"\n
        ","tags":["D205"]},{"location":"rules/missing-blank-line-after-summary/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D205"]},{"location":"rules/missing-copyright-notice/","title":"missing-copyright-notice (CPY001)","text":"

        Derived from the flake8-copyright linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["CPY001"]},{"location":"rules/missing-copyright-notice/#what-it-does","title":"What it does","text":"

        Checks for the absence of copyright notices within Python files.

        Note that this check only searches within the first 4096 bytes of the file.

        ","tags":["CPY001"]},{"location":"rules/missing-copyright-notice/#why-is-this-bad","title":"Why is this bad?","text":"

        In some codebases, it's common to have a license header at the top of every file. This rule ensures that the license header is present.

        ","tags":["CPY001"]},{"location":"rules/missing-copyright-notice/#options","title":"Options","text":"
        • lint.flake8-copyright.author
        • lint.flake8-copyright.min-file-size
        • lint.flake8-copyright.notice-rgx
        ","tags":["CPY001"]},{"location":"rules/missing-dashed-underline-after-section/","title":"missing-dashed-underline-after-section (D407)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D407"]},{"location":"rules/missing-dashed-underline-after-section/#what-it-does","title":"What it does","text":"

        Checks for section headers in docstrings that are not followed by underlines.

        ","tags":["D407"]},{"location":"rules/missing-dashed-underline-after-section/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline numpy-style docstrings, and helps prevent incorrect syntax in docstrings using reStructuredText.

        Multiline numpy-style docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section has a section header and a section body, and the header should be followed by a series of underline characters in the following line.

        This rule enforces a consistent style for multiline numpy-style docstrings with sections. If your docstring uses reStructuredText, the rule also helps protect against incorrect reStructuredText syntax, which would cause errors if you tried to use a tool such as Sphinx to generate documentation from the docstring.

        This rule is enabled when using the numpy convention, and disabled when using the google or pep257 conventions.

        ","tags":["D407"]},{"location":"rules/missing-dashed-underline-after-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n\n    float\n        Speed as distance divided by time.\n\n    Raises\n\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D407"]},{"location":"rules/missing-dashed-underline-after-section/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D407"]},{"location":"rules/missing-dashed-underline-after-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D407"]},{"location":"rules/missing-f-string-syntax/","title":"missing-f-string-syntax (RUF027)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF027"]},{"location":"rules/missing-f-string-syntax/#what-it-does","title":"What it does","text":"

        Searches for strings that look like they were meant to be f-strings, but are missing an f prefix.

        ","tags":["RUF027"]},{"location":"rules/missing-f-string-syntax/#why-is-this-bad","title":"Why is this bad?","text":"

        Expressions inside curly braces are only evaluated if the string has an f prefix.

        ","tags":["RUF027"]},{"location":"rules/missing-f-string-syntax/#details","title":"Details","text":"

        There are many possible string literals which are not meant to be f-strings despite containing f-string-like syntax. As such, this lint ignores all strings where one of the following conditions applies:

        1. The string is a standalone expression. For example, the rule ignores all docstrings.
        2. The string is part of a function call with argument names that match at least one variable (for example: format(\"Message: {value}\", value=\"Hello World\"))
        3. The string (or a parent expression of the string) has a direct method call on it (for example: \"{value}\".format(...))
        4. The string has no {...} expression sections, or uses invalid f-string syntax.
        5. The string references variables that are not in scope, or it doesn't capture variables at all.
        6. Any format specifiers in the potential f-string are invalid.
        7. The string is part of a function call that is known to expect a template string rather than an evaluated f-string: for example, a logging call, a gettext call, or a FastAPI path.
        ","tags":["RUF027"]},{"location":"rules/missing-f-string-syntax/#example","title":"Example","text":"
        name = \"Sarah\"\nday_of_week = \"Tuesday\"\nprint(\"Hello {name}! It is {day_of_week} today!\")\n

        Use instead:

        name = \"Sarah\"\nday_of_week = \"Tuesday\"\nprint(f\"Hello {name}! It is {day_of_week} today!\")\n
        ","tags":["RUF027"]},{"location":"rules/missing-f-string-syntax/#fix-safety","title":"Fix safety","text":"

        This fix will always change the behavior of the program and, despite the precautions detailed above, this may be undesired. As such the fix is always marked as unsafe.

        ","tags":["RUF027"]},{"location":"rules/missing-new-line-after-section-name/","title":"missing-new-line-after-section-name (D406)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D406"]},{"location":"rules/missing-new-line-after-section-name/#what-it-does","title":"What it does","text":"

        Checks for section headers in docstrings that are followed by non-newline characters.

        ","tags":["D406"]},{"location":"rules/missing-new-line-after-section-name/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline numpy-style docstrings.

        Multiline numpy-style docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section has a section header and a section body. The section header should be followed by a newline, rather than by some other character (like a colon).

        This rule is enabled when using the numpy convention, and disabled when using the google or pep257 conventions.

        ","tags":["D406"]},{"location":"rules/missing-new-line-after-section-name/#example","title":"Example","text":"
        # The `Parameters`, `Returns` and `Raises` section headers are all followed\n# by a colon in this function's docstring:\ndef calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters:\n    -----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns:\n    --------\n    float\n        Speed as distance divided by time.\n\n    Raises:\n    -------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D406"]},{"location":"rules/missing-new-line-after-section-name/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D406"]},{"location":"rules/missing-new-line-after-section-name/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D406"]},{"location":"rules/missing-newline-at-end-of-file/","title":"missing-newline-at-end-of-file (W292)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["W292"]},{"location":"rules/missing-newline-at-end-of-file/#what-it-does","title":"What it does","text":"

        Checks for files missing a new line at the end of the file.

        ","tags":["W292"]},{"location":"rules/missing-newline-at-end-of-file/#why-is-this-bad","title":"Why is this bad?","text":"

        Trailing blank lines in a file are superfluous.

        However, the last line of the file should end with a newline.

        ","tags":["W292"]},{"location":"rules/missing-newline-at-end-of-file/#example","title":"Example","text":"
        spam(1)\n

        Use instead:

        spam(1)\\n\n
        ","tags":["W292"]},{"location":"rules/missing-required-import/","title":"missing-required-import (I002)","text":"

        Derived from the isort linter.

        Fix is always available.

        ","tags":["I002"]},{"location":"rules/missing-required-import/#what-it-does","title":"What it does","text":"

        Adds any required imports, as specified by the user, to the top of the file.

        ","tags":["I002"]},{"location":"rules/missing-required-import/#why-is-this-bad","title":"Why is this bad?","text":"

        In some projects, certain imports are required to be present in all files. For example, some projects assume that from __future__ import annotations is enabled, and thus require that import to be present in all files. Omitting a \"required\" import (as specified by the user) can cause errors or unexpected behavior.

        ","tags":["I002"]},{"location":"rules/missing-required-import/#example","title":"Example","text":"
        import typing\n

        Use instead:

        from __future__ import annotations\n\nimport typing\n
        ","tags":["I002"]},{"location":"rules/missing-required-import/#options","title":"Options","text":"
        • lint.isort.required-imports
        ","tags":["I002"]},{"location":"rules/missing-return-type-class-method/","title":"missing-return-type-class-method (ANN206)","text":"

        Derived from the flake8-annotations linter.

        Fix is sometimes available.

        ","tags":["ANN206"]},{"location":"rules/missing-return-type-class-method/#what-it-does","title":"What it does","text":"

        Checks that class methods have return type annotations.

        ","tags":["ANN206"]},{"location":"rules/missing-return-type-class-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the return types of functions. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any returned values, and the types expected by callers, match expectation.

        ","tags":["ANN206"]},{"location":"rules/missing-return-type-class-method/#example","title":"Example","text":"
        class Foo:\n    @classmethod\n    def bar(cls):\n        return 1\n

        Use instead:

        class Foo:\n    @classmethod\n    def bar(cls) -> int:\n        return 1\n
        ","tags":["ANN206"]},{"location":"rules/missing-return-type-private-function/","title":"missing-return-type-private-function (ANN202)","text":"

        Derived from the flake8-annotations linter.

        Fix is sometimes available.

        ","tags":["ANN202"]},{"location":"rules/missing-return-type-private-function/#what-it-does","title":"What it does","text":"

        Checks that private functions and methods have return type annotations.

        ","tags":["ANN202"]},{"location":"rules/missing-return-type-private-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the return types of functions. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any returned values, and the types expected by callers, match expectation.

        ","tags":["ANN202"]},{"location":"rules/missing-return-type-private-function/#example","title":"Example","text":"
        def _add(a, b):\n    return a + b\n

        Use instead:

        def _add(a: int, b: int) -> int:\n    return a + b\n
        ","tags":["ANN202"]},{"location":"rules/missing-return-type-private-function/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for some Python versions, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["ANN202"]},{"location":"rules/missing-return-type-private-function/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["ANN202"]},{"location":"rules/missing-return-type-special-method/","title":"missing-return-type-special-method (ANN204)","text":"

        Derived from the flake8-annotations linter.

        Fix is sometimes available.

        ","tags":["ANN204"]},{"location":"rules/missing-return-type-special-method/#what-it-does","title":"What it does","text":"

        Checks that \"special\" methods, like __init__, __new__, and __call__, have return type annotations.

        ","tags":["ANN204"]},{"location":"rules/missing-return-type-special-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the return types of functions. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any returned values, and the types expected by callers, match expectation.

        Note that type checkers often allow you to omit the return type annotation for __init__ methods, as long as at least one argument has a type annotation. To opt in to this behavior, use the mypy-init-return setting in your pyproject.toml or ruff.toml file:

        [tool.ruff.lint.flake8-annotations]\nmypy-init-return = true\n
        ","tags":["ANN204"]},{"location":"rules/missing-return-type-special-method/#example","title":"Example","text":"
        class Foo:\n    def __init__(self, x: int):\n        self.x = x\n

        Use instead:

        class Foo:\n    def __init__(self, x: int) -> None:\n        self.x = x\n
        ","tags":["ANN204"]},{"location":"rules/missing-return-type-static-method/","title":"missing-return-type-static-method (ANN205)","text":"

        Derived from the flake8-annotations linter.

        Fix is sometimes available.

        ","tags":["ANN205"]},{"location":"rules/missing-return-type-static-method/#what-it-does","title":"What it does","text":"

        Checks that static methods have return type annotations.

        ","tags":["ANN205"]},{"location":"rules/missing-return-type-static-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the return types of functions. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any returned values, and the types expected by callers, match expectation.

        ","tags":["ANN205"]},{"location":"rules/missing-return-type-static-method/#example","title":"Example","text":"
        class Foo:\n    @staticmethod\n    def bar():\n        return 1\n

        Use instead:

        class Foo:\n    @staticmethod\n    def bar() -> int:\n        return 1\n
        ","tags":["ANN205"]},{"location":"rules/missing-return-type-undocumented-public-function/","title":"missing-return-type-undocumented-public-function (ANN201)","text":"

        Derived from the flake8-annotations linter.

        Fix is sometimes available.

        ","tags":["ANN201"]},{"location":"rules/missing-return-type-undocumented-public-function/#what-it-does","title":"What it does","text":"

        Checks that public functions and methods have return type annotations.

        ","tags":["ANN201"]},{"location":"rules/missing-return-type-undocumented-public-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the return types of functions. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any returned values, and the types expected by callers, match expectation.

        ","tags":["ANN201"]},{"location":"rules/missing-return-type-undocumented-public-function/#example","title":"Example","text":"
        def add(a, b):\n    return a + b\n

        Use instead:

        def add(a: int, b: int) -> int:\n    return a + b\n
        ","tags":["ANN201"]},{"location":"rules/missing-return-type-undocumented-public-function/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for some Python versions, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["ANN201"]},{"location":"rules/missing-return-type-undocumented-public-function/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["ANN201"]},{"location":"rules/missing-section-name-colon/","title":"missing-section-name-colon (D416)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D416"]},{"location":"rules/missing-section-name-colon/#what-it-does","title":"What it does","text":"

        Checks for docstring section headers that do not end with a colon.

        ","tags":["D416"]},{"location":"rules/missing-section-name-colon/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline Google-style docstrings. If a multiline Google-style docstring consists of multiple sections, each section header should end with a colon.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body.

        This rule is enabled when using the google convention, and disabled when using the pep257 and numpy conventions.

        ","tags":["D416"]},{"location":"rules/missing-section-name-colon/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns\n        Speed as distance divided by time.\n\n    Raises\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D416"]},{"location":"rules/missing-section-name-colon/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D416"]},{"location":"rules/missing-section-name-colon/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • Google Style Guide
        ","tags":["D416"]},{"location":"rules/missing-section-underline-after-name/","title":"missing-section-underline-after-name (D408)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D408"]},{"location":"rules/missing-section-underline-after-name/#what-it-does","title":"What it does","text":"

        Checks for section underlines in docstrings that are not on the line immediately following the section name.

        ","tags":["D408"]},{"location":"rules/missing-section-underline-after-name/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline numpy-style docstrings, and helps prevent incorrect syntax in docstrings using reStructuredText.

        Multiline numpy-style docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section has a header and a body. There should be a series of underline characters in the line immediately below the header.

        This rule enforces a consistent style for multiline numpy-style docstrings with sections. If your docstring uses reStructuredText, the rule also helps protect against incorrect reStructuredText syntax, which would cause errors if you tried to use a tool such as Sphinx to generate documentation from the docstring.

        This rule is enabled when using the numpy convention, and disabled when using the google or pep257 conventions.

        ","tags":["D408"]},{"location":"rules/missing-section-underline-after-name/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D408"]},{"location":"rules/missing-section-underline-after-name/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D408"]},{"location":"rules/missing-section-underline-after-name/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D408"]},{"location":"rules/missing-space-after-todo-colon/","title":"missing-space-after-todo-colon (TD007)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD007"]},{"location":"rules/missing-space-after-todo-colon/#what-it-does","title":"What it does","text":"

        Checks that the colon after a \"TODO\" tag is followed by a space.

        ","tags":["TD007"]},{"location":"rules/missing-space-after-todo-colon/#why-is-this-bad","title":"Why is this bad?","text":"

        \"TODO\" tags are typically followed by a parenthesized author name, a colon, a space, and a description of the issue, in that order.

        Deviating from this pattern can lead to inconsistent and non-idiomatic comments.

        ","tags":["TD007"]},{"location":"rules/missing-space-after-todo-colon/#example","title":"Example","text":"
        # TODO(charlie):fix this\n

        Use instead:

        # TODO(charlie): fix this\n
        ","tags":["TD007"]},{"location":"rules/missing-terminal-punctuation/","title":"missing-terminal-punctuation (D415)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D415"]},{"location":"rules/missing-terminal-punctuation/#what-it-does","title":"What it does","text":"

        Checks for docstrings in which the first line does not end in a punctuation mark, such as a period, question mark, or exclamation point.

        ","tags":["D415"]},{"location":"rules/missing-terminal-punctuation/#why-is-this-bad","title":"Why is this bad?","text":"

        The first line of a docstring should end with a period, question mark, or exclamation point, for grammatical correctness and consistency.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the google convention, and disabled when using the numpy and pep257 conventions.

        ","tags":["D415"]},{"location":"rules/missing-terminal-punctuation/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D415"]},{"location":"rules/missing-terminal-punctuation/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D415"]},{"location":"rules/missing-terminal-punctuation/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D415"]},{"location":"rules/missing-todo-author/","title":"missing-todo-author (TD002)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD002"]},{"location":"rules/missing-todo-author/#what-it-does","title":"What it does","text":"

        Checks that a TODO comment includes an author.

        ","tags":["TD002"]},{"location":"rules/missing-todo-author/#why-is-this-bad","title":"Why is this bad?","text":"

        Including an author on a TODO provides future readers with context around the issue. While the TODO author is not always considered responsible for fixing the issue, they are typically the individual with the most context.

        ","tags":["TD002"]},{"location":"rules/missing-todo-author/#example","title":"Example","text":"
        # TODO: should assign an author here\n

        Use instead

        # TODO(charlie): now an author is assigned\n
        ","tags":["TD002"]},{"location":"rules/missing-todo-colon/","title":"missing-todo-colon (TD004)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD004"]},{"location":"rules/missing-todo-colon/#what-it-does","title":"What it does","text":"

        Checks that a \"TODO\" tag is followed by a colon.

        ","tags":["TD004"]},{"location":"rules/missing-todo-colon/#why-is-this-bad","title":"Why is this bad?","text":"

        \"TODO\" tags are typically followed by a parenthesized author name, a colon, a space, and a description of the issue, in that order.

        Deviating from this pattern can lead to inconsistent and non-idiomatic comments.

        ","tags":["TD004"]},{"location":"rules/missing-todo-colon/#example","title":"Example","text":"
        # TODO(charlie) fix this colon\n

        Used instead:

        # TODO(charlie): colon fixed\n
        ","tags":["TD004"]},{"location":"rules/missing-todo-description/","title":"missing-todo-description (TD005)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD005"]},{"location":"rules/missing-todo-description/#what-it-does","title":"What it does","text":"

        Checks that a \"TODO\" tag contains a description of the issue following the tag itself.

        ","tags":["TD005"]},{"location":"rules/missing-todo-description/#why-is-this-bad","title":"Why is this bad?","text":"

        TODO comments should include a description of the issue to provide context for future readers.

        ","tags":["TD005"]},{"location":"rules/missing-todo-description/#example","title":"Example","text":"
        # TODO(charlie)\n

        Use instead:

        # TODO(charlie): fix some issue\n
        ","tags":["TD005"]},{"location":"rules/missing-todo-link/","title":"missing-todo-link (TD003)","text":"

        Derived from the flake8-todos linter.

        ","tags":["TD003"]},{"location":"rules/missing-todo-link/#what-it-does","title":"What it does","text":"

        Checks that a TODO comment is associated with a link to a relevant issue or ticket.

        ","tags":["TD003"]},{"location":"rules/missing-todo-link/#why-is-this-bad","title":"Why is this bad?","text":"

        Including an issue link near a TODO makes it easier for resolvers to get context around the issue.

        ","tags":["TD003"]},{"location":"rules/missing-todo-link/#example","title":"Example","text":"
        # TODO: this link has no issue\n

        Use one of these instead:

        # TODO(charlie): this comment has an issue link\n# https://github.com/astral-sh/ruff/issues/3870\n\n# TODO(charlie): this comment has a 3-digit issue code\n# 003\n\n# TODO(charlie): https://github.com/astral-sh/ruff/issues/3870\n# this comment has an issue link\n\n# TODO(charlie): #003 this comment has a 3-digit issue code\n# with leading character `#`\n\n# TODO(charlie): this comment has an issue code (matches the regex `[A-Z]+\\-?\\d+`)\n# SIXCHR-003\n
        ","tags":["TD003"]},{"location":"rules/missing-trailing-comma/","title":"missing-trailing-comma (COM812)","text":"

        Derived from the flake8-commas linter.

        Fix is always available.

        ","tags":["COM812"]},{"location":"rules/missing-trailing-comma/#what-it-does","title":"What it does","text":"

        Checks for the absence of trailing commas.

        ","tags":["COM812"]},{"location":"rules/missing-trailing-comma/#why-is-this-bad","title":"Why is this bad?","text":"

        The presence of a trailing comma can reduce diff size when parameters or elements are added or removed from function calls, function definitions, literals, etc.

        ","tags":["COM812"]},{"location":"rules/missing-trailing-comma/#example","title":"Example","text":"
        foo = {\n    \"bar\": 1,\n    \"baz\": 2\n}\n

        Use instead:

        foo = {\n    \"bar\": 1,\n    \"baz\": 2,\n}\n
        ","tags":["COM812"]},{"location":"rules/missing-trailing-comma/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent use of trailing commas, making the rule redundant.

        ","tags":["COM812"]},{"location":"rules/missing-trailing-period/","title":"missing-trailing-period (D400)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D400"]},{"location":"rules/missing-trailing-period/#what-it-does","title":"What it does","text":"

        Checks for docstrings in which the first line does not end in a period.

        ","tags":["D400"]},{"location":"rules/missing-trailing-period/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that the first line of a docstring is written in the form of a command, ending in a period.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the numpy and pep257 conventions, and disabled when using the google convention.

        ","tags":["D400"]},{"location":"rules/missing-trailing-period/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D400"]},{"location":"rules/missing-trailing-period/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D400"]},{"location":"rules/missing-trailing-period/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D400"]},{"location":"rules/missing-type-args/","title":"missing-type-args (ANN002)","text":"

        Derived from the flake8-annotations linter.

        ","tags":["ANN002"]},{"location":"rules/missing-type-args/#what-it-does","title":"What it does","text":"

        Checks that function *args arguments have type annotations.

        ","tags":["ANN002"]},{"location":"rules/missing-type-args/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the types of function arguments. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any provided arguments match expectation.

        ","tags":["ANN002"]},{"location":"rules/missing-type-args/#example","title":"Example","text":"
        def foo(*args): ...\n

        Use instead:

        def foo(*args: int): ...\n
        ","tags":["ANN002"]},{"location":"rules/missing-type-args/#options","title":"Options","text":"
        • lint.flake8-annotations.suppress-dummy-args
        ","tags":["ANN002"]},{"location":"rules/missing-type-cls/","title":"missing-type-cls (ANN102)","text":"

        Derived from the flake8-annotations linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["ANN102"]},{"location":"rules/missing-type-cls/#removed","title":"Removed","text":"

        This rule has been removed because type checkers can infer this type without annotation.

        ","tags":["ANN102"]},{"location":"rules/missing-type-cls/#what-it-does","title":"What it does","text":"

        Checks that class method cls arguments have type annotations.

        ","tags":["ANN102"]},{"location":"rules/missing-type-cls/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the types of function arguments. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any provided arguments match expectation.

        Note that many type checkers will infer the type of cls automatically, so this annotation is not strictly necessary.

        ","tags":["ANN102"]},{"location":"rules/missing-type-cls/#example","title":"Example","text":"
        class Foo:\n    @classmethod\n    def bar(cls): ...\n

        Use instead:

        class Foo:\n    @classmethod\n    def bar(cls: Type[\"Foo\"]): ...\n
        ","tags":["ANN102"]},{"location":"rules/missing-type-function-argument/","title":"missing-type-function-argument (ANN001)","text":"

        Derived from the flake8-annotations linter.

        ","tags":["ANN001"]},{"location":"rules/missing-type-function-argument/#what-it-does","title":"What it does","text":"

        Checks that function arguments have type annotations.

        ","tags":["ANN001"]},{"location":"rules/missing-type-function-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the types of function arguments. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any provided arguments match expectation.

        ","tags":["ANN001"]},{"location":"rules/missing-type-function-argument/#example","title":"Example","text":"
        def foo(x): ...\n

        Use instead:

        def foo(x: int): ...\n
        ","tags":["ANN001"]},{"location":"rules/missing-type-function-argument/#options","title":"Options","text":"
        • lint.flake8-annotations.suppress-dummy-args
        ","tags":["ANN001"]},{"location":"rules/missing-type-kwargs/","title":"missing-type-kwargs (ANN003)","text":"

        Derived from the flake8-annotations linter.

        ","tags":["ANN003"]},{"location":"rules/missing-type-kwargs/#what-it-does","title":"What it does","text":"

        Checks that function **kwargs arguments have type annotations.

        ","tags":["ANN003"]},{"location":"rules/missing-type-kwargs/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the types of function arguments. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any provided arguments match expectation.

        ","tags":["ANN003"]},{"location":"rules/missing-type-kwargs/#example","title":"Example","text":"
        def foo(**kwargs): ...\n

        Use instead:

        def foo(**kwargs: int): ...\n
        ","tags":["ANN003"]},{"location":"rules/missing-type-kwargs/#options","title":"Options","text":"
        • lint.flake8-annotations.suppress-dummy-args
        ","tags":["ANN003"]},{"location":"rules/missing-type-self/","title":"missing-type-self (ANN101)","text":"

        Derived from the flake8-annotations linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["ANN101"]},{"location":"rules/missing-type-self/#removed","title":"Removed","text":"

        This rule has been removed because type checkers can infer this type without annotation.

        ","tags":["ANN101"]},{"location":"rules/missing-type-self/#what-it-does","title":"What it does","text":"

        Checks that instance method self arguments have type annotations.

        ","tags":["ANN101"]},{"location":"rules/missing-type-self/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotations are a good way to document the types of function arguments. They also help catch bugs, when used alongside a type checker, by ensuring that the types of any provided arguments match expectation.

        Note that many type checkers will infer the type of self automatically, so this annotation is not strictly necessary.

        ","tags":["ANN101"]},{"location":"rules/missing-type-self/#example","title":"Example","text":"
        class Foo:\n    def bar(self): ...\n

        Use instead:

        class Foo:\n    def bar(self: \"Foo\"): ...\n
        ","tags":["ANN101"]},{"location":"rules/missing-whitespace-after-keyword/","title":"missing-whitespace-after-keyword (E275)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E275"]},{"location":"rules/missing-whitespace-after-keyword/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace after keywords.

        ","tags":["E275"]},{"location":"rules/missing-whitespace-after-keyword/#why-is-this-bad","title":"Why is this bad?","text":"

        Missing whitespace after keywords makes the code harder to read.

        ","tags":["E275"]},{"location":"rules/missing-whitespace-after-keyword/#example","title":"Example","text":"
        if(True):\n    pass\n

        Use instead:

        if (True):\n    pass\n
        ","tags":["E275"]},{"location":"rules/missing-whitespace-after-keyword/#references","title":"References","text":"
        • Python documentation: Keywords
        ","tags":["E275"]},{"location":"rules/missing-whitespace-around-arithmetic-operator/","title":"missing-whitespace-around-arithmetic-operator (E226)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E226"]},{"location":"rules/missing-whitespace-around-arithmetic-operator/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace arithmetic operators.

        ","tags":["E226"]},{"location":"rules/missing-whitespace-around-arithmetic-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, there should be one space before and after an arithmetic operator (+, -, /, and *).

        ","tags":["E226"]},{"location":"rules/missing-whitespace-around-arithmetic-operator/#example","title":"Example","text":"
        number = 40+2\n

        Use instead:

        number = 40 + 2\n
        ","tags":["E226"]},{"location":"rules/missing-whitespace-around-bitwise-or-shift-operator/","title":"missing-whitespace-around-bitwise-or-shift-operator (E227)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E227"]},{"location":"rules/missing-whitespace-around-bitwise-or-shift-operator/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace around bitwise and shift operators.

        ","tags":["E227"]},{"location":"rules/missing-whitespace-around-bitwise-or-shift-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, there should be one space before and after bitwise and shift operators (\\<<, >>, &, |, ^).

        ","tags":["E227"]},{"location":"rules/missing-whitespace-around-bitwise-or-shift-operator/#example","title":"Example","text":"
        x = 128<<1\n

        Use instead:

        x = 128 << 1\n
        ","tags":["E227"]},{"location":"rules/missing-whitespace-around-modulo-operator/","title":"missing-whitespace-around-modulo-operator (E228)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E228"]},{"location":"rules/missing-whitespace-around-modulo-operator/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace around the modulo operator.

        ","tags":["E228"]},{"location":"rules/missing-whitespace-around-modulo-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, the modulo operator (%) should have whitespace on either side of it.

        ","tags":["E228"]},{"location":"rules/missing-whitespace-around-modulo-operator/#example","title":"Example","text":"
        remainder = 10%2\n

        Use instead:

        remainder = 10 % 2\n
        ","tags":["E228"]},{"location":"rules/missing-whitespace-around-operator/","title":"missing-whitespace-around-operator (E225)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E225"]},{"location":"rules/missing-whitespace-around-operator/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace around all operators.

        ","tags":["E225"]},{"location":"rules/missing-whitespace-around-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, there should be one space before and after all operators.

        ","tags":["E225"]},{"location":"rules/missing-whitespace-around-operator/#example","title":"Example","text":"
        if number==42:\n    print('you have found the meaning of life')\n

        Use instead:

        if number == 42:\n    print('you have found the meaning of life')\n
        ","tags":["E225"]},{"location":"rules/missing-whitespace-around-parameter-equals/","title":"missing-whitespace-around-parameter-equals (E252)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E252"]},{"location":"rules/missing-whitespace-around-parameter-equals/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace around the equals sign in an annotated function keyword parameter.

        ","tags":["E252"]},{"location":"rules/missing-whitespace-around-parameter-equals/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, the spaces around the equals sign in a keyword parameter should only be omitted when the parameter is unannotated:

        Don\u2019t use spaces around the = sign when used to indicate a keyword argument, or when used to indicate a default value for an unannotated function parameter.

        ","tags":["E252"]},{"location":"rules/missing-whitespace-around-parameter-equals/#example","title":"Example","text":"
        def add(a: int=0) -> int:\n    return a + 1\n

        Use instead:

        def add(a: int = 0) -> int:\n    return a + 1\n
        ","tags":["E252"]},{"location":"rules/missing-whitespace/","title":"missing-whitespace (E231)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E231"]},{"location":"rules/missing-whitespace/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace after ,, ;, and :.

        ","tags":["E231"]},{"location":"rules/missing-whitespace/#why-is-this-bad","title":"Why is this bad?","text":"

        Missing whitespace after ,, ;, and : makes the code harder to read.

        ","tags":["E231"]},{"location":"rules/missing-whitespace/#example","title":"Example","text":"
        a = (1,2)\n

        Use instead:

        a = (1, 2)\n
        ","tags":["E231"]},{"location":"rules/mixed-case-variable-in-class-scope/","title":"mixed-case-variable-in-class-scope (N815)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N815"]},{"location":"rules/mixed-case-variable-in-class-scope/#what-it-does","title":"What it does","text":"

        Checks for class variable names that follow the mixedCase convention.

        ","tags":["N815"]},{"location":"rules/mixed-case-variable-in-class-scope/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that variable names should be lower case and separated by underscores (also known as snake_case).

        Function names should be lowercase, with words separated by underscores as necessary to improve readability.

        Variable names follow the same convention as function names.

        mixedCase is allowed only in contexts where that\u2019s already the prevailing style (e.g. threading.py), to retain backwards compatibility.

        ","tags":["N815"]},{"location":"rules/mixed-case-variable-in-class-scope/#example","title":"Example","text":"
        class MyClass:\n    myVariable = \"hello\"\n    another_variable = \"world\"\n

        Use instead:

        class MyClass:\n    my_variable = \"hello\"\n    another_variable = \"world\"\n
        ","tags":["N815"]},{"location":"rules/mixed-case-variable-in-class-scope/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N815"]},{"location":"rules/mixed-case-variable-in-global-scope/","title":"mixed-case-variable-in-global-scope (N816)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#what-it-does","title":"What it does","text":"

        Checks for global variable names that follow the mixedCase convention.

        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that global variable names should be lower case and separated by underscores (also known as snake_case).

        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#global-variable-names","title":"Global Variable Names","text":"

        (Let\u2019s hope that these variables are meant for use inside one module only.) The conventions are about the same as those for functions.

        Modules that are designed for use via from M import * should use the all mechanism to prevent exporting globals, or use the older convention of prefixing such globals with an underscore (which you might want to do to indicate these globals are \u201cmodule non-public\u201d).

        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#function-and-variable-names","title":"Function and Variable Names","text":"

        Function names should be lowercase, with words separated by underscores as necessary to improve readability.

        Variable names follow the same convention as function names.

        mixedCase is allowed only in contexts where that\u2019s already the prevailing style (e.g. threading.py), to retain backwards compatibility.

        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#example","title":"Example","text":"
        myVariable = \"hello\"\nanother_variable = \"world\"\nyet_anotherVariable = \"foo\"\n

        Use instead:

        my_variable = \"hello\"\nanother_variable = \"world\"\nyet_another_variable = \"foo\"\n
        ","tags":["N816"]},{"location":"rules/mixed-case-variable-in-global-scope/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N816"]},{"location":"rules/mixed-spaces-and-tabs/","title":"mixed-spaces-and-tabs (E101)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E101"]},{"location":"rules/mixed-spaces-and-tabs/#what-it-does","title":"What it does","text":"

        Checks for mixed tabs and spaces in indentation.

        ","tags":["E101"]},{"location":"rules/mixed-spaces-and-tabs/#why-is-this-bad","title":"Why is this bad?","text":"

        Never mix tabs and spaces.

        The most popular way of indenting Python is with spaces only. The second-most popular way is with tabs only. Code indented with a mixture of tabs and spaces should be converted to using spaces exclusively.

        ","tags":["E101"]},{"location":"rules/mixed-spaces-and-tabs/#example","title":"Example","text":"
        if a == 0:\\n        a = 1\\n\\tb = 1\n

        Use instead:

        if a == 0:\\n    a = 1\\n    b = 1\n
        ","tags":["E101"]},{"location":"rules/modified-iterating-set/","title":"modified-iterating-set (PLE4703)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#what-it-does","title":"What it does","text":"

        Checks for loops in which a set is modified during iteration.

        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#why-is-this-bad","title":"Why is this bad?","text":"

        If a set is modified during iteration, it will cause a RuntimeError.

        If you need to modify a set within a loop, consider iterating over a copy of the set instead.

        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#known-problems","title":"Known problems","text":"

        This rule favors false negatives over false positives. Specifically, it will only detect variables that can be inferred to be a set type based on local type inference, and will only detect modifications that are made directly on the variable itself (e.g., set.add()), as opposed to modifications within other function calls (e.g., some_function(set)).

        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#example","title":"Example","text":"
        nums = {1, 2, 3}\nfor num in nums:\n    nums.add(num + 5)\n

        Use instead:

        nums = {1, 2, 3}\nfor num in nums.copy():\n    nums.add(num + 5)\n
        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#fix-safety","title":"Fix safety","text":"

        This fix is always unsafe because it changes the program\u2019s behavior. Replacing the original set with a copy during iteration allows code that would previously raise a RuntimeError to run without error.

        ","tags":["PLE4703"]},{"location":"rules/modified-iterating-set/#references","title":"References","text":"
        • Python documentation: set
        ","tags":["PLE4703"]},{"location":"rules/module-import-not-at-top-of-file/","title":"module-import-not-at-top-of-file (E402)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E402"]},{"location":"rules/module-import-not-at-top-of-file/#what-it-does","title":"What it does","text":"

        Checks for imports that are not at the top of the file.

        ","tags":["E402"]},{"location":"rules/module-import-not-at-top-of-file/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants.\"

        This rule makes an exception for both sys.path modifications (allowing for sys.path.insert, sys.path.append, etc.) and os.environ modifications between imports.

        ","tags":["E402"]},{"location":"rules/module-import-not-at-top-of-file/#example","title":"Example","text":"
        \"One string\"\n\"Two string\"\na = 1\nimport os\nfrom sys import x\n

        Use instead:

        import os\nfrom sys import x\n\n\"One string\"\n\"Two string\"\na = 1\n
        ","tags":["E402"]},{"location":"rules/module-import-not-at-top-of-file/#notebook-behavior","title":"Notebook behavior","text":"

        For Jupyter notebooks, this rule checks for imports that are not at the top of a cell.

        ","tags":["E402"]},{"location":"rules/multi-line-implicit-string-concatenation/","title":"multi-line-implicit-string-concatenation (ISC002)","text":"

        Derived from the flake8-implicit-str-concat linter.

        ","tags":["ISC002"]},{"location":"rules/multi-line-implicit-string-concatenation/#what-it-does","title":"What it does","text":"

        Checks for implicitly concatenated strings that span multiple lines.

        ","tags":["ISC002"]},{"location":"rules/multi-line-implicit-string-concatenation/#why-is-this-bad","title":"Why is this bad?","text":"

        For string literals that wrap across multiple lines, PEP 8 recommends the use of implicit string concatenation within parentheses instead of using a backslash for line continuation, as the former is more readable than the latter.

        By default, this rule will only trigger if the string literal is concatenated via a backslash. To disallow implicit string concatenation altogether, set the lint.flake8-implicit-str-concat.allow-multiline option to false.

        ","tags":["ISC002"]},{"location":"rules/multi-line-implicit-string-concatenation/#example","title":"Example","text":"
        z = \"The quick brown fox jumps over the lazy \"\\\n    \"dog.\"\n

        Use instead:

        z = (\n    \"The quick brown fox jumps over the lazy \"\n    \"dog.\"\n)\n
        ","tags":["ISC002"]},{"location":"rules/multi-line-implicit-string-concatenation/#options","title":"Options","text":"
        • lint.flake8-implicit-str-concat.allow-multiline
        ","tags":["ISC002"]},{"location":"rules/multi-line-implicit-string-concatenation/#formatter-compatibility","title":"Formatter compatibility","text":"

        Using this rule with allow-multiline = false can be incompatible with the formatter because the formatter can introduce new multi-line implicitly concatenated strings. We recommend to either:

        • Enable ISC001 to disallow all implicit concatenated strings
        • Setting allow-multiline = true
        ","tags":["ISC002"]},{"location":"rules/multi-line-summary-first-line/","title":"multi-line-summary-first-line (D212)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D212"]},{"location":"rules/multi-line-summary-first-line/#what-it-does","title":"What it does","text":"

        Checks for docstring summary lines that are not positioned on the first physical line of the docstring.

        ","tags":["D212"]},{"location":"rules/multi-line-summary-first-line/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that multi-line docstrings consist of \"a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description.\"

        The summary line should be located on the first physical line of the docstring, immediately after the opening quotes.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the google convention, and disabled when using the numpy and pep257 conventions.

        For an alternative, see D213.

        ","tags":["D212"]},{"location":"rules/multi-line-summary-first-line/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"\n    Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the\n    bubble sort algorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D212"]},{"location":"rules/multi-line-summary-first-line/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D212"]},{"location":"rules/multi-line-summary-first-line/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D212"]},{"location":"rules/multi-line-summary-second-line/","title":"multi-line-summary-second-line (D213)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D213"]},{"location":"rules/multi-line-summary-second-line/#what-it-does","title":"What it does","text":"

        Checks for docstring summary lines that are not positioned on the second physical line of the docstring.

        ","tags":["D213"]},{"location":"rules/multi-line-summary-second-line/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that multi-line docstrings consist of \"a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description.\"

        The summary line should be located on the second physical line of the docstring, immediately after the opening quotes and the blank line.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is disabled when using the google, numpy, and pep257 conventions.

        For an alternative, see D212.

        ","tags":["D213"]},{"location":"rules/multi-line-summary-second-line/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the\n    bubble sort algorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"\n    Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D213"]},{"location":"rules/multi-line-summary-second-line/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D213"]},{"location":"rules/multi-line-summary-second-line/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D213"]},{"location":"rules/multi-value-repeated-key-literal/","title":"multi-value-repeated-key-literal (F601)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-literal/#what-it-does","title":"What it does","text":"

        Checks for dictionary literals that associate multiple values with the same key.

        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        Dictionary keys should be unique. If a key is associated with multiple values, the earlier values will be overwritten. Including multiple values for the same key in a dictionary literal is likely a mistake.

        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-literal/#example","title":"Example","text":"
        foo = {\n    \"bar\": 1,\n    \"baz\": 2,\n    \"baz\": 3,\n}\nfoo[\"baz\"]  # 3\n

        Use instead:

        foo = {\n    \"bar\": 1,\n    \"baz\": 2,\n}\nfoo[\"baz\"]  # 2\n
        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-literal/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because removing a repeated dictionary key may delete comments that are attached to the removed key-value pair. This can also change the program's behavior if the value expressions have side effects.

        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-literal/#references","title":"References","text":"
        • Python documentation: Dictionaries
        ","tags":["F601"]},{"location":"rules/multi-value-repeated-key-variable/","title":"multi-value-repeated-key-variable (F602)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F602"]},{"location":"rules/multi-value-repeated-key-variable/#what-it-does","title":"What it does","text":"

        Checks for dictionary keys that are repeated with different values.

        ","tags":["F602"]},{"location":"rules/multi-value-repeated-key-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        Dictionary keys should be unique. If a key is repeated with a different value, the first values will be overwritten and the key will correspond to the last value. This is likely a mistake.

        ","tags":["F602"]},{"location":"rules/multi-value-repeated-key-variable/#example","title":"Example","text":"
        foo = {\n    bar: 1,\n    baz: 2,\n    baz: 3,\n}\nfoo[baz]  # 3\n

        Use instead:

        foo = {\n    bar: 1,\n    baz: 2,\n}\nfoo[baz]  # 2\n
        ","tags":["F602"]},{"location":"rules/multi-value-repeated-key-variable/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because removing a repeated dictionary key may delete comments that are attached to the removed key-value pair. This can also change the program's behavior if the value expressions have side effects.

        ","tags":["F602"]},{"location":"rules/multi-value-repeated-key-variable/#references","title":"References","text":"
        • Python documentation: Dictionaries
        ","tags":["F602"]},{"location":"rules/multiple-imports-on-one-line/","title":"multiple-imports-on-one-line (E401)","text":"

        Derived from the pycodestyle linter.

        Fix is sometimes available.

        ","tags":["E401"]},{"location":"rules/multiple-imports-on-one-line/#what-it-does","title":"What it does","text":"

        Check for multiple imports on one line.

        ","tags":["E401"]},{"location":"rules/multiple-imports-on-one-line/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"imports should usually be on separate lines.\"

        ","tags":["E401"]},{"location":"rules/multiple-imports-on-one-line/#example","title":"Example","text":"
        import sys, os\n

        Use instead:

        import os\nimport sys\n
        ","tags":["E401"]},{"location":"rules/multiple-leading-hashes-for-block-comment/","title":"multiple-leading-hashes-for-block-comment (E266)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E266"]},{"location":"rules/multiple-leading-hashes-for-block-comment/#what-it-does","title":"What it does","text":"

        Checks for block comments that start with multiple leading # characters.

        ","tags":["E266"]},{"location":"rules/multiple-leading-hashes-for-block-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Per PEP 8, \"Block comments generally consist of one or more paragraphs built out of complete sentences, with each sentence ending in a period.\"

        Each line of a block comment should start with a # followed by a single space.

        Shebangs (lines starting with #!, at the top of a file) are exempt from this rule.

        ","tags":["E266"]},{"location":"rules/multiple-leading-hashes-for-block-comment/#example","title":"Example","text":"
        ### Block comment\n

        Use instead:

        # Block comment\n

        Alternatively, this rule makes an exception for comments that consist solely of # characters, as in:

        ##############\n# Block header\n##############\n
        ","tags":["E266"]},{"location":"rules/multiple-spaces-after-comma/","title":"multiple-spaces-after-comma (E241)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E241"]},{"location":"rules/multiple-spaces-after-comma/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace after a comma.

        ","tags":["E241"]},{"location":"rules/multiple-spaces-after-comma/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. This rule helps ensure you have a consistent formatting style across your project.

        ","tags":["E241"]},{"location":"rules/multiple-spaces-after-comma/#example","title":"Example","text":"
        a = 4,    5\n

        Use instead:

        a = 4, 5\n
        ","tags":["E241"]},{"location":"rules/multiple-spaces-after-keyword/","title":"multiple-spaces-after-keyword (E271)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E271"]},{"location":"rules/multiple-spaces-after-keyword/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace after keywords.

        ","tags":["E271"]},{"location":"rules/multiple-spaces-after-keyword/#why-is-this-bad","title":"Why is this bad?","text":"","tags":["E271"]},{"location":"rules/multiple-spaces-after-keyword/#example","title":"Example","text":"
        True and  False\n

        Use instead:

        True and False\n
        ","tags":["E271"]},{"location":"rules/multiple-spaces-after-operator/","title":"multiple-spaces-after-operator (E222)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E222"]},{"location":"rules/multiple-spaces-after-operator/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace after an operator.

        ","tags":["E222"]},{"location":"rules/multiple-spaces-after-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, operators should be surrounded by at most a single space on either side.

        ","tags":["E222"]},{"location":"rules/multiple-spaces-after-operator/#example","title":"Example","text":"
        a = 4 +  5\n

        Use instead:

        a = 4 + 5\n
        ","tags":["E222"]},{"location":"rules/multiple-spaces-before-keyword/","title":"multiple-spaces-before-keyword (E272)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E272"]},{"location":"rules/multiple-spaces-before-keyword/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace before keywords.

        ","tags":["E272"]},{"location":"rules/multiple-spaces-before-keyword/#why-is-this-bad","title":"Why is this bad?","text":"","tags":["E272"]},{"location":"rules/multiple-spaces-before-keyword/#example","title":"Example","text":"
        True  and False\n

        Use instead:

        True and False\n
        ","tags":["E272"]},{"location":"rules/multiple-spaces-before-operator/","title":"multiple-spaces-before-operator (E221)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E221"]},{"location":"rules/multiple-spaces-before-operator/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace before an operator.

        ","tags":["E221"]},{"location":"rules/multiple-spaces-before-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, operators should be surrounded by at most a single space on either side.

        ","tags":["E221"]},{"location":"rules/multiple-spaces-before-operator/#example","title":"Example","text":"
        a = 4  + 5\n

        Use instead:

        a = 4 + 5\n
        ","tags":["E221"]},{"location":"rules/multiple-starred-expressions/","title":"multiple-starred-expressions (F622)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F622"]},{"location":"rules/multiple-starred-expressions/#what-it-does","title":"What it does","text":"

        Checks for the use of multiple starred expressions in assignment statements.

        ","tags":["F622"]},{"location":"rules/multiple-starred-expressions/#why-is-this-bad","title":"Why is this bad?","text":"

        In assignment statements, starred expressions can be used to unpack iterables. Including more than one starred expression on the left-hand-side of an assignment will cause a SyntaxError, as it is unclear which expression should receive the remaining values.

        ","tags":["F622"]},{"location":"rules/multiple-starred-expressions/#example","title":"Example","text":"
        *foo, *bar, baz = (1, 2, 3)\n
        ","tags":["F622"]},{"location":"rules/multiple-starred-expressions/#references","title":"References","text":"
        • PEP 3132 \u2013 Extended Iterable Unpacking
        ","tags":["F622"]},{"location":"rules/multiple-starts-ends-with/","title":"multiple-starts-ends-with (PIE810)","text":"

        Derived from the flake8-pie linter.

        Fix is always available.

        ","tags":["PIE810"]},{"location":"rules/multiple-starts-ends-with/#what-it-does","title":"What it does","text":"

        Checks for startswith or endswith calls on the same value with different prefixes or suffixes.

        ","tags":["PIE810"]},{"location":"rules/multiple-starts-ends-with/#why-is-this-bad","title":"Why is this bad?","text":"

        The startswith and endswith methods accept tuples of prefixes or suffixes respectively. Passing a tuple of prefixes or suffixes is more efficient and readable than calling the method multiple times.

        ","tags":["PIE810"]},{"location":"rules/multiple-starts-ends-with/#example","title":"Example","text":"
        msg = \"Hello, world!\"\nif msg.startswith(\"Hello\") or msg.startswith(\"Hi\"):\n    print(\"Greetings!\")\n

        Use instead:

        msg = \"Hello, world!\"\nif msg.startswith((\"Hello\", \"Hi\")):\n    print(\"Greetings!\")\n
        ","tags":["PIE810"]},{"location":"rules/multiple-starts-ends-with/#fix-safety","title":"Fix safety","text":"

        This rule's fix is unsafe, as in some cases, it will be unable to determine whether the argument to an existing .startswith or .endswith call is a tuple. For example, given msg.startswith(x) or msg.startswith(y), if x or y is a tuple, and the semantic model is unable to detect it as such, the rule will suggest msg.startswith((x, y)), which will error at runtime.

        ","tags":["PIE810"]},{"location":"rules/multiple-starts-ends-with/#references","title":"References","text":"
        • Python documentation: str.startswith
        • Python documentation: str.endswith
        ","tags":["PIE810"]},{"location":"rules/multiple-statements-on-one-line-colon/","title":"multiple-statements-on-one-line-colon (E701)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E701"]},{"location":"rules/multiple-statements-on-one-line-colon/#what-it-does","title":"What it does","text":"

        Checks for compound statements (multiple statements on the same line).

        ","tags":["E701"]},{"location":"rules/multiple-statements-on-one-line-colon/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"compound statements are generally discouraged\".

        ","tags":["E701"]},{"location":"rules/multiple-statements-on-one-line-colon/#example","title":"Example","text":"
        if foo == \"blah\": do_blah_thing()\n

        Use instead:

        if foo == \"blah\":\n    do_blah_thing()\n
        ","tags":["E701"]},{"location":"rules/multiple-statements-on-one-line-semicolon/","title":"multiple-statements-on-one-line-semicolon (E702)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E702"]},{"location":"rules/multiple-statements-on-one-line-semicolon/#what-it-does","title":"What it does","text":"

        Checks for multiline statements on one line.

        ","tags":["E702"]},{"location":"rules/multiple-statements-on-one-line-semicolon/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, including multi-clause statements on the same line is discouraged.

        ","tags":["E702"]},{"location":"rules/multiple-statements-on-one-line-semicolon/#example","title":"Example","text":"
        do_one(); do_two(); do_three()\n

        Use instead:

        do_one()\ndo_two()\ndo_three()\n
        ","tags":["E702"]},{"location":"rules/multiple-with-statements/","title":"multiple-with-statements (SIM117)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM117"]},{"location":"rules/multiple-with-statements/#what-it-does","title":"What it does","text":"

        Checks for the unnecessary nesting of multiple consecutive context managers.

        ","tags":["SIM117"]},{"location":"rules/multiple-with-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3, a single with block can include multiple context managers.

        Combining multiple context managers into a single with statement will minimize the indentation depth of the code, making it more readable.

        The following context managers are exempt when used as standalone statements:

        • anyio.{CancelScope, fail_after, move_on_after}
        • asyncio.{timeout, timeout_at}
        • trio.{fail_after, fail_at, move_on_after, move_on_at}
        ","tags":["SIM117"]},{"location":"rules/multiple-with-statements/#example","title":"Example","text":"
        with A() as a:\n    with B() as b:\n        pass\n

        Use instead:

        with A() as a, B() as b:\n    pass\n
        ","tags":["SIM117"]},{"location":"rules/multiple-with-statements/#fix-safety","title":"Fix safety","text":"

        This fix is marked as always unsafe unless preview mode is enabled, in which case it is always marked as safe. Note that the fix is unavailable if it would remove comments (in either case).

        ","tags":["SIM117"]},{"location":"rules/multiple-with-statements/#references","title":"References","text":"
        • Python documentation: The with statement
        ","tags":["SIM117"]},{"location":"rules/mutable-argument-default/","title":"mutable-argument-default (B006)","text":"

        Derived from the flake8-bugbear linter.

        Fix is sometimes available.

        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#what-it-does","title":"What it does","text":"

        Checks for uses of mutable objects as function argument defaults.

        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#why-is-this-bad","title":"Why is this bad?","text":"

        Function defaults are evaluated once, when the function is defined.

        The same mutable object is then shared across all calls to the function. If the object is modified, those modifications will persist across calls, which can lead to unexpected behavior.

        Instead, prefer to use immutable data structures, or take None as a default, and initialize a new mutable object inside the function body for each call.

        Arguments with immutable type annotations will be ignored by this rule. Types outside of the standard library can be marked as immutable with the lint.flake8-bugbear.extend-immutable-calls configuration option.

        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#known-problems","title":"Known problems","text":"

        Mutable argument defaults can be used intentionally to cache computation results. Replacing the default with None or an immutable data structure does not work for such usages. Instead, prefer the @functools.lru_cache decorator from the standard library.

        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#example","title":"Example","text":"
        def add_to_list(item, some_list=[]):\n    some_list.append(item)\n    return some_list\n\n\nl1 = add_to_list(0)  # [0]\nl2 = add_to_list(1)  # [0, 1]\n

        Use instead:

        def add_to_list(item, some_list=None):\n    if some_list is None:\n        some_list = []\n    some_list.append(item)\n    return some_list\n\n\nl1 = add_to_list(0)  # [0]\nl2 = add_to_list(1)  # [1]\n
        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#options","title":"Options","text":"
        • lint.flake8-bugbear.extend-immutable-calls
        ","tags":["B006"]},{"location":"rules/mutable-argument-default/#references","title":"References","text":"
        • Python documentation: Default Argument Values
        ","tags":["B006"]},{"location":"rules/mutable-class-default/","title":"mutable-class-default (RUF012)","text":"","tags":["RUF012"]},{"location":"rules/mutable-class-default/#what-it-does","title":"What it does","text":"

        Checks for mutable default values in class attributes.

        ","tags":["RUF012"]},{"location":"rules/mutable-class-default/#why-is-this-bad","title":"Why is this bad?","text":"

        Mutable default values share state across all instances of the class, while not being obvious. This can lead to bugs when the attributes are changed in one instance, as those changes will unexpectedly affect all other instances.

        Generally speaking, you probably want to avoid having mutable default values in the class body at all; instead, these variables should usually be initialized in __init__. However, other possible fixes for the issue can include:

        • Explicitly annotating the variable with typing.ClassVar to indicate that it is intended to be shared across all instances.
        • Using an immutable data type (e.g. a tuple instead of a list) for the default value.
        ","tags":["RUF012"]},{"location":"rules/mutable-class-default/#example","title":"Example","text":"
        class A:\n    variable_1: list[int] = []\n    variable_2: set[int] = set()\n    variable_3: dict[str, int] = {}\n

        Use instead:

        class A:\n    def __init__(self) -> None:\n        self.variable_1: list[int] = []\n        self.variable_2: set[int] = set()\n        self.variable_3: dict[str, int] = {}\n

        Or:

        from typing import ClassVar\n\n\nclass A:\n    variable_1: ClassVar[list[int]] = []\n    variable_2: ClassVar[set[int]] = set()\n    variable_3: ClassVar[dict[str, int]] = {}\n

        Or:

        class A:\n    variable_1: list[int] | None = None\n    variable_2: set[int] | None = None\n    variable_3: dict[str, int] | None = None\n

        Or:

        from collections.abc import Sequence, Mapping, Set as AbstractSet\nfrom types import MappingProxyType\n\n\nclass A:\n    variable_1: Sequence[int] = ()\n    variable_2: AbstractSet[int] = frozenset()\n    variable_3: Mapping[str, int] = MappingProxyType({})\n
        ","tags":["RUF012"]},{"location":"rules/mutable-contextvar-default/","title":"mutable-contextvar-default (B039)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B039"]},{"location":"rules/mutable-contextvar-default/#what-it-does","title":"What it does","text":"

        Checks for uses of mutable objects as ContextVar defaults.

        ","tags":["B039"]},{"location":"rules/mutable-contextvar-default/#why-is-this-bad","title":"Why is this bad?","text":"

        The ContextVar default is evaluated once, when the ContextVar is defined.

        The same mutable object is then shared across all .get() method calls to the ContextVar. If the object is modified, those modifications will persist across calls, which can lead to unexpected behavior.

        Instead, prefer to use immutable data structures. Alternatively, take None as a default, and initialize a new mutable object inside for each call using the .set() method.

        Types outside the standard library can be marked as immutable with the lint.flake8-bugbear.extend-immutable-calls configuration option.

        ","tags":["B039"]},{"location":"rules/mutable-contextvar-default/#example","title":"Example","text":"
        from contextvars import ContextVar\n\n\ncv: ContextVar[list] = ContextVar(\"cv\", default=[])\n

        Use instead:

        from contextvars import ContextVar\n\n\ncv: ContextVar[list | None] = ContextVar(\"cv\", default=None)\n\n...\n\nif cv.get() is None:\n    cv.set([])\n
        ","tags":["B039"]},{"location":"rules/mutable-contextvar-default/#options","title":"Options","text":"
        • lint.flake8-bugbear.extend-immutable-calls
        ","tags":["B039"]},{"location":"rules/mutable-contextvar-default/#references","title":"References","text":"
        • Python documentation: contextvars \u2014 Context Variables
        ","tags":["B039"]},{"location":"rules/mutable-dataclass-default/","title":"mutable-dataclass-default (RUF008)","text":"","tags":["RUF008"]},{"location":"rules/mutable-dataclass-default/#what-it-does","title":"What it does","text":"

        Checks for mutable default values in dataclass attributes.

        ","tags":["RUF008"]},{"location":"rules/mutable-dataclass-default/#why-is-this-bad","title":"Why is this bad?","text":"

        Mutable default values share state across all instances of the dataclass. This can lead to bugs when the attributes are changed in one instance, as those changes will unexpectedly affect all other instances.

        Instead of sharing mutable defaults, use the field(default_factory=...) pattern.

        If the default value is intended to be mutable, it must be annotated with typing.ClassVar; otherwise, a ValueError will be raised.

        ","tags":["RUF008"]},{"location":"rules/mutable-dataclass-default/#example","title":"Example","text":"
        from dataclasses import dataclass\n\n\n@dataclass\nclass A:\n    # A list without a `default_factory` or `ClassVar` annotation\n    # will raise a `ValueError`.\n    mutable_default: list[int] = []\n

        Use instead:

        from dataclasses import dataclass, field\n\n\n@dataclass\nclass A:\n    mutable_default: list[int] = field(default_factory=list)\n

        Or:

        from dataclasses import dataclass\nfrom typing import ClassVar\n\n\n@dataclass\nclass A:\n    mutable_default: ClassVar[list[int]] = []\n
        ","tags":["RUF008"]},{"location":"rules/mutable-fromkeys-value/","title":"mutable-fromkeys-value (RUF024)","text":"

        Fix is sometimes available.

        ","tags":["RUF024"]},{"location":"rules/mutable-fromkeys-value/#what-it-does","title":"What it does","text":"

        Checks for mutable objects passed as a value argument to dict.fromkeys.

        ","tags":["RUF024"]},{"location":"rules/mutable-fromkeys-value/#why-is-this-bad","title":"Why is this bad?","text":"

        All values in the dictionary created by the dict.fromkeys method refer to the same instance of the provided object. If that object is modified, all values are modified, which can lead to unexpected behavior. For example, if the empty list ([]) is provided as the default value, all values in the dictionary will use the same list; as such, appending to any one entry will append to all entries.

        Instead, use a comprehension to generate a dictionary with distinct instances of the default value.

        ","tags":["RUF024"]},{"location":"rules/mutable-fromkeys-value/#example","title":"Example","text":"
        cities = dict.fromkeys([\"UK\", \"Poland\"], [])\ncities[\"UK\"].append(\"London\")\ncities[\"Poland\"].append(\"Poznan\")\nprint(cities)  # {'UK': ['London', 'Poznan'], 'Poland': ['London', 'Poznan']}\n

        Use instead:

        cities = {country: [] for country in [\"UK\", \"Poland\"]}\ncities[\"UK\"].append(\"London\")\ncities[\"Poland\"].append(\"Poznan\")\nprint(cities)  # {'UK': ['London'], 'Poland': ['Poznan']}\n
        ","tags":["RUF024"]},{"location":"rules/mutable-fromkeys-value/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as the edit will change the behavior of the program by using a distinct object for every value in the dictionary, rather than a shared mutable instance. In some cases, programs may rely on the previous behavior.

        ","tags":["RUF024"]},{"location":"rules/mutable-fromkeys-value/#references","title":"References","text":"
        • Python documentation: dict.fromkeys
        ","tags":["RUF024"]},{"location":"rules/named-expr-without-context/","title":"named-expr-without-context (PLW0131)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0131"]},{"location":"rules/named-expr-without-context/#what-it-does","title":"What it does","text":"

        Checks for uses of named expressions (e.g., a := 42) that can be replaced by regular assignment statements (e.g., a = 42).

        ","tags":["PLW0131"]},{"location":"rules/named-expr-without-context/#why-is-this-bad","title":"Why is this bad?","text":"

        While a top-level named expression is syntactically and semantically valid, it's less clear than a regular assignment statement. Named expressions are intended to be used in comprehensions and generator expressions, where assignment statements are not allowed.

        ","tags":["PLW0131"]},{"location":"rules/named-expr-without-context/#example","title":"Example","text":"
        (a := 42)\n

        Use instead:

        a = 42\n
        ","tags":["PLW0131"]},{"location":"rules/nan-comparison/","title":"nan-comparison (PLW0177)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW0177"]},{"location":"rules/nan-comparison/#what-it-does","title":"What it does","text":"

        Checks for comparisons against NaN values.

        ","tags":["PLW0177"]},{"location":"rules/nan-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing against a NaN value can lead to unexpected results. For example, float(\"NaN\") == float(\"NaN\") will return False and, in general, x == float(\"NaN\") will always return False, even if x is NaN.

        To determine whether a value is NaN, use math.isnan or np.isnan instead of comparing against NaN directly.

        ","tags":["PLW0177"]},{"location":"rules/nan-comparison/#example","title":"Example","text":"
        if x == float(\"NaN\"):\n    pass\n

        Use instead:

        import math\n\nif math.isnan(x):\n    pass\n
        ","tags":["PLW0177"]},{"location":"rules/native-literals/","title":"native-literals (UP018)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP018"]},{"location":"rules/native-literals/#what-it-does","title":"What it does","text":"

        Checks for unnecessary calls to str, bytes, int, float, and bool.

        ","tags":["UP018"]},{"location":"rules/native-literals/#why-is-this-bad","title":"Why is this bad?","text":"

        The mentioned constructors can be replaced with their respective literal forms, which are more readable and idiomatic.

        ","tags":["UP018"]},{"location":"rules/native-literals/#example","title":"Example","text":"
        str(\"foo\")\n

        Use instead:

        \"foo\"\n
        ","tags":["UP018"]},{"location":"rules/native-literals/#fix-safety","title":"Fix safety","text":"

        The fix is marked as unsafe if it might remove comments.

        ","tags":["UP018"]},{"location":"rules/native-literals/#references","title":"References","text":"
        • Python documentation: str
        • Python documentation: bytes
        • Python documentation: int
        • Python documentation: float
        • Python documentation: bool
        ","tags":["UP018"]},{"location":"rules/needless-bool/","title":"needless-bool (SIM103)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM103"]},{"location":"rules/needless-bool/#what-it-does","title":"What it does","text":"

        Checks for if statements that can be replaced with bool.

        ","tags":["SIM103"]},{"location":"rules/needless-bool/#why-is-this-bad","title":"Why is this bad?","text":"

        if statements that return True for a truthy condition and False for a falsy condition can be replaced with boolean casts.

        ","tags":["SIM103"]},{"location":"rules/needless-bool/#example","title":"Example","text":"

        Given:

        def foo(x: int) -> bool:\n    if x > 0:\n        return True\n    else:\n        return False\n

        Use instead:

        def foo(x: int) -> bool:\n    return x > 0\n

        Or, given:

        def foo(x: int) -> bool:\n    if x > 0:\n        return True\n    return False\n

        Use instead:

        def foo(x: int) -> bool:\n    return x > 0\n
        ","tags":["SIM103"]},{"location":"rules/needless-bool/#fix-safety","title":"Fix safety","text":"

        This fix is marked as unsafe because it may change the program\u2019s behavior if the condition does not return a proper Boolean. While the fix will try to wrap non-boolean values in a call to bool, custom implementations of comparison functions like __eq__ can avoid the bool call and still lead to altered behavior.

        ","tags":["SIM103"]},{"location":"rules/needless-bool/#references","title":"References","text":"
        • Python documentation: Truth Value Testing
        ","tags":["SIM103"]},{"location":"rules/needless-else/","title":"needless-else (RUF047)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF047"]},{"location":"rules/needless-else/#what-it-does","title":"What it does","text":"

        Checks for else clauses that only contains pass and ... statements.

        ","tags":["RUF047"]},{"location":"rules/needless-else/#why-is-this-bad","title":"Why is this bad?","text":"

        Such an else clause does nothing and can be removed.

        ","tags":["RUF047"]},{"location":"rules/needless-else/#example","title":"Example","text":"
        if foo:\n    bar()\nelse:\n    pass\n

        Use instead:

        if foo:\n    bar()\n
        ","tags":["RUF047"]},{"location":"rules/negate-equal-op/","title":"negate-equal-op (SIM201)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM201"]},{"location":"rules/negate-equal-op/#what-it-does","title":"What it does","text":"

        Checks for negated == operators.

        ","tags":["SIM201"]},{"location":"rules/negate-equal-op/#why-is-this-bad","title":"Why is this bad?","text":"

        Negated == operators are less readable than != operators. When testing for non-equality, it is more common to use != than ==.

        ","tags":["SIM201"]},{"location":"rules/negate-equal-op/#example","title":"Example","text":"
        not a == b\n

        Use instead:

        a != b\n
        ","tags":["SIM201"]},{"location":"rules/negate-equal-op/#fix-safety","title":"Fix safety","text":"

        The fix is marked as unsafe, as it might change the behaviour if a and/or b overrides __eq__/__ne__ in such a manner that they don't return booleans.

        ","tags":["SIM201"]},{"location":"rules/negate-equal-op/#references","title":"References","text":"
        • Python documentation: Comparisons
        ","tags":["SIM201"]},{"location":"rules/negate-not-equal-op/","title":"negate-not-equal-op (SIM202)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM202"]},{"location":"rules/negate-not-equal-op/#what-it-does","title":"What it does","text":"

        Checks for negated != operators.

        ","tags":["SIM202"]},{"location":"rules/negate-not-equal-op/#why-is-this-bad","title":"Why is this bad?","text":"

        Negated != operators are less readable than == operators, as they avoid a double negation.

        ","tags":["SIM202"]},{"location":"rules/negate-not-equal-op/#example","title":"Example","text":"
        not a != b\n

        Use instead:

        a == b\n
        ","tags":["SIM202"]},{"location":"rules/negate-not-equal-op/#fix-safety","title":"Fix safety","text":"

        The fix is marked as unsafe, as it might change the behaviour if a and/or b overrides __ne__/__eq__ in such a manner that they don't return booleans.

        ","tags":["SIM202"]},{"location":"rules/negate-not-equal-op/#references","title":"References","text":"
        • Python documentation: Comparisons
        ","tags":["SIM202"]},{"location":"rules/nested-min-max/","title":"nested-min-max (PLW3301)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLW3301"]},{"location":"rules/nested-min-max/#what-it-does","title":"What it does","text":"

        Checks for nested min and max calls.

        ","tags":["PLW3301"]},{"location":"rules/nested-min-max/#why-is-this-bad","title":"Why is this bad?","text":"

        Nested min and max calls can be flattened into a single call to improve readability.

        ","tags":["PLW3301"]},{"location":"rules/nested-min-max/#example","title":"Example","text":"
        minimum = min(1, 2, min(3, 4, 5))\nmaximum = max(1, 2, max(3, 4, 5))\ndiff = maximum - minimum\n

        Use instead:

        minimum = min(1, 2, 3, 4, 5)\nmaximum = max(1, 2, 3, 4, 5)\ndiff = maximum - minimum\n
        ","tags":["PLW3301"]},{"location":"rules/nested-min-max/#fix-safety","title":"Fix safety","text":"

        This fix is always unsafe and may change the program's behavior for types without full equivalence relations, such as float comparisons involving NaN.

        print(min(2.0, min(float(\"nan\"), 1.0)))  # before fix: 2.0\nprint(min(2.0, float(\"nan\"), 1.0))  # after fix: 1.0\n\nprint(max(1.0, max(float(\"nan\"), 2.0)))  # before fix: 1.0\nprint(max(1.0, float(\"nan\"), 2.0))  # after fix: 2.0\n
        ","tags":["PLW3301"]},{"location":"rules/nested-min-max/#references","title":"References","text":"
        • Python documentation: min
        • Python documentation: max
        ","tags":["PLW3301"]},{"location":"rules/never-union/","title":"never-union (RUF020)","text":"

        Fix is sometimes available.

        ","tags":["RUF020"]},{"location":"rules/never-union/#what-it-does","title":"What it does","text":"

        Checks for uses of typing.NoReturn and typing.Never in union types.

        ","tags":["RUF020"]},{"location":"rules/never-union/#why-is-this-bad","title":"Why is this bad?","text":"

        typing.NoReturn and typing.Never are special types, used to indicate that a function never returns, or that a type has no values.

        Including typing.NoReturn or typing.Never in a union type is redundant, as, e.g., typing.Never | T is equivalent to T.

        ","tags":["RUF020"]},{"location":"rules/never-union/#example","title":"Example","text":"
        from typing import Never\n\n\ndef func() -> Never | int: ...\n

        Use instead:

        def func() -> int: ...\n
        ","tags":["RUF020"]},{"location":"rules/never-union/#references","title":"References","text":"
        • Python documentation: typing.Never
        • Python documentation: typing.NoReturn
        ","tags":["RUF020"]},{"location":"rules/new-line-after-last-paragraph/","title":"new-line-after-last-paragraph (D209)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D209"]},{"location":"rules/new-line-after-last-paragraph/#what-it-does","title":"What it does","text":"

        Checks for multi-line docstrings whose closing quotes are not on their own line.

        ","tags":["D209"]},{"location":"rules/new-line-after-last-paragraph/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that the closing quotes of a multi-line docstring be on their own line, for consistency and compatibility with documentation tools that may need to parse the docstring.

        ","tags":["D209"]},{"location":"rules/new-line-after-last-paragraph/#example","title":"Example","text":"
        def sort_list(l: List[int]) -> List[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the\n    bubble sort algorithm.\"\"\"\n

        Use instead:

        def sort_list(l: List[int]) -> List[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D209"]},{"location":"rules/new-line-after-last-paragraph/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D209"]},{"location":"rules/no-blank-line-after-section/","title":"no-blank-line-after-section (D410)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D410"]},{"location":"rules/no-blank-line-after-section/#what-it-does","title":"What it does","text":"

        Checks for docstring sections that are not separated by a single blank line.

        ","tags":["D410"]},{"location":"rules/no-blank-line-after-section/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces consistency in your docstrings, and helps ensure compatibility with documentation tooling.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. If a multiline numpy-style or Google-style docstring consists of multiple sections, each section should be separated by a single blank line.

        This rule is enabled when using the numpy and google conventions, and disabled when using the pep257 convention.

        ","tags":["D410"]},{"location":"rules/no-blank-line-after-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D410"]},{"location":"rules/no-blank-line-after-section/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D410"]},{"location":"rules/no-blank-line-after-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Guide
        ","tags":["D410"]},{"location":"rules/no-blank-line-before-section/","title":"no-blank-line-before-section (D411)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D411"]},{"location":"rules/no-blank-line-before-section/#what-it-does","title":"What it does","text":"

        Checks for docstring sections that are not separated by a blank line.

        ","tags":["D411"]},{"location":"rules/no-blank-line-before-section/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces consistency in numpy-style and Google-style docstrings, and helps ensure compatibility with documentation tooling.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. Sections should be separated by a single blank line.

        This rule is enabled when using the numpy and google conventions, and disabled when using the pep257 convention.

        ","tags":["D411"]},{"location":"rules/no-blank-line-before-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D411"]},{"location":"rules/no-blank-line-before-section/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D411"]},{"location":"rules/no-blank-line-before-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D411"]},{"location":"rules/no-classmethod-decorator/","title":"no-classmethod-decorator (PLR0202)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0202"]},{"location":"rules/no-classmethod-decorator/#what-it-does","title":"What it does","text":"

        Checks for the use of a classmethod being made without the decorator.

        ","tags":["PLR0202"]},{"location":"rules/no-classmethod-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        When it comes to consistency and readability, it's preferred to use the decorator.

        ","tags":["PLR0202"]},{"location":"rules/no-classmethod-decorator/#example","title":"Example","text":"
        class Foo:\n    def bar(cls): ...\n\n    bar = classmethod(bar)\n

        Use instead:

        class Foo:\n    @classmethod\n    def bar(cls): ...\n
        ","tags":["PLR0202"]},{"location":"rules/no-explicit-stacklevel/","title":"no-explicit-stacklevel (B028)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B028"]},{"location":"rules/no-explicit-stacklevel/#what-it-does","title":"What it does","text":"

        Checks for warnings.warn calls without an explicit stacklevel keyword argument.

        ","tags":["B028"]},{"location":"rules/no-explicit-stacklevel/#why-is-this-bad","title":"Why is this bad?","text":"

        The warnings.warn method uses a stacklevel of 1 by default, which will output a stack frame of the line on which the \"warn\" method is called. Setting it to a higher number will output a stack frame from higher up the stack.

        It's recommended to use a stacklevel of 2 or higher, to give the caller more context about the warning.

        ","tags":["B028"]},{"location":"rules/no-explicit-stacklevel/#example","title":"Example","text":"
        warnings.warn(\"This is a warning\")\n

        Use instead:

        warnings.warn(\"This is a warning\", stacklevel=2)\n
        ","tags":["B028"]},{"location":"rules/no-explicit-stacklevel/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because it changes the behavior of the code. Moreover, the fix will assign a stacklevel of 2, while the user may wish to assign a higher stacklevel to address the diagnostic.

        ","tags":["B028"]},{"location":"rules/no-explicit-stacklevel/#references","title":"References","text":"
        • Python documentation: warnings.warn
        ","tags":["B028"]},{"location":"rules/no-indented-block-comment/","title":"no-indented-block-comment (E115)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E115"]},{"location":"rules/no-indented-block-comment/#what-it-does","title":"What it does","text":"

        Checks for comments in a code blocks that are lacking indentation.

        ","tags":["E115"]},{"location":"rules/no-indented-block-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Comments within an indented block should themselves be indented, to indicate that they are part of the block.

        ","tags":["E115"]},{"location":"rules/no-indented-block-comment/#example","title":"Example","text":"
        for item in items:\n# Hi\n    pass\n

        Use instead:

        for item in items:\n    # Hi\n    pass\n
        ","tags":["E115"]},{"location":"rules/no-indented-block/","title":"no-indented-block (E112)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E112"]},{"location":"rules/no-indented-block/#what-it-does","title":"What it does","text":"

        Checks for indented blocks that are lacking indentation.

        ","tags":["E112"]},{"location":"rules/no-indented-block/#why-is-this-bad","title":"Why is this bad?","text":"

        All indented blocks should be indented; otherwise, they are not valid Python syntax.

        ","tags":["E112"]},{"location":"rules/no-indented-block/#example","title":"Example","text":"
        for item in items:\npass\n

        Use instead:

        for item in items:\n    pass\n
        ","tags":["E112"]},{"location":"rules/no-return-argument-annotation-in-stub/","title":"no-return-argument-annotation-in-stub (PYI050)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI050"]},{"location":"rules/no-return-argument-annotation-in-stub/#what-it-does","title":"What it does","text":"

        Checks for uses of typing.NoReturn (and typing_extensions.NoReturn) for parameter annotations.

        ","tags":["PYI050"]},{"location":"rules/no-return-argument-annotation-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefer Never over NoReturn for parameter annotations. Never has a clearer name in these contexts, since it makes little sense to talk about a parameter annotation \"not returning\".

        This is a purely stylistic lint: the two types have identical semantics for type checkers. Both represent Python's \"bottom type\" (a type that has no members).

        ","tags":["PYI050"]},{"location":"rules/no-return-argument-annotation-in-stub/#example","title":"Example","text":"
        from typing import NoReturn\n\ndef foo(x: NoReturn): ...\n

        Use instead:

        from typing import Never\n\ndef foo(x: Never): ...\n
        ","tags":["PYI050"]},{"location":"rules/no-return-argument-annotation-in-stub/#references","title":"References","text":"
        • Python documentation: typing.Never
        • Python documentation: typing.NoReturn
        ","tags":["PYI050"]},{"location":"rules/no-self-use/","title":"no-self-use (PLR6301)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR6301"]},{"location":"rules/no-self-use/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused self parameter in methods definitions.

        ","tags":["PLR6301"]},{"location":"rules/no-self-use/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused self parameters are usually a sign of a method that could be replaced by a function, class method, or static method.

        ","tags":["PLR6301"]},{"location":"rules/no-self-use/#example","title":"Example","text":"
        class Person:\n    def greeting(self):\n        print(\"Greetings friend!\")\n

        Use instead:

        def greeting():\n    print(\"Greetings friend!\")\n

        or

        class Person:\n    @staticmethod\n    def greeting():\n        print(\"Greetings friend!\")\n
        ","tags":["PLR6301"]},{"location":"rules/no-slots-in-namedtuple-subclass/","title":"no-slots-in-namedtuple-subclass (SLOT002)","text":"

        Derived from the flake8-slots linter.

        ","tags":["SLOT002"]},{"location":"rules/no-slots-in-namedtuple-subclass/#what-it-does","title":"What it does","text":"

        Checks for subclasses of collections.namedtuple or typing.NamedTuple that lack a __slots__ definition.

        ","tags":["SLOT002"]},{"location":"rules/no-slots-in-namedtuple-subclass/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the __slots__ attribute allows you to explicitly define the attributes (instance variables) that a class can have. By default, Python uses a dictionary to store an object's attributes, which incurs some memory overhead. However, when __slots__ is defined, Python uses a more compact internal structure to store the object's attributes, resulting in memory savings.

        Subclasses of namedtuple inherit all the attributes and methods of the built-in namedtuple class. Since tuples are typically immutable, they don't require additional attributes beyond what the namedtuple class provides. Defining __slots__ for subclasses of namedtuple prevents the creation of a dictionary for each instance, reducing memory consumption.

        ","tags":["SLOT002"]},{"location":"rules/no-slots-in-namedtuple-subclass/#example","title":"Example","text":"
        from collections import namedtuple\n\n\nclass Foo(namedtuple(\"foo\", [\"str\", \"int\"])):\n    pass\n

        Use instead:

        from collections import namedtuple\n\n\nclass Foo(namedtuple(\"foo\", [\"str\", \"int\"])):\n    __slots__ = ()\n
        ","tags":["SLOT002"]},{"location":"rules/no-slots-in-namedtuple-subclass/#references","title":"References","text":"
        • Python documentation: __slots__
        ","tags":["SLOT002"]},{"location":"rules/no-slots-in-str-subclass/","title":"no-slots-in-str-subclass (SLOT000)","text":"

        Derived from the flake8-slots linter.

        ","tags":["SLOT000"]},{"location":"rules/no-slots-in-str-subclass/#what-it-does","title":"What it does","text":"

        Checks for subclasses of str that lack a __slots__ definition.

        ","tags":["SLOT000"]},{"location":"rules/no-slots-in-str-subclass/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the __slots__ attribute allows you to explicitly define the attributes (instance variables) that a class can have. By default, Python uses a dictionary to store an object's attributes, which incurs some memory overhead. However, when __slots__ is defined, Python uses a more compact internal structure to store the object's attributes, resulting in memory savings.

        Subclasses of str inherit all the attributes and methods of the built-in str class. Since strings are typically immutable, they don't require additional attributes beyond what the str class provides. Defining __slots__ for subclasses of str prevents the creation of a dictionary for each instance, reducing memory consumption.

        ","tags":["SLOT000"]},{"location":"rules/no-slots-in-str-subclass/#example","title":"Example","text":"
        class Foo(str):\n    pass\n

        Use instead:

        class Foo(str):\n    __slots__ = ()\n
        ","tags":["SLOT000"]},{"location":"rules/no-slots-in-str-subclass/#references","title":"References","text":"
        • Python documentation: __slots__
        ","tags":["SLOT000"]},{"location":"rules/no-slots-in-tuple-subclass/","title":"no-slots-in-tuple-subclass (SLOT001)","text":"

        Derived from the flake8-slots linter.

        ","tags":["SLOT001"]},{"location":"rules/no-slots-in-tuple-subclass/#what-it-does","title":"What it does","text":"

        Checks for subclasses of tuple that lack a __slots__ definition.

        ","tags":["SLOT001"]},{"location":"rules/no-slots-in-tuple-subclass/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the __slots__ attribute allows you to explicitly define the attributes (instance variables) that a class can have. By default, Python uses a dictionary to store an object's attributes, which incurs some memory overhead. However, when __slots__ is defined, Python uses a more compact internal structure to store the object's attributes, resulting in memory savings.

        Subclasses of tuple inherit all the attributes and methods of the built-in tuple class. Since tuples are typically immutable, they don't require additional attributes beyond what the tuple class provides. Defining __slots__ for subclasses of tuple prevents the creation of a dictionary for each instance, reducing memory consumption.

        ","tags":["SLOT001"]},{"location":"rules/no-slots-in-tuple-subclass/#example","title":"Example","text":"
        class Foo(tuple):\n    pass\n

        Use instead:

        class Foo(tuple):\n    __slots__ = ()\n
        ","tags":["SLOT001"]},{"location":"rules/no-slots-in-tuple-subclass/#references","title":"References","text":"
        • Python documentation: __slots__
        ","tags":["SLOT001"]},{"location":"rules/no-space-after-block-comment/","title":"no-space-after-block-comment (E265)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E265"]},{"location":"rules/no-space-after-block-comment/#what-it-does","title":"What it does","text":"

        Checks for block comments that lack a single space after the leading # character.

        ","tags":["E265"]},{"location":"rules/no-space-after-block-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Per PEP 8, \"Block comments generally consist of one or more paragraphs built out of complete sentences, with each sentence ending in a period.\"

        Block comments should start with a # followed by a single space.

        Shebangs (lines starting with #!, at the top of a file) are exempt from this rule.

        ","tags":["E265"]},{"location":"rules/no-space-after-block-comment/#example","title":"Example","text":"
        #Block comment\n

        Use instead:

        # Block comment\n
        ","tags":["E265"]},{"location":"rules/no-space-after-inline-comment/","title":"no-space-after-inline-comment (E262)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E262"]},{"location":"rules/no-space-after-inline-comment/#what-it-does","title":"What it does","text":"

        Checks if one space is used after inline comments.

        ","tags":["E262"]},{"location":"rules/no-space-after-inline-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        An inline comment is a comment on the same line as a statement.

        Per PEP 8, inline comments should start with a # and a single space.

        ","tags":["E262"]},{"location":"rules/no-space-after-inline-comment/#example","title":"Example","text":"
        x = x + 1  #Increment x\nx = x + 1  #  Increment x\nx = x + 1  # \\xa0Increment x\n

        Use instead:

        x = x + 1  # Increment x\nx = x + 1    # Increment x\n
        ","tags":["E262"]},{"location":"rules/no-staticmethod-decorator/","title":"no-staticmethod-decorator (PLR0203)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0203"]},{"location":"rules/no-staticmethod-decorator/#what-it-does","title":"What it does","text":"

        Checks for the use of a staticmethod being made without the decorator.

        ","tags":["PLR0203"]},{"location":"rules/no-staticmethod-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        When it comes to consistency and readability, it's preferred to use the decorator.

        ","tags":["PLR0203"]},{"location":"rules/no-staticmethod-decorator/#example","title":"Example","text":"
        class Foo:\n    def bar(arg1, arg2): ...\n\n    bar = staticmethod(bar)\n

        Use instead:

        class Foo:\n    @staticmethod\n    def bar(arg1, arg2): ...\n
        ","tags":["PLR0203"]},{"location":"rules/non-ascii-import-name/","title":"non-ascii-import-name (PLC2403)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC2403"]},{"location":"rules/non-ascii-import-name/#what-it-does","title":"What it does","text":"

        Checks for the use of non-ASCII characters in import statements.

        ","tags":["PLC2403"]},{"location":"rules/non-ascii-import-name/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of non-ASCII characters in import statements can cause confusion and compatibility issues (see: PEP 672).

        ","tags":["PLC2403"]},{"location":"rules/non-ascii-import-name/#example","title":"Example","text":"
        import b\u00e1r\n

        Use instead:

        import bar\n

        If the module is third-party, use an ASCII-only alias:

        import b\u00e1r as bar\n
        ","tags":["PLC2403"]},{"location":"rules/non-ascii-name/","title":"non-ascii-name (PLC2401)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC2401"]},{"location":"rules/non-ascii-name/#what-it-does","title":"What it does","text":"

        Checks for the use of non-ASCII characters in variable names.

        ","tags":["PLC2401"]},{"location":"rules/non-ascii-name/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of non-ASCII characters in variable names can cause confusion and compatibility issues (see: PEP 672).

        ","tags":["PLC2401"]},{"location":"rules/non-ascii-name/#example","title":"Example","text":"
        \u00e1pple_count: int\n

        Use instead:

        apple_count: int\n
        ","tags":["PLC2401"]},{"location":"rules/non-augmented-assignment/","title":"non-augmented-assignment (PLR6104)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR6104"]},{"location":"rules/non-augmented-assignment/#what-it-does","title":"What it does","text":"

        Checks for assignments that can be replaced with augmented assignment statements.

        ","tags":["PLR6104"]},{"location":"rules/non-augmented-assignment/#why-is-this-bad","title":"Why is this bad?","text":"

        If the right-hand side of an assignment statement consists of a binary operation in which one operand is the same as the assignment target, it can be rewritten as an augmented assignment. For example, x = x + 1 can be rewritten as x += 1.

        When performing such an operation, an augmented assignment is more concise and idiomatic.

        ","tags":["PLR6104"]},{"location":"rules/non-augmented-assignment/#known-problems","title":"Known problems","text":"

        In some cases, this rule will not detect assignments in which the target is on the right-hand side of a binary operation (e.g., x = y + x, as opposed to x = x + y), as such operations are not commutative for certain data types, like strings.

        For example, x = \"prefix-\" + x is not equivalent to x += \"prefix-\", while x = 1 + x is equivalent to x += 1.

        If the type of the left-hand side cannot be trivially inferred, the rule will ignore the assignment.

        ","tags":["PLR6104"]},{"location":"rules/non-augmented-assignment/#example","title":"Example","text":"
        x = x + 1\n

        Use instead:

        x += 1\n
        ","tags":["PLR6104"]},{"location":"rules/non-augmented-assignment/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as augmented assignments have different semantics when the target is a mutable data type, like a list or dictionary.

        For example, consider the following:

        foo = [1]\nbar = foo\nfoo = foo + [2]\nassert (foo, bar) == ([1, 2], [1])\n

        If the assignment is replaced with an augmented assignment, the update operation will apply to both foo and bar, as they refer to the same object:

        foo = [1]\nbar = foo\nfoo += [2]\nassert (foo, bar) == ([1, 2], [1, 2])\n
        ","tags":["PLR6104"]},{"location":"rules/non-capitalized-section-name/","title":"non-capitalized-section-name (D405)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D405"]},{"location":"rules/non-capitalized-section-name/#what-it-does","title":"What it does","text":"

        Checks for section headers in docstrings that do not begin with capital letters.

        ","tags":["D405"]},{"location":"rules/non-capitalized-section-name/#why-is-this-bad","title":"Why is this bad?","text":"

        For stylistic consistency, all section headers in a docstring should be capitalized.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section typically has a header and a body.

        This rule is enabled when using the numpy and google conventions, and disabled when using the pep257 convention.

        ","tags":["D405"]},{"location":"rules/non-capitalized-section-name/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    returns:\n        Speed as distance divided by time.\n\n    raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D405"]},{"location":"rules/non-capitalized-section-name/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D405"]},{"location":"rules/non-capitalized-section-name/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D405"]},{"location":"rules/non-empty-stub-body/","title":"non-empty-stub-body (PYI010)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI010"]},{"location":"rules/non-empty-stub-body/#what-it-does","title":"What it does","text":"

        Checks for non-empty function stub bodies.

        ","tags":["PYI010"]},{"location":"rules/non-empty-stub-body/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files are never executed at runtime; they should be thought of as \"data files\" for type checkers or IDEs. Function bodies are redundant for this purpose.

        ","tags":["PYI010"]},{"location":"rules/non-empty-stub-body/#example","title":"Example","text":"
        def double(x: int) -> int:\n    return x * 2\n

        Use instead:

        def double(x: int) -> int: ...\n
        ","tags":["PYI010"]},{"location":"rules/non-empty-stub-body/#references","title":"References","text":"
        • Typing documentation - Writing and Maintaining Stub Files
        ","tags":["PYI010"]},{"location":"rules/non-imperative-mood/","title":"non-imperative-mood (D401)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D401"]},{"location":"rules/non-imperative-mood/#what-it-does","title":"What it does","text":"

        Checks for docstring first lines that are not in an imperative mood.

        ","tags":["D401"]},{"location":"rules/non-imperative-mood/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that the first line of a docstring be written in the imperative mood, for consistency.

        Hint: to rewrite the docstring in the imperative, phrase the first line as if it were a command.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the numpy and pep257 conventions, and disabled when using the google conventions.

        ","tags":["D401"]},{"location":"rules/non-imperative-mood/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"Returns the mean of the given values.\"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D401"]},{"location":"rules/non-imperative-mood/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        • lint.pydocstyle.property-decorators
        • lint.pydocstyle.ignore-decorators
        ","tags":["D401"]},{"location":"rules/non-imperative-mood/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        ","tags":["D401"]},{"location":"rules/non-lowercase-variable-in-function/","title":"non-lowercase-variable-in-function (N806)","text":"

        Derived from the pep8-naming linter.

        ","tags":["N806"]},{"location":"rules/non-lowercase-variable-in-function/#what-it-does","title":"What it does","text":"

        Checks for the use of non-lowercase variable names in functions.

        ","tags":["N806"]},{"location":"rules/non-lowercase-variable-in-function/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends that all function variables use lowercase names:

        Function names should be lowercase, with words separated by underscores as necessary to improve readability. Variable names follow the same convention as function names. mixedCase is allowed only in contexts where that's already the prevailing style (e.g. threading.py), to retain backwards compatibility.

        ","tags":["N806"]},{"location":"rules/non-lowercase-variable-in-function/#example","title":"Example","text":"
        def my_function(a):\n    B = a + 3\n    return B\n

        Use instead:

        def my_function(a):\n    b = a + 3\n    return b\n
        ","tags":["N806"]},{"location":"rules/non-lowercase-variable-in-function/#options","title":"Options","text":"
        • lint.pep8-naming.ignore-names
        • lint.pep8-naming.extend-ignore-names
        ","tags":["N806"]},{"location":"rules/non-pep585-annotation/","title":"non-pep585-annotation (UP006)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP006"]},{"location":"rules/non-pep585-annotation/#what-it-does","title":"What it does","text":"

        Checks for the use of generics that can be replaced with standard library variants based on PEP 585.

        ","tags":["UP006"]},{"location":"rules/non-pep585-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 585 enabled collections in the Python standard library (like list) to be used as generics directly, instead of importing analogous members from the typing module (like typing.List).

        When available, the PEP 585 syntax should be used instead of importing members from the typing module, as it's more concise and readable. Importing those members from typing is considered deprecated as of PEP 585.

        This rule is enabled when targeting Python 3.9 or later (see: target-version). By default, it's also enabled for earlier Python versions if from __future__ import annotations is present, as __future__ annotations are not evaluated at runtime. If your code relies on runtime type annotations (either directly or via a library like Pydantic), you can disable this behavior for Python versions prior to 3.9 by setting lint.pyupgrade.keep-runtime-typing to true.

        ","tags":["UP006"]},{"location":"rules/non-pep585-annotation/#example","title":"Example","text":"
        from typing import List\n\nfoo: List[int] = [1, 2, 3]\n

        Use instead:

        foo: list[int] = [1, 2, 3]\n
        ","tags":["UP006"]},{"location":"rules/non-pep585-annotation/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may lead to runtime errors when alongside libraries that rely on runtime type annotations, like Pydantic, on Python versions prior to Python 3.9.

        ","tags":["UP006"]},{"location":"rules/non-pep585-annotation/#options","title":"Options","text":"
        • target-version
        • lint.pyupgrade.keep-runtime-typing
        ","tags":["UP006"]},{"location":"rules/non-pep604-annotation-optional/","title":"non-pep604-annotation-optional (UP045)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-optional/#what-it-does","title":"What it does","text":"

        Check for typing.Optional annotations that can be rewritten based on PEP 604 syntax.

        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-optional/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 604 introduced a new syntax for union type annotations based on the | operator. This syntax is more concise and readable than the previous typing.Optional syntax.

        This rule is enabled when targeting Python 3.10 or later (see: target-version). By default, it's also enabled for earlier Python versions if from __future__ import annotations is present, as __future__ annotations are not evaluated at runtime. If your code relies on runtime type annotations (either directly or via a library like Pydantic), you can disable this behavior for Python versions prior to 3.10 by setting lint.pyupgrade.keep-runtime-typing to true.

        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-optional/#example","title":"Example","text":"
        from typing import Optional\n\nfoo: Optional[int] = None\n

        Use instead:

        foo: int | None = None\n
        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-optional/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may lead to runtime errors when alongside libraries that rely on runtime type annotations, like Pydantic, on Python versions prior to Python 3.10. It may also lead to runtime errors in unusual and likely incorrect type annotations where the type does not support the | operator.

        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-optional/#options","title":"Options","text":"
        • target-version
        • lint.pyupgrade.keep-runtime-typing
        ","tags":["UP045"]},{"location":"rules/non-pep604-annotation-union/","title":"non-pep604-annotation-union (UP007)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#what-it-does","title":"What it does","text":"

        Check for type annotations that can be rewritten based on PEP 604 syntax.

        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 604 introduced a new syntax for union type annotations based on the | operator. This syntax is more concise and readable than the previous typing.Union and typing.Optional syntaxes.

        This rule is enabled when targeting Python 3.10 or later (see: target-version). By default, it's also enabled for earlier Python versions if from __future__ import annotations is present, as __future__ annotations are not evaluated at runtime. If your code relies on runtime type annotations (either directly or via a library like Pydantic), you can disable this behavior for Python versions prior to 3.10 by setting lint.pyupgrade.keep-runtime-typing to true.

        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#example","title":"Example","text":"
        from typing import Union\n\nfoo: Union[int, str] = 1\n

        Use instead:

        foo: int | str = 1\n
        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#preview","title":"Preview","text":"

        In preview mode, this rule only checks for usages of typing.Union, while UP045 checks for typing.Optional.

        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may lead to runtime errors when alongside libraries that rely on runtime type annotations, like Pydantic, on Python versions prior to Python 3.10. It may also lead to runtime errors in unusual and likely incorrect type annotations where the type does not support the | operator.

        ","tags":["UP007"]},{"location":"rules/non-pep604-annotation-union/#options","title":"Options","text":"
        • target-version
        • lint.pyupgrade.keep-runtime-typing
        ","tags":["UP007"]},{"location":"rules/non-pep604-isinstance/","title":"non-pep604-isinstance (UP038)","text":"

        Derived from the pyupgrade linter.

        Warning: This rule is deprecated and will be removed in a future release.

        Fix is always available.

        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#deprecation","title":"Deprecation","text":"

        This rule was deprecated as using PEP 604 syntax in isinstance and issubclass calls isn't recommended practice, and it incorrectly suggests that other typing syntaxes like PEP 695 would be supported by isinstance and issubclass. Using the PEP 604 syntax is also slightly slower.

        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#what-it-does","title":"What it does","text":"

        Checks for uses of isinstance and issubclass that take a tuple of types for comparison.

        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3.10, isinstance and issubclass can be passed a |-separated union of types, which is consistent with the union operator introduced in PEP 604.

        Note that this results in slower code. Ignore this rule if the performance of an isinstance or issubclass check is a concern, e.g., in a hot loop.

        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#example","title":"Example","text":"
        isinstance(x, (int, float))\n

        Use instead:

        isinstance(x, int | float)\n
        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#options","title":"Options","text":"
        • target-version
        ","tags":["UP038"]},{"location":"rules/non-pep604-isinstance/#references","title":"References","text":"
        • Python documentation: isinstance
        • Python documentation: issubclass
        ","tags":["UP038"]},{"location":"rules/non-pep646-unpack/","title":"non-pep646-unpack (UP044)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP044"]},{"location":"rules/non-pep646-unpack/#what-it-does","title":"What it does","text":"

        Checks for uses of Unpack[] on Python 3.11 and above, and suggests using * instead.

        ","tags":["UP044"]},{"location":"rules/non-pep646-unpack/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 646 introduced a new syntax for unpacking sequences based on the * operator. This syntax is more concise and readable than the previous Unpack[] syntax.

        ","tags":["UP044"]},{"location":"rules/non-pep646-unpack/#example","title":"Example","text":"
        from typing import Unpack\n\n\ndef foo(*args: Unpack[tuple[int, ...]]) -> None:\n    pass\n

        Use instead:

        def foo(*args: *tuple[int, ...]) -> None:\n    pass\n
        ","tags":["UP044"]},{"location":"rules/non-pep646-unpack/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as Unpack[T] and *T are considered different values when introspecting types at runtime. However, in most cases, the fix should be safe to apply.

        ","tags":["UP044"]},{"location":"rules/non-pep695-generic-class/","title":"non-pep695-generic-class (UP046)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#what-it-does","title":"What it does","text":"

        Checks for use of standalone type variables and parameter specifications in generic classes.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Special type parameter syntax was introduced in Python 3.12 by PEP 695 for defining generic classes. This syntax is easier to read and provides cleaner support for generics.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#known-problems","title":"Known problems","text":"

        The rule currently skips generic classes nested inside of other functions or classes. It also skips type parameters with the default argument introduced in PEP 696 and implemented in Python 3.13.

        This rule can only offer a fix if all of the generic types in the class definition are defined in the current module. For external type parameters, a diagnostic is emitted without a suggested fix.

        Not all type checkers fully support PEP 695 yet, so even valid fixes suggested by this rule may cause type checking to fail.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#fix-safety","title":"Fix safety","text":"

        This fix is marked as unsafe, as PEP 695 uses inferred variance for type parameters, instead of the covariant and contravariant keywords used by TypeVar variables. As such, replacing a TypeVar variable with an inline type parameter may change its variance.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"T\")\n\n\nclass GenericClass(Generic[T]):\n    var: T\n

        Use instead:

        class GenericClass[T]:\n    var: T\n
        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-class/#see-also","title":"See also","text":"

        This rule replaces standalone type variables in classes but doesn't remove the corresponding type variables even if they are unused after the fix. See unused-private-type-var for a rule to clean up unused private type variables.

        This rule will not rename private type variables to remove leading underscores, even though the new type parameters are restricted in scope to their associated class. See private-type-parameter for a rule to update these names.

        This rule will correctly handle classes with multiple base classes, as long as the single Generic base class is at the end of the argument list, as checked by generic-not-last-base-class. If a Generic base class is found outside of the last position, a diagnostic is emitted without a suggested fix.

        This rule only applies to generic classes and does not include generic functions. See non-pep695-generic-function for the function version.

        ","tags":["UP046"]},{"location":"rules/non-pep695-generic-function/","title":"non-pep695-generic-function (UP047)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#what-it-does","title":"What it does","text":"

        Checks for use of standalone type variables and parameter specifications in generic functions.

        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Special type parameter syntax was introduced in Python 3.12 by PEP 695 for defining generic functions. This syntax is easier to read and provides cleaner support for generics.

        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#known-problems","title":"Known problems","text":"

        The rule currently skips generic functions nested inside of other functions or classes and those with type parameters containing the default argument introduced in PEP 696 and implemented in Python 3.13.

        Not all type checkers fully support PEP 695 yet, so even valid fixes suggested by this rule may cause type checking to fail.

        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#fix-safety","title":"Fix safety","text":"

        This fix is marked unsafe, as PEP 695 uses inferred variance for type parameters, instead of the covariant and contravariant keywords used by TypeVar variables. As such, replacing a TypeVar variable with an inline type parameter may change its variance.

        Additionally, if the rule cannot determine whether a parameter annotation corresponds to a type variable (e.g. for a type imported from another module), it will not add the type to the generic type parameter list. This causes the function to have a mix of old-style type variables and new-style generic type parameters, which will be rejected by type checkers.

        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"T\")\n\n\ndef generic_function(var: T) -> T:\n    return var\n

        Use instead:

        def generic_function[T](var: T) -> T:\n    return var\n
        ","tags":["UP047"]},{"location":"rules/non-pep695-generic-function/#see-also","title":"See also","text":"

        This rule replaces standalone type variables in function signatures but doesn't remove the corresponding type variables even if they are unused after the fix. See unused-private-type-var for a rule to clean up unused private type variables.

        This rule will not rename private type variables to remove leading underscores, even though the new type parameters are restricted in scope to their associated function. See private-type-parameter for a rule to update these names.

        This rule only applies to generic functions and does not include generic classes. See non-pep695-generic-class for the class version.

        ","tags":["UP047"]},{"location":"rules/non-pep695-type-alias/","title":"non-pep695-type-alias (UP040)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#what-it-does","title":"What it does","text":"

        Checks for use of TypeAlias annotations and TypeAliasType assignments for declaring type aliases.

        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        The type keyword was introduced in Python 3.12 by PEP 695 for defining type aliases. The type keyword is easier to read and provides cleaner support for generics.

        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#known-problems","title":"Known problems","text":"

        PEP 695 uses inferred variance for type parameters, instead of the covariant and contravariant keywords used by TypeVar variables. As such, rewriting a type alias using a PEP-695 type statement may change the variance of the alias's type parameters.

        Unlike type aliases that use simple assignments, definitions created using PEP 695 type statements cannot be used as drop-in replacements at runtime for the value on the right-hand side of the statement. This means that while for some simple old-style type aliases you can use them as the second argument to an isinstance() call (for example), doing the same with a PEP 695 type statement will always raise TypeError at runtime.

        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#example","title":"Example","text":"
        ListOfInt: TypeAlias = list[int]\nPositiveInt = TypeAliasType(\"PositiveInt\", Annotated[int, Gt(0)])\n

        Use instead:

        type ListOfInt = list[int]\ntype PositiveInt = Annotated[int, Gt(0)]\n
        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#fix-safety","title":"Fix safety","text":"

        This fix is marked unsafe for TypeAlias assignments outside of stub files because of the runtime behavior around isinstance() calls noted above. The fix is also unsafe for TypeAliasType assignments if there are any comments in the replacement range that would be deleted.

        ","tags":["UP040"]},{"location":"rules/non-pep695-type-alias/#see-also","title":"See also","text":"

        This rule only applies to TypeAliases and TypeAliasTypes. See non-pep695-generic-class and non-pep695-generic-function for similar transformations for generic classes and functions.

        This rule replaces standalone type variables in aliases but doesn't remove the corresponding type variables even if they are unused after the fix. See unused-private-type-var for a rule to clean up unused private type variables.

        This rule will not rename private type variables to remove leading underscores, even though the new type parameters are restricted in scope to their associated aliases. See private-type-parameter for a rule to update these names.

        ","tags":["UP040"]},{"location":"rules/non-self-return-type/","title":"non-self-return-type (PYI034)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#what-it-does","title":"What it does","text":"

        Checks for methods that are annotated with a fixed return type which should instead be returning Self.

        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#why-is-this-bad","title":"Why is this bad?","text":"

        If methods that generally return self at runtime are annotated with a fixed return type, and the class is subclassed, type checkers will not be able to infer the correct return type.

        For example:

        class Shape:\n    def set_scale(self, scale: float) -> Shape:\n        self.scale = scale\n        return self\n\nclass Circle(Shape):\n    def set_radius(self, radius: float) -> Circle:\n        self.radius = radius\n        return self\n\n# Type checker infers return type as `Shape`, not `Circle`.\nCircle().set_scale(0.5)\n\n# Thus, this expression is invalid, as `Shape` has no attribute `set_radius`.\nCircle().set_scale(0.5).set_radius(2.7)\n

        Specifically, this check enforces that the return type of the following methods is Self:

        1. In-place binary-operation dunder methods, like __iadd__, __imul__, etc.
        2. __new__, __enter__, and __aenter__, if those methods return the class name.
        3. __iter__ methods that return Iterator, despite the class inheriting directly from Iterator.
        4. __aiter__ methods that return AsyncIterator, despite the class inheriting directly from AsyncIterator.
        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#example","title":"Example","text":"
        class Foo:\n    def __new__(cls, *args: Any, **kwargs: Any) -> Foo: ...\n    def __enter__(self) -> Foo: ...\n    async def __aenter__(self) -> Foo: ...\n    def __iadd__(self, other: Foo) -> Foo: ...\n

        Use instead:

        from typing_extensions import Self\n\nclass Foo:\n    def __new__(cls, *args: Any, **kwargs: Any) -> Self: ...\n    def __enter__(self) -> Self: ...\n    async def __aenter__(self) -> Self: ...\n    def __iadd__(self, other: Foo) -> Self: ...\n
        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe as it changes the meaning of your type annotations.

        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for Python versions before 3.11, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["PYI034"]},{"location":"rules/non-self-return-type/#references","title":"References","text":"
        • Python documentation: typing.Self
        ","tags":["PYI034"]},{"location":"rules/non-slot-assignment/","title":"non-slot-assignment (PLE0237)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0237"]},{"location":"rules/non-slot-assignment/#what-it-does","title":"What it does","text":"

        Checks for assignments to attributes that are not defined in __slots__.

        ","tags":["PLE0237"]},{"location":"rules/non-slot-assignment/#why-is-this-bad","title":"Why is this bad?","text":"

        When using __slots__, only the specified attributes are allowed. Attempting to assign to an attribute that is not defined in __slots__ will result in an AttributeError at runtime.

        ","tags":["PLE0237"]},{"location":"rules/non-slot-assignment/#known-problems","title":"Known problems","text":"

        This rule can't detect __slots__ implementations in superclasses, and so limits its analysis to classes that inherit from (at most) object.

        ","tags":["PLE0237"]},{"location":"rules/non-slot-assignment/#example","title":"Example","text":"
        class Student:\n    __slots__ = (\"name\",)\n\n    def __init__(self, name, surname):\n        self.name = name\n        self.surname = surname  # [assigning-non-slot]\n        self.setup()\n\n    def setup(self):\n        pass\n

        Use instead:

        class Student:\n    __slots__ = (\"name\", \"surname\")\n\n    def __init__(self, name, surname):\n        self.name = name\n        self.surname = surname\n        self.setup()\n\n    def setup(self):\n        pass\n
        ","tags":["PLE0237"]},{"location":"rules/non-unique-enums/","title":"non-unique-enums (PIE796)","text":"

        Derived from the flake8-pie linter.

        ","tags":["PIE796"]},{"location":"rules/non-unique-enums/#what-it-does","title":"What it does","text":"

        Checks for enums that contain duplicate values.

        ","tags":["PIE796"]},{"location":"rules/non-unique-enums/#why-is-this-bad","title":"Why is this bad?","text":"

        Enum values should be unique. Non-unique values are redundant and likely a mistake.

        ","tags":["PIE796"]},{"location":"rules/non-unique-enums/#example","title":"Example","text":"
        from enum import Enum\n\n\nclass Foo(Enum):\n    A = 1\n    B = 2\n    C = 1\n

        Use instead:

        from enum import Enum\n\n\nclass Foo(Enum):\n    A = 1\n    B = 2\n    C = 3\n
        ","tags":["PIE796"]},{"location":"rules/non-unique-enums/#references","title":"References","text":"
        • Python documentation: enum.Enum
        ","tags":["PIE796"]},{"location":"rules/none-comparison/","title":"none-comparison (E711)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["E711"]},{"location":"rules/none-comparison/#what-it-does","title":"What it does","text":"

        Checks for comparisons to None which are not using the is operator.

        ","tags":["E711"]},{"location":"rules/none-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"Comparisons to singletons like None should always be done with is or is not, never the equality operators.\"

        ","tags":["E711"]},{"location":"rules/none-comparison/#example","title":"Example","text":"
        if arg != None:\n    pass\nif None == arg:\n    pass\n

        Use instead:

        if arg is not None:\n    pass\n
        ","tags":["E711"]},{"location":"rules/none-comparison/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may alter runtime behavior when used with libraries that override the ==/__eq__ or !=/__ne__ operators. In these cases, is/is not may not be equivalent to ==/!=. For more information, see this issue.

        ","tags":["E711"]},{"location":"rules/none-not-at-end-of-union/","title":"none-not-at-end-of-union (RUF036)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF036"]},{"location":"rules/none-not-at-end-of-union/#what-it-does","title":"What it does","text":"

        Checks for type annotations where None is not at the end of an union.

        ","tags":["RUF036"]},{"location":"rules/none-not-at-end-of-union/#why-is-this-bad","title":"Why is this bad?","text":"

        Type annotation unions are associative, meaning that the order of the elements does not matter. The None literal represents the absence of a value. For readability, it's preferred to write the more informative type expressions first.

        ","tags":["RUF036"]},{"location":"rules/none-not-at-end-of-union/#example","title":"Example","text":"
        def func(arg: None | int): ...\n

        Use instead:

        def func(arg: int | None): ...\n
        ","tags":["RUF036"]},{"location":"rules/none-not-at-end-of-union/#references","title":"References","text":"
        • Python documentation: Union type
        • Python documentation: typing.Optional
        • Python documentation: None
        ","tags":["RUF036"]},{"location":"rules/nonlocal-and-global/","title":"nonlocal-and-global (PLE0115)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0115"]},{"location":"rules/nonlocal-and-global/#what-it-does","title":"What it does","text":"

        Checks for variables which are both declared as both nonlocal and global.

        ","tags":["PLE0115"]},{"location":"rules/nonlocal-and-global/#why-is-this-bad","title":"Why is this bad?","text":"

        A nonlocal variable is a variable that is defined in the nearest enclosing scope, but not in the global scope, while a global variable is a variable that is defined in the global scope.

        Declaring a variable as both nonlocal and global is contradictory and will raise a SyntaxError.

        ","tags":["PLE0115"]},{"location":"rules/nonlocal-and-global/#example","title":"Example","text":"
        counter = 0\n\n\ndef increment():\n    global counter\n    nonlocal counter\n    counter += 1\n

        Use instead:

        counter = 0\n\n\ndef increment():\n    global counter\n    counter += 1\n
        ","tags":["PLE0115"]},{"location":"rules/nonlocal-and-global/#references","title":"References","text":"
        • Python documentation: The global statement
        • Python documentation: The nonlocal statement
        ","tags":["PLE0115"]},{"location":"rules/nonlocal-without-binding/","title":"nonlocal-without-binding (PLE0117)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0117"]},{"location":"rules/nonlocal-without-binding/#what-it-does","title":"What it does","text":"

        Checks for nonlocal names without bindings.

        ","tags":["PLE0117"]},{"location":"rules/nonlocal-without-binding/#why-is-this-bad","title":"Why is this bad?","text":"

        nonlocal names must be bound to a name in an outer scope. Violating this rule leads to a SyntaxError at runtime.

        ","tags":["PLE0117"]},{"location":"rules/nonlocal-without-binding/#example","title":"Example","text":"
        def foo():\n    def get_bar(self):\n        nonlocal bar\n        ...\n

        Use instead:

        def foo():\n    bar = 1\n\n    def get_bar(self):\n        nonlocal bar\n        ...\n
        ","tags":["PLE0117"]},{"location":"rules/nonlocal-without-binding/#references","title":"References","text":"
        • Python documentation: The nonlocal statement
        • PEP 3104 \u2013 Access to Names in Outer Scopes
        ","tags":["PLE0117"]},{"location":"rules/not-in-test/","title":"not-in-test (E713)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["E713"]},{"location":"rules/not-in-test/#what-it-does","title":"What it does","text":"

        Checks for membership tests using not {element} in {collection}.

        ","tags":["E713"]},{"location":"rules/not-in-test/#why-is-this-bad","title":"Why is this bad?","text":"

        Testing membership with {element} not in {collection} is more readable.

        ","tags":["E713"]},{"location":"rules/not-in-test/#example","title":"Example","text":"
        Z = not X in Y\nif not X.B in Y:\n    pass\n

        Use instead:

        Z = X not in Y\nif X.B not in Y:\n    pass\n
        ","tags":["E713"]},{"location":"rules/not-is-test/","title":"not-is-test (E714)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["E714"]},{"location":"rules/not-is-test/#what-it-does","title":"What it does","text":"

        Checks for identity comparisons using not {foo} is {bar}.

        ","tags":["E714"]},{"location":"rules/not-is-test/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP8, testing for an object's identity with is not is more readable.

        ","tags":["E714"]},{"location":"rules/not-is-test/#example","title":"Example","text":"
        if not X is Y:\n    pass\nZ = not X.B is Y\n

        Use instead:

        if X is not Y:\n    pass\nZ = X.B is not Y\n
        ","tags":["E714"]},{"location":"rules/numeric-literal-too-long/","title":"numeric-literal-too-long (PYI054)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI054"]},{"location":"rules/numeric-literal-too-long/#what-it-does","title":"What it does","text":"

        Checks for numeric literals with a string representation longer than ten characters.

        ","tags":["PYI054"]},{"location":"rules/numeric-literal-too-long/#why-is-this-bad","title":"Why is this bad?","text":"

        If a function has a default value where the literal representation is greater than 10 characters, the value is likely to be an implementation detail or a constant that varies depending on the system you're running on.

        Default values like these should generally be omitted from stubs. Use ellipses (...) instead.

        ","tags":["PYI054"]},{"location":"rules/numeric-literal-too-long/#example","title":"Example","text":"
        def foo(arg: int = 693568516352839939918568862861217771399698285293568) -> None: ...\n

        Use instead:

        def foo(arg: int = ...) -> None: ...\n
        ","tags":["PYI054"]},{"location":"rules/numpy-deprecated-function/","title":"numpy-deprecated-function (NPY003)","text":"

        Fix is sometimes available.

        ","tags":["NPY003"]},{"location":"rules/numpy-deprecated-function/#what-it-does","title":"What it does","text":"

        Checks for uses of deprecated NumPy functions.

        ","tags":["NPY003"]},{"location":"rules/numpy-deprecated-function/#why-is-this-bad","title":"Why is this bad?","text":"

        When NumPy functions are deprecated, they are usually replaced with newer, more efficient versions, or with functions that are more consistent with the rest of the NumPy API.

        Prefer newer APIs over deprecated ones.

        ","tags":["NPY003"]},{"location":"rules/numpy-deprecated-function/#example","title":"Example","text":"
        import numpy as np\n\nnp.alltrue([True, False])\n

        Use instead:

        import numpy as np\n\nnp.all([True, False])\n
        ","tags":["NPY003"]},{"location":"rules/numpy-deprecated-type-alias/","title":"numpy-deprecated-type-alias (NPY001)","text":"

        Fix is sometimes available.

        ","tags":["NPY001"]},{"location":"rules/numpy-deprecated-type-alias/#what-it-does","title":"What it does","text":"

        Checks for deprecated NumPy type aliases.

        ","tags":["NPY001"]},{"location":"rules/numpy-deprecated-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        NumPy's np.int has long been an alias of the builtin int; the same is true of np.float and others. These aliases exist primarily for historic reasons, and have been a cause of frequent confusion for newcomers.

        These aliases were deprecated in 1.20, and removed in 1.24. Note, however, that np.bool and np.long were reintroduced in 2.0 with different semantics, and are thus omitted from this rule.

        ","tags":["NPY001"]},{"location":"rules/numpy-deprecated-type-alias/#example","title":"Example","text":"
        import numpy as np\n\nnp.int\n

        Use instead:

        int\n
        ","tags":["NPY001"]},{"location":"rules/numpy-legacy-random/","title":"numpy-legacy-random (NPY002)","text":"","tags":["NPY002"]},{"location":"rules/numpy-legacy-random/#what-it-does","title":"What it does","text":"

        Checks for the use of legacy np.random function calls.

        ","tags":["NPY002"]},{"location":"rules/numpy-legacy-random/#why-is-this-bad","title":"Why is this bad?","text":"

        According to the NumPy documentation's Legacy Random Generation:

        The RandomState provides access to legacy generators... This class should only be used if it is essential to have randoms that are identical to what would have been produced by previous versions of NumPy.

        The members exposed directly on the random module are convenience functions that alias to methods on a global singleton RandomState instance. NumPy recommends using a dedicated Generator instance rather than the random variate generation methods exposed directly on the random module, as the new Generator is both faster and has better statistical properties.

        See the documentation on Random Sampling and NEP 19 for further details.

        ","tags":["NPY002"]},{"location":"rules/numpy-legacy-random/#example","title":"Example","text":"
        import numpy as np\n\nnp.random.seed(1337)\nnp.random.normal()\n

        Use instead:

        rng = np.random.default_rng(1337)\nrng.normal()\n
        ","tags":["NPY002"]},{"location":"rules/numpy2-deprecation/","title":"numpy2-deprecation (NPY201)","text":"

        Fix is sometimes available.

        ","tags":["NPY201"]},{"location":"rules/numpy2-deprecation/#what-it-does","title":"What it does","text":"

        Checks for uses of NumPy functions and constants that were removed from the main namespace in NumPy 2.0.

        ","tags":["NPY201"]},{"location":"rules/numpy2-deprecation/#why-is-this-bad","title":"Why is this bad?","text":"

        NumPy 2.0 includes an overhaul of NumPy's Python API, intended to remove redundant aliases and routines, and establish unambiguous mechanisms for accessing constants, dtypes, and functions.

        As part of this overhaul, a variety of deprecated NumPy functions and constants were removed from the main namespace.

        The majority of these functions and constants can be automatically replaced by other members of the NumPy API or by equivalents from the Python standard library. With the exception of renaming numpy.byte_bounds to numpy.lib.array_utils.byte_bounds, all such replacements are backwards compatible with earlier versions of NumPy.

        This rule flags all uses of removed members, along with automatic fixes for any backwards-compatible replacements.

        ","tags":["NPY201"]},{"location":"rules/numpy2-deprecation/#example","title":"Example","text":"
        import numpy as np\n\narr1 = [np.Infinity, np.NaN, np.nan, np.PINF, np.inf]\narr2 = [np.float_(1.5), np.float64(5.1)]\nnp.round_(arr2)\n

        Use instead:

        import numpy as np\n\narr1 = [np.inf, np.nan, np.nan, np.inf, np.inf]\narr2 = [np.float64(1.5), np.float64(5.1)]\nnp.round(arr2)\n
        ","tags":["NPY201"]},{"location":"rules/open-alias/","title":"open-alias (UP020)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP020"]},{"location":"rules/open-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of io.open.

        ","tags":["UP020"]},{"location":"rules/open-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3, io.open is an alias for open. Prefer using open directly, as it is more idiomatic.

        ","tags":["UP020"]},{"location":"rules/open-alias/#example","title":"Example","text":"
        import io\n\nwith io.open(\"file.txt\") as f:\n    ...\n

        Use instead:

        with open(\"file.txt\") as f:\n    ...\n
        ","tags":["UP020"]},{"location":"rules/open-alias/#references","title":"References","text":"
        • Python documentation: io.open
        ","tags":["UP020"]},{"location":"rules/open-file-with-context-handler/","title":"open-file-with-context-handler (SIM115)","text":"

        Derived from the flake8-simplify linter.

        ","tags":["SIM115"]},{"location":"rules/open-file-with-context-handler/#what-it-does","title":"What it does","text":"

        Checks for cases where files are opened (e.g., using the builtin open() function) without using a context manager.

        ","tags":["SIM115"]},{"location":"rules/open-file-with-context-handler/#why-is-this-bad","title":"Why is this bad?","text":"

        If a file is opened without a context manager, it is not guaranteed that the file will be closed (e.g., if an exception is raised), which can cause resource leaks. The rule detects a wide array of IO calls where context managers could be used, such as open, pathlib.Path(...).open(), tempfile.TemporaryFile() ortarfile.TarFile(...).gzopen().

        ","tags":["SIM115"]},{"location":"rules/open-file-with-context-handler/#example","title":"Example","text":"
        file = open(\"foo.txt\")\n...\nfile.close()\n

        Use instead:

        with open(\"foo.txt\") as file:\n    ...\n
        ","tags":["SIM115"]},{"location":"rules/open-file-with-context-handler/#references","title":"References","text":"
        • Python documentation: open
        ","tags":["SIM115"]},{"location":"rules/os-chmod/","title":"os-chmod (PTH101)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH101"]},{"location":"rules/os-chmod/#what-it-does","title":"What it does","text":"

        Checks for uses of os.chmod.

        ","tags":["PTH101"]},{"location":"rules/os-chmod/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.chmod() can improve readability over the os module's counterparts (e.g., os.chmod()).

        ","tags":["PTH101"]},{"location":"rules/os-chmod/#examples","title":"Examples","text":"
        import os\n\nos.chmod(\"file.py\", 0o444)\n

        Use instead:

        from pathlib import Path\n\nPath(\"file.py\").chmod(0o444)\n
        ","tags":["PTH101"]},{"location":"rules/os-chmod/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH101"]},{"location":"rules/os-chmod/#references","title":"References","text":"
        • Python documentation: Path.chmod
        • Python documentation: os.chmod
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH101"]},{"location":"rules/os-error-alias/","title":"os-error-alias (UP024)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP024"]},{"location":"rules/os-error-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of exceptions that alias OSError.

        ","tags":["UP024"]},{"location":"rules/os-error-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        OSError is the builtin error type used for exceptions that relate to the operating system.

        In Python 3.3, a variety of other exceptions, like WindowsError were aliased to OSError. These aliases remain in place for compatibility with older versions of Python, but may be removed in future versions.

        Prefer using OSError directly, as it is more idiomatic and future-proof.

        ","tags":["UP024"]},{"location":"rules/os-error-alias/#example","title":"Example","text":"
        raise IOError\n

        Use instead:

        raise OSError\n
        ","tags":["UP024"]},{"location":"rules/os-error-alias/#references","title":"References","text":"
        • Python documentation: OSError
        ","tags":["UP024"]},{"location":"rules/os-getcwd/","title":"os-getcwd (PTH109)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH109"]},{"location":"rules/os-getcwd/#what-it-does","title":"What it does","text":"

        Checks for uses of os.getcwd and os.getcwdb.

        ","tags":["PTH109"]},{"location":"rules/os-getcwd/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.cwd() can improve readability over the os module's counterparts (e.g., os.getcwd()).

        ","tags":["PTH109"]},{"location":"rules/os-getcwd/#examples","title":"Examples","text":"
        import os\n\ncwd = os.getcwd()\n

        Use instead:

        from pathlib import Path\n\ncwd = Path.cwd()\n
        ","tags":["PTH109"]},{"location":"rules/os-getcwd/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH109"]},{"location":"rules/os-getcwd/#references","title":"References","text":"
        • Python documentation: Path.cwd
        • Python documentation: os.getcwd
        • Python documentation: os.getcwdb
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH109"]},{"location":"rules/os-listdir/","title":"os-listdir (PTH208)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH208"]},{"location":"rules/os-listdir/#what-it-does","title":"What it does","text":"

        Checks for uses of os.listdir.

        ","tags":["PTH208"]},{"location":"rules/os-listdir/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using pathlib's Path.iterdir() can improve readability over os.listdir().

        ","tags":["PTH208"]},{"location":"rules/os-listdir/#example","title":"Example","text":"
        p = \".\"\nfor d in os.listdir(p):\n    ...\n\nif os.listdir(p):\n    ...\n\nif \"file\" in os.listdir(p):\n    ...\n

        Use instead:

        p = Path(\".\")\nfor d in p.iterdir():\n    ...\n\nif any(p.iterdir()):\n    ...\n\nif (p / \"file\").exists():\n    ...\n
        ","tags":["PTH208"]},{"location":"rules/os-listdir/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH208"]},{"location":"rules/os-listdir/#references","title":"References","text":"
        • Python documentation: Path.iterdir
        • Python documentation: os.listdir
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH208"]},{"location":"rules/os-makedirs/","title":"os-makedirs (PTH103)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH103"]},{"location":"rules/os-makedirs/#what-it-does","title":"What it does","text":"

        Checks for uses of os.makedirs.

        ","tags":["PTH103"]},{"location":"rules/os-makedirs/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.mkdir(parents=True) can improve readability over the os module's counterparts (e.g., os.makedirs().

        ","tags":["PTH103"]},{"location":"rules/os-makedirs/#examples","title":"Examples","text":"
        import os\n\nos.makedirs(\"./nested/directory/\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"./nested/directory/\").mkdir(parents=True)\n
        ","tags":["PTH103"]},{"location":"rules/os-makedirs/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH103"]},{"location":"rules/os-makedirs/#references","title":"References","text":"
        • Python documentation: Path.mkdir
        • Python documentation: os.makedirs
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH103"]},{"location":"rules/os-mkdir/","title":"os-mkdir (PTH102)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH102"]},{"location":"rules/os-mkdir/#what-it-does","title":"What it does","text":"

        Checks for uses of os.mkdir.

        ","tags":["PTH102"]},{"location":"rules/os-mkdir/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.mkdir() can improve readability over the os module's counterparts (e.g., os.mkdir()).

        ","tags":["PTH102"]},{"location":"rules/os-mkdir/#examples","title":"Examples","text":"
        import os\n\nos.mkdir(\"./directory/\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"./directory/\").mkdir()\n
        ","tags":["PTH102"]},{"location":"rules/os-mkdir/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH102"]},{"location":"rules/os-mkdir/#references","title":"References","text":"
        • Python documentation: Path.mkdir
        • Python documentation: os.mkdir
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH102"]},{"location":"rules/os-path-abspath/","title":"os-path-abspath (PTH100)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH100"]},{"location":"rules/os-path-abspath/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.abspath.

        ","tags":["PTH100"]},{"location":"rules/os-path-abspath/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.resolve() can improve readability over the os.path module's counterparts (e.g., os.path.abspath()).

        ","tags":["PTH100"]},{"location":"rules/os-path-abspath/#examples","title":"Examples","text":"
        import os\n\nfile_path = os.path.abspath(\"../path/to/file\")\n

        Use instead:

        from pathlib import Path\n\nfile_path = Path(\"../path/to/file\").resolve()\n
        ","tags":["PTH100"]},{"location":"rules/os-path-abspath/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH100"]},{"location":"rules/os-path-abspath/#references","title":"References","text":"
        • Python documentation: Path.resolve
        • Python documentation: os.path.abspath
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH100"]},{"location":"rules/os-path-basename/","title":"os-path-basename (PTH119)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH119"]},{"location":"rules/os-path-basename/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.basename.

        ","tags":["PTH119"]},{"location":"rules/os-path-basename/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.name can improve readability over the os.path module's counterparts (e.g., os.path.basename()).

        ","tags":["PTH119"]},{"location":"rules/os-path-basename/#examples","title":"Examples","text":"
        import os\n\nos.path.basename(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).name\n
        ","tags":["PTH119"]},{"location":"rules/os-path-basename/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH119"]},{"location":"rules/os-path-basename/#references","title":"References","text":"
        • Python documentation: PurePath.name
        • Python documentation: os.path.basename
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH119"]},{"location":"rules/os-path-dirname/","title":"os-path-dirname (PTH120)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH120"]},{"location":"rules/os-path-dirname/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.dirname.

        ","tags":["PTH120"]},{"location":"rules/os-path-dirname/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.parent can improve readability over the os.path module's counterparts (e.g., os.path.dirname()).

        ","tags":["PTH120"]},{"location":"rules/os-path-dirname/#examples","title":"Examples","text":"
        import os\n\nos.path.dirname(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).parent\n
        ","tags":["PTH120"]},{"location":"rules/os-path-dirname/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH120"]},{"location":"rules/os-path-dirname/#references","title":"References","text":"
        • Python documentation: PurePath.parent
        • Python documentation: os.path.dirname
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH120"]},{"location":"rules/os-path-exists/","title":"os-path-exists (PTH110)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH110"]},{"location":"rules/os-path-exists/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.exists.

        ","tags":["PTH110"]},{"location":"rules/os-path-exists/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.exists() can improve readability over the os.path module's counterparts (e.g., os.path.exists()).

        ","tags":["PTH110"]},{"location":"rules/os-path-exists/#examples","title":"Examples","text":"
        import os\n\nos.path.exists(\"file.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"file.py\").exists()\n
        ","tags":["PTH110"]},{"location":"rules/os-path-exists/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH110"]},{"location":"rules/os-path-exists/#references","title":"References","text":"
        • Python documentation: Path.exists
        • Python documentation: os.path.exists
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH110"]},{"location":"rules/os-path-expanduser/","title":"os-path-expanduser (PTH111)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH111"]},{"location":"rules/os-path-expanduser/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.expanduser.

        ","tags":["PTH111"]},{"location":"rules/os-path-expanduser/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.expanduser() can improve readability over the os.path module's counterparts (e.g., as os.path.expanduser()).

        ","tags":["PTH111"]},{"location":"rules/os-path-expanduser/#examples","title":"Examples","text":"
        import os\n\nos.path.expanduser(\"~/films/Monty Python\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"~/films/Monty Python\").expanduser()\n
        ","tags":["PTH111"]},{"location":"rules/os-path-expanduser/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH111"]},{"location":"rules/os-path-expanduser/#references","title":"References","text":"
        • Python documentation: Path.expanduser
        • Python documentation: os.path.expanduser
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH111"]},{"location":"rules/os-path-getatime/","title":"os-path-getatime (PTH203)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH203"]},{"location":"rules/os-path-getatime/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.getatime.

        ","tags":["PTH203"]},{"location":"rules/os-path-getatime/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path.

        When possible, using Path object methods such as Path.stat() can improve readability over the os.path module's counterparts (e.g., os.path.getatime()).

        ","tags":["PTH203"]},{"location":"rules/os-path-getatime/#example","title":"Example","text":"
        import os\n\nos.path.getatime(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).stat().st_atime\n
        ","tags":["PTH203"]},{"location":"rules/os-path-getatime/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH203"]},{"location":"rules/os-path-getatime/#references","title":"References","text":"
        • Python documentation: Path.stat
        • Python documentation: os.path.getatime
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH203"]},{"location":"rules/os-path-getctime/","title":"os-path-getctime (PTH205)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH205"]},{"location":"rules/os-path-getctime/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.getctime.

        ","tags":["PTH205"]},{"location":"rules/os-path-getctime/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path.

        When possible, using Path object methods such as Path.stat() can improve readability over the os.path module's counterparts (e.g., os.path.getctime()).

        ","tags":["PTH205"]},{"location":"rules/os-path-getctime/#example","title":"Example","text":"
        import os\n\nos.path.getctime(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).stat().st_ctime\n
        ","tags":["PTH205"]},{"location":"rules/os-path-getctime/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH205"]},{"location":"rules/os-path-getctime/#references","title":"References","text":"
        • Python documentation: Path.stat
        • Python documentation: os.path.getctime
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH205"]},{"location":"rules/os-path-getmtime/","title":"os-path-getmtime (PTH204)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH204"]},{"location":"rules/os-path-getmtime/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.getmtime.

        ","tags":["PTH204"]},{"location":"rules/os-path-getmtime/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path.

        When possible, using Path object methods such as Path.stat() can improve readability over the os.path module's counterparts (e.g., os.path.getmtime()).

        ","tags":["PTH204"]},{"location":"rules/os-path-getmtime/#example","title":"Example","text":"
        import os\n\nos.path.getmtime(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).stat().st_mtime\n
        ","tags":["PTH204"]},{"location":"rules/os-path-getmtime/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH204"]},{"location":"rules/os-path-getmtime/#references","title":"References","text":"
        • Python documentation: Path.stat
        • Python documentation: os.path.getmtime
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH204"]},{"location":"rules/os-path-getsize/","title":"os-path-getsize (PTH202)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH202"]},{"location":"rules/os-path-getsize/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.getsize.

        ","tags":["PTH202"]},{"location":"rules/os-path-getsize/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path.

        When possible, using Path object methods such as Path.stat() can improve readability over the os.path module's counterparts (e.g., os.path.getsize()).

        ","tags":["PTH202"]},{"location":"rules/os-path-getsize/#example","title":"Example","text":"
        import os\n\nos.path.getsize(__file__)\n

        Use instead:

        from pathlib import Path\n\nPath(__file__).stat().st_size\n
        ","tags":["PTH202"]},{"location":"rules/os-path-getsize/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH202"]},{"location":"rules/os-path-getsize/#references","title":"References","text":"
        • Python documentation: Path.stat
        • Python documentation: os.path.getsize
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH202"]},{"location":"rules/os-path-isabs/","title":"os-path-isabs (PTH117)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH117"]},{"location":"rules/os-path-isabs/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.isabs.

        ","tags":["PTH117"]},{"location":"rules/os-path-isabs/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.is_absolute() can improve readability over the os.path module's counterparts (e.g., as os.path.isabs()).

        ","tags":["PTH117"]},{"location":"rules/os-path-isabs/#examples","title":"Examples","text":"
        import os\n\nif os.path.isabs(file_name):\n    print(\"Absolute path!\")\n

        Use instead:

        from pathlib import Path\n\nif Path(file_name).is_absolute():\n    print(\"Absolute path!\")\n
        ","tags":["PTH117"]},{"location":"rules/os-path-isabs/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH117"]},{"location":"rules/os-path-isabs/#references","title":"References","text":"
        • Python documentation: PurePath.is_absolute
        • Python documentation: os.path.isabs
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH117"]},{"location":"rules/os-path-isdir/","title":"os-path-isdir (PTH112)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH112"]},{"location":"rules/os-path-isdir/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.isdir.

        ","tags":["PTH112"]},{"location":"rules/os-path-isdir/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.is_dir() can improve readability over the os.path module's counterparts (e.g., os.path.isdir()).

        ","tags":["PTH112"]},{"location":"rules/os-path-isdir/#examples","title":"Examples","text":"
        import os\n\nos.path.isdir(\"docs\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"docs\").is_dir()\n
        ","tags":["PTH112"]},{"location":"rules/os-path-isdir/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH112"]},{"location":"rules/os-path-isdir/#references","title":"References","text":"
        • Python documentation: Path.is_dir
        • Python documentation: os.path.isdir
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH112"]},{"location":"rules/os-path-isfile/","title":"os-path-isfile (PTH113)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH113"]},{"location":"rules/os-path-isfile/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.isfile.

        ","tags":["PTH113"]},{"location":"rules/os-path-isfile/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.is_file() can improve readability over the os.path module's counterparts (e.g., os.path.isfile()).

        ","tags":["PTH113"]},{"location":"rules/os-path-isfile/#examples","title":"Examples","text":"
        import os\n\nos.path.isfile(\"docs\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"docs\").is_file()\n
        ","tags":["PTH113"]},{"location":"rules/os-path-isfile/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH113"]},{"location":"rules/os-path-isfile/#references","title":"References","text":"
        • Python documentation: Path.is_file
        • Python documentation: os.path.isfile
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH113"]},{"location":"rules/os-path-islink/","title":"os-path-islink (PTH114)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH114"]},{"location":"rules/os-path-islink/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.islink.

        ","tags":["PTH114"]},{"location":"rules/os-path-islink/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.is_symlink() can improve readability over the os.path module's counterparts (e.g., os.path.islink()).

        ","tags":["PTH114"]},{"location":"rules/os-path-islink/#examples","title":"Examples","text":"
        import os\n\nos.path.islink(\"docs\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"docs\").is_symlink()\n
        ","tags":["PTH114"]},{"location":"rules/os-path-islink/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH114"]},{"location":"rules/os-path-islink/#references","title":"References","text":"
        • Python documentation: Path.is_symlink
        • Python documentation: os.path.islink
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH114"]},{"location":"rules/os-path-join/","title":"os-path-join (PTH118)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH118"]},{"location":"rules/os-path-join/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.join.

        ","tags":["PTH118"]},{"location":"rules/os-path-join/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.joinpath() or the / operator can improve readability over the os.path module's counterparts (e.g., os.path.join()).

        ","tags":["PTH118"]},{"location":"rules/os-path-join/#examples","title":"Examples","text":"
        import os\n\nos.path.join(os.path.join(ROOT_PATH, \"folder\"), \"file.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(ROOT_PATH) / \"folder\" / \"file.py\"\n
        ","tags":["PTH118"]},{"location":"rules/os-path-join/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH118"]},{"location":"rules/os-path-join/#references","title":"References","text":"
        • Python documentation: PurePath.joinpath
        • Python documentation: os.path.join
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH118"]},{"location":"rules/os-path-samefile/","title":"os-path-samefile (PTH121)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH121"]},{"location":"rules/os-path-samefile/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.samefile.

        ","tags":["PTH121"]},{"location":"rules/os-path-samefile/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.samefile() can improve readability over the os.path module's counterparts (e.g., os.path.samefile()).

        ","tags":["PTH121"]},{"location":"rules/os-path-samefile/#examples","title":"Examples","text":"
        import os\n\nos.path.samefile(\"f1.py\", \"f2.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"f1.py\").samefile(\"f2.py\")\n
        ","tags":["PTH121"]},{"location":"rules/os-path-samefile/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH121"]},{"location":"rules/os-path-samefile/#references","title":"References","text":"
        • Python documentation: Path.samefile
        • Python documentation: os.path.samefile
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH121"]},{"location":"rules/os-path-splitext/","title":"os-path-splitext (PTH122)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH122"]},{"location":"rules/os-path-splitext/#what-it-does","title":"What it does","text":"

        Checks for uses of os.path.splitext.

        ","tags":["PTH122"]},{"location":"rules/os-path-splitext/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os.path. When possible, using Path object methods such as Path.suffix and Path.stem can improve readability over the os.path module's counterparts (e.g., os.path.splitext()).

        os.path.splitext() specifically returns a tuple of the file root and extension (e.g., given splitext('/foo/bar.py'), os.path.splitext() returns (\"foo/bar\", \".py\"). These outputs can be reconstructed through a combination of Path.suffix (\".py\"), Path.stem (\"bar\"), and Path.parent (\"foo\").

        ","tags":["PTH122"]},{"location":"rules/os-path-splitext/#examples","title":"Examples","text":"
        import os\n\n(root, ext) = os.path.splitext(\"foo/bar.py\")\n

        Use instead:

        from pathlib import Path\n\npath = Path(\"foo/bar.py\")\nroot = path.parent / path.stem\next = path.suffix\n
        ","tags":["PTH122"]},{"location":"rules/os-path-splitext/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH122"]},{"location":"rules/os-path-splitext/#references","title":"References","text":"
        • Python documentation: Path.suffix
        • Python documentation: Path.suffixes
        • Python documentation: os.path.splitext
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH122"]},{"location":"rules/os-readlink/","title":"os-readlink (PTH115)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH115"]},{"location":"rules/os-readlink/#what-it-does","title":"What it does","text":"

        Checks for uses of os.readlink.

        ","tags":["PTH115"]},{"location":"rules/os-readlink/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.readlink() can improve readability over the os module's counterparts (e.g., os.readlink()).

        ","tags":["PTH115"]},{"location":"rules/os-readlink/#examples","title":"Examples","text":"
        import os\n\nos.readlink(file_name)\n

        Use instead:

        from pathlib import Path\n\nPath(file_name).readlink()\n
        ","tags":["PTH115"]},{"location":"rules/os-readlink/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH115"]},{"location":"rules/os-readlink/#references","title":"References","text":"
        • Python documentation: Path.readlink
        • Python documentation: os.readlink
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH115"]},{"location":"rules/os-remove/","title":"os-remove (PTH107)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH107"]},{"location":"rules/os-remove/#what-it-does","title":"What it does","text":"

        Checks for uses of os.remove.

        ","tags":["PTH107"]},{"location":"rules/os-remove/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.unlink() can improve readability over the os module's counterparts (e.g., os.remove()).

        ","tags":["PTH107"]},{"location":"rules/os-remove/#examples","title":"Examples","text":"
        import os\n\nos.remove(\"file.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"file.py\").unlink()\n
        ","tags":["PTH107"]},{"location":"rules/os-remove/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH107"]},{"location":"rules/os-remove/#references","title":"References","text":"
        • Python documentation: Path.unlink
        • Python documentation: os.remove
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH107"]},{"location":"rules/os-rename/","title":"os-rename (PTH104)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH104"]},{"location":"rules/os-rename/#what-it-does","title":"What it does","text":"

        Checks for uses of os.rename.

        ","tags":["PTH104"]},{"location":"rules/os-rename/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.rename() can improve readability over the os module's counterparts (e.g., os.rename()).

        ","tags":["PTH104"]},{"location":"rules/os-rename/#examples","title":"Examples","text":"
        import os\n\nos.rename(\"old.py\", \"new.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"old.py\").rename(\"new.py\")\n
        ","tags":["PTH104"]},{"location":"rules/os-rename/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH104"]},{"location":"rules/os-rename/#references","title":"References","text":"
        • Python documentation: Path.rename
        • Python documentation: os.rename
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH104"]},{"location":"rules/os-replace/","title":"os-replace (PTH105)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH105"]},{"location":"rules/os-replace/#what-it-does","title":"What it does","text":"

        Checks for uses of os.replace.

        ","tags":["PTH105"]},{"location":"rules/os-replace/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.replace() can improve readability over the os module's counterparts (e.g., os.replace()).

        Note that os functions may be preferable if performance is a concern, e.g., in hot loops.

        ","tags":["PTH105"]},{"location":"rules/os-replace/#examples","title":"Examples","text":"
        import os\n\nos.replace(\"old.py\", \"new.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"old.py\").replace(\"new.py\")\n
        ","tags":["PTH105"]},{"location":"rules/os-replace/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH105"]},{"location":"rules/os-replace/#references","title":"References","text":"
        • Python documentation: Path.replace
        • Python documentation: os.replace
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH105"]},{"location":"rules/os-rmdir/","title":"os-rmdir (PTH106)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH106"]},{"location":"rules/os-rmdir/#what-it-does","title":"What it does","text":"

        Checks for uses of os.rmdir.

        ","tags":["PTH106"]},{"location":"rules/os-rmdir/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.rmdir() can improve readability over the os module's counterparts (e.g., os.rmdir()).

        ","tags":["PTH106"]},{"location":"rules/os-rmdir/#examples","title":"Examples","text":"
        import os\n\nos.rmdir(\"folder/\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"folder/\").rmdir()\n
        ","tags":["PTH106"]},{"location":"rules/os-rmdir/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH106"]},{"location":"rules/os-rmdir/#references","title":"References","text":"
        • Python documentation: Path.rmdir
        • Python documentation: os.rmdir
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH106"]},{"location":"rules/os-sep-split/","title":"os-sep-split (PTH206)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH206"]},{"location":"rules/os-sep-split/#what-it-does","title":"What it does","text":"

        Checks for uses of .split(os.sep)

        ","tags":["PTH206"]},{"location":"rules/os-sep-split/#why-is-this-bad","title":"Why is this bad?","text":"

        The pathlib module in the standard library should be used for path manipulation. It provides a high-level API with the functionality needed for common operations on Path objects.

        ","tags":["PTH206"]},{"location":"rules/os-sep-split/#example","title":"Example","text":"

        If not all parts of the path are needed, then the name and parent attributes of the Path object should be used. Otherwise, the parts attribute can be used as shown in the last example.

        import os\n\n\"path/to/file_name.txt\".split(os.sep)[-1]\n\n\"path/to/file_name.txt\".split(os.sep)[-2]\n\n# Iterating over the path parts\nif any(part in blocklist for part in \"my/file/path\".split(os.sep)):\n    ...\n

        Use instead:

        from pathlib import Path\n\nPath(\"path/to/file_name.txt\").name\n\nPath(\"path/to/file_name.txt\").parent.name\n\n# Iterating over the path parts\nif any(part in blocklist for part in Path(\"my/file/path\").parts):\n    ...\n
        ","tags":["PTH206"]},{"location":"rules/os-sep-split/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than working directly with strings, especially on older versions of Python.

        ","tags":["PTH206"]},{"location":"rules/os-sep-split/#references","title":"References","text":"
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH206"]},{"location":"rules/os-stat/","title":"os-stat (PTH116)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH116"]},{"location":"rules/os-stat/#what-it-does","title":"What it does","text":"

        Checks for uses of os.stat.

        ","tags":["PTH116"]},{"location":"rules/os-stat/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.stat() can improve readability over the os module's counterparts (e.g., os.path.stat()).

        ","tags":["PTH116"]},{"location":"rules/os-stat/#examples","title":"Examples","text":"
        import os\nfrom pwd import getpwuid\nfrom grp import getgrgid\n\nstat = os.stat(file_name)\nowner_name = getpwuid(stat.st_uid).pw_name\ngroup_name = getgrgid(stat.st_gid).gr_name\n

        Use instead:

        from pathlib import Path\n\nfile_path = Path(file_name)\nstat = file_path.stat()\nowner_name = file_path.owner()\ngroup_name = file_path.group()\n
        ","tags":["PTH116"]},{"location":"rules/os-stat/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH116"]},{"location":"rules/os-stat/#references","title":"References","text":"
        • Python documentation: Path.stat
        • Python documentation: Path.group
        • Python documentation: Path.owner
        • Python documentation: os.stat
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH116"]},{"location":"rules/os-unlink/","title":"os-unlink (PTH108)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH108"]},{"location":"rules/os-unlink/#what-it-does","title":"What it does","text":"

        Checks for uses of os.unlink.

        ","tags":["PTH108"]},{"location":"rules/os-unlink/#why-is-this-bad","title":"Why is this bad?","text":"

        pathlib offers a high-level API for path manipulation, as compared to the lower-level API offered by os. When possible, using Path object methods such as Path.unlink() can improve readability over the os module's counterparts (e.g., os.unlink()).

        ","tags":["PTH108"]},{"location":"rules/os-unlink/#examples","title":"Examples","text":"
        import os\n\nos.unlink(\"file.py\")\n

        Use instead:

        from pathlib import Path\n\nPath(\"file.py\").unlink()\n
        ","tags":["PTH108"]},{"location":"rules/os-unlink/#known-issues","title":"Known issues","text":"

        While using pathlib can improve the readability and type safety of your code, it can be less performant than the lower-level alternatives that work directly with strings, especially on older versions of Python.

        ","tags":["PTH108"]},{"location":"rules/os-unlink/#references","title":"References","text":"
        • Python documentation: Path.unlink
        • Python documentation: os.unlink
        • PEP 428 \u2013 The pathlib module \u2013 object-oriented filesystem paths
        • Correspondence between os and pathlib
        • Why you should be using pathlib
        • No really, pathlib is great
        ","tags":["PTH108"]},{"location":"rules/outdated-version-block/","title":"outdated-version-block (UP036)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#what-it-does","title":"What it does","text":"

        Checks for conditional blocks gated on sys.version_info comparisons that are outdated for the minimum supported Python version.

        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, code can be conditionally executed based on the active Python version by comparing against the sys.version_info tuple.

        If a code block is only executed for Python versions older than the minimum supported version, it should be removed.

        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#example","title":"Example","text":"
        import sys\n\nif sys.version_info < (3, 0):\n    print(\"py2\")\nelse:\n    print(\"py3\")\n

        Use instead:

        print(\"py3\")\n
        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#options","title":"Options","text":"
        • target-version
        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because it will remove all code, comments, and annotations within unreachable version blocks.

        ","tags":["UP036"]},{"location":"rules/outdated-version-block/#references","title":"References","text":"
        • Python documentation: sys.version_info
        ","tags":["UP036"]},{"location":"rules/over-indentation/","title":"over-indentation (D208)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D208"]},{"location":"rules/over-indentation/#what-it-does","title":"What it does","text":"

        Checks for over-indented docstrings.

        ","tags":["D208"]},{"location":"rules/over-indentation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that docstrings be indented to the same level as their opening quotes. Avoid over-indenting docstrings, for consistency.

        ","tags":["D208"]},{"location":"rules/over-indentation/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n        Sort the list in ascending order and return a copy of the result using the\n        bubble sort algorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D208"]},{"location":"rules/over-indentation/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        ","tags":["D208"]},{"location":"rules/over-indentation/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D208"]},{"location":"rules/over-indented/","title":"over-indented (E117)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E117"]},{"location":"rules/over-indented/#what-it-does","title":"What it does","text":"

        Checks for over-indented code.

        ","tags":["E117"]},{"location":"rules/over-indented/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, 4 spaces per indentation level should be preferred. Increased indentation can lead to inconsistent formatting, which can hurt readability.

        ","tags":["E117"]},{"location":"rules/over-indented/#example","title":"Example","text":"
        for item in items:\n      pass\n

        Use instead:

        for item in items:\n    pass\n
        ","tags":["E117"]},{"location":"rules/over-indented/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        ","tags":["E117"]},{"location":"rules/overindented-section-underline/","title":"overindented-section-underline (D215)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D215"]},{"location":"rules/overindented-section-underline/#what-it-does","title":"What it does","text":"

        Checks for over-indented section underlines in docstrings.

        ","tags":["D215"]},{"location":"rules/overindented-section-underline/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for multiline numpy-style docstrings, and helps prevent incorrect syntax in docstrings using reStructuredText.

        Multiline numpy-style docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections. Each section has a section header and a section body, and there should be a series of underline characters in the line following the header. The underline should have the same indentation as the header.

        This rule enforces a consistent style for multiline numpy-style docstrings with sections. If your docstring uses reStructuredText, the rule also helps protect against incorrect reStructuredText syntax, which would cause errors if you tried to use a tool such as Sphinx to generate documentation from the docstring.

        This rule is enabled when using the numpy convention, and disabled when using the google or pep257 conventions.

        ","tags":["D215"]},{"location":"rules/overindented-section-underline/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n        ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n          -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n      ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D215"]},{"location":"rules/overindented-section-underline/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D215"]},{"location":"rules/overindented-section-underline/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        ","tags":["D215"]},{"location":"rules/overindented-section/","title":"overindented-section (D214)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D214"]},{"location":"rules/overindented-section/#what-it-does","title":"What it does","text":"

        Checks for over-indented sections in docstrings.

        ","tags":["D214"]},{"location":"rules/overindented-section/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule enforces a consistent style for docstrings with multiple sections.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. The convention is that all sections should use consistent indentation. In each section, the header should match the indentation of the docstring's opening quotes, and the body should be indented one level further.

        This rule is enabled when using the numpy and google conventions, and disabled when using the pep257 convention.

        ","tags":["D214"]},{"location":"rules/overindented-section/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n        Args:\n            distance: Distance traveled.\n            time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D214"]},{"location":"rules/overindented-section/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D214"]},{"location":"rules/overindented-section/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D214"]},{"location":"rules/overload-with-docstring/","title":"overload-with-docstring (D418)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D418"]},{"location":"rules/overload-with-docstring/#what-it-does","title":"What it does","text":"

        Checks for @overload function definitions that contain a docstring.

        ","tags":["D418"]},{"location":"rules/overload-with-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        The @overload decorator is used to define multiple compatible signatures for a given function, to support type-checking. A series of @overload definitions should be followed by a single non-decorated definition that contains the implementation of the function.

        @overload function definitions should not contain a docstring; instead, the docstring should be placed on the non-decorated definition that contains the implementation.

        ","tags":["D418"]},{"location":"rules/overload-with-docstring/#example","title":"Example","text":"
        from typing import overload\n\n\n@overload\ndef factorial(n: int) -> int:\n    \"\"\"Return the factorial of n.\"\"\"\n\n\n@overload\ndef factorial(n: float) -> float:\n    \"\"\"Return the factorial of n.\"\"\"\n\n\ndef factorial(n):\n    \"\"\"Return the factorial of n.\"\"\"\n\n\nfactorial.__doc__  # \"Return the factorial of n.\"\n

        Use instead:

        from typing import overload\n\n\n@overload\ndef factorial(n: int) -> int: ...\n\n\n@overload\ndef factorial(n: float) -> float: ...\n\n\ndef factorial(n):\n    \"\"\"Return the factorial of n.\"\"\"\n\n\nfactorial.__doc__  # \"Return the factorial of n.\"\n
        ","tags":["D418"]},{"location":"rules/overload-with-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • Python documentation: typing.overload
        ","tags":["D418"]},{"location":"rules/p-print/","title":"p-print (T203)","text":"

        Derived from the flake8-print linter.

        Fix is sometimes available.

        ","tags":["T203"]},{"location":"rules/p-print/#what-it-does","title":"What it does","text":"

        Checks for pprint statements.

        ","tags":["T203"]},{"location":"rules/p-print/#why-is-this-bad","title":"Why is this bad?","text":"

        Like print statements, pprint statements used for debugging should be omitted from production code. They can lead the accidental inclusion of sensitive information in logs, and are not configurable by clients, unlike logging statements.

        pprint statements used to produce output as a part of a command-line interface program are not typically a problem.

        ","tags":["T203"]},{"location":"rules/p-print/#example","title":"Example","text":"
        import pprint\n\n\ndef merge_dicts(dict_a, dict_b):\n    dict_c = {**dict_a, **dict_b}\n    pprint.pprint(dict_c)\n    return dict_c\n

        Use instead:

        def merge_dicts(dict_a, dict_b):\n    dict_c = {**dict_a, **dict_b}\n    return dict_c\n
        ","tags":["T203"]},{"location":"rules/p-print/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it will remove pprint statements that are used beyond debugging purposes.

        ","tags":["T203"]},{"location":"rules/pandas-df-variable-name/","title":"pandas-df-variable-name (PD901)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD901"]},{"location":"rules/pandas-df-variable-name/#what-it-does","title":"What it does","text":"

        Checks for assignments to the variable df.

        ","tags":["PD901"]},{"location":"rules/pandas-df-variable-name/#why-is-this-bad","title":"Why is this bad?","text":"

        Although df is a common variable name for a Pandas DataFrame, it's not a great variable name for production code, as it's non-descriptive and prone to name conflicts.

        Instead, use a more descriptive variable name.

        ","tags":["PD901"]},{"location":"rules/pandas-df-variable-name/#example","title":"Example","text":"
        import pandas as pd\n\ndf = pd.read_csv(\"animals.csv\")\n

        Use instead:

        import pandas as pd\n\nanimals = pd.read_csv(\"animals.csv\")\n
        ","tags":["PD901"]},{"location":"rules/pandas-nunique-constant-series-check/","title":"pandas-nunique-constant-series-check (PD101)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD101"]},{"location":"rules/pandas-nunique-constant-series-check/#what-it-does","title":"What it does","text":"

        Check for uses of .nunique() to check if a Pandas Series is constant (i.e., contains only one unique value).

        ","tags":["PD101"]},{"location":"rules/pandas-nunique-constant-series-check/#why-is-this-bad","title":"Why is this bad?","text":"

        .nunique() is computationally inefficient for checking if a Series is constant.

        Consider, for example, a Series of length n that consists of increasing integer values (e.g., 1, 2, 3, 4). The .nunique() method will iterate over the entire Series to count the number of unique values. But in this case, we can detect that the Series is non-constant after visiting the first two values, which are non-equal.

        In general, .nunique() requires iterating over the entire Series, while a more efficient approach allows short-circuiting the operation as soon as a non-equal value is found.

        Instead of calling .nunique(), convert the Series to a NumPy array, and check if all values in the array are equal to the first observed value.

        ","tags":["PD101"]},{"location":"rules/pandas-nunique-constant-series-check/#example","title":"Example","text":"
        import pandas as pd\n\ndata = pd.Series(range(1000))\nif data.nunique() <= 1:\n    print(\"Series is constant\")\n

        Use instead:

        import pandas as pd\n\ndata = pd.Series(range(1000))\narray = data.to_numpy()\nif array.shape[0] == 0 or (array[0] == array).all():\n    print(\"Series is constant\")\n
        ","tags":["PD101"]},{"location":"rules/pandas-nunique-constant-series-check/#references","title":"References","text":"
        • Pandas Cookbook: \"Constant Series\"
        • Pandas documentation: nunique
        ","tags":["PD101"]},{"location":"rules/pandas-use-of-dot-at/","title":"pandas-use-of-dot-at (PD008)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD008"]},{"location":"rules/pandas-use-of-dot-at/#what-it-does","title":"What it does","text":"

        Checks for uses of .at on Pandas objects.

        ","tags":["PD008"]},{"location":"rules/pandas-use-of-dot-at/#why-is-this-bad","title":"Why is this bad?","text":"

        The .at method selects a single value from a DataFrame or Series based on a label index, and is slightly faster than using .loc. However, .loc is more idiomatic and versatile, as it can be used to select multiple values at once.

        If performance is an important consideration, convert the object to a NumPy array, which will provide a much greater performance boost than using .at over .loc.

        ","tags":["PD008"]},{"location":"rules/pandas-use-of-dot-at/#example","title":"Example","text":"
        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.at[\"Maria\"]\n

        Use instead:

        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.loc[\"Maria\"]\n
        ","tags":["PD008"]},{"location":"rules/pandas-use-of-dot-at/#references","title":"References","text":"
        • Pandas documentation: loc
        • Pandas documentation: at
        ","tags":["PD008"]},{"location":"rules/pandas-use-of-dot-iat/","title":"pandas-use-of-dot-iat (PD009)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD009"]},{"location":"rules/pandas-use-of-dot-iat/#what-it-does","title":"What it does","text":"

        Checks for uses of .iat on Pandas objects.

        ","tags":["PD009"]},{"location":"rules/pandas-use-of-dot-iat/#why-is-this-bad","title":"Why is this bad?","text":"

        The .iat method selects a single value from a DataFrame or Series based on an ordinal index, and is slightly faster than using .iloc. However, .iloc is more idiomatic and versatile, as it can be used to select multiple values at once.

        If performance is an important consideration, convert the object to a NumPy array, which will provide a much greater performance boost than using .iat over .iloc.

        ","tags":["PD009"]},{"location":"rules/pandas-use-of-dot-iat/#example","title":"Example","text":"
        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.iat[0]\n

        Use instead:

        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.iloc[0]\n

        Or, using NumPy:

        import numpy as np\nimport pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.to_numpy()[0]\n
        ","tags":["PD009"]},{"location":"rules/pandas-use-of-dot-iat/#references","title":"References","text":"
        • Pandas documentation: iloc
        • Pandas documentation: iat
        ","tags":["PD009"]},{"location":"rules/pandas-use-of-dot-is-null/","title":"pandas-use-of-dot-is-null (PD003)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD003"]},{"location":"rules/pandas-use-of-dot-is-null/#what-it-does","title":"What it does","text":"

        Checks for uses of .isnull on Pandas objects.

        ","tags":["PD003"]},{"location":"rules/pandas-use-of-dot-is-null/#why-is-this-bad","title":"Why is this bad?","text":"

        In the Pandas API, .isna and .isnull are equivalent. For consistency, prefer .isna over .isnull.

        As a name, .isna more accurately reflects the behavior of the method, since these methods check for NaN and NaT values in addition to None values.

        ","tags":["PD003"]},{"location":"rules/pandas-use-of-dot-is-null/#example","title":"Example","text":"
        import pandas as pd\n\nanimals_df = pd.read_csv(\"animals.csv\")\npd.isnull(animals_df)\n

        Use instead:

        import pandas as pd\n\nanimals_df = pd.read_csv(\"animals.csv\")\npd.isna(animals_df)\n
        ","tags":["PD003"]},{"location":"rules/pandas-use-of-dot-is-null/#references","title":"References","text":"
        • Pandas documentation: isnull
        • Pandas documentation: isna
        ","tags":["PD003"]},{"location":"rules/pandas-use-of-dot-ix/","title":"pandas-use-of-dot-ix (PD007)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD007"]},{"location":"rules/pandas-use-of-dot-ix/#what-it-does","title":"What it does","text":"

        Checks for uses of .ix on Pandas objects.

        ","tags":["PD007"]},{"location":"rules/pandas-use-of-dot-ix/#why-is-this-bad","title":"Why is this bad?","text":"

        The .ix method is deprecated as its behavior is ambiguous. Specifically, it's often unclear whether .ix is indexing by label or by ordinal position.

        Instead, prefer the .loc method for label-based indexing, and .iloc for ordinal indexing.

        ","tags":["PD007"]},{"location":"rules/pandas-use-of-dot-ix/#example","title":"Example","text":"
        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.ix[0]  # 0th row or row with label 0?\n

        Use instead:

        import pandas as pd\n\nstudents_df = pd.read_csv(\"students.csv\")\nstudents_df.iloc[0]  # 0th row.\n
        ","tags":["PD007"]},{"location":"rules/pandas-use-of-dot-ix/#references","title":"References","text":"
        • Pandas release notes: Deprecate .ix
        • Pandas documentation: loc
        • Pandas documentation: iloc
        ","tags":["PD007"]},{"location":"rules/pandas-use-of-dot-not-null/","title":"pandas-use-of-dot-not-null (PD004)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD004"]},{"location":"rules/pandas-use-of-dot-not-null/#what-it-does","title":"What it does","text":"

        Checks for uses of .notnull on Pandas objects.

        ","tags":["PD004"]},{"location":"rules/pandas-use-of-dot-not-null/#why-is-this-bad","title":"Why is this bad?","text":"

        In the Pandas API, .notna and .notnull are equivalent. For consistency, prefer .notna over .notnull.

        As a name, .notna more accurately reflects the behavior of the method, since these methods check for NaN and NaT values in addition to None values.

        ","tags":["PD004"]},{"location":"rules/pandas-use-of-dot-not-null/#example","title":"Example","text":"
        import pandas as pd\n\nanimals_df = pd.read_csv(\"animals.csv\")\npd.notnull(animals_df)\n

        Use instead:

        import pandas as pd\n\nanimals_df = pd.read_csv(\"animals.csv\")\npd.notna(animals_df)\n
        ","tags":["PD004"]},{"location":"rules/pandas-use-of-dot-not-null/#references","title":"References","text":"
        • Pandas documentation: notnull
        • Pandas documentation: notna
        ","tags":["PD004"]},{"location":"rules/pandas-use-of-dot-pivot-or-unstack/","title":"pandas-use-of-dot-pivot-or-unstack (PD010)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD010"]},{"location":"rules/pandas-use-of-dot-pivot-or-unstack/#what-it-does","title":"What it does","text":"

        Checks for uses of .pivot or .unstack on Pandas objects.

        ","tags":["PD010"]},{"location":"rules/pandas-use-of-dot-pivot-or-unstack/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefer .pivot_table to .pivot or .unstack. .pivot_table is more general and can be used to implement the same behavior as .pivot and .unstack.

        ","tags":["PD010"]},{"location":"rules/pandas-use-of-dot-pivot-or-unstack/#example","title":"Example","text":"
        import pandas as pd\n\ndf = pd.read_csv(\"cities.csv\")\ndf.pivot(index=\"city\", columns=\"year\", values=\"population\")\n

        Use instead:

        import pandas as pd\n\ndf = pd.read_csv(\"cities.csv\")\ndf.pivot_table(index=\"city\", columns=\"year\", values=\"population\")\n
        ","tags":["PD010"]},{"location":"rules/pandas-use-of-dot-pivot-or-unstack/#references","title":"References","text":"
        • Pandas documentation: Reshaping and pivot tables
        • Pandas documentation: pivot_table
        ","tags":["PD010"]},{"location":"rules/pandas-use-of-dot-read-table/","title":"pandas-use-of-dot-read-table (PD012)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD012"]},{"location":"rules/pandas-use-of-dot-read-table/#what-it-does","title":"What it does","text":"

        Checks for uses of pd.read_table to read CSV files.

        ","tags":["PD012"]},{"location":"rules/pandas-use-of-dot-read-table/#why-is-this-bad","title":"Why is this bad?","text":"

        In the Pandas API, pd.read_csv and pd.read_table are equivalent apart from their default separator: pd.read_csv defaults to a comma (,), while pd.read_table defaults to a tab (\\t) as the default separator.

        Prefer pd.read_csv over pd.read_table when reading comma-separated data (like CSV files), as it is more idiomatic.

        ","tags":["PD012"]},{"location":"rules/pandas-use-of-dot-read-table/#example","title":"Example","text":"
        import pandas as pd\n\ncities_df = pd.read_table(\"cities.csv\", sep=\",\")\n

        Use instead:

        import pandas as pd\n\ncities_df = pd.read_csv(\"cities.csv\")\n
        ","tags":["PD012"]},{"location":"rules/pandas-use-of-dot-read-table/#references","title":"References","text":"
        • Pandas documentation: read_csv
        • Pandas documentation: read_table
        ","tags":["PD012"]},{"location":"rules/pandas-use-of-dot-stack/","title":"pandas-use-of-dot-stack (PD013)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD013"]},{"location":"rules/pandas-use-of-dot-stack/#what-it-does","title":"What it does","text":"

        Checks for uses of .stack on Pandas objects.

        ","tags":["PD013"]},{"location":"rules/pandas-use-of-dot-stack/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefer .melt to .stack, which has the same functionality but with support for direct column renaming and no dependence on MultiIndex.

        ","tags":["PD013"]},{"location":"rules/pandas-use-of-dot-stack/#example","title":"Example","text":"
        import pandas as pd\n\ncities_df = pd.read_csv(\"cities.csv\")\ncities_df.set_index(\"city\").stack()\n

        Use instead:

        import pandas as pd\n\ncities_df = pd.read_csv(\"cities.csv\")\ncities_df.melt(id_vars=\"city\")\n
        ","tags":["PD013"]},{"location":"rules/pandas-use-of-dot-stack/#references","title":"References","text":"
        • Pandas documentation: melt
        • Pandas documentation: stack
        ","tags":["PD013"]},{"location":"rules/pandas-use-of-dot-values/","title":"pandas-use-of-dot-values (PD011)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD011"]},{"location":"rules/pandas-use-of-dot-values/#what-it-does","title":"What it does","text":"

        Checks for uses of .values on Pandas Series and Index objects.

        ","tags":["PD011"]},{"location":"rules/pandas-use-of-dot-values/#why-is-this-bad","title":"Why is this bad?","text":"

        The .values attribute is ambiguous as its return type is unclear. As such, it is no longer recommended by the Pandas documentation.

        Instead, use .to_numpy() to return a NumPy array, or .array to return a Pandas ExtensionArray.

        ","tags":["PD011"]},{"location":"rules/pandas-use-of-dot-values/#example","title":"Example","text":"
        import pandas as pd\n\nanimals = pd.read_csv(\"animals.csv\").values  # Ambiguous.\n

        Use instead:

        import pandas as pd\n\nanimals = pd.read_csv(\"animals.csv\").to_numpy()  # Explicit.\n
        ","tags":["PD011"]},{"location":"rules/pandas-use-of-dot-values/#references","title":"References","text":"
        • Pandas documentation: Accessing the values in a Series or Index
        ","tags":["PD011"]},{"location":"rules/pandas-use-of-inplace-argument/","title":"pandas-use-of-inplace-argument (PD002)","text":"

        Derived from the pandas-vet linter.

        Fix is sometimes available.

        ","tags":["PD002"]},{"location":"rules/pandas-use-of-inplace-argument/#what-it-does","title":"What it does","text":"

        Checks for inplace=True usages in pandas function and method calls.

        ","tags":["PD002"]},{"location":"rules/pandas-use-of-inplace-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Using inplace=True encourages mutation rather than immutable data, which is harder to reason about and may cause bugs. It also removes the ability to use the method chaining style for pandas operations.

        Further, in many cases, inplace=True does not provide a performance benefit, as pandas will often copy DataFrames in the background.

        ","tags":["PD002"]},{"location":"rules/pandas-use-of-inplace-argument/#example","title":"Example","text":"
        df.sort_values(\"col1\", inplace=True)\n

        Use instead:

        sorted_df = df.sort_values(\"col1\")\n
        ","tags":["PD002"]},{"location":"rules/pandas-use-of-inplace-argument/#references","title":"References","text":"
        • Why You Should Probably Never Use pandas inplace=True
        ","tags":["PD002"]},{"location":"rules/pandas-use-of-pd-merge/","title":"pandas-use-of-pd-merge (PD015)","text":"

        Derived from the pandas-vet linter.

        ","tags":["PD015"]},{"location":"rules/pandas-use-of-pd-merge/#what-it-does","title":"What it does","text":"

        Checks for uses of pd.merge on Pandas objects.

        ","tags":["PD015"]},{"location":"rules/pandas-use-of-pd-merge/#why-is-this-bad","title":"Why is this bad?","text":"

        In Pandas, the .merge method (exposed on, e.g., DataFrame objects) and the pd.merge function (exposed on the Pandas module) are equivalent.

        For consistency, prefer calling .merge on an object over calling pd.merge on the Pandas module, as the former is more idiomatic.

        Further, pd.merge is not a method, but a function, which prohibits it from being used in method chains, a common pattern in Pandas code.

        ","tags":["PD015"]},{"location":"rules/pandas-use-of-pd-merge/#example","title":"Example","text":"
        import pandas as pd\n\ncats_df = pd.read_csv(\"cats.csv\")\ndogs_df = pd.read_csv(\"dogs.csv\")\nrabbits_df = pd.read_csv(\"rabbits.csv\")\npets_df = pd.merge(pd.merge(cats_df, dogs_df), rabbits_df)  # Hard to read.\n

        Use instead:

        import pandas as pd\n\ncats_df = pd.read_csv(\"cats.csv\")\ndogs_df = pd.read_csv(\"dogs.csv\")\nrabbits_df = pd.read_csv(\"rabbits.csv\")\npets_df = cats_df.merge(dogs_df).merge(rabbits_df)\n
        ","tags":["PD015"]},{"location":"rules/pandas-use-of-pd-merge/#references","title":"References","text":"
        • Pandas documentation: merge
        • Pandas documentation: pd.merge
        ","tags":["PD015"]},{"location":"rules/paramiko-call/","title":"paramiko-call (S601)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S601"]},{"location":"rules/paramiko-call/#what-it-does","title":"What it does","text":"

        Checks for paramiko calls.

        ","tags":["S601"]},{"location":"rules/paramiko-call/#why-is-this-bad","title":"Why is this bad?","text":"

        paramiko calls allow users to execute arbitrary shell commands on a remote machine. If the inputs to these calls are not properly sanitized, they can be vulnerable to shell injection attacks.

        ","tags":["S601"]},{"location":"rules/paramiko-call/#example","title":"Example","text":"
        import paramiko\n\nclient = paramiko.SSHClient()\nclient.exec_command(\"echo $HOME\")\n
        ","tags":["S601"]},{"location":"rules/paramiko-call/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-78
        • Paramiko documentation: SSHClient.exec_command()
        ","tags":["S601"]},{"location":"rules/parenthesize-chained-operators/","title":"parenthesize-chained-operators (RUF021)","text":"

        Fix is always available.

        ","tags":["RUF021"]},{"location":"rules/parenthesize-chained-operators/#what-it-does","title":"What it does","text":"

        Checks for chained operators where adding parentheses could improve the clarity of the code.

        ","tags":["RUF021"]},{"location":"rules/parenthesize-chained-operators/#why-is-this-bad","title":"Why is this bad?","text":"

        and always binds more tightly than or when chaining the two together, but this can be hard to remember (and sometimes surprising). Adding parentheses in these situations can greatly improve code readability, with no change to semantics or performance.

        For example:

        a, b, c = 1, 0, 2\nx = a or b and c\n\nd, e, f = 0, 1, 2\ny = d and e or f\n

        Use instead:

        a, b, c = 1, 0, 2\nx = a or (b and c)\n\nd, e, f = 0, 1, 2\ny = (d and e) or f\n
        ","tags":["RUF021"]},{"location":"rules/pass-in-class-body/","title":"pass-in-class-body (PYI012)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI012"]},{"location":"rules/pass-in-class-body/#what-it-does","title":"What it does","text":"

        Checks for the presence of the pass statement in non-empty class bodies in .pyi files.

        ","tags":["PYI012"]},{"location":"rules/pass-in-class-body/#why-is-this-bad","title":"Why is this bad?","text":"

        The pass statement is always unnecessary in non-empty class bodies in stubs.

        ","tags":["PYI012"]},{"location":"rules/pass-in-class-body/#example","title":"Example","text":"
        class MyClass:\n    x: int\n    pass\n

        Use instead:

        class MyClass:\n    x: int\n
        ","tags":["PYI012"]},{"location":"rules/pass-statement-stub-body/","title":"pass-statement-stub-body (PYI009)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI009"]},{"location":"rules/pass-statement-stub-body/#what-it-does","title":"What it does","text":"

        Checks for pass statements in empty stub bodies.

        ","tags":["PYI009"]},{"location":"rules/pass-statement-stub-body/#why-is-this-bad","title":"Why is this bad?","text":"

        For stylistic consistency, ... should always be used rather than pass in stub files.

        ","tags":["PYI009"]},{"location":"rules/pass-statement-stub-body/#example","title":"Example","text":"
        def foo(bar: int) -> list[int]: pass\n

        Use instead:

        def foo(bar: int) -> list[int]: ...\n
        ","tags":["PYI009"]},{"location":"rules/pass-statement-stub-body/#references","title":"References","text":"
        • Typing documentation - Writing and Maintaining Stub Files
        ","tags":["PYI009"]},{"location":"rules/patch-version-comparison/","title":"patch-version-comparison (PYI004)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI004"]},{"location":"rules/patch-version-comparison/#what-it-does","title":"What it does","text":"

        Checks for Python version comparisons in stubs that compare against patch versions (e.g., Python 3.8.3) instead of major and minor versions (e.g., Python 3.8).

        ","tags":["PYI004"]},{"location":"rules/patch-version-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files support simple conditionals to test for differences in Python versions and platforms. However, type checkers only understand a limited subset of these conditionals. In particular, type checkers don't support patch versions (e.g., Python 3.8.3), only major and minor versions (e.g., Python 3.8). Therefore, version checks in stubs should only use the major and minor versions.

        ","tags":["PYI004"]},{"location":"rules/patch-version-comparison/#example","title":"Example","text":"
        import sys\n\nif sys.version_info >= (3, 4, 3): ...\n

        Use instead:

        import sys\n\nif sys.version_info >= (3, 4): ...\n
        ","tags":["PYI004"]},{"location":"rules/patch-version-comparison/#references","title":"References","text":"
        • Typing documentation: Version and Platform checking
        ","tags":["PYI004"]},{"location":"rules/path-constructor-current-directory/","title":"path-constructor-current-directory (PTH201)","text":"

        Derived from the flake8-use-pathlib linter.

        Fix is always available.

        ","tags":["PTH201"]},{"location":"rules/path-constructor-current-directory/#what-it-does","title":"What it does","text":"

        Checks for pathlib.Path objects that are initialized with the current directory.

        ","tags":["PTH201"]},{"location":"rules/path-constructor-current-directory/#why-is-this-bad","title":"Why is this bad?","text":"

        The Path() constructor defaults to the current directory, so passing it in explicitly (as \".\") is unnecessary.

        ","tags":["PTH201"]},{"location":"rules/path-constructor-current-directory/#example","title":"Example","text":"
        from pathlib import Path\n\n_ = Path(\".\")\n

        Use instead:

        from pathlib import Path\n\n_ = Path()\n
        ","tags":["PTH201"]},{"location":"rules/path-constructor-current-directory/#references","title":"References","text":"
        • Python documentation: Path
        ","tags":["PTH201"]},{"location":"rules/pep484-style-positional-only-parameter/","title":"pep484-style-positional-only-parameter (PYI063)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI063"]},{"location":"rules/pep484-style-positional-only-parameter/#what-it-does","title":"What it does","text":"

        Checks for the presence of PEP 484-style positional-only parameters.

        ","tags":["PYI063"]},{"location":"rules/pep484-style-positional-only-parameter/#why-is-this-bad","title":"Why is this bad?","text":"

        Historically, PEP 484 recommended prefixing parameter names with double underscores (__) to indicate to a type checker that they were positional-only. However, PEP 570 (introduced in Python 3.8) introduced dedicated syntax for positional-only arguments. If a forward slash (/) is present in a function signature on Python 3.8+, all parameters prior to the slash are interpreted as positional-only.

        The new syntax should be preferred as it is more widely used, more concise and more readable. It is also respected by Python at runtime, whereas the old-style syntax was only understood by type checkers.

        ","tags":["PYI063"]},{"location":"rules/pep484-style-positional-only-parameter/#example","title":"Example","text":"
        def foo(__x: int) -> None: ...\n

        Use instead:

        def foo(x: int, /) -> None: ...\n
        ","tags":["PYI063"]},{"location":"rules/pep484-style-positional-only-parameter/#options","title":"Options","text":"
        • target-version
        ","tags":["PYI063"]},{"location":"rules/percent-format-expected-mapping/","title":"percent-format-expected-mapping (F502)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F502"]},{"location":"rules/percent-format-expected-mapping/#what-it-does","title":"What it does","text":"

        Checks for named placeholders in printf-style format strings without mapping-type values.

        ","tags":["F502"]},{"location":"rules/percent-format-expected-mapping/#why-is-this-bad","title":"Why is this bad?","text":"

        When using named placeholders in printf-style format strings, the values must be a map type (such as a dictionary). Otherwise, the expression will raise a TypeError.

        ","tags":["F502"]},{"location":"rules/percent-format-expected-mapping/#example","title":"Example","text":"
        \"%(greeting)s, %(name)s\" % (\"Hello\", \"World\")\n

        Use instead:

        \"%(greeting)s, %(name)s\" % {\"greeting\": \"Hello\", \"name\": \"World\"}\n

        Or:

        \"%s, %s\" % (\"Hello\", \"World\")\n
        ","tags":["F502"]},{"location":"rules/percent-format-expected-mapping/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F502"]},{"location":"rules/percent-format-expected-sequence/","title":"percent-format-expected-sequence (F503)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F503"]},{"location":"rules/percent-format-expected-sequence/#what-it-does","title":"What it does","text":"

        Checks for uses of mapping-type values in printf-style format strings without named placeholders.

        ","tags":["F503"]},{"location":"rules/percent-format-expected-sequence/#why-is-this-bad","title":"Why is this bad?","text":"

        When using mapping-type values (such as dict) in printf-style format strings, the keys must be named. Otherwise, the expression will raise a TypeError.

        ","tags":["F503"]},{"location":"rules/percent-format-expected-sequence/#example","title":"Example","text":"
        \"%s, %s\" % {\"greeting\": \"Hello\", \"name\": \"World\"}\n

        Use instead:

        \"%(greeting)s, %(name)s\" % {\"greeting\": \"Hello\", \"name\": \"World\"}\n

        Or:

        \"%s, %s\" % (\"Hello\", \"World\")\n
        ","tags":["F503"]},{"location":"rules/percent-format-expected-sequence/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F503"]},{"location":"rules/percent-format-extra-named-arguments/","title":"percent-format-extra-named-arguments (F504)","text":"

        Derived from the Pyflakes linter.

        Fix is always available.

        ","tags":["F504"]},{"location":"rules/percent-format-extra-named-arguments/#what-it-does","title":"What it does","text":"

        Checks for unused mapping keys in printf-style format strings.

        ","tags":["F504"]},{"location":"rules/percent-format-extra-named-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused named placeholders in printf-style format strings are unnecessary, and likely indicative of a mistake. They should be removed.

        ","tags":["F504"]},{"location":"rules/percent-format-extra-named-arguments/#example","title":"Example","text":"
        \"Hello, %(name)s\" % {\"greeting\": \"Hello\", \"name\": \"World\"}\n

        Use instead:

        \"Hello, %(name)s\" % {\"name\": \"World\"}\n
        ","tags":["F504"]},{"location":"rules/percent-format-extra-named-arguments/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F504"]},{"location":"rules/percent-format-invalid-format/","title":"percent-format-invalid-format (F501)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F501"]},{"location":"rules/percent-format-invalid-format/#what-it-does","title":"What it does","text":"

        Checks for invalid printf-style format strings.

        ","tags":["F501"]},{"location":"rules/percent-format-invalid-format/#why-is-this-bad","title":"Why is this bad?","text":"

        Conversion specifiers are required for printf-style format strings. These specifiers must contain a % character followed by a conversion type.

        ","tags":["F501"]},{"location":"rules/percent-format-invalid-format/#example","title":"Example","text":"
        \"Hello, %\" % \"world\"\n

        Use instead:

        \"Hello, %s\" % \"world\"\n
        ","tags":["F501"]},{"location":"rules/percent-format-invalid-format/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F501"]},{"location":"rules/percent-format-missing-argument/","title":"percent-format-missing-argument (F505)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F505"]},{"location":"rules/percent-format-missing-argument/#what-it-does","title":"What it does","text":"

        Checks for named placeholders in printf-style format strings that are not present in the provided mapping.

        ","tags":["F505"]},{"location":"rules/percent-format-missing-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Named placeholders that lack a corresponding value in the provided mapping will raise a KeyError.

        ","tags":["F505"]},{"location":"rules/percent-format-missing-argument/#example","title":"Example","text":"
        \"%(greeting)s, %(name)s\" % {\"name\": \"world\"}\n

        Use instead:

        \"Hello, %(name)s\" % {\"name\": \"world\"}\n
        ","tags":["F505"]},{"location":"rules/percent-format-missing-argument/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F505"]},{"location":"rules/percent-format-mixed-positional-and-named/","title":"percent-format-mixed-positional-and-named (F506)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F506"]},{"location":"rules/percent-format-mixed-positional-and-named/#what-it-does","title":"What it does","text":"

        Checks for printf-style format strings that have mixed positional and named placeholders.

        ","tags":["F506"]},{"location":"rules/percent-format-mixed-positional-and-named/#why-is-this-bad","title":"Why is this bad?","text":"

        Python does not support mixing positional and named placeholders in printf-style format strings. The use of mixed placeholders will raise a TypeError at runtime.

        ","tags":["F506"]},{"location":"rules/percent-format-mixed-positional-and-named/#example","title":"Example","text":"
        \"%s, %(name)s\" % (\"Hello\", {\"name\": \"World\"})\n

        Use instead:

        \"%s, %s\" % (\"Hello\", \"World\")\n

        Or:

        \"%(greeting)s, %(name)s\" % {\"greeting\": \"Hello\", \"name\": \"World\"}\n
        ","tags":["F506"]},{"location":"rules/percent-format-mixed-positional-and-named/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F506"]},{"location":"rules/percent-format-positional-count-mismatch/","title":"percent-format-positional-count-mismatch (F507)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F507"]},{"location":"rules/percent-format-positional-count-mismatch/#what-it-does","title":"What it does","text":"

        Checks for printf-style format strings that have a mismatch between the number of positional placeholders and the number of substitution values.

        ","tags":["F507"]},{"location":"rules/percent-format-positional-count-mismatch/#why-is-this-bad","title":"Why is this bad?","text":"

        When a printf-style format string is provided with too many or too few substitution values, it will raise a TypeError at runtime.

        ","tags":["F507"]},{"location":"rules/percent-format-positional-count-mismatch/#example","title":"Example","text":"
        \"%s, %s\" % (\"Hello\", \"world\", \"!\")\n

        Use instead:

        \"%s, %s\" % (\"Hello\", \"world\")\n
        ","tags":["F507"]},{"location":"rules/percent-format-positional-count-mismatch/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F507"]},{"location":"rules/percent-format-star-requires-sequence/","title":"percent-format-star-requires-sequence (F508)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F508"]},{"location":"rules/percent-format-star-requires-sequence/#what-it-does","title":"What it does","text":"

        Checks for printf-style format strings that use the * specifier with non-tuple values.

        ","tags":["F508"]},{"location":"rules/percent-format-star-requires-sequence/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of the * specifier with non-tuple values will raise a TypeError at runtime.

        ","tags":["F508"]},{"location":"rules/percent-format-star-requires-sequence/#example","title":"Example","text":"
        from math import pi\n\n\"%(n).*f\" % {\"n\": (2, pi)}\n

        Use instead:

        from math import pi\n\n\"%.*f\" % (2, pi)  # 3.14\n
        ","tags":["F508"]},{"location":"rules/percent-format-star-requires-sequence/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F508"]},{"location":"rules/percent-format-unsupported-format-character/","title":"percent-format-unsupported-format-character (F509)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F509"]},{"location":"rules/percent-format-unsupported-format-character/#what-it-does","title":"What it does","text":"

        Checks for printf-style format strings with invalid format characters.

        ","tags":["F509"]},{"location":"rules/percent-format-unsupported-format-character/#why-is-this-bad","title":"Why is this bad?","text":"

        In printf-style format strings, the % character is used to indicate placeholders. If a % character is not followed by a valid format character, it will raise a ValueError at runtime.

        ","tags":["F509"]},{"location":"rules/percent-format-unsupported-format-character/#example","title":"Example","text":"
        \"Hello, %S\" % \"world\"\n

        Use instead:

        \"Hello, %s\" % \"world\"\n
        ","tags":["F509"]},{"location":"rules/percent-format-unsupported-format-character/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        ","tags":["F509"]},{"location":"rules/post-init-default/","title":"post-init-default (RUF033)","text":"

        Fix is sometimes available.

        ","tags":["RUF033"]},{"location":"rules/post-init-default/#what-it-does","title":"What it does","text":"

        Checks for __post_init__ dataclass methods with parameter defaults.

        ","tags":["RUF033"]},{"location":"rules/post-init-default/#why-is-this-bad","title":"Why is this bad?","text":"

        Adding a default value to a parameter in a __post_init__ method has no impact on whether the parameter will have a default value in the dataclass's generated __init__ method. To create an init-only dataclass parameter with a default value, you should use an InitVar field in the dataclass's class body and give that InitVar field a default value.

        As the documentation states:

        Init-only fields are added as parameters to the generated __init__() method, and are passed to the optional __post_init__() method. They are not otherwise used by dataclasses.

        ","tags":["RUF033"]},{"location":"rules/post-init-default/#example","title":"Example","text":"
        from dataclasses import InitVar, dataclass\n\n\n@dataclass\nclass Foo:\n    bar: InitVar[int] = 0\n\n    def __post_init__(self, bar: int = 1, baz: int = 2) -> None:\n        print(bar, baz)\n\n\nfoo = Foo()  # Prints '0 2'.\n

        Use instead:

        from dataclasses import InitVar, dataclass\n\n\n@dataclass\nclass Foo:\n    bar: InitVar[int] = 1\n    baz: InitVar[int] = 2\n\n    def __post_init__(self, bar: int, baz: int) -> None:\n        print(bar, baz)\n\n\nfoo = Foo()  # Prints '1 2'.\n
        ","tags":["RUF033"]},{"location":"rules/post-init-default/#fix-safety","title":"Fix safety","text":"

        This fix is always marked as unsafe because, although switching to InitVar is usually correct, it is incorrect when the parameter is not intended to be part of the public API or when the value is meant to be shared across all instances.

        ","tags":["RUF033"]},{"location":"rules/post-init-default/#references","title":"References","text":"
        • Python documentation: Post-init processing
        • Python documentation: Init-only variables
        ","tags":["RUF033"]},{"location":"rules/potential-index-error/","title":"potential-index-error (PLE0643)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0643"]},{"location":"rules/potential-index-error/#what-it-does","title":"What it does","text":"

        Checks for hard-coded sequence accesses that are known to be out of bounds.

        ","tags":["PLE0643"]},{"location":"rules/potential-index-error/#why-is-this-bad","title":"Why is this bad?","text":"

        Attempting to access a sequence with an out-of-bounds index will cause an IndexError to be raised at runtime. When the sequence and index are defined statically (e.g., subscripts on list and tuple literals, with integer indexes), such errors can be detected ahead of time.

        ","tags":["PLE0643"]},{"location":"rules/potential-index-error/#example","title":"Example","text":"
        print([0, 1, 2][3])\n
        ","tags":["PLE0643"]},{"location":"rules/print-empty-string/","title":"print-empty-string (FURB105)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB105"]},{"location":"rules/print-empty-string/#what-it-does","title":"What it does","text":"

        Checks for print calls with unnecessary empty strings as positional arguments and unnecessary sep keyword arguments.

        ","tags":["FURB105"]},{"location":"rules/print-empty-string/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefer calling print without any positional arguments, which is equivalent and more concise.

        Similarly, when printing one or fewer items, the sep keyword argument, (used to define the string that separates the print arguments) can be omitted, as it's redundant when there are no items to separate.

        ","tags":["FURB105"]},{"location":"rules/print-empty-string/#example","title":"Example","text":"
        print(\"\")\n

        Use instead:

        print()\n
        ","tags":["FURB105"]},{"location":"rules/print-empty-string/#references","title":"References","text":"
        • Python documentation: print
        ","tags":["FURB105"]},{"location":"rules/print/","title":"print (T201)","text":"

        Derived from the flake8-print linter.

        Fix is sometimes available.

        ","tags":["T201"]},{"location":"rules/print/#what-it-does","title":"What it does","text":"

        Checks for print statements.

        ","tags":["T201"]},{"location":"rules/print/#why-is-this-bad","title":"Why is this bad?","text":"

        print statements used for debugging should be omitted from production code. They can lead the accidental inclusion of sensitive information in logs, and are not configurable by clients, unlike logging statements.

        print statements used to produce output as a part of a command-line interface program are not typically a problem.

        ","tags":["T201"]},{"location":"rules/print/#example","title":"Example","text":"
        def sum_less_than_four(a, b):\n    print(f\"Calling sum_less_than_four\")\n    return a + b < 4\n

        The automatic fix will remove the print statement entirely:

        def sum_less_than_four(a, b):\n    return a + b < 4\n

        To keep the line for logging purposes, instead use something like:

        import logging\n\nlogging.basicConfig(level=logging.INFO)\n\n\ndef sum_less_than_four(a, b):\n    logging.debug(\"Calling sum_less_than_four\")\n    return a + b < 4\n
        ","tags":["T201"]},{"location":"rules/print/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it will remove print statements that are used beyond debugging purposes.

        ","tags":["T201"]},{"location":"rules/printf-in-get-text-func-call/","title":"printf-in-get-text-func-call (INT003)","text":"

        Derived from the flake8-gettext linter.

        ","tags":["INT003"]},{"location":"rules/printf-in-get-text-func-call/#what-it-does","title":"What it does","text":"

        Checks for printf-style formatted strings in gettext function calls.

        ","tags":["INT003"]},{"location":"rules/printf-in-get-text-func-call/#why-is-this-bad","title":"Why is this bad?","text":"

        In the gettext API, the gettext function (often aliased to _) returns a translation of its input argument by looking it up in a translation catalog.

        Calling gettext with a formatted string as its argument can cause unexpected behavior. Since the formatted string is resolved before the function call, the translation catalog will look up the formatted string, rather than the printf-style template.

        Instead, format the value returned by the function call, rather than its argument.

        ","tags":["INT003"]},{"location":"rules/printf-in-get-text-func-call/#example","title":"Example","text":"
        from gettext import gettext as _\n\nname = \"Maria\"\n_(\"Hello, %s!\" % name)  # Looks for \"Hello, Maria!\".\n

        Use instead:

        from gettext import gettext as _\n\nname = \"Maria\"\n_(\"Hello, %s!\") % name  # Looks for \"Hello, %s!\".\n
        ","tags":["INT003"]},{"location":"rules/printf-in-get-text-func-call/#references","title":"References","text":"
        • Python documentation: gettext \u2014 Multilingual internationalization services
        ","tags":["INT003"]},{"location":"rules/printf-string-formatting/","title":"printf-string-formatting (UP031)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP031"]},{"location":"rules/printf-string-formatting/#what-it-does","title":"What it does","text":"

        Checks for printf-style string formatting, and offers to replace it with str.format calls.

        ","tags":["UP031"]},{"location":"rules/printf-string-formatting/#why-is-this-bad","title":"Why is this bad?","text":"

        printf-style string formatting has a number of quirks, and leads to less readable code than using str.format calls or f-strings. In general, prefer the newer str.format and f-strings constructs over printf-style string formatting.

        ","tags":["UP031"]},{"location":"rules/printf-string-formatting/#example","title":"Example","text":"
        \"%s, %s\" % (\"Hello\", \"World\")  # \"Hello, World\"\n

        Use instead:

        \"{}, {}\".format(\"Hello\", \"World\")  # \"Hello, World\"\n
        f\"{'Hello'}, {'World'}\"  # \"Hello, World\"\n
        ","tags":["UP031"]},{"location":"rules/printf-string-formatting/#fix-safety","title":"Fix safety","text":"

        In cases where the format string contains a single generic format specifier (e.g. %s), and the right-hand side is an ambiguous expression, we cannot offer a safe fix.

        For example, given:

        \"%s\" % val\n

        val could be a single-element tuple, or a single value (not contained in a tuple). Both of these would resolve to the same formatted string when using printf-style formatting, but resolve differently when using f-strings:

        val = 1\nprint(\"%s\" % val)  # \"1\"\nprint(\"{}\".format(val))  # \"1\"\n\nval = (1,)\nprint(\"%s\" % val)  # \"1\"\nprint(\"{}\".format(val))  # \"(1,)\"\n
        ","tags":["UP031"]},{"location":"rules/printf-string-formatting/#references","title":"References","text":"
        • Python documentation: printf-style String Formatting
        • Python documentation: str.format
        ","tags":["UP031"]},{"location":"rules/private-member-access/","title":"private-member-access (SLF001)","text":"

        Derived from the flake8-self linter.

        ","tags":["SLF001"]},{"location":"rules/private-member-access/#what-it-does","title":"What it does","text":"

        Checks for accesses on \"private\" class members.

        ","tags":["SLF001"]},{"location":"rules/private-member-access/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the convention is such that class members that are prefixed with a single underscore, or prefixed but not suffixed with a double underscore, are considered private and intended for internal use.

        Using such \"private\" members is considered a misuse of the class, as there are no guarantees that the member will be present in future versions, that it will have the same type, or that it will have the same behavior. Instead, use the class's public interface.

        This rule ignores accesses on dunder methods (e.g., __init__) and sunder methods (e.g., _missing_).

        ","tags":["SLF001"]},{"location":"rules/private-member-access/#example","title":"Example","text":"
        class Class:\n    def __init__(self):\n        self._private_member = \"...\"\n\n\nvar = Class()\nprint(var._private_member)\n

        Use instead:

        class Class:\n    def __init__(self):\n        self.public_member = \"...\"\n\n\nvar = Class()\nprint(var.public_member)\n
        ","tags":["SLF001"]},{"location":"rules/private-member-access/#options","title":"Options","text":"
        • lint.flake8-self.ignore-names
        ","tags":["SLF001"]},{"location":"rules/private-member-access/#references","title":"References","text":"
        • What is the meaning of single or double underscores before an object name?
        ","tags":["SLF001"]},{"location":"rules/private-type-parameter/","title":"private-type-parameter (UP049)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["UP049"]},{"location":"rules/private-type-parameter/#what-it-does","title":"What it does","text":"

        Checks for use of PEP 695 type parameters with leading underscores in generic classes and functions.

        ","tags":["UP049"]},{"location":"rules/private-type-parameter/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 695 type parameters are already restricted in scope to the class or function in which they appear, so leading underscores just hurt readability without the usual privacy benefits.

        However, neither a diagnostic nor a fix will be emitted for \"sunder\" (_T_) or \"dunder\" (__T__) type parameter names as these are not considered private.

        ","tags":["UP049"]},{"location":"rules/private-type-parameter/#example","title":"Example","text":"
        class GenericClass[_T]:\n    var: _T\n\n\ndef generic_function[_T](var: _T) -> list[_T]:\n    return var[0]\n

        Use instead:

        class GenericClass[T]:\n    var: T\n\n\ndef generic_function[T](var: T) -> list[T]:\n    return var[0]\n
        ","tags":["UP049"]},{"location":"rules/private-type-parameter/#fix-availability","title":"Fix availability","text":"

        If the name without an underscore would shadow a builtin or another variable, would be a keyword, or would otherwise be an invalid identifier, a fix will not be available. In these situations, you can consider using a trailing underscore or a different name entirely to satisfy the lint rule.

        ","tags":["UP049"]},{"location":"rules/private-type-parameter/#see-also","title":"See also","text":"

        This rule renames private PEP 695 type parameters but doesn't convert pre-PEP 695 generics to the new format. See non-pep695-generic-function and non-pep695-generic-class for rules that will make this transformation. Those rules do not remove unused type variables after their changes, so you may also want to consider enabling unused-private-type-var to complete the transition to PEP 695 generics.

        ","tags":["UP049"]},{"location":"rules/prohibited-trailing-comma/","title":"prohibited-trailing-comma (COM819)","text":"

        Derived from the flake8-commas linter.

        Fix is always available.

        ","tags":["COM819"]},{"location":"rules/prohibited-trailing-comma/#what-it-does","title":"What it does","text":"

        Checks for the presence of prohibited trailing commas.

        ","tags":["COM819"]},{"location":"rules/prohibited-trailing-comma/#why-is-this-bad","title":"Why is this bad?","text":"

        Trailing commas are not essential in some cases and can therefore be viewed as unnecessary.

        ","tags":["COM819"]},{"location":"rules/prohibited-trailing-comma/#example","title":"Example","text":"
        foo = (1, 2, 3,)\n

        Use instead:

        foo = (1, 2, 3)\n
        ","tags":["COM819"]},{"location":"rules/prohibited-trailing-comma/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent use of trailing commas, making the rule redundant.

        ","tags":["COM819"]},{"location":"rules/property-with-parameters/","title":"property-with-parameters (PLR0206)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0206"]},{"location":"rules/property-with-parameters/#what-it-does","title":"What it does","text":"

        Checks for property definitions that accept function parameters.

        ","tags":["PLR0206"]},{"location":"rules/property-with-parameters/#why-is-this-bad","title":"Why is this bad?","text":"

        Properties cannot be called with parameters.

        If you need to pass parameters to a property, create a method with the desired parameters and call that method instead.

        ","tags":["PLR0206"]},{"location":"rules/property-with-parameters/#example","title":"Example","text":"
        class Cat:\n    @property\n    def purr(self, volume): ...\n

        Use instead:

        class Cat:\n    @property\n    def purr(self): ...\n\n    def purr_volume(self, volume): ...\n
        ","tags":["PLR0206"]},{"location":"rules/property-with-parameters/#references","title":"References","text":"
        • Python documentation: property
        ","tags":["PLR0206"]},{"location":"rules/py-path/","title":"py-path (PTH124)","text":"

        Derived from the flake8-use-pathlib linter.

        ","tags":["PTH124"]},{"location":"rules/py-path/#what-it-does","title":"What it does","text":"

        Checks for uses of the py.path library.

        ","tags":["PTH124"]},{"location":"rules/py-path/#why-is-this-bad","title":"Why is this bad?","text":"

        The py.path library is in maintenance mode. Instead, prefer the standard library's pathlib module, or third-party modules like path (formerly py.path).

        ","tags":["PTH124"]},{"location":"rules/py-path/#examples","title":"Examples","text":"
        import py.path\n\np = py.path.local(\"/foo/bar\").join(\"baz/qux\")\n

        Use instead:

        from pathlib import Path\n\np = Path(\"/foo/bar\") / \"bar\" / \"qux\"\n
        ","tags":["PTH124"]},{"location":"rules/py-path/#references","title":"References","text":"
        • Python documentation: Pathlib
        • Path repository
        ","tags":["PTH124"]},{"location":"rules/pytest-assert-always-false/","title":"pytest-assert-always-false (PT015)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT015"]},{"location":"rules/pytest-assert-always-false/#what-it-does","title":"What it does","text":"

        Checks for assert statements whose test expression is a falsy value.

        ","tags":["PT015"]},{"location":"rules/pytest-assert-always-false/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.fail conveys the intent more clearly than assert falsy_value.

        ","tags":["PT015"]},{"location":"rules/pytest-assert-always-false/#example","title":"Example","text":"
        def test_foo():\n    if some_condition:\n        assert False, \"some_condition was True\"\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    if some_condition:\n        pytest.fail(\"some_condition was True\")\n    ...\n
        ","tags":["PT015"]},{"location":"rules/pytest-assert-always-false/#references","title":"References","text":"
        • pytest documentation: pytest.fail
        ","tags":["PT015"]},{"location":"rules/pytest-assert-in-except/","title":"pytest-assert-in-except (PT017)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT017"]},{"location":"rules/pytest-assert-in-except/#what-it-does","title":"What it does","text":"

        Checks for assert statements in except clauses.

        ","tags":["PT017"]},{"location":"rules/pytest-assert-in-except/#why-is-this-bad","title":"Why is this bad?","text":"

        When testing for exceptions, pytest.raises() should be used instead of assert statements in except clauses, as it's more explicit and idiomatic. Further, pytest.raises() will fail if the exception is not raised, unlike the assert statement.

        ","tags":["PT017"]},{"location":"rules/pytest-assert-in-except/#example","title":"Example","text":"
        def test_foo():\n    try:\n        1 / 0\n    except ZeroDivisionError as e:\n        assert e.args\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    with pytest.raises(ZeroDivisionError) as exc_info:\n        1 / 0\n    assert exc_info.value.args\n
        ","tags":["PT017"]},{"location":"rules/pytest-assert-in-except/#references","title":"References","text":"
        • pytest documentation: pytest.raises
        ","tags":["PT017"]},{"location":"rules/pytest-composite-assertion/","title":"pytest-composite-assertion (PT018)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT018"]},{"location":"rules/pytest-composite-assertion/#what-it-does","title":"What it does","text":"

        Checks for assertions that combine multiple independent conditions.

        ","tags":["PT018"]},{"location":"rules/pytest-composite-assertion/#why-is-this-bad","title":"Why is this bad?","text":"

        Composite assertion statements are harder to debug upon failure, as the failure message will not indicate which condition failed.

        ","tags":["PT018"]},{"location":"rules/pytest-composite-assertion/#example","title":"Example","text":"
        def test_foo():\n    assert something and something_else\n\n\ndef test_bar():\n    assert not (something or something_else)\n

        Use instead:

        def test_foo():\n    assert something\n    assert something_else\n\n\ndef test_bar():\n    assert not something\n    assert not something_else\n
        ","tags":["PT018"]},{"location":"rules/pytest-deprecated-yield-fixture/","title":"pytest-deprecated-yield-fixture (PT020)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT020"]},{"location":"rules/pytest-deprecated-yield-fixture/#what-it-does","title":"What it does","text":"

        Checks for pytest.yield_fixture usage.

        ","tags":["PT020"]},{"location":"rules/pytest-deprecated-yield-fixture/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.yield_fixture is deprecated. pytest.fixture should be used instead.

        ","tags":["PT020"]},{"location":"rules/pytest-deprecated-yield-fixture/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.yield_fixture()\ndef my_fixture():\n    obj = SomeClass()\n    yield obj\n    obj.cleanup()\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef my_fixture():\n    obj = SomeClass()\n    yield obj\n    obj.cleanup()\n
        ","tags":["PT020"]},{"location":"rules/pytest-deprecated-yield-fixture/#references","title":"References","text":"
        • pytest documentation: yield_fixture functions
        ","tags":["PT020"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/","title":"pytest-duplicate-parametrize-test-cases (PT014)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT014"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/#what-it-does","title":"What it does","text":"

        Checks for duplicate test cases in pytest.mark.parametrize.

        ","tags":["PT014"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/#why-is-this-bad","title":"Why is this bad?","text":"

        Duplicate test cases are redundant and should be removed.

        ","tags":["PT014"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.mark.parametrize(\n    (\"param1\", \"param2\"),\n    [\n        (1, 2),\n        (1, 2),\n    ],\n)\ndef test_foo(param1, param2): ...\n

        Use instead:

        import pytest\n\n\n@pytest.mark.parametrize(\n    (\"param1\", \"param2\"),\n    [\n        (1, 2),\n    ],\n)\ndef test_foo(param1, param2): ...\n
        ","tags":["PT014"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as tests that rely on mutable global state may be affected by removing duplicate test cases.

        ","tags":["PT014"]},{"location":"rules/pytest-duplicate-parametrize-test-cases/#references","title":"References","text":"
        • pytest documentation: How to parametrize fixtures and test functions
        ","tags":["PT014"]},{"location":"rules/pytest-erroneous-use-fixtures-on-fixture/","title":"pytest-erroneous-use-fixtures-on-fixture (PT025)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT025"]},{"location":"rules/pytest-erroneous-use-fixtures-on-fixture/#what-it-does","title":"What it does","text":"

        Checks for pytest.mark.usefixtures decorators applied to pytest fixtures.

        ","tags":["PT025"]},{"location":"rules/pytest-erroneous-use-fixtures-on-fixture/#why-is-this-bad","title":"Why is this bad?","text":"

        The pytest.mark.usefixtures decorator has no effect on pytest fixtures.

        ","tags":["PT025"]},{"location":"rules/pytest-erroneous-use-fixtures-on-fixture/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef a():\n    pass\n\n\n@pytest.mark.usefixtures(\"a\")\n@pytest.fixture()\ndef b(a):\n    pass\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef a():\n    pass\n\n\n@pytest.fixture()\ndef b(a):\n    pass\n
        ","tags":["PT025"]},{"location":"rules/pytest-erroneous-use-fixtures-on-fixture/#references","title":"References","text":"
        • pytest documentation: pytest.mark.usefixtures
        ","tags":["PT025"]},{"location":"rules/pytest-extraneous-scope-function/","title":"pytest-extraneous-scope-function (PT003)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT003"]},{"location":"rules/pytest-extraneous-scope-function/#what-it-does","title":"What it does","text":"

        Checks for pytest.fixture calls with scope=\"function\".

        ","tags":["PT003"]},{"location":"rules/pytest-extraneous-scope-function/#why-is-this-bad","title":"Why is this bad?","text":"

        scope=\"function\" can be omitted, as it is the default.

        ","tags":["PT003"]},{"location":"rules/pytest-extraneous-scope-function/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture(scope=\"function\")\ndef my_fixture(): ...\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef my_fixture(): ...\n
        ","tags":["PT003"]},{"location":"rules/pytest-extraneous-scope-function/#references","title":"References","text":"
        • pytest documentation: @pytest.fixture functions
        ","tags":["PT003"]},{"location":"rules/pytest-fail-without-message/","title":"pytest-fail-without-message (PT016)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT016"]},{"location":"rules/pytest-fail-without-message/#what-it-does","title":"What it does","text":"

        Checks for pytest.fail calls without a message.

        ","tags":["PT016"]},{"location":"rules/pytest-fail-without-message/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.fail calls without a message make it harder to understand and debug test failures.

        ","tags":["PT016"]},{"location":"rules/pytest-fail-without-message/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    pytest.fail()\n\n\ndef test_bar():\n    pytest.fail(\"\")\n\n\ndef test_baz():\n    pytest.fail(reason=\"\")\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    pytest.fail(\"...\")\n\n\ndef test_bar():\n    pytest.fail(reason=\"...\")\n
        ","tags":["PT016"]},{"location":"rules/pytest-fail-without-message/#references","title":"References","text":"
        • pytest documentation: pytest.fail
        ","tags":["PT016"]},{"location":"rules/pytest-fixture-finalizer-callback/","title":"pytest-fixture-finalizer-callback (PT021)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT021"]},{"location":"rules/pytest-fixture-finalizer-callback/#what-it-does","title":"What it does","text":"

        Checks for unnecessary request.addfinalizer usages in pytest fixtures.

        ","tags":["PT021"]},{"location":"rules/pytest-fixture-finalizer-callback/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest offers two ways to perform cleanup in fixture code. The first is sequential (via the yield statement), the second callback-based (via request.addfinalizer).

        The sequential approach is more readable and should be preferred, unless the fixture uses the \"factory as fixture\" pattern.

        ","tags":["PT021"]},{"location":"rules/pytest-fixture-finalizer-callback/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef my_fixture(request):\n    resource = acquire_resource()\n    request.addfinalizer(resource.release)\n    return resource\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef my_fixture():\n    resource = acquire_resource()\n    yield resource\n    resource.release()\n\n\n# \"factory-as-fixture\" pattern\n@pytest.fixture()\ndef my_factory(request):\n    def create_resource(arg):\n        resource = acquire_resource(arg)\n        request.addfinalizer(resource.release)\n        return resource\n\n    return create_resource\n
        ","tags":["PT021"]},{"location":"rules/pytest-fixture-finalizer-callback/#references","title":"References","text":"
        • pytest documentation: Adding finalizers directly
        • pytest documentation: Factories as fixtures
        ","tags":["PT021"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/","title":"pytest-fixture-incorrect-parentheses-style (PT001)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT001"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/#what-it-does","title":"What it does","text":"

        Checks for argument-free @pytest.fixture() decorators with or without parentheses, depending on the lint.flake8-pytest-style.fixture-parentheses setting.

        ","tags":["PT001"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/#why-is-this-bad","title":"Why is this bad?","text":"

        If a @pytest.fixture() doesn't take any arguments, the parentheses are optional.

        Either removing those unnecessary parentheses or requiring them for all fixtures is fine, but it's best to be consistent. The rule defaults to removing unnecessary parentheses, to match the documentation of the official pytest projects.

        ","tags":["PT001"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef my_fixture(): ...\n

        Use instead:

        import pytest\n\n\n@pytest.fixture\ndef my_fixture(): ...\n
        ","tags":["PT001"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/#options","title":"Options","text":"
        • lint.flake8-pytest-style.fixture-parentheses
        ","tags":["PT001"]},{"location":"rules/pytest-fixture-incorrect-parentheses-style/#references","title":"References","text":"
        • pytest documentation: API Reference: Fixtures
        ","tags":["PT001"]},{"location":"rules/pytest-fixture-param-without-value/","title":"pytest-fixture-param-without-value (PT019)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT019"]},{"location":"rules/pytest-fixture-param-without-value/#what-it-does","title":"What it does","text":"

        Checks for pytest test functions that should be decorated with @pytest.mark.usefixtures.

        ","tags":["PT019"]},{"location":"rules/pytest-fixture-param-without-value/#why-is-this-bad","title":"Why is this bad?","text":"

        In pytest, fixture injection is used to activate fixtures in a test function.

        Fixtures can be injected either by passing them as parameters to the test function, or by using the @pytest.mark.usefixtures decorator.

        If the test function depends on the fixture being activated, but does not use it in the test body or otherwise rely on its return value, prefer the @pytest.mark.usefixtures decorator, to make the dependency explicit and avoid the confusion caused by unused arguments.

        ","tags":["PT019"]},{"location":"rules/pytest-fixture-param-without-value/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture\ndef _patch_something(): ...\n\n\ndef test_foo(_patch_something): ...\n

        Use instead:

        import pytest\n\n\n@pytest.fixture\ndef _patch_something(): ...\n\n\n@pytest.mark.usefixtures(\"_patch_something\")\ndef test_foo(): ...\n
        ","tags":["PT019"]},{"location":"rules/pytest-fixture-param-without-value/#references","title":"References","text":"
        • pytest documentation: pytest.mark.usefixtures
        ","tags":["PT019"]},{"location":"rules/pytest-fixture-positional-args/","title":"pytest-fixture-positional-args (PT002)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT002"]},{"location":"rules/pytest-fixture-positional-args/#what-it-does","title":"What it does","text":"

        Checks for pytest.fixture calls with positional arguments.

        ","tags":["PT002"]},{"location":"rules/pytest-fixture-positional-args/#why-is-this-bad","title":"Why is this bad?","text":"

        For clarity and consistency, prefer using keyword arguments to specify fixture configuration.

        ","tags":["PT002"]},{"location":"rules/pytest-fixture-positional-args/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture(\"module\")\ndef my_fixture(): ...\n

        Use instead:

        import pytest\n\n\n@pytest.fixture(scope=\"module\")\ndef my_fixture(): ...\n
        ","tags":["PT002"]},{"location":"rules/pytest-fixture-positional-args/#references","title":"References","text":"
        • pytest documentation: @pytest.fixture functions
        ","tags":["PT002"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/","title":"pytest-incorrect-fixture-name-underscore (PT005)","text":"

        Derived from the flake8-pytest-style linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/#removal","title":"Removal","text":"

        This rule has been removed because marking fixtures that do not return a value with an underscore isn't a practice recommended by the pytest community.

        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/#what-it-does","title":"What it does","text":"

        Checks for pytest fixtures that return a value, but are named with a leading underscore.

        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/#why-is-this-bad","title":"Why is this bad?","text":"

        By convention, fixtures that don't return a value should be named with a leading underscore, while fixtures that do return a value should not.

        This rule ignores abstract fixtures.

        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef _some_object():\n    return SomeClass()\n\n\n@pytest.fixture()\ndef _some_object_with_cleanup():\n    obj = SomeClass()\n    yield obj\n    obj.cleanup()\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef some_object():\n    return SomeClass()\n\n\n@pytest.fixture()\ndef some_object_with_cleanup():\n    obj = SomeClass()\n    yield obj\n    obj.cleanup()\n
        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-fixture-name-underscore/#references","title":"References","text":"
        • pytest documentation: @pytest.fixture functions
        ","tags":["PT005"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/","title":"pytest-incorrect-mark-parentheses-style (PT023)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/#what-it-does","title":"What it does","text":"

        Checks for argument-free @pytest.mark.<marker>() decorators with or without parentheses, depending on the lint.flake8-pytest-style.mark-parentheses setting.

        The rule defaults to removing unnecessary parentheses, to match the documentation of the official pytest projects.

        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/#why-is-this-bad","title":"Why is this bad?","text":"

        If a @pytest.mark.<marker>() doesn't take any arguments, the parentheses are optional.

        Either removing those unnecessary parentheses or requiring them for all fixtures is fine, but it's best to be consistent.

        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.mark.foo\ndef test_something(): ...\n

        Use instead:

        import pytest\n\n\n@pytest.mark.foo()\ndef test_something(): ...\n
        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/#options","title":"Options","text":"
        • lint.flake8-pytest-style.mark-parentheses
        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-mark-parentheses-style/#references","title":"References","text":"
        • pytest documentation: Marks
        ","tags":["PT023"]},{"location":"rules/pytest-incorrect-pytest-import/","title":"pytest-incorrect-pytest-import (PT013)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT013"]},{"location":"rules/pytest-incorrect-pytest-import/#what-it-does","title":"What it does","text":"

        Checks for incorrect import of pytest.

        ","tags":["PT013"]},{"location":"rules/pytest-incorrect-pytest-import/#why-is-this-bad","title":"Why is this bad?","text":"

        For consistency, pytest should be imported as import pytest and its members should be accessed in the form of pytest.xxx.yyy for consistency

        ","tags":["PT013"]},{"location":"rules/pytest-incorrect-pytest-import/#example","title":"Example","text":"
        import pytest as pt\nfrom pytest import fixture\n

        Use instead:

        import pytest\n
        ","tags":["PT013"]},{"location":"rules/pytest-missing-fixture-name-underscore/","title":"pytest-missing-fixture-name-underscore (PT004)","text":"

        Derived from the flake8-pytest-style linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["PT004"]},{"location":"rules/pytest-missing-fixture-name-underscore/#removal","title":"Removal","text":"

        This rule has been removed because marking fixtures that do not return a value with an underscore isn't a practice recommended by the pytest community.

        ","tags":["PT004"]},{"location":"rules/pytest-missing-fixture-name-underscore/#what-it-does","title":"What it does","text":"

        Checks for pytest fixtures that do not return a value, but are not named with a leading underscore.

        ","tags":["PT004"]},{"location":"rules/pytest-missing-fixture-name-underscore/#why-is-this-bad","title":"Why is this bad?","text":"

        By convention, fixtures that don't return a value should be named with a leading underscore, while fixtures that do return a value should not.

        This rule ignores abstract fixtures and generators.

        ","tags":["PT004"]},{"location":"rules/pytest-missing-fixture-name-underscore/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef patch_something(mocker):\n    mocker.patch(\"module.object\")\n\n\n@pytest.fixture()\ndef use_context():\n    with create_context():\n        yield\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef _patch_something(mocker):\n    mocker.patch(\"module.object\")\n\n\n@pytest.fixture()\ndef _use_context():\n    with create_context():\n        yield\n
        ","tags":["PT004"]},{"location":"rules/pytest-missing-fixture-name-underscore/#references","title":"References","text":"
        • pytest documentation: @pytest.fixture functions
        ","tags":["PT004"]},{"location":"rules/pytest-parameter-with-default-argument/","title":"pytest-parameter-with-default-argument (PT028)","text":"

        Derived from the flake8-pytest-style linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PT028"]},{"location":"rules/pytest-parameter-with-default-argument/#what-it-does","title":"What it does","text":"

        Checks for parameters of test functions with default arguments.

        ","tags":["PT028"]},{"location":"rules/pytest-parameter-with-default-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Such a parameter will always have the default value during the test regardless of whether a fixture with the same name is defined.

        ","tags":["PT028"]},{"location":"rules/pytest-parameter-with-default-argument/#example","title":"Example","text":"
        def test_foo(a=1): ...\n

        Use instead:

        def test_foo(a): ...\n
        ","tags":["PT028"]},{"location":"rules/pytest-parameter-with-default-argument/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as modifying a function signature can change the behavior of the code.

        ","tags":["PT028"]},{"location":"rules/pytest-parameter-with-default-argument/#references","title":"References","text":"
        • Original Pytest issue
        ","tags":["PT028"]},{"location":"rules/pytest-parametrize-names-wrong-type/","title":"pytest-parametrize-names-wrong-type (PT006)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-names-wrong-type/#what-it-does","title":"What it does","text":"

        Checks for the type of parameter names passed to pytest.mark.parametrize.

        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-names-wrong-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The argnames argument of pytest.mark.parametrize takes a string or a sequence of strings. For a single parameter, it's preferable to use a string. For multiple parameters, it's preferable to use the style configured via the lint.flake8-pytest-style.parametrize-names-type setting.

        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-names-wrong-type/#example","title":"Example","text":"
        import pytest\n\n\n# single parameter, always expecting string\n@pytest.mark.parametrize((\"param\",), [1, 2, 3])\ndef test_foo(param): ...\n\n\n# multiple parameters, expecting tuple\n@pytest.mark.parametrize([\"param1\", \"param2\"], [(1, 2), (3, 4)])\ndef test_bar(param1, param2): ...\n\n\n# multiple parameters, expecting tuple\n@pytest.mark.parametrize(\"param1,param2\", [(1, 2), (3, 4)])\ndef test_baz(param1, param2): ...\n

        Use instead:

        import pytest\n\n\n@pytest.mark.parametrize(\"param\", [1, 2, 3])\ndef test_foo(param): ...\n\n\n@pytest.mark.parametrize((\"param1\", \"param2\"), [(1, 2), (3, 4)])\ndef test_bar(param1, param2): ...\n
        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-names-wrong-type/#options","title":"Options","text":"
        • lint.flake8-pytest-style.parametrize-names-type
        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-names-wrong-type/#references","title":"References","text":"
        • pytest documentation: How to parametrize fixtures and test functions
        ","tags":["PT006"]},{"location":"rules/pytest-parametrize-values-wrong-type/","title":"pytest-parametrize-values-wrong-type (PT007)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT007"]},{"location":"rules/pytest-parametrize-values-wrong-type/#what-it-does","title":"What it does","text":"

        Checks for the type of parameter values passed to pytest.mark.parametrize.

        ","tags":["PT007"]},{"location":"rules/pytest-parametrize-values-wrong-type/#why-is-this-bad","title":"Why is this bad?","text":"

        The argvalues argument of pytest.mark.parametrize takes an iterator of parameter values, which can be provided as lists or tuples.

        To aid in readability, it's recommended to use a consistent style for the list of values rows, and, in the case of multiple parameters, for each row of values.

        The style for the list of values rows can be configured via the lint.flake8-pytest-style.parametrize-values-type setting, while the style for each row of values can be configured via the lint.flake8-pytest-style.parametrize-values-row-type setting.

        For example, lint.flake8-pytest-style.parametrize-values-type will lead to the following expectations:

        • tuple: @pytest.mark.parametrize(\"value\", (\"a\", \"b\", \"c\"))
        • list: @pytest.mark.parametrize(\"value\", [\"a\", \"b\", \"c\"])

        Similarly, lint.flake8-pytest-style.parametrize-values-row-type will lead to the following expectations:

        • tuple: @pytest.mark.parametrize((\"key\", \"value\"), [(\"a\", \"b\"), (\"c\", \"d\")])
        • list: @pytest.mark.parametrize((\"key\", \"value\"), [[\"a\", \"b\"], [\"c\", \"d\"]])
        ","tags":["PT007"]},{"location":"rules/pytest-parametrize-values-wrong-type/#example","title":"Example","text":"
        import pytest\n\n\n# expected list, got tuple\n@pytest.mark.parametrize(\"param\", (1, 2))\ndef test_foo(param): ...\n\n\n# expected top-level list, got tuple\n@pytest.mark.parametrize(\n    (\"param1\", \"param2\"),\n    (\n        (1, 2),\n        (3, 4),\n    ),\n)\ndef test_bar(param1, param2): ...\n\n\n# expected individual rows to be tuples, got lists\n@pytest.mark.parametrize(\n    (\"param1\", \"param2\"),\n    [\n        [1, 2],\n        [3, 4],\n    ],\n)\ndef test_baz(param1, param2): ...\n

        Use instead:

        import pytest\n\n\n@pytest.mark.parametrize(\"param\", [1, 2, 3])\ndef test_foo(param): ...\n\n\n@pytest.mark.parametrize((\"param1\", \"param2\"), [(1, 2), (3, 4)])\ndef test_bar(param1, param2): ...\n
        ","tags":["PT007"]},{"location":"rules/pytest-parametrize-values-wrong-type/#options","title":"Options","text":"
        • lint.flake8-pytest-style.parametrize-values-type
        • lint.flake8-pytest-style.parametrize-values-row-type
        ","tags":["PT007"]},{"location":"rules/pytest-parametrize-values-wrong-type/#references","title":"References","text":"
        • pytest documentation: How to parametrize fixtures and test functions
        ","tags":["PT007"]},{"location":"rules/pytest-patch-with-lambda/","title":"pytest-patch-with-lambda (PT008)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT008"]},{"location":"rules/pytest-patch-with-lambda/#what-it-does","title":"What it does","text":"

        Checks for mocked calls that use a dummy lambda function instead of return_value.

        ","tags":["PT008"]},{"location":"rules/pytest-patch-with-lambda/#why-is-this-bad","title":"Why is this bad?","text":"

        When patching calls, an explicit return_value better conveys the intent than a lambda function, assuming the lambda does not use the arguments passed to it.

        return_value is also robust to changes in the patched function's signature, and enables additional assertions to verify behavior. For example, return_value allows for verification of the number of calls or the arguments passed to the patched function via assert_called_once_with and related methods.

        ","tags":["PT008"]},{"location":"rules/pytest-patch-with-lambda/#example","title":"Example","text":"
        def test_foo(mocker):\n    mocker.patch(\"module.target\", lambda x, y: 7)\n

        Use instead:

        def test_foo(mocker):\n    mocker.patch(\"module.target\", return_value=7)\n\n    # If the lambda makes use of the arguments, no diagnostic is emitted.\n    mocker.patch(\"module.other_target\", lambda x, y: x)\n
        ","tags":["PT008"]},{"location":"rules/pytest-patch-with-lambda/#references","title":"References","text":"
        • Python documentation: unittest.mock.patch
        • PyPI: pytest-mock
        ","tags":["PT008"]},{"location":"rules/pytest-raises-ambiguous-pattern/","title":"pytest-raises-ambiguous-pattern (RUF043)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF043"]},{"location":"rules/pytest-raises-ambiguous-pattern/#what-it-does","title":"What it does","text":"

        Checks for non-raw literal string arguments passed to the match parameter of pytest.raises() where the string contains at least one unescaped regex metacharacter.

        ","tags":["RUF043"]},{"location":"rules/pytest-raises-ambiguous-pattern/#why-is-this-bad","title":"Why is this bad?","text":"

        The match argument is implicitly converted to a regex under the hood. It should be made explicit whether the string is meant to be a regex or a \"plain\" pattern by prefixing the string with the r suffix, escaping the metacharacter(s) in the string using backslashes, or wrapping the entire string in a call to re.escape().

        ","tags":["RUF043"]},{"location":"rules/pytest-raises-ambiguous-pattern/#example","title":"Example","text":"
        import pytest\n\n\nwith pytest.raises(Exception, match=\"A full sentence.\"):\n    do_thing_that_raises()\n

        Use instead:

        import pytest\n\n\nwith pytest.raises(Exception, match=r\"A full sentence.\"):\n    do_thing_that_raises()\n

        Alternatively:

        import pytest\nimport re\n\n\nwith pytest.raises(Exception, match=re.escape(\"A full sentence.\")):\n    do_thing_that_raises()\n

        or:

        import pytest\nimport re\n\n\nwith pytest.raises(Exception, \"A full sentence\\\\.\"):\n    do_thing_that_raises()\n
        ","tags":["RUF043"]},{"location":"rules/pytest-raises-ambiguous-pattern/#references","title":"References","text":"
        • Python documentation: re.escape
        • pytest documentation: pytest.raises
        ","tags":["RUF043"]},{"location":"rules/pytest-raises-too-broad/","title":"pytest-raises-too-broad (PT011)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT011"]},{"location":"rules/pytest-raises-too-broad/#what-it-does","title":"What it does","text":"

        Checks for pytest.raises calls without a match parameter.

        ","tags":["PT011"]},{"location":"rules/pytest-raises-too-broad/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.raises(Error) will catch any Error and may catch errors that are unrelated to the code under test. To avoid this, pytest.raises should be called with a match parameter. The exception names that require a match parameter can be configured via the lint.flake8-pytest-style.raises-require-match-for and lint.flake8-pytest-style.raises-extend-require-match-for settings.

        ","tags":["PT011"]},{"location":"rules/pytest-raises-too-broad/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    with pytest.raises(ValueError):\n        ...\n\n    # empty string is also an error\n    with pytest.raises(ValueError, match=\"\"):\n        ...\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    with pytest.raises(ValueError, match=\"expected message\"):\n        ...\n
        ","tags":["PT011"]},{"location":"rules/pytest-raises-too-broad/#options","title":"Options","text":"
        • lint.flake8-pytest-style.raises-require-match-for
        • lint.flake8-pytest-style.raises-extend-require-match-for
        ","tags":["PT011"]},{"location":"rules/pytest-raises-too-broad/#references","title":"References","text":"
        • pytest documentation: pytest.raises
        ","tags":["PT011"]},{"location":"rules/pytest-raises-with-multiple-statements/","title":"pytest-raises-with-multiple-statements (PT012)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT012"]},{"location":"rules/pytest-raises-with-multiple-statements/#what-it-does","title":"What it does","text":"

        Checks for pytest.raises context managers with multiple statements.

        This rule allows pytest.raises bodies to contain for loops with empty bodies (e.g., pass or ... statements), to test iterator behavior.

        ","tags":["PT012"]},{"location":"rules/pytest-raises-with-multiple-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        When a pytest.raises is used as a context manager and contains multiple statements, it can lead to the test passing when it actually should fail.

        A pytest.raises context manager should only contain a single simple statement that raises the expected exception.

        ","tags":["PT012"]},{"location":"rules/pytest-raises-with-multiple-statements/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    with pytest.raises(MyError):\n        setup()\n        func_to_test()  # not executed if `setup()` raises `MyError`\n        assert foo()  # not executed\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    setup()\n    with pytest.raises(MyError):\n        func_to_test()\n    assert foo()\n
        ","tags":["PT012"]},{"location":"rules/pytest-raises-with-multiple-statements/#references","title":"References","text":"
        • pytest documentation: pytest.raises
        ","tags":["PT012"]},{"location":"rules/pytest-raises-without-exception/","title":"pytest-raises-without-exception (PT010)","text":"

        Derived from the flake8-pytest-style linter.

        ","tags":["PT010"]},{"location":"rules/pytest-raises-without-exception/#what-it-does","title":"What it does","text":"

        Checks for pytest.raises calls without an expected exception.

        ","tags":["PT010"]},{"location":"rules/pytest-raises-without-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.raises expects to receive an expected exception as its first argument. If omitted, the pytest.raises call will fail at runtime.

        ","tags":["PT010"]},{"location":"rules/pytest-raises-without-exception/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    with pytest.raises():\n        do_something()\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    with pytest.raises(SomeException):\n        do_something()\n
        ","tags":["PT010"]},{"location":"rules/pytest-raises-without-exception/#references","title":"References","text":"
        • pytest documentation: pytest.raises
        ","tags":["PT010"]},{"location":"rules/pytest-unittest-assertion/","title":"pytest-unittest-assertion (PT009)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT009"]},{"location":"rules/pytest-unittest-assertion/#what-it-does","title":"What it does","text":"

        Checks for uses of assertion methods from the unittest module.

        ","tags":["PT009"]},{"location":"rules/pytest-unittest-assertion/#why-is-this-bad","title":"Why is this bad?","text":"

        To make use of pytest's assertion rewriting, a regular assert statement is preferred over unittest's assertion methods.

        ","tags":["PT009"]},{"location":"rules/pytest-unittest-assertion/#example","title":"Example","text":"
        import unittest\n\n\nclass TestFoo(unittest.TestCase):\n    def test_foo(self):\n        self.assertEqual(a, b)\n

        Use instead:

        import unittest\n\n\nclass TestFoo(unittest.TestCase):\n    def test_foo(self):\n        assert a == b\n
        ","tags":["PT009"]},{"location":"rules/pytest-unittest-assertion/#references","title":"References","text":"
        • pytest documentation: Assertion introspection details
        ","tags":["PT009"]},{"location":"rules/pytest-unittest-raises-assertion/","title":"pytest-unittest-raises-assertion (PT027)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is sometimes available.

        ","tags":["PT027"]},{"location":"rules/pytest-unittest-raises-assertion/#what-it-does","title":"What it does","text":"

        Checks for uses of exception-related assertion methods from the unittest module.

        ","tags":["PT027"]},{"location":"rules/pytest-unittest-raises-assertion/#why-is-this-bad","title":"Why is this bad?","text":"

        To enforce the assertion style recommended by pytest, pytest.raises is preferred over the exception-related assertion methods in unittest, like assertRaises.

        ","tags":["PT027"]},{"location":"rules/pytest-unittest-raises-assertion/#example","title":"Example","text":"
        import unittest\n\n\nclass TestFoo(unittest.TestCase):\n    def test_foo(self):\n        with self.assertRaises(ValueError):\n            raise ValueError(\"foo\")\n

        Use instead:

        import unittest\nimport pytest\n\n\nclass TestFoo(unittest.TestCase):\n    def test_foo(self):\n        with pytest.raises(ValueError):\n            raise ValueError(\"foo\")\n
        ","tags":["PT027"]},{"location":"rules/pytest-unittest-raises-assertion/#references","title":"References","text":"
        • pytest documentation: Assertions about expected exceptions
        ","tags":["PT027"]},{"location":"rules/pytest-unnecessary-asyncio-mark-on-fixture/","title":"pytest-unnecessary-asyncio-mark-on-fixture (PT024)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT024"]},{"location":"rules/pytest-unnecessary-asyncio-mark-on-fixture/#what-it-does","title":"What it does","text":"

        Checks for unnecessary @pytest.mark.asyncio decorators applied to fixtures.

        ","tags":["PT024"]},{"location":"rules/pytest-unnecessary-asyncio-mark-on-fixture/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.mark.asyncio is unnecessary for fixtures.

        ","tags":["PT024"]},{"location":"rules/pytest-unnecessary-asyncio-mark-on-fixture/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.mark.asyncio()\n@pytest.fixture()\nasync def my_fixture():\n    return 0\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\nasync def my_fixture():\n    return 0\n
        ","tags":["PT024"]},{"location":"rules/pytest-unnecessary-asyncio-mark-on-fixture/#references","title":"References","text":"
        • PyPI: pytest-asyncio
        ","tags":["PT024"]},{"location":"rules/pytest-use-fixtures-without-parameters/","title":"pytest-use-fixtures-without-parameters (PT026)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT026"]},{"location":"rules/pytest-use-fixtures-without-parameters/#what-it-does","title":"What it does","text":"

        Checks for @pytest.mark.usefixtures() decorators that aren't passed any arguments.

        ","tags":["PT026"]},{"location":"rules/pytest-use-fixtures-without-parameters/#why-is-this-bad","title":"Why is this bad?","text":"

        A @pytest.mark.usefixtures() decorator that isn't passed any arguments is useless and should be removed.

        ","tags":["PT026"]},{"location":"rules/pytest-use-fixtures-without-parameters/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.mark.usefixtures()\ndef test_something(): ...\n

        Use instead:

        def test_something(): ...\n
        ","tags":["PT026"]},{"location":"rules/pytest-use-fixtures-without-parameters/#references","title":"References","text":"
        • pytest documentation: pytest.mark.usefixtures
        ","tags":["PT026"]},{"location":"rules/pytest-useless-yield-fixture/","title":"pytest-useless-yield-fixture (PT022)","text":"

        Derived from the flake8-pytest-style linter.

        Fix is always available.

        ","tags":["PT022"]},{"location":"rules/pytest-useless-yield-fixture/#what-it-does","title":"What it does","text":"

        Checks for unnecessary yield expressions in pytest fixtures.

        ","tags":["PT022"]},{"location":"rules/pytest-useless-yield-fixture/#why-is-this-bad","title":"Why is this bad?","text":"

        In pytest fixtures, the yield expression should only be used for fixtures that include teardown code, to clean up the fixture after the test function has finished executing.

        ","tags":["PT022"]},{"location":"rules/pytest-useless-yield-fixture/#example","title":"Example","text":"
        import pytest\n\n\n@pytest.fixture()\ndef my_fixture():\n    resource = acquire_resource()\n    yield resource\n

        Use instead:

        import pytest\n\n\n@pytest.fixture()\ndef my_fixture_with_teardown():\n    resource = acquire_resource()\n    yield resource\n    resource.release()\n\n\n@pytest.fixture()\ndef my_fixture_without_teardown():\n    resource = acquire_resource()\n    return resource\n
        ","tags":["PT022"]},{"location":"rules/pytest-useless-yield-fixture/#references","title":"References","text":"
        • pytest documentation: Teardown/Cleanup
        ","tags":["PT022"]},{"location":"rules/pytest-warns-too-broad/","title":"pytest-warns-too-broad (PT030)","text":"

        Derived from the flake8-pytest-style linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PT030"]},{"location":"rules/pytest-warns-too-broad/#what-it-does","title":"What it does","text":"

        Checks for pytest.warns calls without a match parameter.

        ","tags":["PT030"]},{"location":"rules/pytest-warns-too-broad/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.warns(Warning) will catch any Warning and may catch warnings that are unrelated to the code under test. To avoid this, pytest.warns should be called with a match parameter. The warning names that require a match parameter can be configured via the lint.flake8-pytest-style.warns-require-match-for and lint.flake8-pytest-style.warns-extend-require-match-for settings.

        ","tags":["PT030"]},{"location":"rules/pytest-warns-too-broad/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    with pytest.warns(RuntimeWarning):\n        ...\n\n    # empty string is also an error\n    with pytest.warns(RuntimeWarning, match=\"\"):\n        ...\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    with pytest.warns(RuntimeWarning, match=\"expected message\"):\n        ...\n
        ","tags":["PT030"]},{"location":"rules/pytest-warns-too-broad/#options","title":"Options","text":"
        • lint.flake8-pytest-style.warns-require-match-for
        • lint.flake8-pytest-style.warns-extend-require-match-for
        ","tags":["PT030"]},{"location":"rules/pytest-warns-too-broad/#references","title":"References","text":"
        • pytest documentation: pytest.warns
        ","tags":["PT030"]},{"location":"rules/pytest-warns-with-multiple-statements/","title":"pytest-warns-with-multiple-statements (PT031)","text":"

        Derived from the flake8-pytest-style linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PT031"]},{"location":"rules/pytest-warns-with-multiple-statements/#what-it-does","title":"What it does","text":"

        Checks for pytest.warns context managers with multiple statements.

        This rule allows pytest.warns bodies to contain for loops with empty bodies (e.g., pass or ... statements), to test iterator behavior.

        ","tags":["PT031"]},{"location":"rules/pytest-warns-with-multiple-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        When pytest.warns is used as a context manager and contains multiple statements, it can lead to the test passing when it should instead fail.

        A pytest.warns context manager should only contain a single simple statement that triggers the expected warning.

        ","tags":["PT031"]},{"location":"rules/pytest-warns-with-multiple-statements/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo_warns():\n    with pytest.warns(Warning):\n        setup()  # False negative if setup triggers a warning but foo does not.\n        foo()\n

        Use instead:

        import pytest\n\n\ndef test_foo_warns():\n    setup()\n    with pytest.warns(Warning):\n        foo()\n
        ","tags":["PT031"]},{"location":"rules/pytest-warns-with-multiple-statements/#references","title":"References","text":"
        • pytest documentation: pytest.warns
        ","tags":["PT031"]},{"location":"rules/pytest-warns-without-warning/","title":"pytest-warns-without-warning (PT029)","text":"

        Derived from the flake8-pytest-style linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PT029"]},{"location":"rules/pytest-warns-without-warning/#what-it-does","title":"What it does","text":"

        Checks for pytest.warns calls without an expected warning.

        ","tags":["PT029"]},{"location":"rules/pytest-warns-without-warning/#why-is-this-bad","title":"Why is this bad?","text":"

        pytest.warns expects to receive an expected warning as its first argument. If omitted, the pytest.warns call will fail at runtime.

        ","tags":["PT029"]},{"location":"rules/pytest-warns-without-warning/#example","title":"Example","text":"
        import pytest\n\n\ndef test_foo():\n    with pytest.warns():\n        do_something()\n

        Use instead:

        import pytest\n\n\ndef test_foo():\n    with pytest.warns(SomeWarning):\n        do_something()\n
        ","tags":["PT029"]},{"location":"rules/pytest-warns-without-warning/#references","title":"References","text":"
        • pytest documentation: pytest.warns
        ","tags":["PT029"]},{"location":"rules/quadratic-list-summation/","title":"quadratic-list-summation (RUF017)","text":"

        Fix is always available.

        ","tags":["RUF017"]},{"location":"rules/quadratic-list-summation/#what-it-does","title":"What it does","text":"

        Checks for the use of sum() to flatten lists of lists, which has quadratic complexity.

        ","tags":["RUF017"]},{"location":"rules/quadratic-list-summation/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of sum() to flatten lists of lists is quadratic in the number of lists, as sum() creates a new list for each element in the summation.

        Instead, consider using another method of flattening lists to avoid quadratic complexity. The following methods are all linear in the number of lists:

        • functools.reduce(operator.iadd, lists, [])
        • list(itertools.chain.from_iterable(lists))
        • [item for sublist in lists for item in sublist]

        When fixing relevant violations, Ruff defaults to the functools.reduce form, which outperforms the other methods in microbenchmarks.

        ","tags":["RUF017"]},{"location":"rules/quadratic-list-summation/#example","title":"Example","text":"
        lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\njoined = sum(lists, [])\n

        Use instead:

        import functools\nimport operator\n\n\nlists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\nfunctools.reduce(operator.iadd, lists, [])\n
        ","tags":["RUF017"]},{"location":"rules/quadratic-list-summation/#fix-safety","title":"Fix safety","text":"

        This fix is always marked as unsafe because sum uses the __add__ magic method while operator.iadd uses the __iadd__ magic method, and these behave differently on lists. The former requires the right summand to be a list, whereas the latter allows for any iterable. Therefore, the fix could inadvertently cause code that previously raised an error to silently succeed. Moreover, the fix could remove comments from the original code.

        ","tags":["RUF017"]},{"location":"rules/quadratic-list-summation/#references","title":"References","text":"
        • How Not to Flatten a List of Lists in Python
        • How do I make a flat list out of a list of lists?
        ","tags":["RUF017"]},{"location":"rules/quoted-annotation-in-stub/","title":"quoted-annotation-in-stub (PYI020)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI020"]},{"location":"rules/quoted-annotation-in-stub/#what-it-does","title":"What it does","text":"

        Checks for quoted type annotations in stub (.pyi) files, which should be avoided.

        ","tags":["PYI020"]},{"location":"rules/quoted-annotation-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files natively support forward references in all contexts, as stubs are never executed at runtime. (They should be thought of as \"data files\" for type checkers and IDEs.) As such, quotes are never required for type annotations in stub files, and should be omitted.

        ","tags":["PYI020"]},{"location":"rules/quoted-annotation-in-stub/#example","title":"Example","text":"
        def function() -> \"int\": ...\n

        Use instead:

        def function() -> int: ...\n
        ","tags":["PYI020"]},{"location":"rules/quoted-annotation-in-stub/#references","title":"References","text":"
        • Typing documentation - Writing and Maintaining Stub Files
        ","tags":["PYI020"]},{"location":"rules/quoted-annotation/","title":"quoted-annotation (UP037)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP037"]},{"location":"rules/quoted-annotation/#what-it-does","title":"What it does","text":"

        Checks for the presence of unnecessary quotes in type annotations.

        ","tags":["UP037"]},{"location":"rules/quoted-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, type annotations can be quoted to avoid forward references.

        However, if from __future__ import annotations is present, Python will always evaluate type annotations in a deferred manner, making the quotes unnecessary.

        Similarly, if the annotation is located in a typing-only context and won't be evaluated by Python at runtime, the quotes will also be considered unnecessary. For example, Python does not evaluate type annotations on assignments in function bodies.

        ","tags":["UP037"]},{"location":"rules/quoted-annotation/#example","title":"Example","text":"

        Given:

        from __future__ import annotations\n\n\ndef foo(bar: \"Bar\") -> \"Bar\": ...\n

        Use instead:

        from __future__ import annotations\n\n\ndef foo(bar: Bar) -> Bar: ...\n

        Given:

        def foo() -> None:\n    bar: \"Bar\"\n

        Use instead:

        def foo() -> None:\n    bar: Bar\n
        ","tags":["UP037"]},{"location":"rules/quoted-annotation/#see-also","title":"See also","text":"
        • quoted-annotation-in-stub: A rule that removes all quoted annotations from stub files
        • quoted-type-alias: A rule that removes unnecessary quotes from type aliases.
        ","tags":["UP037"]},{"location":"rules/quoted-annotation/#references","title":"References","text":"
        • PEP 563 \u2013 Postponed Evaluation of Annotations
        • Python documentation: __future__
        ","tags":["UP037"]},{"location":"rules/quoted-type-alias/","title":"quoted-type-alias (TC008)","text":"

        Derived from the flake8-type-checking linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#what-it-does","title":"What it does","text":"

        Checks for unnecessary quotes in PEP 613 explicit type aliases and PEP 695 type statements.

        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        Unnecessary string forward references can lead to additional overhead in runtime libraries making use of type hints. They can also have bad interactions with other runtime uses like PEP 604 type unions.

        PEP-613 type aliases are only flagged by the rule if Ruff can have high confidence that the quotes are unnecessary. Specifically, any PEP-613 type alias where the type expression on the right-hand side contains subscripts or attribute accesses will not be flagged. This is because type aliases can reference types that are, for example, generic in stub files but not at runtime. That can mean that a type checker expects the referenced type to be subscripted with type arguments despite the fact that doing so would fail at runtime if the type alias value was not quoted. Similarly, a type alias might need to reference a module-level attribute that exists in a stub file but not at runtime, meaning that the type alias value would need to be quoted to avoid a runtime error.

        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#example","title":"Example","text":"

        Given:

        OptInt: TypeAlias = \"int | None\"\n

        Use instead:

        OptInt: TypeAlias = int | None\n

        Given:

        type OptInt = \"int | None\"\n

        Use instead:

        type OptInt = int | None\n
        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the type annotation contains comments.

        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#see-also","title":"See also","text":"

        This rule only applies to type aliases in non-stub files. For removing quotes in other contexts or in stub files, see:

        • quoted-annotation-in-stub: A rule that removes all quoted annotations from stub files
        • quoted-annotation: A rule that removes unnecessary quotes from annotations in runtime files.
        ","tags":["TC008"]},{"location":"rules/quoted-type-alias/#references","title":"References","text":"
        • PEP 613 \u2013 Explicit Type Aliases
        • PEP 695: Generic Type Alias
        • PEP 604 \u2013 Allow writing union types as X | Y
        ","tags":["TC008"]},{"location":"rules/raise-literal/","title":"raise-literal (B016)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B016"]},{"location":"rules/raise-literal/#what-it-does","title":"What it does","text":"

        Checks for raise statements that raise a literal value.

        ","tags":["B016"]},{"location":"rules/raise-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        raise must be followed by an exception instance or an exception class, and exceptions must be instances of BaseException or a subclass thereof. Raising a literal will raise a TypeError at runtime.

        ","tags":["B016"]},{"location":"rules/raise-literal/#example","title":"Example","text":"
        raise \"foo\"\n

        Use instead:

        raise Exception(\"foo\")\n
        ","tags":["B016"]},{"location":"rules/raise-literal/#references","title":"References","text":"
        • Python documentation: raise statement
        ","tags":["B016"]},{"location":"rules/raise-not-implemented/","title":"raise-not-implemented (F901)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F901"]},{"location":"rules/raise-not-implemented/#what-it-does","title":"What it does","text":"

        Checks for raise statements that raise NotImplemented.

        ","tags":["F901"]},{"location":"rules/raise-not-implemented/#why-is-this-bad","title":"Why is this bad?","text":"

        NotImplemented is an exception used by binary special methods to indicate that an operation is not implemented with respect to a particular type.

        NotImplemented should not be raised directly. Instead, raise NotImplementedError, which is used to indicate that the method is abstract or not implemented in the derived class.

        ","tags":["F901"]},{"location":"rules/raise-not-implemented/#example","title":"Example","text":"
        class Foo:\n    def bar(self):\n        raise NotImplemented\n

        Use instead:

        class Foo:\n    def bar(self):\n        raise NotImplementedError\n
        ","tags":["F901"]},{"location":"rules/raise-not-implemented/#references","title":"References","text":"
        • Python documentation: NotImplemented
        • Python documentation: NotImplementedError
        ","tags":["F901"]},{"location":"rules/raise-vanilla-args/","title":"raise-vanilla-args (TRY003)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY003"]},{"location":"rules/raise-vanilla-args/#what-it-does","title":"What it does","text":"

        Checks for long exception messages that are not defined in the exception class itself.

        ","tags":["TRY003"]},{"location":"rules/raise-vanilla-args/#why-is-this-bad","title":"Why is this bad?","text":"

        By formatting an exception message at the raise site, the exception class becomes less reusable, and may now raise inconsistent messages depending on where it is raised.

        If the exception message is instead defined within the exception class, it will be consistent across all raise invocations.

        This rule is not enforced for some built-in exceptions that are commonly raised with a message and would be unusual to subclass, such as NotImplementedError.

        ","tags":["TRY003"]},{"location":"rules/raise-vanilla-args/#example","title":"Example","text":"
        class CantBeNegative(Exception):\n    pass\n\n\ndef foo(x):\n    if x < 0:\n        raise CantBeNegative(f\"{x} is negative\")\n

        Use instead:

        class CantBeNegative(Exception):\n    def __init__(self, number):\n        super().__init__(f\"{number} is negative\")\n\n\ndef foo(x):\n    if x < 0:\n        raise CantBeNegative(x)\n
        ","tags":["TRY003"]},{"location":"rules/raise-vanilla-class/","title":"raise-vanilla-class (TRY002)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY002"]},{"location":"rules/raise-vanilla-class/#what-it-does","title":"What it does","text":"

        Checks for code that raises Exception or BaseException directly.

        ","tags":["TRY002"]},{"location":"rules/raise-vanilla-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Handling such exceptions requires the use of except Exception or except BaseException. These will capture almost any raised exception, including failed assertions, division by zero, and more.

        Prefer to raise your own exception, or a more specific built-in exception, so that you can avoid over-capturing exceptions that you don't intend to handle.

        ","tags":["TRY002"]},{"location":"rules/raise-vanilla-class/#example","title":"Example","text":"
        def main_function():\n    if not cond:\n        raise Exception()\n\n\ndef consumer_func():\n    try:\n        do_step()\n        prepare()\n        main_function()\n    except Exception:\n        logger.error(\"Oops\")\n

        Use instead:

        def main_function():\n    if not cond:\n        raise CustomException()\n\n\ndef consumer_func():\n    try:\n        do_step()\n        prepare()\n        main_function()\n    except CustomException:\n        logger.error(\"Main function failed\")\n    except Exception:\n        logger.error(\"Oops\")\n
        ","tags":["TRY002"]},{"location":"rules/raise-within-try/","title":"raise-within-try (TRY301)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY301"]},{"location":"rules/raise-within-try/#what-it-does","title":"What it does","text":"

        Checks for raise statements within try blocks. The only raises caught are those that throw exceptions caught by the try statement itself.

        ","tags":["TRY301"]},{"location":"rules/raise-within-try/#why-is-this-bad","title":"Why is this bad?","text":"

        Raising and catching exceptions within the same try block is redundant, as the code can be refactored to avoid the try block entirely.

        Alternatively, the raise can be moved within an inner function, making the exception reusable across multiple call sites.

        ","tags":["TRY301"]},{"location":"rules/raise-within-try/#example","title":"Example","text":"
        def bar():\n    pass\n\n\ndef foo():\n    try:\n        a = bar()\n        if not a:\n            raise ValueError\n    except ValueError:\n        raise\n

        Use instead:

        def bar():\n    raise ValueError\n\n\ndef foo():\n    try:\n        a = bar()  # refactored `bar` to raise `ValueError`\n    except ValueError:\n        raise\n
        ","tags":["TRY301"]},{"location":"rules/raise-without-from-inside-except/","title":"raise-without-from-inside-except (B904)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B904"]},{"location":"rules/raise-without-from-inside-except/#what-it-does","title":"What it does","text":"

        Checks for raise statements in exception handlers that lack a from clause.

        ","tags":["B904"]},{"location":"rules/raise-without-from-inside-except/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, raise can be used with or without an exception from which the current exception is derived. This is known as exception chaining. When printing the stack trace, chained exceptions are displayed in such a way so as make it easier to trace the exception back to its root cause.

        When raising an exception from within an except clause, always include a from clause to facilitate exception chaining. If the exception is not chained, it will be difficult to trace the exception back to its root cause.

        ","tags":["B904"]},{"location":"rules/raise-without-from-inside-except/#example","title":"Example","text":"
        try:\n    ...\nexcept FileNotFoundError:\n    if ...:\n        raise RuntimeError(\"...\")\n    else:\n        raise UserWarning(\"...\")\n

        Use instead:

        try:\n    ...\nexcept FileNotFoundError as exc:\n    if ...:\n        raise RuntimeError(\"...\") from None\n    else:\n        raise UserWarning(\"...\") from exc\n
        ","tags":["B904"]},{"location":"rules/raise-without-from-inside-except/#references","title":"References","text":"
        • Python documentation: raise statement
        ","tags":["B904"]},{"location":"rules/raw-string-in-exception/","title":"raw-string-in-exception (EM101)","text":"

        Derived from the flake8-errmsg linter.

        Fix is sometimes available.

        ","tags":["EM101"]},{"location":"rules/raw-string-in-exception/#what-it-does","title":"What it does","text":"

        Checks for the use of string literals in exception constructors.

        ","tags":["EM101"]},{"location":"rules/raw-string-in-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Python includes the raise in the default traceback (and formatters like Rich and IPython do too).

        By using a string literal, the error message will be duplicated in the traceback, which can make the traceback less readable.

        ","tags":["EM101"]},{"location":"rules/raw-string-in-exception/#example","title":"Example","text":"

        Given:

        raise RuntimeError(\"'Some value' is incorrect\")\n

        Python will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 2, in <module>\n    raise RuntimeError(\"'Some value' is incorrect\")\nRuntimeError: 'Some value' is incorrect\n

        Instead, assign the string to a variable:

        msg = \"'Some value' is incorrect\"\nraise RuntimeError(msg)\n

        Which will produce a traceback like:

        Traceback (most recent call last):\n  File \"tmp.py\", line 3, in <module>\n    raise RuntimeError(msg)\nRuntimeError: 'Some value' is incorrect\n
        ","tags":["EM101"]},{"location":"rules/re-sub-positional-args/","title":"re-sub-positional-args (B034)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B034"]},{"location":"rules/re-sub-positional-args/#what-it-does","title":"What it does","text":"

        Checks for calls to re.sub, re.subn, and re.split that pass count, maxsplit, or flags as positional arguments.

        ","tags":["B034"]},{"location":"rules/re-sub-positional-args/#why-is-this-bad","title":"Why is this bad?","text":"

        Passing count, maxsplit, or flags as positional arguments to re.sub, re.subn, or re.split can lead to confusion, as most methods in the re module accept flags as the third positional argument, while re.sub, re.subn, and re.split have different signatures.

        Instead, pass count, maxsplit, and flags as keyword arguments.

        ","tags":["B034"]},{"location":"rules/re-sub-positional-args/#example","title":"Example","text":"
        import re\n\nre.split(\"pattern\", \"replacement\", 1)\n

        Use instead:

        import re\n\nre.split(\"pattern\", \"replacement\", maxsplit=1)\n
        ","tags":["B034"]},{"location":"rules/re-sub-positional-args/#references","title":"References","text":"
        • Python documentation: re.sub
        • Python documentation: re.subn
        • Python documentation: re.split
        ","tags":["B034"]},{"location":"rules/read-whole-file/","title":"read-whole-file (FURB101)","text":"

        Derived from the refurb linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB101"]},{"location":"rules/read-whole-file/#what-it-does","title":"What it does","text":"

        Checks for uses of open and read that can be replaced by pathlib methods, like Path.read_text and Path.read_bytes.

        ","tags":["FURB101"]},{"location":"rules/read-whole-file/#why-is-this-bad","title":"Why is this bad?","text":"

        When reading the entire contents of a file into a variable, it's simpler and more concise to use pathlib methods like Path.read_text and Path.read_bytes instead of open and read calls via with statements.

        ","tags":["FURB101"]},{"location":"rules/read-whole-file/#example","title":"Example","text":"
        with open(filename) as f:\n    contents = f.read()\n

        Use instead:

        from pathlib import Path\n\ncontents = Path(filename).read_text()\n
        ","tags":["FURB101"]},{"location":"rules/read-whole-file/#references","title":"References","text":"
        • Python documentation: Path.read_bytes
        • Python documentation: Path.read_text
        ","tags":["FURB101"]},{"location":"rules/readlines-in-for/","title":"readlines-in-for (FURB129)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB129"]},{"location":"rules/readlines-in-for/#what-it-does","title":"What it does","text":"

        Checks for uses of readlines() when iterating over a file line-by-line.

        ","tags":["FURB129"]},{"location":"rules/readlines-in-for/#why-is-this-bad","title":"Why is this bad?","text":"

        Rather than iterating over all lines in a file by calling readlines(), it's more convenient and performant to iterate over the file object directly.

        ","tags":["FURB129"]},{"location":"rules/readlines-in-for/#example","title":"Example","text":"
        with open(\"file.txt\") as fp:\n    for line in fp.readlines():\n        ...\n

        Use instead:

        with open(\"file.txt\") as fp:\n    for line in fp:\n        ...\n
        ","tags":["FURB129"]},{"location":"rules/readlines-in-for/#references","title":"References","text":"
        • Python documentation: io.IOBase.readlines
        ","tags":["FURB129"]},{"location":"rules/redeclared-assigned-name/","title":"redeclared-assigned-name (PLW0128)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0128"]},{"location":"rules/redeclared-assigned-name/#what-it-does","title":"What it does","text":"

        Checks for declared assignments to the same variable multiple times in the same assignment.

        ","tags":["PLW0128"]},{"location":"rules/redeclared-assigned-name/#why-is-this-bad","title":"Why is this bad?","text":"

        Assigning a variable multiple times in the same assignment is redundant, as the final assignment to the variable is what the value will be.

        ","tags":["PLW0128"]},{"location":"rules/redeclared-assigned-name/#example","title":"Example","text":"
        a, b, a = (1, 2, 3)\nprint(a)  # 3\n

        Use instead:

        # this is assuming you want to assign 3 to `a`\n_, b, a = (1, 2, 3)\nprint(a)  # 3\n
        ","tags":["PLW0128"]},{"location":"rules/redefined-argument-from-local/","title":"redefined-argument-from-local (PLR1704)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR1704"]},{"location":"rules/redefined-argument-from-local/#what-it-does","title":"What it does","text":"

        Checks for variables defined in for, try, with statements that redefine function parameters.

        ","tags":["PLR1704"]},{"location":"rules/redefined-argument-from-local/#why-is-this-bad","title":"Why is this bad?","text":"

        Redefined variables can cause unexpected behavior because of overridden function parameters. If nested functions are declared, an inner function's body can override an outer function's parameters.

        ","tags":["PLR1704"]},{"location":"rules/redefined-argument-from-local/#example","title":"Example","text":"
        def show(host_id=10.11):\n    for host_id, host in [[12.13, \"Venus\"], [14.15, \"Mars\"]]:\n        print(host_id, host)\n

        Use instead:

        def show(host_id=10.11):\n    for inner_host_id, host in [[12.13, \"Venus\"], [14.15, \"Mars\"]]:\n        print(host_id, inner_host_id, host)\n
        ","tags":["PLR1704"]},{"location":"rules/redefined-argument-from-local/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["PLR1704"]},{"location":"rules/redefined-argument-from-local/#references","title":"References","text":"
        • Pylint documentation
        ","tags":["PLR1704"]},{"location":"rules/redefined-loop-name/","title":"redefined-loop-name (PLW2901)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW2901"]},{"location":"rules/redefined-loop-name/#what-it-does","title":"What it does","text":"

        Checks for variables defined in for loops and with statements that get overwritten within the body, for example by another for loop or with statement or by direct assignment.

        ","tags":["PLW2901"]},{"location":"rules/redefined-loop-name/#why-is-this-bad","title":"Why is this bad?","text":"

        Redefinition of a loop variable inside the loop's body causes its value to differ from the original loop iteration for the remainder of the block, in a way that will likely cause bugs.

        In Python, unlike many other languages, for loops and with statements don't define their own scopes. Therefore, a nested loop that uses the same target variable name as an outer loop will reuse the same actual variable, and the value from the last iteration will \"leak out\" into the remainder of the enclosing loop.

        While this mistake is easy to spot in small examples, it can be hidden in larger blocks of code, where the definition and redefinition of the variable may not be visible at the same time.

        ","tags":["PLW2901"]},{"location":"rules/redefined-loop-name/#example","title":"Example","text":"
        for i in range(10):\n    i = 9\n    print(i)  # prints 9 every iteration\n\nfor i in range(10):\n    for i in range(10):  # original value overwritten\n        pass\n    print(i)  # also prints 9 every iteration\n\nwith path1.open() as f:\n    with path2.open() as f:\n        f = path2.open()\n    print(f.readline())  # prints a line from path2\n
        ","tags":["PLW2901"]},{"location":"rules/redefined-slots-in-subclass/","title":"redefined-slots-in-subclass (PLW0244)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW0244"]},{"location":"rules/redefined-slots-in-subclass/#what-it-does","title":"What it does","text":"

        Checks for a re-defined slot in a subclass.

        ","tags":["PLW0244"]},{"location":"rules/redefined-slots-in-subclass/#why-is-this-bad","title":"Why is this bad?","text":"

        If a class defines a slot also defined in a base class, the instance variable defined by the base class slot is inaccessible (except by retrieving its descriptor directly from the base class).

        ","tags":["PLW0244"]},{"location":"rules/redefined-slots-in-subclass/#example","title":"Example","text":"
        class Base:\n    __slots__ = (\"a\", \"b\")\n\n\nclass Subclass(Base):\n    __slots__ = (\"a\", \"d\")  # slot \"a\" redefined\n

        Use instead:

        class Base:\n    __slots__ = (\"a\", \"b\")\n\n\nclass Subclass(Base):\n    __slots__ = \"d\"\n
        ","tags":["PLW0244"]},{"location":"rules/redefined-while-unused/","title":"redefined-while-unused (F811)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F811"]},{"location":"rules/redefined-while-unused/#what-it-does","title":"What it does","text":"

        Checks for variable definitions that redefine (or \"shadow\") unused variables.

        ","tags":["F811"]},{"location":"rules/redefined-while-unused/#why-is-this-bad","title":"Why is this bad?","text":"

        Redefinitions of unused names are unnecessary and often indicative of a mistake.

        ","tags":["F811"]},{"location":"rules/redefined-while-unused/#example","title":"Example","text":"
        import foo\nimport bar\nimport foo  # Redefinition of unused `foo` from line 1\n

        Use instead:

        import foo\nimport bar\n
        ","tags":["F811"]},{"location":"rules/redirected-noqa/","title":"redirected-noqa (RUF101)","text":"

        Fix is always available.

        ","tags":["RUF101"]},{"location":"rules/redirected-noqa/#what-it-does","title":"What it does","text":"

        Checks for noqa directives that use redirected rule codes.

        ","tags":["RUF101"]},{"location":"rules/redirected-noqa/#why-is-this-bad","title":"Why is this bad?","text":"

        When one of Ruff's rule codes has been redirected, the implication is that the rule has been deprecated in favor of another rule or code. To keep your codebase consistent and up-to-date, prefer the canonical rule code over the deprecated code.

        ","tags":["RUF101"]},{"location":"rules/redirected-noqa/#example","title":"Example","text":"
        x = eval(command)  # noqa: PGH001\n

        Use instead:

        x = eval(command)  # noqa: S307\n
        ","tags":["RUF101"]},{"location":"rules/redundant-backslash/","title":"redundant-backslash (E502)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E502"]},{"location":"rules/redundant-backslash/#what-it-does","title":"What it does","text":"

        Checks for redundant backslashes between brackets.

        ","tags":["E502"]},{"location":"rules/redundant-backslash/#why-is-this-bad","title":"Why is this bad?","text":"

        Explicit line joins using a backslash are redundant between brackets.

        ","tags":["E502"]},{"location":"rules/redundant-backslash/#example","title":"Example","text":"
        x = (2 + \\\n    2)\n

        Use instead:

        x = (2 +\n    2)\n
        ","tags":["E502"]},{"location":"rules/redundant-bool-literal/","title":"redundant-bool-literal (RUF038)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF038"]},{"location":"rules/redundant-bool-literal/#what-it-does","title":"What it does","text":"

        Checks for Literal[True, False] type annotations.

        ","tags":["RUF038"]},{"location":"rules/redundant-bool-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        Literal[True, False] can be replaced with bool in type annotations, which has the same semantic meaning but is more concise and readable.

        bool type has exactly two constant instances: True and False. Static type checkers such as mypy treat Literal[True, False] as equivalent to bool in a type annotation.

        ","tags":["RUF038"]},{"location":"rules/redundant-bool-literal/#example","title":"Example","text":"
        from typing import Literal\n\nx: Literal[True, False]\ny: Literal[True, False, \"hello\", \"world\"]\n

        Use instead:

        from typing import Literal\n\nx: bool\ny: Literal[\"hello\", \"world\"] | bool\n
        ","tags":["RUF038"]},{"location":"rules/redundant-bool-literal/#fix-safety","title":"Fix safety","text":"

        The fix for this rule is marked as unsafe, as it may change the semantics of the code. Specifically:

        • Type checkers may not treat bool as equivalent when overloading boolean arguments with Literal[True] and Literal[False] (see, e.g., #14764 and #5421).
        • bool is not strictly equivalent to Literal[True, False], as bool is a subclass of int, and this rule may not apply if the type annotations are used in a numeric context.

        Further, the Literal slice may contain trailing-line comments which the fix would remove.

        ","tags":["RUF038"]},{"location":"rules/redundant-bool-literal/#references","title":"References","text":"
        • Typing documentation: Legal parameters for Literal at type check time
        • Python documentation: Boolean type - bool
        ","tags":["RUF038"]},{"location":"rules/redundant-final-literal/","title":"redundant-final-literal (PYI064)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI064"]},{"location":"rules/redundant-final-literal/#what-it-does","title":"What it does","text":"

        Checks for redundant Final[Literal[...]] annotations.

        ","tags":["PYI064"]},{"location":"rules/redundant-final-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        All constant variables annotated as Final are understood as implicitly having Literal types by a type checker. As such, a Final[Literal[...]] annotation can often be replaced with a bare Final, annotation, which will have the same meaning to the type checker while being more concise and more readable.

        ","tags":["PYI064"]},{"location":"rules/redundant-final-literal/#example","title":"Example","text":"
        from typing import Final, Literal\n\nx: Final[Literal[42]]\ny: Final[Literal[42]] = 42\n

        Use instead:

        from typing import Final, Literal\n\nx: Final = 42\ny: Final = 42\n
        ","tags":["PYI064"]},{"location":"rules/redundant-literal-union/","title":"redundant-literal-union (PYI051)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI051"]},{"location":"rules/redundant-literal-union/#what-it-does","title":"What it does","text":"

        Checks for redundant unions between a Literal and a builtin supertype of that Literal.

        ","tags":["PYI051"]},{"location":"rules/redundant-literal-union/#why-is-this-bad","title":"Why is this bad?","text":"

        Using a Literal type in a union with its builtin supertype is redundant, as the supertype will be strictly more general than the Literal type. For example, Literal[\"A\"] | str is equivalent to str, and Literal[1] | int is equivalent to int, as str and int are the supertypes of \"A\" and 1 respectively.

        ","tags":["PYI051"]},{"location":"rules/redundant-literal-union/#example","title":"Example","text":"
        from typing import Literal\n\nx: Literal[\"A\", b\"B\"] | str\n

        Use instead:

        from typing import Literal\n\nx: Literal[b\"B\"] | str\n
        ","tags":["PYI051"]},{"location":"rules/redundant-log-base/","title":"redundant-log-base (FURB163)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        ","tags":["FURB163"]},{"location":"rules/redundant-log-base/#what-it-does","title":"What it does","text":"

        Checks for math.log calls with a redundant base.

        ","tags":["FURB163"]},{"location":"rules/redundant-log-base/#why-is-this-bad","title":"Why is this bad?","text":"

        The default base of math.log is e, so specifying it explicitly is redundant.

        Instead of passing 2 or 10 as the base, use math.log2 or math.log10 respectively, as these dedicated variants are typically more accurate than math.log.

        ","tags":["FURB163"]},{"location":"rules/redundant-log-base/#example","title":"Example","text":"
        import math\n\nmath.log(4, math.e)\nmath.log(4, 2)\nmath.log(4, 10)\n

        Use instead:

        import math\n\nmath.log(4)\nmath.log2(4)\nmath.log10(4)\n
        ","tags":["FURB163"]},{"location":"rules/redundant-log-base/#references","title":"References","text":"
        • Python documentation: math.log
        • Python documentation: math.log2
        • Python documentation: math.log10
        • Python documentation: math.e
        ","tags":["FURB163"]},{"location":"rules/redundant-none-literal/","title":"redundant-none-literal (PYI061)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PYI061"]},{"location":"rules/redundant-none-literal/#what-it-does","title":"What it does","text":"

        Checks for redundant Literal[None] annotations.

        ","tags":["PYI061"]},{"location":"rules/redundant-none-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        While Literal[None] is a valid type annotation, it is semantically equivalent to None. Prefer None over Literal[None] for both consistency and readability.

        ","tags":["PYI061"]},{"location":"rules/redundant-none-literal/#example","title":"Example","text":"
        from typing import Literal\n\nLiteral[None]\nLiteral[1, 2, 3, \"foo\", 5, None]\n

        Use instead:

        from typing import Literal\n\nNone\nLiteral[1, 2, 3, \"foo\", 5] | None\n
        ","tags":["PYI061"]},{"location":"rules/redundant-none-literal/#fix-safety-and-availability","title":"Fix safety and availability","text":"

        This rule's fix is marked as safe unless the literal contains comments.

        There is currently no fix available when applying the fix would lead to a TypeError from an expression of the form None | None or when we are unable to import the symbol typing.Optional and the Python version is 3.9 or below.

        ","tags":["PYI061"]},{"location":"rules/redundant-none-literal/#references","title":"References","text":"
        • Typing documentation: Legal parameters for Literal at type check time
        ","tags":["PYI061"]},{"location":"rules/redundant-numeric-union/","title":"redundant-numeric-union (PYI041)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI041"]},{"location":"rules/redundant-numeric-union/#what-it-does","title":"What it does","text":"

        Checks for parameter annotations that contain redundant unions between builtin numeric types (e.g., int | float).

        ","tags":["PYI041"]},{"location":"rules/redundant-numeric-union/#why-is-this-bad","title":"Why is this bad?","text":"

        The typing specification states:

        Python\u2019s numeric types complex, float and int are not subtypes of each other, but to support common use cases, the type system contains a straightforward shortcut: when an argument is annotated as having type float, an argument of type int is acceptable; similar, for an argument annotated as having type complex, arguments of type float or int are acceptable.

        As such, a union that includes both int and float is redundant in the specific context of a parameter annotation, as it is equivalent to a union that only includes float. For readability and clarity, unions should omit redundant elements.

        ","tags":["PYI041"]},{"location":"rules/redundant-numeric-union/#example","title":"Example","text":"
        def foo(x: float | int | str) -> None: ...\n

        Use instead:

        def foo(x: float | str) -> None: ...\n
        ","tags":["PYI041"]},{"location":"rules/redundant-numeric-union/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the type annotation contains comments.

        Note that while the fix may flatten nested unions into a single top-level union, the semantics of the annotation will remain unchanged.

        ","tags":["PYI041"]},{"location":"rules/redundant-numeric-union/#references","title":"References","text":"
        • Python documentation: The numeric tower
        • PEP 484: The numeric tower
        ","tags":["PYI041"]},{"location":"rules/redundant-open-modes/","title":"redundant-open-modes (UP015)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP015"]},{"location":"rules/redundant-open-modes/#what-it-does","title":"What it does","text":"

        Checks for redundant open mode arguments.

        ","tags":["UP015"]},{"location":"rules/redundant-open-modes/#why-is-this-bad","title":"Why is this bad?","text":"

        Redundant open mode arguments are unnecessary and should be removed to avoid confusion.

        ","tags":["UP015"]},{"location":"rules/redundant-open-modes/#example","title":"Example","text":"
        with open(\"foo.txt\", \"r\") as f:\n    ...\n

        Use instead:

        with open(\"foo.txt\") as f:\n    ...\n
        ","tags":["UP015"]},{"location":"rules/redundant-open-modes/#references","title":"References","text":"
        • Python documentation: open
        ","tags":["UP015"]},{"location":"rules/redundant-tuple-in-exception-handler/","title":"redundant-tuple-in-exception-handler (B013)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B013"]},{"location":"rules/redundant-tuple-in-exception-handler/#what-it-does","title":"What it does","text":"

        Checks for single-element tuples in exception handlers (e.g., except (ValueError,):).

        Note: Single-element tuples consisting of a starred expression are allowed.

        ","tags":["B013"]},{"location":"rules/redundant-tuple-in-exception-handler/#why-is-this-bad","title":"Why is this bad?","text":"

        A tuple with a single element can be more concisely and idiomatically expressed as a single value.

        ","tags":["B013"]},{"location":"rules/redundant-tuple-in-exception-handler/#example","title":"Example","text":"
        try:\n    ...\nexcept (ValueError,):\n    ...\n

        Use instead:

        try:\n    ...\nexcept ValueError:\n    ...\n
        ","tags":["B013"]},{"location":"rules/redundant-tuple-in-exception-handler/#references","title":"References","text":"
        • Python documentation: except clause
        ","tags":["B013"]},{"location":"rules/regex-flag-alias/","title":"regex-flag-alias (FURB167)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB167"]},{"location":"rules/regex-flag-alias/#what-it-does","title":"What it does","text":"

        Checks for the use of shorthand aliases for regular expression flags (e.g., re.I instead of re.IGNORECASE).

        ","tags":["FURB167"]},{"location":"rules/regex-flag-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        The regular expression module provides descriptive names for each flag, along with single-letter aliases. Prefer the descriptive names, as they are more readable and self-documenting.

        ","tags":["FURB167"]},{"location":"rules/regex-flag-alias/#example","title":"Example","text":"
        import re\n\nif re.match(\"^hello\", \"hello world\", re.I):\n    ...\n

        Use instead:

        import re\n\nif re.match(\"^hello\", \"hello world\", re.IGNORECASE):\n    ...\n
        ","tags":["FURB167"]},{"location":"rules/reimplemented-builtin/","title":"reimplemented-builtin (SIM110)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM110"]},{"location":"rules/reimplemented-builtin/#what-it-does","title":"What it does","text":"

        Checks for for loops that can be replaced with a builtin function, like any or all.

        ","tags":["SIM110"]},{"location":"rules/reimplemented-builtin/#why-is-this-bad","title":"Why is this bad?","text":"

        Using a builtin function is more concise and readable.

        ","tags":["SIM110"]},{"location":"rules/reimplemented-builtin/#example","title":"Example","text":"
        for item in iterable:\n    if predicate(item):\n        return True\nreturn False\n

        Use instead:

        return any(predicate(item) for item in iterable)\n
        ","tags":["SIM110"]},{"location":"rules/reimplemented-builtin/#fix-safety","title":"Fix safety","text":"

        This fix is always marked as unsafe because it might remove comments.

        ","tags":["SIM110"]},{"location":"rules/reimplemented-builtin/#references","title":"References","text":"
        • Python documentation: any
        • Python documentation: all
        ","tags":["SIM110"]},{"location":"rules/reimplemented-container-builtin/","title":"reimplemented-container-builtin (PIE807)","text":"

        Derived from the flake8-pie linter.

        Fix is sometimes available.

        ","tags":["PIE807"]},{"location":"rules/reimplemented-container-builtin/#what-it-does","title":"What it does","text":"

        Checks for lambdas that can be replaced with the list or dict builtins.

        ","tags":["PIE807"]},{"location":"rules/reimplemented-container-builtin/#why-is-this-bad","title":"Why is this bad?","text":"

        Using container builtins are more succinct and idiomatic than wrapping the literal in a lambda.

        ","tags":["PIE807"]},{"location":"rules/reimplemented-container-builtin/#example","title":"Example","text":"
        from dataclasses import dataclass, field\n\n\n@dataclass\nclass Foo:\n    bar: list[int] = field(default_factory=lambda: [])\n

        Use instead:

        from dataclasses import dataclass, field\n\n\n@dataclass\nclass Foo:\n    bar: list[int] = field(default_factory=list)\n    baz: dict[str, int] = field(default_factory=dict)\n
        ","tags":["PIE807"]},{"location":"rules/reimplemented-container-builtin/#references","title":"References","text":"
        • Python documentation: list
        ","tags":["PIE807"]},{"location":"rules/reimplemented-operator/","title":"reimplemented-operator (FURB118)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB118"]},{"location":"rules/reimplemented-operator/#what-it-does","title":"What it does","text":"

        Checks for lambda expressions and function definitions that can be replaced with a function from the operator module.

        ","tags":["FURB118"]},{"location":"rules/reimplemented-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        The operator module provides functions that implement the same functionality as the corresponding operators. For example, operator.add is often equivalent to lambda x, y: x + y. Using the functions from the operator module is more concise and communicates the intent of the code more clearly.

        ","tags":["FURB118"]},{"location":"rules/reimplemented-operator/#example","title":"Example","text":"
        import functools\n\nnums = [1, 2, 3]\ntotal = functools.reduce(lambda x, y: x + y, nums)\n

        Use instead:

        import functools\nimport operator\n\nnums = [1, 2, 3]\ntotal = functools.reduce(operator.add, nums)\n
        ","tags":["FURB118"]},{"location":"rules/reimplemented-operator/#fix-safety","title":"Fix safety","text":"

        The fix offered by this rule is always marked as unsafe. While the changes the fix would make would rarely break your code, there are two ways in which functions from the operator module differ from user-defined functions. It would be non-trivial for Ruff to detect whether or not these differences would matter in a specific situation where Ruff is emitting a diagnostic for this rule.

        The first difference is that operator functions cannot be called with keyword arguments, but most user-defined functions can. If an add function is defined as add = lambda x, y: x + y, replacing this function with operator.add will cause the later call to raise TypeError if the function is later called with keyword arguments, e.g. add(x=1, y=2).

        The second difference is that user-defined functions are descriptors, but this is not true of the functions defined in the operator module. Practically speaking, this means that defining a function in a class body (either by using a def statement or assigning a lambda function to a variable) is a valid way of defining an instance method on that class; monkeypatching a user-defined function onto a class after the class has been created also has the same effect. The same is not true of an operator function: assigning an operator function to a variable in a class body or monkeypatching one onto a class will not create a valid instance method. Ruff will refrain from emitting diagnostics for this rule on function definitions in class bodies; however, it does not currently have sophisticated enough type inference to avoid emitting this diagnostic if a user-defined function is being monkeypatched onto a class after the class has been constructed.

        ","tags":["FURB118"]},{"location":"rules/reimplemented-starmap/","title":"reimplemented-starmap (FURB140)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB140"]},{"location":"rules/reimplemented-starmap/#what-it-does","title":"What it does","text":"

        Checks for generator expressions, list and set comprehensions that can be replaced with itertools.starmap.

        ","tags":["FURB140"]},{"location":"rules/reimplemented-starmap/#why-is-this-bad","title":"Why is this bad?","text":"

        When unpacking values from iterators to pass them directly to a function, prefer itertools.starmap.

        Using itertools.starmap is more concise and readable. Furthermore, it is more efficient than generator expressions, and in some versions of Python, it is more efficient than comprehensions.

        ","tags":["FURB140"]},{"location":"rules/reimplemented-starmap/#known-problems","title":"Known problems","text":"

        Since Python 3.12, itertools.starmap is less efficient than comprehensions (#7771). This is due to PEP 709, which made comprehensions faster.

        ","tags":["FURB140"]},{"location":"rules/reimplemented-starmap/#example","title":"Example","text":"
        all(predicate(a, b) for a, b in some_iterable)\n

        Use instead:

        from itertools import starmap\n\n\nall(starmap(predicate, some_iterable))\n
        ","tags":["FURB140"]},{"location":"rules/reimplemented-starmap/#references","title":"References","text":"
        • Python documentation: itertools.starmap
        ","tags":["FURB140"]},{"location":"rules/relative-imports/","title":"relative-imports (TID252)","text":"

        Derived from the flake8-tidy-imports linter.

        Fix is sometimes available.

        ","tags":["TID252"]},{"location":"rules/relative-imports/#what-it-does","title":"What it does","text":"

        Checks for relative imports.

        ","tags":["TID252"]},{"location":"rules/relative-imports/#why-is-this-bad","title":"Why is this bad?","text":"

        Absolute imports, or relative imports from siblings, are recommended by PEP 8:

        Absolute imports are recommended, as they are usually more readable and tend to be better behaved...

        import mypkg.sibling\nfrom mypkg import sibling\nfrom mypkg.sibling import example\n

        However, explicit relative imports are an acceptable alternative to absolute imports, especially when dealing with complex package layouts where using absolute imports would be unnecessarily verbose:

        from . import sibling\nfrom .sibling import example\n
        ","tags":["TID252"]},{"location":"rules/relative-imports/#example","title":"Example","text":"
        from .. import foo\n

        Use instead:

        from mypkg import foo\n
        ","tags":["TID252"]},{"location":"rules/relative-imports/#options","title":"Options","text":"
        • lint.flake8-tidy-imports.ban-relative-imports
        ","tags":["TID252"]},{"location":"rules/repeated-append/","title":"repeated-append (FURB113)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB113"]},{"location":"rules/repeated-append/#what-it-does","title":"What it does","text":"

        Checks for consecutive calls to append.

        ","tags":["FURB113"]},{"location":"rules/repeated-append/#why-is-this-bad","title":"Why is this bad?","text":"

        Consecutive calls to append can be less efficient than batching them into a single extend. Each append resizes the list individually, whereas an extend can resize the list once for all elements.

        ","tags":["FURB113"]},{"location":"rules/repeated-append/#known-problems","title":"Known problems","text":"

        This rule is prone to false negatives due to type inference limitations, as it will only detect lists that are instantiated as literals or annotated with a type annotation.

        ","tags":["FURB113"]},{"location":"rules/repeated-append/#example","title":"Example","text":"
        nums = [1, 2, 3]\n\nnums.append(4)\nnums.append(5)\nnums.append(6)\n

        Use instead:

        nums = [1, 2, 3]\n\nnums.extend((4, 5, 6))\n
        ","tags":["FURB113"]},{"location":"rules/repeated-append/#references","title":"References","text":"
        • Python documentation: More on Lists
        ","tags":["FURB113"]},{"location":"rules/repeated-equality-comparison/","title":"repeated-equality-comparison (PLR1714)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLR1714"]},{"location":"rules/repeated-equality-comparison/#what-it-does","title":"What it does","text":"

        Checks for repeated equality comparisons that can be rewritten as a membership test.

        This rule will try to determine if the values are hashable and the fix will use a set if they are. If unable to determine, the fix will use a tuple and suggest the use of a set.

        ","tags":["PLR1714"]},{"location":"rules/repeated-equality-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        To check if a variable is equal to one of many values, it is common to write a series of equality comparisons (e.g., foo == \"bar\" or foo == \"baz\").

        Instead, prefer to combine the values into a collection and use the in operator to check for membership, which is more performant and succinct. If the items are hashable, use a set for efficiency; otherwise, use a tuple.

        ","tags":["PLR1714"]},{"location":"rules/repeated-equality-comparison/#example","title":"Example","text":"
        foo == \"bar\" or foo == \"baz\" or foo == \"qux\"\n

        Use instead:

        foo in {\"bar\", \"baz\", \"qux\"}\n
        ","tags":["PLR1714"]},{"location":"rules/repeated-equality-comparison/#references","title":"References","text":"
        • Python documentation: Comparisons
        • Python documentation: Membership test operations
        • Python documentation: set
        ","tags":["PLR1714"]},{"location":"rules/repeated-global/","title":"repeated-global (FURB154)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB154"]},{"location":"rules/repeated-global/#what-it-does","title":"What it does","text":"

        Checks for consecutive global (or nonlocal) statements.

        ","tags":["FURB154"]},{"location":"rules/repeated-global/#why-is-this-bad","title":"Why is this bad?","text":"

        The global and nonlocal keywords accepts multiple comma-separated names. Instead of using multiple global (or nonlocal) statements for separate variables, you can use a single statement to declare multiple variables at once.

        ","tags":["FURB154"]},{"location":"rules/repeated-global/#example","title":"Example","text":"
        def func():\n    global x\n    global y\n\n    print(x, y)\n

        Use instead:

        def func():\n    global x, y\n\n    print(x, y)\n
        ","tags":["FURB154"]},{"location":"rules/repeated-global/#references","title":"References","text":"
        • Python documentation: the global statement
        • Python documentation: the nonlocal statement
        ","tags":["FURB154"]},{"location":"rules/repeated-isinstance-calls/","title":"repeated-isinstance-calls (PLR1701)","text":"

        Derived from the Pylint linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        Fix is always available.

        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#removed","title":"Removed","text":"

        This rule is identical to SIM101 which should be used instead.

        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#what-it-does","title":"What it does","text":"

        Checks for repeated isinstance calls on the same object.

        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#why-is-this-bad","title":"Why is this bad?","text":"

        Repeated isinstance calls on the same object can be merged into a single call.

        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe on Python 3.10 and later, as combining multiple isinstance calls with a binary operator (|) will fail at runtime if any of the operands are themselves tuples.

        For example, given TYPES = (dict, list), then isinstance(None, TYPES | set | float) will raise a TypeError at runtime, while isinstance(None, set | float) will not.

        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#example","title":"Example","text":"
        def is_number(x):\n    return isinstance(x, int) or isinstance(x, float) or isinstance(x, complex)\n

        Use instead:

        def is_number(x):\n    return isinstance(x, (int, float, complex))\n

        Or, for Python 3.10 and later:

        def is_number(x):\n    return isinstance(x, int | float | complex)\n
        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#options","title":"Options","text":"
        • target-version
        ","tags":["PLR1701"]},{"location":"rules/repeated-isinstance-calls/#references","title":"References","text":"
        • Python documentation: isinstance
        ","tags":["PLR1701"]},{"location":"rules/repeated-keyword-argument/","title":"repeated-keyword-argument (PLE1132)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1132"]},{"location":"rules/repeated-keyword-argument/#what-it-does","title":"What it does","text":"

        Checks for repeated keyword arguments in function calls.

        ","tags":["PLE1132"]},{"location":"rules/repeated-keyword-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        Python does not allow repeated keyword arguments in function calls. If a function is called with the same keyword argument multiple times, the interpreter will raise an exception.

        ","tags":["PLE1132"]},{"location":"rules/repeated-keyword-argument/#example","title":"Example","text":"
        func(1, 2, c=3, **{\"c\": 4})\n
        ","tags":["PLE1132"]},{"location":"rules/repeated-keyword-argument/#references","title":"References","text":"
        • Python documentation: Argument
        ","tags":["PLE1132"]},{"location":"rules/replace-stdout-stderr/","title":"replace-stdout-stderr (UP022)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP022"]},{"location":"rules/replace-stdout-stderr/#what-it-does","title":"What it does","text":"

        Checks for uses of subprocess.run that send stdout and stderr to a pipe.

        ","tags":["UP022"]},{"location":"rules/replace-stdout-stderr/#why-is-this-bad","title":"Why is this bad?","text":"

        As of Python 3.7, subprocess.run has a capture_output keyword argument that can be set to True to capture stdout and stderr outputs. This is equivalent to setting stdout and stderr to subprocess.PIPE, but is more explicit and readable.

        ","tags":["UP022"]},{"location":"rules/replace-stdout-stderr/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.run([\"foo\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n

        Use instead:

        import subprocess\n\nsubprocess.run([\"foo\"], capture_output=True)\n
        ","tags":["UP022"]},{"location":"rules/replace-stdout-stderr/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because replacing stdout=subprocess.PIPE and stderr=subprocess.PIPE with capture_output=True may delete comments attached to the original arguments.

        ","tags":["UP022"]},{"location":"rules/replace-stdout-stderr/#references","title":"References","text":"
        • Python 3.7 release notes
        • Python documentation: subprocess.run
        ","tags":["UP022"]},{"location":"rules/replace-str-enum/","title":"replace-str-enum (UP042)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["UP042"]},{"location":"rules/replace-str-enum/#what-it-does","title":"What it does","text":"

        Checks for classes that inherit from both str and enum.Enum.

        ","tags":["UP042"]},{"location":"rules/replace-str-enum/#why-is-this-bad","title":"Why is this bad?","text":"

        Python 3.11 introduced enum.StrEnum, which is preferred over inheriting from both str and enum.Enum.

        ","tags":["UP042"]},{"location":"rules/replace-str-enum/#example","title":"Example","text":"
        import enum\n\n\nclass Foo(str, enum.Enum): ...\n

        Use instead:

        import enum\n\n\nclass Foo(enum.StrEnum): ...\n
        ","tags":["UP042"]},{"location":"rules/replace-str-enum/#fix-safety","title":"Fix safety","text":"

        Python 3.11 introduced a breaking change for enums that inherit from both str and enum.Enum. Consider the following enum:

        from enum import Enum\n\n\nclass Foo(str, Enum):\n    BAR = \"bar\"\n

        In Python 3.11, the formatted representation of Foo.BAR changed as follows:

        # Python 3.10\nf\"{Foo.BAR}\"  # > bar\n# Python 3.11\nf\"{Foo.BAR}\"  # > Foo.BAR\n

        Migrating from str and enum.Enum to enum.StrEnum will restore the previous behavior, such that:

        from enum import StrEnum\n\n\nclass Foo(StrEnum):\n    BAR = \"bar\"\n\n\nf\"{Foo.BAR}\"  # > bar\n

        As such, migrating to enum.StrEnum will introduce a behavior change for code that relies on the Python 3.11 behavior.

        ","tags":["UP042"]},{"location":"rules/replace-str-enum/#references","title":"References","text":"
        • enum.StrEnum
        ","tags":["UP042"]},{"location":"rules/replace-universal-newlines/","title":"replace-universal-newlines (UP021)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP021"]},{"location":"rules/replace-universal-newlines/#what-it-does","title":"What it does","text":"

        Checks for uses of subprocess.run that set the universal_newlines keyword argument.

        ","tags":["UP021"]},{"location":"rules/replace-universal-newlines/#why-is-this-bad","title":"Why is this bad?","text":"

        As of Python 3.7, the universal_newlines keyword argument has been renamed to text, and now exists for backwards compatibility. The universal_newlines keyword argument may be removed in a future version of Python. Prefer text, which is more explicit and readable.

        ","tags":["UP021"]},{"location":"rules/replace-universal-newlines/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.run([\"foo\"], universal_newlines=True)\n

        Use instead:

        import subprocess\n\nsubprocess.run([\"foo\"], text=True)\n
        ","tags":["UP021"]},{"location":"rules/replace-universal-newlines/#references","title":"References","text":"
        • Python 3.7 release notes
        • Python documentation: subprocess.run
        ","tags":["UP021"]},{"location":"rules/request-with-no-cert-validation/","title":"request-with-no-cert-validation (S501)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S501"]},{"location":"rules/request-with-no-cert-validation/#what-it-does","title":"What it does","text":"

        Checks for HTTPS requests that disable SSL certificate checks.

        ","tags":["S501"]},{"location":"rules/request-with-no-cert-validation/#why-is-this-bad","title":"Why is this bad?","text":"

        If SSL certificates are not verified, an attacker could perform a \"man in the middle\" attack by intercepting and modifying traffic between the client and server.

        ","tags":["S501"]},{"location":"rules/request-with-no-cert-validation/#example","title":"Example","text":"
        import requests\n\nrequests.get(\"https://www.example.com\", verify=False)\n

        Use instead:

        import requests\n\nrequests.get(\"https://www.example.com\")  # By default, `verify=True`.\n
        ","tags":["S501"]},{"location":"rules/request-with-no-cert-validation/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-295
        ","tags":["S501"]},{"location":"rules/request-without-timeout/","title":"request-without-timeout (S113)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S113"]},{"location":"rules/request-without-timeout/#what-it-does","title":"What it does","text":"

        Checks for uses of the Python requests or httpx module that omit the timeout parameter.

        ","tags":["S113"]},{"location":"rules/request-without-timeout/#why-is-this-bad","title":"Why is this bad?","text":"

        The timeout parameter is used to set the maximum time to wait for a response from the server. By omitting the timeout parameter, the program may hang indefinitely while awaiting a response.

        ","tags":["S113"]},{"location":"rules/request-without-timeout/#example","title":"Example","text":"
        import requests\n\nrequests.get(\"https://www.example.com/\")\n

        Use instead:

        import requests\n\nrequests.get(\"https://www.example.com/\", timeout=10)\n
        ","tags":["S113"]},{"location":"rules/request-without-timeout/#references","title":"References","text":"
        • Requests documentation: Timeouts
        • httpx documentation: Timeouts
        ","tags":["S113"]},{"location":"rules/reraise-no-cause/","title":"reraise-no-cause (TRY200)","text":"

        Derived from the tryceratops linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["TRY200"]},{"location":"rules/reraise-no-cause/#removed","title":"Removed","text":"

        This rule is identical to B904 which should be used instead.

        ","tags":["TRY200"]},{"location":"rules/reraise-no-cause/#what-it-does","title":"What it does","text":"

        Checks for exceptions that are re-raised without specifying the cause via the from keyword.

        ","tags":["TRY200"]},{"location":"rules/reraise-no-cause/#why-is-this-bad","title":"Why is this bad?","text":"

        The from keyword sets the __cause__ attribute of the exception, which stores the \"cause\" of the exception. The availability of an exception \"cause\" is useful for debugging.

        ","tags":["TRY200"]},{"location":"rules/reraise-no-cause/#example","title":"Example","text":"
        def reciprocal(n):\n    try:\n        return 1 / n\n    except ZeroDivisionError:\n        raise ValueError()\n

        Use instead:

        def reciprocal(n):\n    try:\n        return 1 / n\n    except ZeroDivisionError as exc:\n        raise ValueError() from exc\n
        ","tags":["TRY200"]},{"location":"rules/reraise-no-cause/#references","title":"References","text":"
        • Python documentation: Exception context
        ","tags":["TRY200"]},{"location":"rules/return-in-generator/","title":"return-in-generator (B901)","text":"

        Derived from the flake8-bugbear linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["B901"]},{"location":"rules/return-in-generator/#what-it-does","title":"What it does","text":"

        Checks for return {value} statements in functions that also contain yield or yield from statements.

        ","tags":["B901"]},{"location":"rules/return-in-generator/#why-is-this-bad","title":"Why is this bad?","text":"

        Using return {value} in a generator function was syntactically invalid in Python 2. In Python 3 return {value} can be used in a generator; however, the combination of yield and return can lead to confusing behavior, as the return statement will cause the generator to raise StopIteration with the value provided, rather than returning the value to the caller.

        For example, given:

        from collections.abc import Iterable\nfrom pathlib import Path\n\n\ndef get_file_paths(file_types: Iterable[str] | None = None) -> Iterable[Path]:\n    dir_path = Path(\".\")\n    if file_types is None:\n        return dir_path.glob(\"*\")\n\n    for file_type in file_types:\n        yield from dir_path.glob(f\"*.{file_type}\")\n

        Readers might assume that get_file_paths() would return an iterable of Path objects in the directory; in reality, though, list(get_file_paths()) evaluates to [], since the return statement causes the generator to raise StopIteration with the value dir_path.glob(\"*\"):

        >>> list(get_file_paths(file_types=[\"cfg\", \"toml\"]))\n[PosixPath('setup.cfg'), PosixPath('pyproject.toml')]\n>>> list(get_file_paths())\n[]\n

        For intentional uses of return in a generator, consider suppressing this diagnostic.

        ","tags":["B901"]},{"location":"rules/return-in-generator/#example","title":"Example","text":"
        from collections.abc import Iterable\nfrom pathlib import Path\n\n\ndef get_file_paths(file_types: Iterable[str] | None = None) -> Iterable[Path]:\n    dir_path = Path(\".\")\n    if file_types is None:\n        return dir_path.glob(\"*\")\n\n    for file_type in file_types:\n        yield from dir_path.glob(f\"*.{file_type}\")\n

        Use instead:

        from collections.abc import Iterable\nfrom pathlib import Path\n\n\ndef get_file_paths(file_types: Iterable[str] | None = None) -> Iterable[Path]:\n    dir_path = Path(\".\")\n    if file_types is None:\n        yield from dir_path.glob(\"*\")\n    else:\n        for file_type in file_types:\n            yield from dir_path.glob(f\"*.{file_type}\")\n
        ","tags":["B901"]},{"location":"rules/return-in-init/","title":"return-in-init (PLE0101)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0101"]},{"location":"rules/return-in-init/#what-it-does","title":"What it does","text":"

        Checks for __init__ methods that return values.

        ","tags":["PLE0101"]},{"location":"rules/return-in-init/#why-is-this-bad","title":"Why is this bad?","text":"

        The __init__ method is the constructor for a given Python class, responsible for initializing, rather than creating, new objects.

        The __init__ method has to return None. Returning any value from an __init__ method will result in a runtime error.

        ","tags":["PLE0101"]},{"location":"rules/return-in-init/#example","title":"Example","text":"
        class Example:\n    def __init__(self):\n        return []\n

        Use instead:

        class Example:\n    def __init__(self):\n        self.value = []\n
        ","tags":["PLE0101"]},{"location":"rules/return-in-init/#references","title":"References","text":"
        • CodeQL: py-explicit-return-in-init
        ","tags":["PLE0101"]},{"location":"rules/return-in-try-except-finally/","title":"return-in-try-except-finally (SIM107)","text":"

        Derived from the flake8-simplify linter.

        ","tags":["SIM107"]},{"location":"rules/return-in-try-except-finally/#what-it-does","title":"What it does","text":"

        Checks for return statements in try-except and finally blocks.

        ","tags":["SIM107"]},{"location":"rules/return-in-try-except-finally/#why-is-this-bad","title":"Why is this bad?","text":"

        The return statement in a finally block will always be executed, even if an exception is raised in the try or except block. This can lead to unexpected behavior.

        ","tags":["SIM107"]},{"location":"rules/return-in-try-except-finally/#example","title":"Example","text":"
        def squared(n):\n    try:\n        sqr = n**2\n        return sqr\n    except Exception:\n        return \"An exception occurred\"\n    finally:\n        return -1  # Always returns -1.\n

        Use instead:

        def squared(n):\n    try:\n        return_value = n**2\n    except Exception:\n        return_value = \"An exception occurred\"\n    finally:\n        return_value = -1\n    return return_value\n
        ","tags":["SIM107"]},{"location":"rules/return-in-try-except-finally/#references","title":"References","text":"
        • Python documentation: Defining Clean-up Actions
        ","tags":["SIM107"]},{"location":"rules/return-outside-function/","title":"return-outside-function (F706)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F706"]},{"location":"rules/return-outside-function/#what-it-does","title":"What it does","text":"

        Checks for return statements outside of functions.

        ","tags":["F706"]},{"location":"rules/return-outside-function/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of a return statement outside of a function will raise a SyntaxError.

        ","tags":["F706"]},{"location":"rules/return-outside-function/#example","title":"Example","text":"
        class Foo:\n    return 1\n
        ","tags":["F706"]},{"location":"rules/return-outside-function/#references","title":"References","text":"
        • Python documentation: return
        ","tags":["F706"]},{"location":"rules/reuse-of-groupby-generator/","title":"reuse-of-groupby-generator (B031)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B031"]},{"location":"rules/reuse-of-groupby-generator/#what-it-does","title":"What it does","text":"

        Checks for multiple usage of the generator returned from itertools.groupby().

        ","tags":["B031"]},{"location":"rules/reuse-of-groupby-generator/#why-is-this-bad","title":"Why is this bad?","text":"

        Using the generator more than once will do nothing on the second usage. If that data is needed later, it should be stored as a list.

        ","tags":["B031"]},{"location":"rules/reuse-of-groupby-generator/#example","title":"Example:","text":"
        import itertools\n\nfor name, group in itertools.groupby(data):\n    for _ in range(5):\n        do_something_with_the_group(group)\n

        Use instead:

        import itertools\n\nfor name, group in itertools.groupby(data):\n    values = list(group)\n    for _ in range(5):\n        do_something_with_the_group(values)\n
        ","tags":["B031"]},{"location":"rules/root-logger-call/","title":"root-logger-call (LOG015)","text":"

        Derived from the flake8-logging linter.

        ","tags":["LOG015"]},{"location":"rules/root-logger-call/#what-it-does","title":"What it does","text":"

        Checks for usages of the following logging top-level functions: debug, info, warn, warning, error, critical, log, exception.

        ","tags":["LOG015"]},{"location":"rules/root-logger-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Using the root logger causes the messages to have no source information, making them less useful for debugging.

        ","tags":["LOG015"]},{"location":"rules/root-logger-call/#example","title":"Example","text":"
        import logging\n\nlogging.info(\"Foobar\")\n

        Use instead:

        import logging\n\nlogger = logging.getLogger(__name__)\nlogger.info(\"Foobar\")\n
        ","tags":["LOG015"]},{"location":"rules/ruff-static-key-dict-comprehension/","title":"ruff-static-key-dict-comprehension (RUF011)","text":"

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["RUF011"]},{"location":"rules/ruff-static-key-dict-comprehension/#removed","title":"Removed","text":"

        This rule was implemented in flake8-bugbear and has been remapped to B035

        ","tags":["RUF011"]},{"location":"rules/ruff-static-key-dict-comprehension/#what-it-does","title":"What it does","text":"

        Checks for dictionary comprehensions that use a static key, like a string literal or a variable defined outside the comprehension.

        ","tags":["RUF011"]},{"location":"rules/ruff-static-key-dict-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        Using a static key (like a string literal) in a dictionary comprehension is usually a mistake, as it will result in a dictionary with only one key, despite the comprehension iterating over multiple values.

        ","tags":["RUF011"]},{"location":"rules/ruff-static-key-dict-comprehension/#example","title":"Example","text":"
        data = [\"some\", \"Data\"]\n{\"key\": value.upper() for value in data}\n

        Use instead:

        data = [\"some\", \"Data\"]\n{value: value.upper() for value in data}\n
        ","tags":["RUF011"]},{"location":"rules/ruff-unsafe-markup-use/","title":"ruff-unsafe-markup-use (RUF035)","text":"

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#removed","title":"Removed","text":"

        This rule was implemented in bandit and has been remapped to S704

        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#what-it-does","title":"What it does","text":"

        Checks for non-literal strings being passed to markupsafe.Markup.

        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#why-is-this-bad","title":"Why is this bad?","text":"

        markupsafe.Markup does not perform any escaping, so passing dynamic content, like f-strings, variables or interpolated strings will potentially lead to XSS vulnerabilities.

        Instead you should interpolate the Markup object.

        Using lint.flake8-bandit.extend-markup-names additional objects can be treated like Markup.

        This rule was originally inspired by flake8-markupsafe but doesn't carve out any exceptions for i18n related calls by default.

        You can use lint.flake8-bandit.allowed-markup-calls to specify exceptions.

        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#example","title":"Example","text":"

        Given:

        from markupsafe import Markup\n\ncontent = \"<script>alert('Hello, world!')</script>\"\nhtml = Markup(f\"<b>{content}</b>\")  # XSS\n

        Use instead:

        from markupsafe import Markup\n\ncontent = \"<script>alert('Hello, world!')</script>\"\nhtml = Markup(\"<b>{}</b>\").format(content)  # Safe\n

        Given:

        from markupsafe import Markup\n\nlines = [\n    Markup(\"<b>heading</b>\"),\n    \"<script>alert('XSS attempt')</script>\",\n]\nhtml = Markup(\"<br>\".join(lines))  # XSS\n

        Use instead:

        from markupsafe import Markup\n\nlines = [\n    Markup(\"<b>heading</b>\"),\n    \"<script>alert('XSS attempt')</script>\",\n]\nhtml = Markup(\"<br>\").join(lines)  # Safe\n
        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#options","title":"Options","text":"
        • lint.flake8-bandit.extend-markup-names
        • lint.flake8-bandit.allowed-markup-calls
        ","tags":["RUF035"]},{"location":"rules/ruff-unsafe-markup-use/#references","title":"References","text":"
        • MarkupSafe on PyPI
        • markupsafe.Markup API documentation
        ","tags":["RUF035"]},{"location":"rules/run-process-in-async-function/","title":"run-process-in-async-function (ASYNC221)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC221"]},{"location":"rules/run-process-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not run processes with blocking methods.

        ","tags":["ASYNC221"]},{"location":"rules/run-process-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a blocking call will block the entire event loop, preventing it from executing other tasks while waiting for the call to complete, negating the benefits of asynchronous programming.

        Instead of making a blocking call, use an equivalent asynchronous library or function, like trio.run_process() or anyio.run_process().

        ","tags":["ASYNC221"]},{"location":"rules/run-process-in-async-function/#example","title":"Example","text":"
        async def foo():\n    subprocess.run(cmd)\n

        Use instead:

        async def foo():\n    asyncio.create_subprocess_shell(cmd)\n
        ","tags":["ASYNC221"]},{"location":"rules/runtime-cast-value/","title":"runtime-cast-value (TC006)","text":"

        Derived from the flake8-type-checking linter.

        Fix is always available.

        ","tags":["TC006"]},{"location":"rules/runtime-cast-value/#what-it-does","title":"What it does","text":"

        Checks for unquoted type expressions in typing.cast() calls.

        ","tags":["TC006"]},{"location":"rules/runtime-cast-value/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule helps enforce a consistent style across your codebase.

        It's often necessary to quote the first argument passed to cast(), as type expressions can involve forward references, or references to symbols which are only imported in typing.TYPE_CHECKING blocks. This can lead to a visual inconsistency across different cast() calls, where some type expressions are quoted but others are not. By enabling this rule, you ensure that all type expressions passed to cast() are quoted, enforcing stylistic consistency across all of your cast() calls.

        In some cases where cast() is used in a hot loop, this rule may also help avoid overhead from repeatedly evaluating complex type expressions at runtime.

        ","tags":["TC006"]},{"location":"rules/runtime-cast-value/#example","title":"Example","text":"
        from typing import cast\n\nx = cast(dict[str, int], foo)\n

        Use instead:

        from typing import cast\n\nx = cast(\"dict[str, int]\", foo)\n
        ","tags":["TC006"]},{"location":"rules/runtime-cast-value/#fix-safety","title":"Fix safety","text":"

        This fix is safe as long as the type expression doesn't span multiple lines and includes comments on any of the lines apart from the last one.

        ","tags":["TC006"]},{"location":"rules/runtime-import-in-type-checking-block/","title":"runtime-import-in-type-checking-block (TC004)","text":"

        Derived from the flake8-type-checking linter.

        Fix is sometimes available.

        ","tags":["TC004"]},{"location":"rules/runtime-import-in-type-checking-block/#what-it-does","title":"What it does","text":"

        Checks for imports that are required at runtime but are only defined in type-checking blocks.

        ","tags":["TC004"]},{"location":"rules/runtime-import-in-type-checking-block/#why-is-this-bad","title":"Why is this bad?","text":"

        The type-checking block is not executed at runtime, so if the only definition of a symbol is in a type-checking block, it will not be available at runtime.

        If lint.flake8-type-checking.quote-annotations is set to true, annotations will be wrapped in quotes if doing so would enable the corresponding import to remain in the type-checking block.

        ","tags":["TC004"]},{"location":"rules/runtime-import-in-type-checking-block/#example","title":"Example","text":"
        from typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    import foo\n\n\ndef bar() -> None:\n    foo.bar()  # raises NameError: name 'foo' is not defined\n

        Use instead:

        import foo\n\n\ndef bar() -> None:\n    foo.bar()\n
        ","tags":["TC004"]},{"location":"rules/runtime-import-in-type-checking-block/#options","title":"Options","text":"
        • lint.flake8-type-checking.quote-annotations
        ","tags":["TC004"]},{"location":"rules/runtime-import-in-type-checking-block/#references","title":"References","text":"
        • PEP 563: Runtime annotation resolution and TYPE_CHECKING
        ","tags":["TC004"]},{"location":"rules/runtime-string-union/","title":"runtime-string-union (TC010)","text":"

        Derived from the flake8-type-checking linter.

        ","tags":["TC010"]},{"location":"rules/runtime-string-union/#what-it-does","title":"What it does","text":"

        Checks for the presence of string literals in X | Y-style union types.

        ","tags":["TC010"]},{"location":"rules/runtime-string-union/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 604 introduced a new syntax for union type annotations based on the | operator.

        While Python's type annotations can typically be wrapped in strings to avoid runtime evaluation, the use of a string member within an X | Y-style union type will cause a runtime error.

        Instead, remove the quotes, wrap the entire union in quotes, or use from __future__ import annotations to disable runtime evaluation of annotations entirely.

        ","tags":["TC010"]},{"location":"rules/runtime-string-union/#example","title":"Example","text":"
        var: str | \"int\"\n

        Use instead:

        var: str | int\n

        Or, extend the quotes to include the entire union:

        var: \"str | int\"\n
        ","tags":["TC010"]},{"location":"rules/runtime-string-union/#references","title":"References","text":"
        • PEP 563 - Postponed Evaluation of Annotations
        • PEP 604 \u2013 Allow writing union types as X | Y
        ","tags":["TC010"]},{"location":"rules/self-assigning-variable/","title":"self-assigning-variable (PLW0127)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0127"]},{"location":"rules/self-assigning-variable/#what-it-does","title":"What it does","text":"

        Checks for self-assignment of variables.

        ","tags":["PLW0127"]},{"location":"rules/self-assigning-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        Self-assignment of variables is redundant and likely a mistake.

        ","tags":["PLW0127"]},{"location":"rules/self-assigning-variable/#example","title":"Example","text":"
        country = \"Poland\"\ncountry = country\n

        Use instead:

        country = \"Poland\"\n
        ","tags":["PLW0127"]},{"location":"rules/self-or-cls-assignment/","title":"self-or-cls-assignment (PLW0642)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW0642"]},{"location":"rules/self-or-cls-assignment/#what-it-does","title":"What it does","text":"

        Checks for assignment of self and cls in instance and class methods respectively.

        This check also applies to __new__ even though this is technically a static method.

        ","tags":["PLW0642"]},{"location":"rules/self-or-cls-assignment/#why-is-this-bad","title":"Why is this bad?","text":"

        The identifiers self and cls are conventional in Python for the first parameter of instance methods and class methods, respectively. Assigning new values to these variables can be confusing for others reading your code; using a different variable name can lead to clearer code.

        ","tags":["PLW0642"]},{"location":"rules/self-or-cls-assignment/#example","title":"Example","text":"
        class Version:\n    def add(self, other):\n        self = self + other\n        return self\n\n    @classmethod\n    def superclass(cls):\n        cls = cls.__mro__[-1]\n        return cls\n

        Use instead:

        class Version:\n    def add(self, other):\n        new_version = self + other\n        return new_version\n\n    @classmethod\n    def superclass(cls):\n        supercls = cls.__mro__[-1]\n        return supercls\n
        ","tags":["PLW0642"]},{"location":"rules/set-attr-with-constant/","title":"set-attr-with-constant (B010)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B010"]},{"location":"rules/set-attr-with-constant/#what-it-does","title":"What it does","text":"

        Checks for uses of setattr that take a constant attribute value as an argument (e.g., setattr(obj, \"foo\", 42)).

        ","tags":["B010"]},{"location":"rules/set-attr-with-constant/#why-is-this-bad","title":"Why is this bad?","text":"

        setattr is used to set attributes dynamically. If the attribute is defined as a constant, it is no safer than a typical property access. When possible, prefer property access over setattr calls, as the former is more concise and idiomatic.

        ","tags":["B010"]},{"location":"rules/set-attr-with-constant/#example","title":"Example","text":"
        setattr(obj, \"foo\", 42)\n

        Use instead:

        obj.foo = 42\n
        ","tags":["B010"]},{"location":"rules/set-attr-with-constant/#references","title":"References","text":"
        • Python documentation: setattr
        ","tags":["B010"]},{"location":"rules/shallow-copy-environ/","title":"shallow-copy-environ (PLW1507)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLW1507"]},{"location":"rules/shallow-copy-environ/#what-it-does","title":"What it does","text":"

        Check for shallow os.environ copies.

        ","tags":["PLW1507"]},{"location":"rules/shallow-copy-environ/#why-is-this-bad","title":"Why is this bad?","text":"

        os.environ is not a dict object, but rather, a proxy object. As such, mutating a shallow copy of os.environ will also mutate the original object.

        See BPO 15373 for more information.

        ","tags":["PLW1507"]},{"location":"rules/shallow-copy-environ/#example","title":"Example","text":"
        import copy\nimport os\n\nenv = copy.copy(os.environ)\n

        Use instead:

        import os\n\nenv = os.environ.copy()\n
        ","tags":["PLW1507"]},{"location":"rules/shallow-copy-environ/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because replacing a shallow copy with a deep copy can lead to unintended side effects. If the program modifies the shallow copy at some point, changing it to a deep copy may prevent those modifications from affecting the original data, potentially altering the program's behavior.

        ","tags":["PLW1507"]},{"location":"rules/shallow-copy-environ/#references","title":"References","text":"
        • Python documentation: copy \u2014 Shallow and deep copy operations
        • Python documentation: os.environ
        ","tags":["PLW1507"]},{"location":"rules/shebang-leading-whitespace/","title":"shebang-leading-whitespace (EXE004)","text":"

        Derived from the flake8-executable linter.

        Fix is always available.

        ","tags":["EXE004"]},{"location":"rules/shebang-leading-whitespace/#what-it-does","title":"What it does","text":"

        Checks for whitespace before a shebang directive.

        ","tags":["EXE004"]},{"location":"rules/shebang-leading-whitespace/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a shebang (also known as a hashbang) is the first line of a script, which specifies the interpreter that should be used to run the script.

        The shebang's #! prefix must be the first two characters of a file. The presence of whitespace before the shebang will cause the shebang to be ignored, which is likely a mistake.

        ","tags":["EXE004"]},{"location":"rules/shebang-leading-whitespace/#example","title":"Example","text":"
         #!/usr/bin/env python3\n

        Use instead:

        #!/usr/bin/env python3\n
        ","tags":["EXE004"]},{"location":"rules/shebang-leading-whitespace/#references","title":"References","text":"
        • Python documentation: Executable Python Scripts
        ","tags":["EXE004"]},{"location":"rules/shebang-missing-executable-file/","title":"shebang-missing-executable-file (EXE002)","text":"

        Derived from the flake8-executable linter.

        ","tags":["EXE002"]},{"location":"rules/shebang-missing-executable-file/#what-it-does","title":"What it does","text":"

        Checks for executable .py files that do not have a shebang.

        ","tags":["EXE002"]},{"location":"rules/shebang-missing-executable-file/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a shebang (also known as a hashbang) is the first line of a script, which specifies the interpreter that should be used to run the script.

        If a .py file is executable, but does not have a shebang, it may be run with the wrong interpreter, or fail to run at all.

        If the file is meant to be executable, add a shebang, as in:

        #!/usr/bin/env python\n

        Otherwise, remove the executable bit from the file (e.g., chmod -x __main__.py or git update-index --chmod=-x __main__.py).

        A file is considered executable if it has the executable bit set (i.e., its permissions mode intersects with 0o111). As such, this rule is only available on Unix-like systems, and is not enforced on Windows or WSL.

        ","tags":["EXE002"]},{"location":"rules/shebang-missing-executable-file/#references","title":"References","text":"
        • Python documentation: Executable Python Scripts
        • Git documentation: git update-index --chmod
        ","tags":["EXE002"]},{"location":"rules/shebang-missing-python/","title":"shebang-missing-python (EXE003)","text":"

        Derived from the flake8-executable linter.

        ","tags":["EXE003"]},{"location":"rules/shebang-missing-python/#what-it-does","title":"What it does","text":"

        Checks for a shebang directive in .py files that does not contain python, pytest, or uv run.

        ","tags":["EXE003"]},{"location":"rules/shebang-missing-python/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a shebang (also known as a hashbang) is the first line of a script, which specifies the command that should be used to run the script.

        For Python scripts, if the shebang does not include a command that explicitly or implicitly specifies an interpreter, then the file will be executed with the default interpreter, which is likely a mistake.

        ","tags":["EXE003"]},{"location":"rules/shebang-missing-python/#example","title":"Example","text":"
        #!/usr/bin/env bash\n

        Use instead:

        #!/usr/bin/env python3\n
        ","tags":["EXE003"]},{"location":"rules/shebang-missing-python/#references","title":"References","text":"
        • Python documentation: Executable Python Scripts
        ","tags":["EXE003"]},{"location":"rules/shebang-not-executable/","title":"shebang-not-executable (EXE001)","text":"

        Derived from the flake8-executable linter.

        ","tags":["EXE001"]},{"location":"rules/shebang-not-executable/#what-it-does","title":"What it does","text":"

        Checks for a shebang directive in a file that is not executable.

        ","tags":["EXE001"]},{"location":"rules/shebang-not-executable/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a shebang (also known as a hashbang) is the first line of a script, which specifies the interpreter that should be used to run the script.

        The presence of a shebang suggests that a file is intended to be executable. If a file contains a shebang but is not executable, then the shebang is misleading, or the file is missing the executable bit.

        If the file is meant to be executable, add the executable bit to the file (e.g., chmod +x __main__.py or git update-index --chmod=+x __main__.py).

        Otherwise, remove the shebang.

        A file is considered executable if it has the executable bit set (i.e., its permissions mode intersects with 0o111). As such, this rule is only available on Unix-like systems, and is not enforced on Windows or WSL.

        ","tags":["EXE001"]},{"location":"rules/shebang-not-executable/#example","title":"Example","text":"
        #!/usr/bin/env python\n
        ","tags":["EXE001"]},{"location":"rules/shebang-not-executable/#references","title":"References","text":"
        • Python documentation: Executable Python Scripts
        • Git documentation: git update-index --chmod
        ","tags":["EXE001"]},{"location":"rules/shebang-not-first-line/","title":"shebang-not-first-line (EXE005)","text":"

        Derived from the flake8-executable linter.

        ","tags":["EXE005"]},{"location":"rules/shebang-not-first-line/#what-it-does","title":"What it does","text":"

        Checks for a shebang directive that is not at the beginning of the file.

        ","tags":["EXE005"]},{"location":"rules/shebang-not-first-line/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a shebang (also known as a hashbang) is the first line of a script, which specifies the interpreter that should be used to run the script.

        The shebang's #! prefix must be the first two characters of a file. If the shebang is not at the beginning of the file, it will be ignored, which is likely a mistake.

        ","tags":["EXE005"]},{"location":"rules/shebang-not-first-line/#example","title":"Example","text":"
        foo = 1\n#!/usr/bin/env python3\n

        Use instead:

        #!/usr/bin/env python3\nfoo = 1\n
        ","tags":["EXE005"]},{"location":"rules/shebang-not-first-line/#references","title":"References","text":"
        • Python documentation: Executable Python Scripts
        ","tags":["EXE005"]},{"location":"rules/signature-in-docstring/","title":"signature-in-docstring (D402)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D402"]},{"location":"rules/signature-in-docstring/#what-it-does","title":"What it does","text":"

        Checks for function docstrings that include the function's signature in the summary line.

        ","tags":["D402"]},{"location":"rules/signature-in-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends against including a function's signature in its docstring. Instead, consider using type annotations as a form of documentation for the function's parameters and return value.

        This rule may not apply to all projects; its applicability is a matter of convention. By default, this rule is enabled when using the google and pep257 conventions, and disabled when using the numpy convention.

        ","tags":["D402"]},{"location":"rules/signature-in-docstring/#example","title":"Example","text":"
        def foo(a, b):\n    \"\"\"foo(a: int, b: int) -> list[int]\"\"\"\n

        Use instead:

        def foo(a: int, b: int) -> list[int]:\n    \"\"\"Return a list of a and b.\"\"\"\n
        ","tags":["D402"]},{"location":"rules/signature-in-docstring/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        ","tags":["D402"]},{"location":"rules/signature-in-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D402"]},{"location":"rules/single-item-membership-test/","title":"single-item-membership-test (FURB171)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB171"]},{"location":"rules/single-item-membership-test/#what-it-does","title":"What it does","text":"

        Checks for membership tests against single-item containers.

        ","tags":["FURB171"]},{"location":"rules/single-item-membership-test/#why-is-this-bad","title":"Why is this bad?","text":"

        Performing a membership test against a container (like a list or set) with a single item is less readable and less efficient than comparing against the item directly.

        ","tags":["FURB171"]},{"location":"rules/single-item-membership-test/#example","title":"Example","text":"
        1 in [1]\n

        Use instead:

        1 == 1\n
        ","tags":["FURB171"]},{"location":"rules/single-item-membership-test/#fix-safety","title":"Fix safety","text":"

        When the right-hand side is a string, the fix is marked as unsafe. This is because c in \"a\" is true both when c is \"a\" and when c is the empty string, so the fix can change the behavior of your program in these cases.

        Additionally, if there are comments within the fix's range, it will also be marked as unsafe.

        ","tags":["FURB171"]},{"location":"rules/single-item-membership-test/#references","title":"References","text":"
        • Python documentation: Comparisons
        • Python documentation: Membership test operations
        ","tags":["FURB171"]},{"location":"rules/single-line-implicit-string-concatenation/","title":"single-line-implicit-string-concatenation (ISC001)","text":"

        Derived from the flake8-implicit-str-concat linter.

        Fix is sometimes available.

        ","tags":["ISC001"]},{"location":"rules/single-line-implicit-string-concatenation/#what-it-does","title":"What it does","text":"

        Checks for implicitly concatenated strings on a single line.

        ","tags":["ISC001"]},{"location":"rules/single-line-implicit-string-concatenation/#why-is-this-bad","title":"Why is this bad?","text":"

        While it is valid Python syntax to concatenate multiple string or byte literals implicitly (via whitespace delimiters), it is unnecessary and negatively affects code readability.

        In some cases, the implicit concatenation may also be unintentional, as code formatters are capable of introducing single-line implicit concatenations when collapsing long lines.

        ","tags":["ISC001"]},{"location":"rules/single-line-implicit-string-concatenation/#example","title":"Example","text":"
        z = \"The quick \" \"brown fox.\"\n

        Use instead:

        z = \"The quick brown fox.\"\n
        ","tags":["ISC001"]},{"location":"rules/single-string-slots/","title":"single-string-slots (PLC0205)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC0205"]},{"location":"rules/single-string-slots/#what-it-does","title":"What it does","text":"

        Checks for single strings assigned to __slots__.

        ","tags":["PLC0205"]},{"location":"rules/single-string-slots/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the __slots__ attribute allows you to explicitly define the attributes (instance variables) that a class can have. By default, Python uses a dictionary to store an object's attributes, which incurs some memory overhead. However, when __slots__ is defined, Python uses a more compact internal structure to store the object's attributes, resulting in memory savings.

        Any string iterable may be assigned to __slots__ (most commonly, a tuple of strings). If a string is assigned to __slots__, it is interpreted as a single attribute name, rather than an iterable of attribute names. This can cause confusion, as users that iterate over the __slots__ value may expect to iterate over a sequence of attributes, but would instead iterate over the characters of the string.

        To use a single string attribute in __slots__, wrap the string in an iterable container type, like a tuple.

        ","tags":["PLC0205"]},{"location":"rules/single-string-slots/#example","title":"Example","text":"
        class Person:\n    __slots__: str = \"name\"\n\n    def __init__(self, name: str) -> None:\n        self.name = name\n

        Use instead:

        class Person:\n    __slots__: tuple[str, ...] = (\"name\",)\n\n    def __init__(self, name: str) -> None:\n        self.name = name\n
        ","tags":["PLC0205"]},{"location":"rules/single-string-slots/#references","title":"References","text":"
        • Python documentation: __slots__
        ","tags":["PLC0205"]},{"location":"rules/singledispatch-method/","title":"singledispatch-method (PLE1519)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE1519"]},{"location":"rules/singledispatch-method/#what-it-does","title":"What it does","text":"

        Checks for methods decorated with @singledispatch.

        ","tags":["PLE1519"]},{"location":"rules/singledispatch-method/#why-is-this-bad","title":"Why is this bad?","text":"

        The @singledispatch decorator is intended for use with functions, not methods.

        Instead, use the @singledispatchmethod decorator, or migrate the method to a standalone function.

        ","tags":["PLE1519"]},{"location":"rules/singledispatch-method/#example","title":"Example","text":"
        from functools import singledispatch\n\n\nclass Class:\n    @singledispatch\n    def method(self, arg): ...\n

        Use instead:

        from functools import singledispatchmethod\n\n\nclass Class:\n    @singledispatchmethod\n    def method(self, arg): ...\n
        ","tags":["PLE1519"]},{"location":"rules/singledispatch-method/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as migrating from @singledispatch to @singledispatchmethod may change the behavior of the code.

        ","tags":["PLE1519"]},{"location":"rules/singledispatchmethod-function/","title":"singledispatchmethod-function (PLE1520)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLE1520"]},{"location":"rules/singledispatchmethod-function/#what-it-does","title":"What it does","text":"

        Checks for non-method functions decorated with @singledispatchmethod.

        ","tags":["PLE1520"]},{"location":"rules/singledispatchmethod-function/#why-is-this-bad","title":"Why is this bad?","text":"

        The @singledispatchmethod decorator is intended for use with methods, not functions.

        Instead, use the @singledispatch decorator.

        ","tags":["PLE1520"]},{"location":"rules/singledispatchmethod-function/#example","title":"Example","text":"
        from functools import singledispatchmethod\n\n\n@singledispatchmethod\ndef func(arg): ...\n

        Use instead:

        from functools import singledispatch\n\n\n@singledispatch\ndef func(arg): ...\n
        ","tags":["PLE1520"]},{"location":"rules/singledispatchmethod-function/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as migrating from @singledispatchmethod to @singledispatch may change the behavior of the code.

        ","tags":["PLE1520"]},{"location":"rules/six-py3/","title":"six-py3 (YTT202)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT202"]},{"location":"rules/six-py3/#what-it-does","title":"What it does","text":"

        Checks for uses of six.PY3.

        ","tags":["YTT202"]},{"location":"rules/six-py3/#why-is-this-bad","title":"Why is this bad?","text":"

        six.PY3 will evaluate to False on Python 4 and greater. This is likely unintended, and may cause code intended to run on Python 2 to run on Python 4 too.

        Instead, use not six.PY2 to validate that the current Python major version is not equal to 2, to future-proof the code.

        ","tags":["YTT202"]},{"location":"rules/six-py3/#example","title":"Example","text":"
        import six\n\nsix.PY3  # `False` on Python 4.\n

        Use instead:

        import six\n\nnot six.PY2  # `True` on Python 4.\n
        ","tags":["YTT202"]},{"location":"rules/six-py3/#references","title":"References","text":"
        • PyPI: six
        • Six documentation: six.PY2
        • Six documentation: six.PY3
        ","tags":["YTT202"]},{"location":"rules/slice-copy/","title":"slice-copy (FURB145)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB145"]},{"location":"rules/slice-copy/#what-it-does","title":"What it does","text":"

        Checks for unbounded slice expressions to copy a list.

        ","tags":["FURB145"]},{"location":"rules/slice-copy/#why-is-this-bad","title":"Why is this bad?","text":"

        The list.copy method is more readable and consistent with copying other types.

        ","tags":["FURB145"]},{"location":"rules/slice-copy/#known-problems","title":"Known problems","text":"

        This rule is prone to false negatives due to type inference limitations, as it will only detect lists that are instantiated as literals or annotated with a type annotation.

        ","tags":["FURB145"]},{"location":"rules/slice-copy/#example","title":"Example","text":"
        a = [1, 2, 3]\nb = a[:]\n

        Use instead:

        a = [1, 2, 3]\nb = a.copy()\n
        ","tags":["FURB145"]},{"location":"rules/slice-copy/#references","title":"References","text":"
        • Python documentation: Mutable Sequence Types
        ","tags":["FURB145"]},{"location":"rules/slice-to-remove-prefix-or-suffix/","title":"slice-to-remove-prefix-or-suffix (FURB188)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB188"]},{"location":"rules/slice-to-remove-prefix-or-suffix/#what-it-does","title":"What it does","text":"

        Checks for code that could be written more idiomatically using str.removeprefix() or str.removesuffix().

        Specifically, the rule flags code that conditionally removes a prefix or suffix using a slice operation following an if test that uses str.startswith() or str.endswith().

        The rule is only applied if your project targets Python 3.9 or later.

        ","tags":["FURB188"]},{"location":"rules/slice-to-remove-prefix-or-suffix/#why-is-this-bad","title":"Why is this bad?","text":"

        The methods str.removeprefix() and str.removesuffix(), introduced in Python 3.9, have the same behavior while being more readable and efficient.

        ","tags":["FURB188"]},{"location":"rules/slice-to-remove-prefix-or-suffix/#example","title":"Example","text":"
        def example(filename: str, text: str):\n    filename = filename[:-4] if filename.endswith(\".txt\") else filename\n\n    if text.startswith(\"pre\"):\n        text = text[3:]\n

        Use instead:

        def example(filename: str, text: str):\n    filename = filename.removesuffix(\".txt\")\n    text = text.removeprefix(\"pre\")\n
        ","tags":["FURB188"]},{"location":"rules/snake-case-type-alias/","title":"snake-case-type-alias (PYI042)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI042"]},{"location":"rules/snake-case-type-alias/#what-it-does","title":"What it does","text":"

        Checks for type aliases that do not use the CamelCase naming convention.

        ","tags":["PYI042"]},{"location":"rules/snake-case-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        It's conventional to use the CamelCase naming convention for type aliases, to distinguish them from other variables.

        ","tags":["PYI042"]},{"location":"rules/snake-case-type-alias/#example","title":"Example","text":"
        type_alias_name: TypeAlias = int\n

        Use instead:

        TypeAliasName: TypeAlias = int\n
        ","tags":["PYI042"]},{"location":"rules/snmp-insecure-version/","title":"snmp-insecure-version (S508)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S508"]},{"location":"rules/snmp-insecure-version/#what-it-does","title":"What it does","text":"

        Checks for uses of SNMPv1 or SNMPv2.

        ","tags":["S508"]},{"location":"rules/snmp-insecure-version/#why-is-this-bad","title":"Why is this bad?","text":"

        The SNMPv1 and SNMPv2 protocols are considered insecure as they do not support encryption. Instead, prefer SNMPv3, which supports encryption.

        ","tags":["S508"]},{"location":"rules/snmp-insecure-version/#example","title":"Example","text":"
        from pysnmp.hlapi import CommunityData\n\nCommunityData(\"public\", mpModel=0)\n

        Use instead:

        from pysnmp.hlapi import CommunityData\n\nCommunityData(\"public\", mpModel=2)\n
        ","tags":["S508"]},{"location":"rules/snmp-insecure-version/#references","title":"References","text":"
        • Cybersecurity and Infrastructure Security Agency (CISA): Alert TA17-156A
        • Common Weakness Enumeration: CWE-319
        ","tags":["S508"]},{"location":"rules/snmp-weak-cryptography/","title":"snmp-weak-cryptography (S509)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S509"]},{"location":"rules/snmp-weak-cryptography/#what-it-does","title":"What it does","text":"

        Checks for uses of the SNMPv3 protocol without encryption.

        ","tags":["S509"]},{"location":"rules/snmp-weak-cryptography/#why-is-this-bad","title":"Why is this bad?","text":"

        Unencrypted SNMPv3 communication can be intercepted and read by unauthorized parties. Instead, enable encryption when using SNMPv3.

        ","tags":["S509"]},{"location":"rules/snmp-weak-cryptography/#example","title":"Example","text":"
        from pysnmp.hlapi import UsmUserData\n\nUsmUserData(\"user\")\n

        Use instead:

        from pysnmp.hlapi import UsmUserData\n\nUsmUserData(\"user\", \"authkey\", \"privkey\")\n
        ","tags":["S509"]},{"location":"rules/snmp-weak-cryptography/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-319
        ","tags":["S509"]},{"location":"rules/sorted-min-max/","title":"sorted-min-max (FURB192)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB192"]},{"location":"rules/sorted-min-max/#what-it-does","title":"What it does","text":"

        Checks for uses of sorted() to retrieve the minimum or maximum value in a sequence.

        ","tags":["FURB192"]},{"location":"rules/sorted-min-max/#why-is-this-bad","title":"Why is this bad?","text":"

        Using sorted() to compute the minimum or maximum value in a sequence is inefficient and less readable than using min() or max() directly.

        ","tags":["FURB192"]},{"location":"rules/sorted-min-max/#example","title":"Example","text":"
        nums = [3, 1, 4, 1, 5]\nlowest = sorted(nums)[0]\nhighest = sorted(nums)[-1]\nhighest = sorted(nums, reverse=True)[0]\n

        Use instead:

        nums = [3, 1, 4, 1, 5]\nlowest = min(nums)\nhighest = max(nums)\n
        ","tags":["FURB192"]},{"location":"rules/sorted-min-max/#fix-safety","title":"Fix safety","text":"

        In some cases, migrating to min or max can lead to a change in behavior, notably when breaking ties.

        As an example, sorted(data, key=itemgetter(0), reverse=True)[0] will return the last \"minimum\" element in the list, if there are multiple elements with the same key. However, min(data, key=itemgetter(0)) will return the first \"minimum\" element in the list in the same scenario.

        As such, this rule's fix is marked as unsafe when the reverse keyword is used.

        ","tags":["FURB192"]},{"location":"rules/sorted-min-max/#references","title":"References","text":"
        • Python documentation: min
        • Python documentation: max
        ","tags":["FURB192"]},{"location":"rules/split-static-string/","title":"split-static-string (SIM905)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM905"]},{"location":"rules/split-static-string/#what-it-does","title":"What it does","text":"

        Checks for static str.split calls that can be replaced with list literals.

        ","tags":["SIM905"]},{"location":"rules/split-static-string/#why-is-this-bad","title":"Why is this bad?","text":"

        List literals are more readable and do not require the overhead of calling str.split.

        ","tags":["SIM905"]},{"location":"rules/split-static-string/#example","title":"Example","text":"
        \"a,b,c,d\".split(\",\")\n

        Use instead:

        [\"a\", \"b\", \"c\", \"d\"]\n
        ","tags":["SIM905"]},{"location":"rules/split-static-string/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for implicit string concatenations with comments interleaved between segments, as comments may be removed.

        For example, the fix would be marked as unsafe in the following case:

        (\n    \"a\"  # comment\n    \",\"  # comment\n    \"b\"  # comment\n).split(\",\")\n

        as this is converted to [\"a\", \"b\"] without any of the comments.

        ","tags":["SIM905"]},{"location":"rules/split-static-string/#references","title":"References","text":"
        • Python documentation: str.split
        ","tags":["SIM905"]},{"location":"rules/ssh-no-host-key-verification/","title":"ssh-no-host-key-verification (S507)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S507"]},{"location":"rules/ssh-no-host-key-verification/#what-it-does","title":"What it does","text":"

        Checks for uses of policies disabling SSH verification in Paramiko.

        ","tags":["S507"]},{"location":"rules/ssh-no-host-key-verification/#why-is-this-bad","title":"Why is this bad?","text":"

        By default, Paramiko checks the identity of the remote host when establishing an SSH connection. Disabling the verification might lead to the client connecting to a malicious host, without the client knowing.

        ","tags":["S507"]},{"location":"rules/ssh-no-host-key-verification/#example","title":"Example","text":"
        from paramiko import client\n\nssh_client = client.SSHClient()\nssh_client.set_missing_host_key_policy(client.AutoAddPolicy)\n

        Use instead:

        from paramiko import client\n\nssh_client = client.SSHClient()\nssh_client.set_missing_host_key_policy(client.RejectPolicy)\n
        ","tags":["S507"]},{"location":"rules/ssh-no-host-key-verification/#references","title":"References","text":"
        • Paramiko documentation: set_missing_host_key_policy
        ","tags":["S507"]},{"location":"rules/ssl-insecure-version/","title":"ssl-insecure-version (S502)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S502"]},{"location":"rules/ssl-insecure-version/#what-it-does","title":"What it does","text":"

        Checks for function calls with parameters that indicate the use of insecure SSL and TLS protocol versions.

        ","tags":["S502"]},{"location":"rules/ssl-insecure-version/#why-is-this-bad","title":"Why is this bad?","text":"

        Several highly publicized exploitable flaws have been discovered in all versions of SSL and early versions of TLS. The following versions are considered insecure, and should be avoided:

        • SSL v2
        • SSL v3
        • TLS v1
        • TLS v1.1

        This method supports detection on the Python's built-in ssl module and the pyOpenSSL module.

        ","tags":["S502"]},{"location":"rules/ssl-insecure-version/#example","title":"Example","text":"
        import ssl\n\nssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1)\n

        Use instead:

        import ssl\n\nssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1_2)\n
        ","tags":["S502"]},{"location":"rules/ssl-with-bad-defaults/","title":"ssl-with-bad-defaults (S503)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S503"]},{"location":"rules/ssl-with-bad-defaults/#what-it-does","title":"What it does","text":"

        Checks for function definitions with default arguments set to insecure SSL and TLS protocol versions.

        ","tags":["S503"]},{"location":"rules/ssl-with-bad-defaults/#why-is-this-bad","title":"Why is this bad?","text":"

        Several highly publicized exploitable flaws have been discovered in all versions of SSL and early versions of TLS. The following versions are considered insecure, and should be avoided:

        • SSL v2
        • SSL v3
        • TLS v1
        • TLS v1.1
        ","tags":["S503"]},{"location":"rules/ssl-with-bad-defaults/#example","title":"Example","text":"
        import ssl\n\n\ndef func(version=ssl.PROTOCOL_TLSv1): ...\n

        Use instead:

        import ssl\n\n\ndef func(version=ssl.PROTOCOL_TLSv1_2): ...\n
        ","tags":["S503"]},{"location":"rules/ssl-with-no-version/","title":"ssl-with-no-version (S504)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S504"]},{"location":"rules/ssl-with-no-version/#what-it-does","title":"What it does","text":"

        Checks for calls to ssl.wrap_socket() without an ssl_version.

        ","tags":["S504"]},{"location":"rules/ssl-with-no-version/#why-is-this-bad","title":"Why is this bad?","text":"

        This method is known to provide a default value that maximizes compatibility, but permits use of insecure protocols.

        ","tags":["S504"]},{"location":"rules/ssl-with-no-version/#example","title":"Example","text":"
        import ssl\n\nssl.wrap_socket()\n

        Use instead:

        import ssl\n\nssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1_2)\n
        ","tags":["S504"]},{"location":"rules/star-arg-unpacking-after-keyword-arg/","title":"star-arg-unpacking-after-keyword-arg (B026)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B026"]},{"location":"rules/star-arg-unpacking-after-keyword-arg/#what-it-does","title":"What it does","text":"

        Checks for function calls that use star-argument unpacking after providing a keyword argument

        ","tags":["B026"]},{"location":"rules/star-arg-unpacking-after-keyword-arg/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, you can use star-argument unpacking to pass a list or tuple of arguments to a function.

        Providing a star-argument after a keyword argument can lead to confusing behavior, and is only supported for backwards compatibility.

        ","tags":["B026"]},{"location":"rules/star-arg-unpacking-after-keyword-arg/#example","title":"Example","text":"
        def foo(x, y, z):\n    return x, y, z\n\n\nfoo(1, 2, 3)  # (1, 2, 3)\nfoo(1, *[2, 3])  # (1, 2, 3)\n# foo(x=1, *[2, 3])  # TypeError\n# foo(y=2, *[1, 3])  # TypeError\nfoo(z=3, *[1, 2])  # (1, 2, 3)  # No error, but confusing!\n

        Use instead:

        def foo(x, y, z):\n    return x, y, z\n\n\nfoo(1, 2, 3)  # (1, 2, 3)\nfoo(x=1, y=2, z=3)  # (1, 2, 3)\nfoo(*[1, 2, 3])  # (1, 2, 3)\nfoo(*[1, 2], 3)  # (1, 2, 3)\n
        ","tags":["B026"]},{"location":"rules/star-arg-unpacking-after-keyword-arg/#references","title":"References","text":"
        • Python documentation: Calls
        • Disallow iterable argument unpacking after a keyword argument?
        ","tags":["B026"]},{"location":"rules/starmap-zip/","title":"starmap-zip (RUF058)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF058"]},{"location":"rules/starmap-zip/#what-it-does","title":"What it does","text":"

        Checks for itertools.starmap calls where the second argument is a zip call.

        ","tags":["RUF058"]},{"location":"rules/starmap-zip/#why-is-this-bad","title":"Why is this bad?","text":"

        zip-ping iterables only to unpack them later from within starmap is unnecessary. For such cases, map() should be used instead.

        ","tags":["RUF058"]},{"location":"rules/starmap-zip/#example","title":"Example","text":"
        from itertools import starmap\n\n\nstarmap(func, zip(a, b))\nstarmap(func, zip(a, b, strict=True))\n

        Use instead:

        map(func, a, b)\nmap(func, a, b, strict=True)  # 3.14+\n
        ","tags":["RUF058"]},{"location":"rules/starmap-zip/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe if the starmap or zip expressions contain comments that would be deleted by applying the fix. Otherwise, the fix can be applied safely.

        ","tags":["RUF058"]},{"location":"rules/starmap-zip/#fix-availability","title":"Fix availability","text":"

        This rule will emit a diagnostic but not suggest a fix if map has been shadowed from its builtin binding.

        ","tags":["RUF058"]},{"location":"rules/start-process-with-a-shell/","title":"start-process-with-a-shell (S605)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S605"]},{"location":"rules/start-process-with-a-shell/#what-it-does","title":"What it does","text":"

        Checks for calls that start a process with a shell, providing guidance on whether the usage is safe or not.

        ","tags":["S605"]},{"location":"rules/start-process-with-a-shell/#why-is-this-bad","title":"Why is this bad?","text":"

        Starting a process with a shell can introduce security risks, such as code injection vulnerabilities. It's important to be aware of whether the usage of the shell is safe or not.

        This rule triggers on functions like os.system, popen, etc., which start processes with a shell. It evaluates whether the provided command is a literal string or an expression. If the command is a literal string, it's considered safe. If the command is an expression, it's considered (potentially) unsafe.

        ","tags":["S605"]},{"location":"rules/start-process-with-a-shell/#example","title":"Example","text":"
        import os\n\n# Safe usage (literal string)\ncommand = \"ls -l\"\nos.system(command)\n\n# Potentially unsafe usage (expression)\ncmd = get_user_input()\nos.system(cmd)\n
        ","tags":["S605"]},{"location":"rules/start-process-with-a-shell/#note","title":"Note","text":"

        The subprocess module provides more powerful facilities for spawning new processes and retrieving their results, and using that module is preferable to using os.system or similar functions. Consider replacing such usages with subprocess.call or related functions.

        ","tags":["S605"]},{"location":"rules/start-process-with-a-shell/#references","title":"References","text":"
        • Python documentation: subprocess
        ","tags":["S605"]},{"location":"rules/start-process-with-no-shell/","title":"start-process-with-no-shell (S606)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S606"]},{"location":"rules/start-process-with-no-shell/#what-it-does","title":"What it does","text":"

        Checks for functions that start a process without a shell.

        ","tags":["S606"]},{"location":"rules/start-process-with-no-shell/#why-is-this-bad","title":"Why is this bad?","text":"

        Invoking any kind of external executable via a function call can pose security risks if arbitrary variables are passed to the executable, or if the input is otherwise unsanitised or unvalidated.

        This rule specifically flags functions in the os module that spawn subprocesses without the use of a shell. Note that these typically pose a much smaller security risk than subprocesses that are started with a shell, which are flagged by start-process-with-a-shell (S605). This gives you the option of enabling one rule while disabling the other if you decide that the security risk from these functions is acceptable for your use case.

        ","tags":["S606"]},{"location":"rules/start-process-with-no-shell/#example","title":"Example","text":"
        import os\n\n\ndef insecure_function(arbitrary_user_input: str):\n    os.spawnlp(os.P_NOWAIT, \"/bin/mycmd\", \"mycmd\", arbitrary_user_input)\n
        ","tags":["S606"]},{"location":"rules/start-process-with-partial-path/","title":"start-process-with-partial-path (S607)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S607"]},{"location":"rules/start-process-with-partial-path/#what-it-does","title":"What it does","text":"

        Checks for the starting of a process with a partial executable path.

        ","tags":["S607"]},{"location":"rules/start-process-with-partial-path/#why-is-this-bad","title":"Why is this bad?","text":"

        Starting a process with a partial executable path can allow attackers to execute an arbitrary executable by adjusting the PATH environment variable. Consider using a full path to the executable instead.

        ","tags":["S607"]},{"location":"rules/start-process-with-partial-path/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.Popen([\"ruff\", \"check\", \"file.py\"])\n

        Use instead:

        import subprocess\n\nsubprocess.Popen([\"/usr/bin/ruff\", \"check\", \"file.py\"])\n
        ","tags":["S607"]},{"location":"rules/start-process-with-partial-path/#references","title":"References","text":"
        • Python documentation: subprocess.Popen()
        • Common Weakness Enumeration: CWE-426
        ","tags":["S607"]},{"location":"rules/static-join-to-f-string/","title":"static-join-to-f-string (FLY002)","text":"

        Derived from the flynt linter.

        Fix is always available.

        ","tags":["FLY002"]},{"location":"rules/static-join-to-f-string/#what-it-does","title":"What it does","text":"

        Checks for str.join calls that can be replaced with f-strings.

        ","tags":["FLY002"]},{"location":"rules/static-join-to-f-string/#why-is-this-bad","title":"Why is this bad?","text":"

        f-strings are more readable and generally preferred over str.join calls.

        ","tags":["FLY002"]},{"location":"rules/static-join-to-f-string/#example","title":"Example","text":"
        \" \".join((foo, bar))\n

        Use instead:

        f\"{foo} {bar}\"\n
        ","tags":["FLY002"]},{"location":"rules/static-join-to-f-string/#fix-safety","title":"Fix safety","text":"

        The fix is always marked unsafe because the evaluation of the f-string expressions will default to calling the __format__ method of each object, whereas str.join expects each object to be an instance of str and uses the corresponding string. Therefore it is possible for the values of the resulting strings to differ, or for one expression to raise an exception while the other does not.

        ","tags":["FLY002"]},{"location":"rules/static-join-to-f-string/#references","title":"References","text":"
        • Python documentation: f-strings
        ","tags":["FLY002"]},{"location":"rules/static-key-dict-comprehension/","title":"static-key-dict-comprehension (B035)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B035"]},{"location":"rules/static-key-dict-comprehension/#what-it-does","title":"What it does","text":"

        Checks for dictionary comprehensions that use a static key, like a string literal or a variable defined outside the comprehension.

        ","tags":["B035"]},{"location":"rules/static-key-dict-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        Using a static key (like a string literal) in a dictionary comprehension is usually a mistake, as it will result in a dictionary with only one key, despite the comprehension iterating over multiple values.

        ","tags":["B035"]},{"location":"rules/static-key-dict-comprehension/#example","title":"Example","text":"
        data = [\"some\", \"Data\"]\n{\"key\": value.upper() for value in data}\n

        Use instead:

        data = [\"some\", \"Data\"]\n{value: value.upper() for value in data}\n
        ","tags":["B035"]},{"location":"rules/stdlib-module-shadowing/","title":"stdlib-module-shadowing (A005)","text":"

        Derived from the flake8-builtins linter.

        ","tags":["A005"]},{"location":"rules/stdlib-module-shadowing/#what-it-does","title":"What it does","text":"

        Checks for modules that use the same names as Python standard-library modules.

        ","tags":["A005"]},{"location":"rules/stdlib-module-shadowing/#why-is-this-bad","title":"Why is this bad?","text":"

        Reusing a standard-library module name for the name of a module increases the difficulty of reading and maintaining the code, and can cause non-obvious errors. Readers may mistake the first-party module for the standard-library module and vice versa.

        Standard-library modules can be marked as exceptions to this rule via the lint.flake8-builtins.allowed-modules configuration option.

        By default, the module path relative to the project root or src directories is considered, so a top-level logging.py or logging/__init__.py will clash with the builtin logging module, but utils/logging.py, for example, will not. With the lint.flake8-builtins.strict-checking option set to true, only the last component of the module name is considered, so logging.py, utils/logging.py, and utils/logging/__init__.py will all trigger the rule.

        This rule is not applied to stub files, as the name of a stub module is out of the control of the author of the stub file. Instead, a stub should aim to faithfully emulate the runtime module it is stubbing.

        As of Python 3.13, errors from modules that use the same name as standard-library modules now display a custom message.

        ","tags":["A005"]},{"location":"rules/stdlib-module-shadowing/#example","title":"Example","text":"
        $ touch random.py\n$ python3 -c 'from random import choice'\nTraceback (most recent call last):\n  File \"<string>\", line 1, in <module>\n    from random import choice\nImportError: cannot import name 'choice' from 'random' (consider renaming '/random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)\n
        ","tags":["A005"]},{"location":"rules/stdlib-module-shadowing/#options","title":"Options","text":"
        • lint.flake8-builtins.allowed-modules
        • lint.flake8-builtins.strict-checking
        ","tags":["A005"]},{"location":"rules/str-or-repr-defined-in-stub/","title":"str-or-repr-defined-in-stub (PYI029)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI029"]},{"location":"rules/str-or-repr-defined-in-stub/#what-it-does","title":"What it does","text":"

        Checks for redundant definitions of __str__ or __repr__ in stubs.

        ","tags":["PYI029"]},{"location":"rules/str-or-repr-defined-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Defining __str__ or __repr__ in a stub is almost always redundant, as the signatures are almost always identical to those of the default equivalent, object.__str__ and object.__repr__, respectively.

        ","tags":["PYI029"]},{"location":"rules/str-or-repr-defined-in-stub/#example","title":"Example","text":"
        class Foo:\n    def __repr__(self) -> str: ...\n
        ","tags":["PYI029"]},{"location":"rules/string-dot-format-extra-named-arguments/","title":"string-dot-format-extra-named-arguments (F522)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F522"]},{"location":"rules/string-dot-format-extra-named-arguments/#what-it-does","title":"What it does","text":"

        Checks for str.format calls with unused keyword arguments.

        ","tags":["F522"]},{"location":"rules/string-dot-format-extra-named-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused keyword arguments are redundant, and often indicative of a mistake. They should be removed.

        ","tags":["F522"]},{"location":"rules/string-dot-format-extra-named-arguments/#example","title":"Example","text":"
        \"Hello, {name}\".format(greeting=\"Hello\", name=\"World\")\n

        Use instead:

        \"Hello, {name}\".format(name=\"World\")\n
        ","tags":["F522"]},{"location":"rules/string-dot-format-extra-named-arguments/#references","title":"References","text":"
        • Python documentation: str.format
        ","tags":["F522"]},{"location":"rules/string-dot-format-extra-positional-arguments/","title":"string-dot-format-extra-positional-arguments (F523)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F523"]},{"location":"rules/string-dot-format-extra-positional-arguments/#what-it-does","title":"What it does","text":"

        Checks for str.format calls with unused positional arguments.

        ","tags":["F523"]},{"location":"rules/string-dot-format-extra-positional-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused positional arguments are redundant, and often indicative of a mistake. They should be removed.

        ","tags":["F523"]},{"location":"rules/string-dot-format-extra-positional-arguments/#example","title":"Example","text":"
        \"Hello, {0}\".format(\"world\", \"!\")\n

        Use instead:

        \"Hello, {0}\".format(\"world\")\n
        ","tags":["F523"]},{"location":"rules/string-dot-format-extra-positional-arguments/#references","title":"References","text":"
        • Python documentation: str.format
        ","tags":["F523"]},{"location":"rules/string-dot-format-invalid-format/","title":"string-dot-format-invalid-format (F521)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F521"]},{"location":"rules/string-dot-format-invalid-format/#what-it-does","title":"What it does","text":"

        Checks for str.format calls with invalid format strings.

        ","tags":["F521"]},{"location":"rules/string-dot-format-invalid-format/#why-is-this-bad","title":"Why is this bad?","text":"

        Invalid format strings will raise a ValueError.

        ","tags":["F521"]},{"location":"rules/string-dot-format-invalid-format/#example","title":"Example","text":"
        \"{\".format(foo)\n

        Use instead:

        \"{}\".format(foo)\n
        ","tags":["F521"]},{"location":"rules/string-dot-format-invalid-format/#references","title":"References","text":"
        • Python documentation: str.format
        ","tags":["F521"]},{"location":"rules/string-dot-format-missing-arguments/","title":"string-dot-format-missing-arguments (F524)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F524"]},{"location":"rules/string-dot-format-missing-arguments/#what-it-does","title":"What it does","text":"

        Checks for str.format calls with placeholders that are missing arguments.

        ","tags":["F524"]},{"location":"rules/string-dot-format-missing-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        In str.format calls, omitting arguments for placeholders will raise a KeyError at runtime.

        ","tags":["F524"]},{"location":"rules/string-dot-format-missing-arguments/#example","title":"Example","text":"
        \"{greeting}, {name}\".format(name=\"World\")\n

        Use instead:

        \"{greeting}, {name}\".format(greeting=\"Hello\", name=\"World\")\n
        ","tags":["F524"]},{"location":"rules/string-dot-format-missing-arguments/#references","title":"References","text":"
        • Python documentation: str.format
        ","tags":["F524"]},{"location":"rules/string-dot-format-mixing-automatic/","title":"string-dot-format-mixing-automatic (F525)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F525"]},{"location":"rules/string-dot-format-mixing-automatic/#what-it-does","title":"What it does","text":"

        Checks for str.format calls that mix automatic and manual numbering.

        ","tags":["F525"]},{"location":"rules/string-dot-format-mixing-automatic/#why-is-this-bad","title":"Why is this bad?","text":"

        In str.format calls, mixing automatic and manual numbering will raise a ValueError at runtime.

        ","tags":["F525"]},{"location":"rules/string-dot-format-mixing-automatic/#example","title":"Example","text":"
        \"{0}, {}\".format(\"Hello\", \"World\")\n

        Use instead:

        \"{0}, {1}\".format(\"Hello\", \"World\")\n

        Or:

        \"{}, {}\".format(\"Hello\", \"World\")\n
        ","tags":["F525"]},{"location":"rules/string-dot-format-mixing-automatic/#references","title":"References","text":"
        • Python documentation: str.format
        ","tags":["F525"]},{"location":"rules/string-or-bytes-too-long/","title":"string-or-bytes-too-long (PYI053)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI053"]},{"location":"rules/string-or-bytes-too-long/#what-it-does","title":"What it does","text":"

        Checks for the use of string and bytes literals longer than 50 characters in stub (.pyi) files.

        ","tags":["PYI053"]},{"location":"rules/string-or-bytes-too-long/#why-is-this-bad","title":"Why is this bad?","text":"

        If a function or variable has a default value where the string or bytes representation is greater than 50 characters long, it is likely to be an implementation detail or a constant that varies depending on the system you're running on.

        Although IDEs may find them useful, default values are ignored by type checkers, the primary consumers of stub files. Replace very long constants with ellipses (...) to simplify the stub.

        ","tags":["PYI053"]},{"location":"rules/string-or-bytes-too-long/#example","title":"Example","text":"
        def foo(arg: str = \"51 character stringgggggggggggggggggggggggggggggggg\") -> None: ...\n

        Use instead:

        def foo(arg: str = ...) -> None: ...\n
        ","tags":["PYI053"]},{"location":"rules/strip-with-multi-characters/","title":"strip-with-multi-characters (B005)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B005"]},{"location":"rules/strip-with-multi-characters/#what-it-does","title":"What it does","text":"

        Checks for uses of multi-character strings in .strip(), .lstrip(), and .rstrip() calls.

        ","tags":["B005"]},{"location":"rules/strip-with-multi-characters/#why-is-this-bad","title":"Why is this bad?","text":"

        All characters in the call to .strip(), .lstrip(), or .rstrip() are removed from the leading and trailing ends of the string. If the string contains multiple characters, the reader may be misled into thinking that a prefix or suffix is being removed, rather than a set of characters.

        In Python 3.9 and later, you can use str.removeprefix and str.removesuffix to remove an exact prefix or suffix from a string, respectively, which should be preferred when possible.

        ","tags":["B005"]},{"location":"rules/strip-with-multi-characters/#known-problems","title":"Known problems","text":"

        As a heuristic, this rule only flags multi-character strings that contain duplicate characters. This allows usages like .strip(\"xyz\"), which removes all occurrences of the characters x, y, and z from the leading and trailing ends of the string, but not .strip(\"foo\").

        The use of unique, multi-character strings may be intentional and consistent with the intent of .strip(), .lstrip(), or .rstrip(), while the use of duplicate-character strings is very likely to be a mistake.

        ","tags":["B005"]},{"location":"rules/strip-with-multi-characters/#example","title":"Example","text":"
        \"text.txt\".strip(\".txt\")  # \"e\"\n

        Use instead:

        \"text.txt\".removesuffix(\".txt\")  # \"text\"\n
        ","tags":["B005"]},{"location":"rules/strip-with-multi-characters/#references","title":"References","text":"
        • Python documentation: str.strip
        ","tags":["B005"]},{"location":"rules/stub-body-multiple-statements/","title":"stub-body-multiple-statements (PYI048)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI048"]},{"location":"rules/stub-body-multiple-statements/#what-it-does","title":"What it does","text":"

        Checks for functions in stub (.pyi) files that contain multiple statements.

        ","tags":["PYI048"]},{"location":"rules/stub-body-multiple-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files are never executed, and are only intended to define type hints. As such, functions in stub files should not contain functional code, and should instead contain only a single statement (e.g., ...).

        ","tags":["PYI048"]},{"location":"rules/stub-body-multiple-statements/#example","title":"Example","text":"
        def function():\n    x = 1\n    y = 2\n    return x + y\n

        Use instead:

        def function(): ...\n
        ","tags":["PYI048"]},{"location":"rules/subclass-builtin/","title":"subclass-builtin (FURB189)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB189"]},{"location":"rules/subclass-builtin/#what-it-does","title":"What it does","text":"

        Checks for subclasses of dict, list or str.

        ","tags":["FURB189"]},{"location":"rules/subclass-builtin/#why-is-this-bad","title":"Why is this bad?","text":"

        Built-in types don't consistently use their own dunder methods. For example, dict.__init__ and dict.update() bypass __setitem__, making inheritance unreliable.

        Use the UserDict, UserList, and UserString objects from the collections module instead.

        ","tags":["FURB189"]},{"location":"rules/subclass-builtin/#example","title":"Example","text":"
        class UppercaseDict(dict):\n    def __setitem__(self, key, value):\n        super().__setitem__(key.upper(), value)\n\n\nd = UppercaseDict({\"a\": 1, \"b\": 2})  # Bypasses __setitem__\nprint(d)  # {'a': 1, 'b': 2}\n

        Use instead:

        from collections import UserDict\n\n\nclass UppercaseDict(UserDict):\n    def __setitem__(self, key, value):\n        super().__setitem__(key.upper(), value)\n\n\nd = UppercaseDict({\"a\": 1, \"b\": 2})  # Uses __setitem__\nprint(d)  # {'A': 1, 'B': 2}\n
        ","tags":["FURB189"]},{"location":"rules/subclass-builtin/#fix-safety","title":"Fix safety","text":"

        This fix is marked as unsafe because isinstance() checks for dict, list, and str types will fail when using the corresponding User class. If you need to pass custom dict or list objects to code you don't control, ignore this check. If you do control the code, consider using the following type checks instead:

        • dict -> collections.abc.MutableMapping
        • list -> collections.abc.MutableSequence
        • str -> No such conversion exists
        ","tags":["FURB189"]},{"location":"rules/subclass-builtin/#references","title":"References","text":"
        • Python documentation: collections
        ","tags":["FURB189"]},{"location":"rules/subprocess-popen-preexec-fn/","title":"subprocess-popen-preexec-fn (PLW1509)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW1509"]},{"location":"rules/subprocess-popen-preexec-fn/#what-it-does","title":"What it does","text":"

        Checks for uses of subprocess.Popen with a preexec_fn argument.

        ","tags":["PLW1509"]},{"location":"rules/subprocess-popen-preexec-fn/#why-is-this-bad","title":"Why is this bad?","text":"

        The preexec_fn argument is unsafe within threads as it can lead to deadlocks. Furthermore, preexec_fn is targeted for deprecation.

        Instead, consider using task-specific arguments such as env, start_new_session, and process_group. These are not prone to deadlocks and are more explicit.

        ","tags":["PLW1509"]},{"location":"rules/subprocess-popen-preexec-fn/#example","title":"Example","text":"
        import os, subprocess\n\nsubprocess.Popen(foo, preexec_fn=os.setsid)\nsubprocess.Popen(bar, preexec_fn=os.setpgid(0, 0))\n

        Use instead:

        import subprocess\n\nsubprocess.Popen(foo, start_new_session=True)\nsubprocess.Popen(bar, process_group=0)  # Introduced in Python 3.11\n
        ","tags":["PLW1509"]},{"location":"rules/subprocess-popen-preexec-fn/#references","title":"References","text":"
        • Python documentation: subprocess.Popen
        • Why preexec_fn in subprocess.Popen may lead to deadlock?
        ","tags":["PLW1509"]},{"location":"rules/subprocess-popen-with-shell-equals-true/","title":"subprocess-popen-with-shell-equals-true (S602)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S602"]},{"location":"rules/subprocess-popen-with-shell-equals-true/#what-it-does","title":"What it does","text":"

        Check for method calls that initiate a subprocess with a shell.

        ","tags":["S602"]},{"location":"rules/subprocess-popen-with-shell-equals-true/#why-is-this-bad","title":"Why is this bad?","text":"

        Starting a subprocess with a shell can allow attackers to execute arbitrary shell commands. Consider starting the process without a shell call and sanitize the input to mitigate the risk of shell injection.

        ","tags":["S602"]},{"location":"rules/subprocess-popen-with-shell-equals-true/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.run(\"ls -l\", shell=True)\n

        Use instead:

        import subprocess\n\nsubprocess.run([\"ls\", \"-l\"])\n
        ","tags":["S602"]},{"location":"rules/subprocess-popen-with-shell-equals-true/#references","title":"References","text":"
        • Python documentation: subprocess \u2014 Subprocess management
        • Common Weakness Enumeration: CWE-78
        ","tags":["S602"]},{"location":"rules/subprocess-run-without-check/","title":"subprocess-run-without-check (PLW1510)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLW1510"]},{"location":"rules/subprocess-run-without-check/#what-it-does","title":"What it does","text":"

        Checks for uses of subprocess.run without an explicit check argument.

        ","tags":["PLW1510"]},{"location":"rules/subprocess-run-without-check/#why-is-this-bad","title":"Why is this bad?","text":"

        By default, subprocess.run does not check the return code of the process it runs. This can lead to silent failures.

        Instead, consider using check=True to raise an exception if the process fails, or set check=False explicitly to mark the behavior as intentional.

        ","tags":["PLW1510"]},{"location":"rules/subprocess-run-without-check/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.run([\"ls\", \"nonexistent\"])  # No exception raised.\n

        Use instead:

        import subprocess\n\nsubprocess.run([\"ls\", \"nonexistent\"], check=True)  # Raises exception.\n

        Or:

        import subprocess\n\nsubprocess.run([\"ls\", \"nonexistent\"], check=False)  # Explicitly no check.\n
        ","tags":["PLW1510"]},{"location":"rules/subprocess-run-without-check/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for function calls that contain **kwargs, as adding a check keyword argument to such a call may lead to a duplicate keyword argument error.

        ","tags":["PLW1510"]},{"location":"rules/subprocess-run-without-check/#references","title":"References","text":"
        • Python documentation: subprocess.run
        ","tags":["PLW1510"]},{"location":"rules/subprocess-without-shell-equals-true/","title":"subprocess-without-shell-equals-true (S603)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S603"]},{"location":"rules/subprocess-without-shell-equals-true/#what-it-does","title":"What it does","text":"

        Check for method calls that initiate a subprocess without a shell.

        ","tags":["S603"]},{"location":"rules/subprocess-without-shell-equals-true/#why-is-this-bad","title":"Why is this bad?","text":"

        Starting a subprocess without a shell can prevent attackers from executing arbitrary shell commands; however, it is still error-prone. Consider validating the input.

        ","tags":["S603"]},{"location":"rules/subprocess-without-shell-equals-true/#known-problems","title":"Known problems","text":"

        Prone to false positives as it is difficult to determine whether the passed arguments have been validated (#4045).

        ","tags":["S603"]},{"location":"rules/subprocess-without-shell-equals-true/#example","title":"Example","text":"
        import subprocess\n\ncmd = input(\"Enter a command: \").split()\nsubprocess.run(cmd)\n
        ","tags":["S603"]},{"location":"rules/subprocess-without-shell-equals-true/#references","title":"References","text":"
        • Python documentation: subprocess \u2014 Subprocess management
        ","tags":["S603"]},{"location":"rules/super-call-with-parameters/","title":"super-call-with-parameters (UP008)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP008"]},{"location":"rules/super-call-with-parameters/#what-it-does","title":"What it does","text":"

        Checks for super calls that pass redundant arguments.

        ","tags":["UP008"]},{"location":"rules/super-call-with-parameters/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3, super can be invoked without any arguments when: (1) the first argument is __class__, and (2) the second argument is equivalent to the first argument of the enclosing method.

        When possible, omit the arguments to super to make the code more concise and maintainable.

        ","tags":["UP008"]},{"location":"rules/super-call-with-parameters/#example","title":"Example","text":"
        class A:\n    def foo(self):\n        pass\n\n\nclass B(A):\n    def bar(self):\n        super(B, self).foo()\n

        Use instead:

        class A:\n    def foo(self):\n        pass\n\n\nclass B(A):\n    def bar(self):\n        super().foo()\n
        ","tags":["UP008"]},{"location":"rules/super-call-with-parameters/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because removing the arguments from a call may delete comments that are attached to the arguments.

        ","tags":["UP008"]},{"location":"rules/super-call-with-parameters/#references","title":"References","text":"
        • Python documentation: super
        • super/MRO, Python's most misunderstood feature.
        ","tags":["UP008"]},{"location":"rules/super-without-brackets/","title":"super-without-brackets (PLW0245)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLW0245"]},{"location":"rules/super-without-brackets/#what-it-does","title":"What it does","text":"

        Detects attempts to use super without parentheses.

        ","tags":["PLW0245"]},{"location":"rules/super-without-brackets/#why-is-this-bad","title":"Why is this bad?","text":"

        The super() callable can be used inside method definitions to create a proxy object that delegates attribute access to a superclass of the current class. Attempting to access attributes on super itself, however, instead of the object returned by a call to super(), will raise AttributeError.

        ","tags":["PLW0245"]},{"location":"rules/super-without-brackets/#example","title":"Example","text":"
        class Animal:\n    @staticmethod\n    def speak():\n        return \"This animal says something.\"\n\n\nclass Dog(Animal):\n    @staticmethod\n    def speak():\n        original_speak = super.speak()  # ERROR: `super.speak()`\n        return f\"{original_speak} But as a dog, it barks!\"\n

        Use instead:

        class Animal:\n    @staticmethod\n    def speak():\n        return \"This animal says something.\"\n\n\nclass Dog(Animal):\n    @staticmethod\n    def speak():\n        original_speak = super().speak()  # Correct: `super().speak()`\n        return f\"{original_speak} But as a dog, it barks!\"\n
        ","tags":["PLW0245"]},{"location":"rules/superfluous-else-break/","title":"superfluous-else-break (RET508)","text":"

        Derived from the flake8-return linter.

        Fix is sometimes available.

        ","tags":["RET508"]},{"location":"rules/superfluous-else-break/#what-it-does","title":"What it does","text":"

        Checks for else statements with a break statement in the preceding if block.

        ","tags":["RET508"]},{"location":"rules/superfluous-else-break/#why-is-this-bad","title":"Why is this bad?","text":"

        The else statement is not needed, as the break statement will always break out of the loop. Removing the else will reduce nesting and make the code more readable.

        ","tags":["RET508"]},{"location":"rules/superfluous-else-break/#example","title":"Example","text":"
        def foo(bar, baz):\n    for i in bar:\n        if i > baz:\n            break\n        else:\n            x = 0\n

        Use instead:

        def foo(bar, baz):\n    for i in bar:\n        if i > baz:\n            break\n        x = 0\n
        ","tags":["RET508"]},{"location":"rules/superfluous-else-continue/","title":"superfluous-else-continue (RET507)","text":"

        Derived from the flake8-return linter.

        Fix is sometimes available.

        ","tags":["RET507"]},{"location":"rules/superfluous-else-continue/#what-it-does","title":"What it does","text":"

        Checks for else statements with a continue statement in the preceding if block.

        ","tags":["RET507"]},{"location":"rules/superfluous-else-continue/#why-is-this-bad","title":"Why is this bad?","text":"

        The else statement is not needed, as the continue statement will always continue onto the next iteration of a loop. Removing the else will reduce nesting and make the code more readable.

        ","tags":["RET507"]},{"location":"rules/superfluous-else-continue/#example","title":"Example","text":"
        def foo(bar, baz):\n    for i in bar:\n        if i < baz:\n            continue\n        else:\n            x = 0\n

        Use instead:

        def foo(bar, baz):\n    for i in bar:\n        if i < baz:\n            continue\n        x = 0\n
        ","tags":["RET507"]},{"location":"rules/superfluous-else-raise/","title":"superfluous-else-raise (RET506)","text":"

        Derived from the flake8-return linter.

        Fix is sometimes available.

        ","tags":["RET506"]},{"location":"rules/superfluous-else-raise/#what-it-does","title":"What it does","text":"

        Checks for else statements with a raise statement in the preceding if block.

        ","tags":["RET506"]},{"location":"rules/superfluous-else-raise/#why-is-this-bad","title":"Why is this bad?","text":"

        The else statement is not needed as the raise statement will always break out of the current scope. Removing the else will reduce nesting and make the code more readable.

        ","tags":["RET506"]},{"location":"rules/superfluous-else-raise/#example","title":"Example","text":"
        def foo(bar, baz):\n    if bar == \"Specific Error\":\n        raise Exception(bar)\n    else:\n        raise Exception(baz)\n

        Use instead:

        def foo(bar, baz):\n    if bar == \"Specific Error\":\n        raise Exception(bar)\n    raise Exception(baz)\n
        ","tags":["RET506"]},{"location":"rules/superfluous-else-return/","title":"superfluous-else-return (RET505)","text":"

        Derived from the flake8-return linter.

        Fix is sometimes available.

        ","tags":["RET505"]},{"location":"rules/superfluous-else-return/#what-it-does","title":"What it does","text":"

        Checks for else statements with a return statement in the preceding if block.

        ","tags":["RET505"]},{"location":"rules/superfluous-else-return/#why-is-this-bad","title":"Why is this bad?","text":"

        The else statement is not needed as the return statement will always break out of the enclosing function. Removing the else will reduce nesting and make the code more readable.

        ","tags":["RET505"]},{"location":"rules/superfluous-else-return/#example","title":"Example","text":"
        def foo(bar, baz):\n    if bar:\n        return 1\n    else:\n        return baz\n

        Use instead:

        def foo(bar, baz):\n    if bar:\n        return 1\n    return baz\n
        ","tags":["RET505"]},{"location":"rules/suppressible-exception/","title":"suppressible-exception (SIM105)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM105"]},{"location":"rules/suppressible-exception/#what-it-does","title":"What it does","text":"

        Checks for try-except-pass blocks that can be replaced with the contextlib.suppress context manager.

        ","tags":["SIM105"]},{"location":"rules/suppressible-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        Using contextlib.suppress is more concise and directly communicates the intent of the code: to suppress a given exception.

        Note that contextlib.suppress is slower than using try-except-pass directly. For performance-critical code, consider retaining the try-except-pass pattern.

        ","tags":["SIM105"]},{"location":"rules/suppressible-exception/#example","title":"Example","text":"
        try:\n    1 / 0\nexcept ZeroDivisionError:\n    pass\n

        Use instead:

        import contextlib\n\nwith contextlib.suppress(ZeroDivisionError):\n    1 / 0\n
        ","tags":["SIM105"]},{"location":"rules/suppressible-exception/#references","title":"References","text":"
        • Python documentation: contextlib.suppress
        • Python documentation: try statement
        • a simpler try/except (and why maybe shouldn't)
        ","tags":["SIM105"]},{"location":"rules/surrounding-whitespace/","title":"surrounding-whitespace (D210)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D210"]},{"location":"rules/surrounding-whitespace/#what-it-does","title":"What it does","text":"

        Checks for surrounding whitespace in docstrings.

        ","tags":["D210"]},{"location":"rules/surrounding-whitespace/#why-is-this-bad","title":"Why is this bad?","text":"

        Remove surrounding whitespace from the docstring, for consistency.

        ","tags":["D210"]},{"location":"rules/surrounding-whitespace/#example","title":"Example","text":"
        def factorial(n: int) -> int:\n    \"\"\" Return the factorial of n. \"\"\"\n

        Use instead:

        def factorial(n: int) -> int:\n    \"\"\"Return the factorial of n.\"\"\"\n
        ","tags":["D210"]},{"location":"rules/surrounding-whitespace/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D210"]},{"location":"rules/suspicious-eval-usage/","title":"suspicious-eval-usage (S307)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S307"]},{"location":"rules/suspicious-eval-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of the builtin eval() function.

        ","tags":["S307"]},{"location":"rules/suspicious-eval-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        The eval() function is insecure as it enables arbitrary code execution.

        If you need to evaluate an expression from a string, consider using ast.literal_eval() instead, which will raise an exception if the expression is not a valid Python literal.

        In preview, this rule will also flag references to eval.

        ","tags":["S307"]},{"location":"rules/suspicious-eval-usage/#example","title":"Example","text":"
        x = eval(input(\"Enter a number: \"))\n

        Use instead:

        from ast import literal_eval\n\nx = literal_eval(input(\"Enter a number: \"))\n
        ","tags":["S307"]},{"location":"rules/suspicious-eval-usage/#references","title":"References","text":"
        • Python documentation: eval
        • Python documentation: literal_eval
        • Eval really is dangerous by Ned Batchelder
        ","tags":["S307"]},{"location":"rules/suspicious-ftp-lib-usage/","title":"suspicious-ftp-lib-usage (S321)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S321"]},{"location":"rules/suspicious-ftp-lib-usage/#what-it-does","title":"What it does","text":"

        Checks for the use of FTP-related functions.

        ","tags":["S321"]},{"location":"rules/suspicious-ftp-lib-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        FTP is considered insecure as it does not encrypt data sent over the connection and is thus vulnerable to numerous attacks.

        Instead, consider using FTPS (which secures FTP using SSL/TLS) or SFTP.

        In preview, this rule will also flag references to FTP-related functions.

        ","tags":["S321"]},{"location":"rules/suspicious-ftp-lib-usage/#references","title":"References","text":"
        • Python documentation: ftplib \u2014 FTP protocol client
        ","tags":["S321"]},{"location":"rules/suspicious-ftplib-import/","title":"suspicious-ftplib-import (S402)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S402"]},{"location":"rules/suspicious-ftplib-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the ftplib module.

        ","tags":["S402"]},{"location":"rules/suspicious-ftplib-import/#why-is-this-bad","title":"Why is this bad?","text":"

        FTP is considered insecure. Instead, use SSH, SFTP, SCP, or another encrypted protocol.

        ","tags":["S402"]},{"location":"rules/suspicious-ftplib-import/#example","title":"Example","text":"
        import ftplib\n
        ","tags":["S402"]},{"location":"rules/suspicious-ftplib-import/#references","title":"References","text":"
        • Python documentation: ftplib - FTP protocol client
        ","tags":["S402"]},{"location":"rules/suspicious-httpoxy-import/","title":"suspicious-httpoxy-import (S412)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S412"]},{"location":"rules/suspicious-httpoxy-import/#what-it-does","title":"What it does","text":"

        Checks for imports of wsgiref.handlers.CGIHandler and twisted.web.twcgi.CGIScript.

        ","tags":["S412"]},{"location":"rules/suspicious-httpoxy-import/#why-is-this-bad","title":"Why is this bad?","text":"

        httpoxy is a set of vulnerabilities that affect application code running in CGI or CGI-like environments. The use of CGI for web applications should be avoided to prevent this class of attack.

        ","tags":["S412"]},{"location":"rules/suspicious-httpoxy-import/#example","title":"Example","text":"
        import wsgiref.handlers.CGIHandler\n
        ","tags":["S412"]},{"location":"rules/suspicious-httpoxy-import/#references","title":"References","text":"
        • httpoxy website
        ","tags":["S412"]},{"location":"rules/suspicious-insecure-cipher-mode-usage/","title":"suspicious-insecure-cipher-mode-usage (S305)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S305"]},{"location":"rules/suspicious-insecure-cipher-mode-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of weak or broken cryptographic cipher modes.

        ","tags":["S305"]},{"location":"rules/suspicious-insecure-cipher-mode-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Weak or broken cryptographic ciphers may be susceptible to attacks that allow an attacker to decrypt ciphertext without knowing the key or otherwise compromise the security of the cipher, such as forgeries.

        Use strong, modern cryptographic ciphers instead of weak or broken ones.

        In preview, this rule will also flag references to insecure cipher modes.

        ","tags":["S305"]},{"location":"rules/suspicious-insecure-cipher-mode-usage/#example","title":"Example","text":"
        from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes\n\nalgorithm = algorithms.ARC4(key)\ncipher = Cipher(algorithm, mode=modes.ECB(iv))\nencryptor = cipher.encryptor()\n

        Use instead:

        from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes\n\nalgorithm = algorithms.ARC4(key)\ncipher = Cipher(algorithm, mode=modes.CTR(iv))\nencryptor = cipher.encryptor()\n
        ","tags":["S305"]},{"location":"rules/suspicious-insecure-cipher-mode-usage/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-327
        ","tags":["S305"]},{"location":"rules/suspicious-insecure-cipher-usage/","title":"suspicious-insecure-cipher-usage (S304)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S304"]},{"location":"rules/suspicious-insecure-cipher-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of weak or broken cryptographic ciphers.

        ","tags":["S304"]},{"location":"rules/suspicious-insecure-cipher-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Weak or broken cryptographic ciphers may be susceptible to attacks that allow an attacker to decrypt ciphertext without knowing the key or otherwise compromise the security of the cipher, such as forgeries.

        Use strong, modern cryptographic ciphers instead of weak or broken ones.

        In preview, this rule will also flag references to insecure ciphers.

        ","tags":["S304"]},{"location":"rules/suspicious-insecure-cipher-usage/#example","title":"Example","text":"
        from cryptography.hazmat.primitives.ciphers import Cipher, algorithms\n\nalgorithm = algorithms.ARC4(key)\ncipher = Cipher(algorithm, mode=None)\nencryptor = cipher.encryptor()\n

        Use instead:

        from cryptography.fernet import Fernet\n\nfernet = Fernet(key)\n
        ","tags":["S304"]},{"location":"rules/suspicious-insecure-cipher-usage/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-327
        ","tags":["S304"]},{"location":"rules/suspicious-insecure-hash-usage/","title":"suspicious-insecure-hash-usage (S303)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S303"]},{"location":"rules/suspicious-insecure-hash-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of weak or broken cryptographic hash functions.

        ","tags":["S303"]},{"location":"rules/suspicious-insecure-hash-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Weak or broken cryptographic hash functions may be susceptible to collision attacks (where two different inputs produce the same hash) or pre-image attacks (where an attacker can find an input that produces a given hash). This can lead to security vulnerabilities in applications that rely on these hash functions.

        Avoid using weak or broken cryptographic hash functions in security contexts. Instead, use a known secure hash function such as SHA-256.

        In preview, this rule will also flag references to insecure hash functions.

        ","tags":["S303"]},{"location":"rules/suspicious-insecure-hash-usage/#example","title":"Example","text":"
        from cryptography.hazmat.primitives import hashes\n\ndigest = hashes.Hash(hashes.MD5())\ndigest.update(b\"Hello, world!\")\ndigest.finalize()\n

        Use instead:

        from cryptography.hazmat.primitives import hashes\n\ndigest = hashes.Hash(hashes.SHA256())\ndigest.update(b\"Hello, world!\")\ndigest.finalize()\n
        ","tags":["S303"]},{"location":"rules/suspicious-insecure-hash-usage/#references","title":"References","text":"
        • Python documentation: hashlib \u2014 Secure hashes and message digests
        • Common Weakness Enumeration: CWE-327
        • Common Weakness Enumeration: CWE-328
        • Common Weakness Enumeration: CWE-916
        ","tags":["S303"]},{"location":"rules/suspicious-lxml-import/","title":"suspicious-lxml-import (S410)","text":"

        Derived from the flake8-bandit linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["S410"]},{"location":"rules/suspicious-lxml-import/#removed","title":"Removed","text":"

        This rule was removed as the lxml library has been modified to address known vulnerabilities and unsafe defaults. As such, the defusedxml library is no longer necessary, defusedxml has deprecated its lxml module.

        ","tags":["S410"]},{"location":"rules/suspicious-lxml-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the lxml module.

        ","tags":["S410"]},{"location":"rules/suspicious-lxml-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from the lxml module to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package.

        ","tags":["S410"]},{"location":"rules/suspicious-lxml-import/#example","title":"Example","text":"
        import lxml\n
        ","tags":["S410"]},{"location":"rules/suspicious-mark-safe-usage/","title":"suspicious-mark-safe-usage (S308)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S308"]},{"location":"rules/suspicious-mark-safe-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of calls to django.utils.safestring.mark_safe.

        ","tags":["S308"]},{"location":"rules/suspicious-mark-safe-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Cross-site scripting (XSS) vulnerabilities allow attackers to execute arbitrary JavaScript. To guard against XSS attacks, Django templates assumes that data is unsafe and automatically escapes malicious strings before rending them.

        django.utils.safestring.mark_safe marks a string as safe for use in HTML templates, bypassing XSS protection. Its usage can be dangerous if the contents of the string are dynamically generated, because it may allow cross-site scripting attacks if the string is not properly escaped.

        For dynamically generated strings, consider utilizing django.utils.html.format_html.

        In preview, this rule will also flag references to django.utils.safestring.mark_safe.

        ","tags":["S308"]},{"location":"rules/suspicious-mark-safe-usage/#example","title":"Example","text":"
        from django.utils.safestring import mark_safe\n\n\ndef render_username(username):\n    return mark_safe(f\"<i>{username}</i>\")  # Dangerous if username is user-provided.\n

        Use instead:

        from django.utils.html import format_html\n\n\ndef render_username(username):\n    return django.utils.html.format_html(\"<i>{}</i>\", username)  # username is escaped.\n
        ","tags":["S308"]},{"location":"rules/suspicious-mark-safe-usage/#references","title":"References","text":"
        • Django documentation: mark_safe
        • Django documentation: Cross Site Scripting (XSS) protection
        • Common Weakness Enumeration: CWE-80
        ","tags":["S308"]},{"location":"rules/suspicious-marshal-usage/","title":"suspicious-marshal-usage (S302)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S302"]},{"location":"rules/suspicious-marshal-usage/#what-it-does","title":"What it does","text":"

        Checks for calls to marshal functions.

        ","tags":["S302"]},{"location":"rules/suspicious-marshal-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Deserializing untrusted data with marshal is insecure, as it can allow for the creation of arbitrary objects, which can then be used to achieve arbitrary code execution and otherwise unexpected behavior.

        Avoid deserializing untrusted data with marshal. Instead, consider safer formats, such as JSON.

        If you must deserialize untrusted data with marshal, consider signing the data with a secret key and verifying the signature before deserializing the payload. This will prevent an attacker from injecting arbitrary objects into the serialized data.

        In preview, this rule will also flag references to marshal functions.

        ","tags":["S302"]},{"location":"rules/suspicious-marshal-usage/#example","title":"Example","text":"
        import marshal\n\nwith open(\"foo.marshal\", \"rb\") as file:\n    foo = marshal.load(file)\n

        Use instead:

        import json\n\nwith open(\"foo.json\", \"rb\") as file:\n    foo = json.load(file)\n
        ","tags":["S302"]},{"location":"rules/suspicious-marshal-usage/#references","title":"References","text":"
        • Python documentation: marshal \u2014 Internal Python object serialization
        • Common Weakness Enumeration: CWE-502
        ","tags":["S302"]},{"location":"rules/suspicious-mktemp-usage/","title":"suspicious-mktemp-usage (S306)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S306"]},{"location":"rules/suspicious-mktemp-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of tempfile.mktemp.

        ","tags":["S306"]},{"location":"rules/suspicious-mktemp-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        tempfile.mktemp returns a pathname of a file that does not exist at the time the call is made; then, the caller is responsible for creating the file and subsequently using it. This is insecure because another process could create a file with the same name between the time the function returns and the time the caller creates the file.

        tempfile.mktemp is deprecated in favor of tempfile.mkstemp which creates the file when it is called. Consider using tempfile.mkstemp instead, either directly or via a context manager such as tempfile.TemporaryFile.

        In preview, this rule will also flag references to tempfile.mktemp.

        ","tags":["S306"]},{"location":"rules/suspicious-mktemp-usage/#example","title":"Example","text":"
        import tempfile\n\ntmp_file = tempfile.mktemp()\nwith open(tmp_file, \"w\") as file:\n    file.write(\"Hello, world!\")\n

        Use instead:

        import tempfile\n\nwith tempfile.TemporaryFile() as file:\n    file.write(\"Hello, world!\")\n
        ","tags":["S306"]},{"location":"rules/suspicious-mktemp-usage/#references","title":"References","text":"
        • Python documentation:mktemp
        ","tags":["S306"]},{"location":"rules/suspicious-non-cryptographic-random-usage/","title":"suspicious-non-cryptographic-random-usage (S311)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S311"]},{"location":"rules/suspicious-non-cryptographic-random-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of cryptographically weak pseudo-random number generators.

        ","tags":["S311"]},{"location":"rules/suspicious-non-cryptographic-random-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Cryptographically weak pseudo-random number generators are insecure, as they are easily predictable. This can allow an attacker to guess the generated numbers and compromise the security of the system.

        Instead, use a cryptographically secure pseudo-random number generator (such as using the secrets module) when generating random numbers for security purposes.

        In preview, this rule will also flag references to these generators.

        ","tags":["S311"]},{"location":"rules/suspicious-non-cryptographic-random-usage/#example","title":"Example","text":"
        import random\n\nrandom.randrange(10)\n

        Use instead:

        import secrets\n\nsecrets.randbelow(10)\n
        ","tags":["S311"]},{"location":"rules/suspicious-non-cryptographic-random-usage/#references","title":"References","text":"
        • Python documentation: random \u2014 Generate pseudo-random numbers
        ","tags":["S311"]},{"location":"rules/suspicious-pickle-import/","title":"suspicious-pickle-import (S403)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S403"]},{"location":"rules/suspicious-pickle-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the pickle, cPickle, dill, and shelve modules.

        ","tags":["S403"]},{"location":"rules/suspicious-pickle-import/#why-is-this-bad","title":"Why is this bad?","text":"

        It is possible to construct malicious pickle data which will execute arbitrary code during unpickling. Consider possible security implications associated with these modules.

        ","tags":["S403"]},{"location":"rules/suspicious-pickle-import/#example","title":"Example","text":"
        import pickle\n
        ","tags":["S403"]},{"location":"rules/suspicious-pickle-import/#references","title":"References","text":"
        • Python documentation: pickle \u2014 Python object serialization
        ","tags":["S403"]},{"location":"rules/suspicious-pickle-usage/","title":"suspicious-pickle-usage (S301)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S301"]},{"location":"rules/suspicious-pickle-usage/#what-it-does","title":"What it does","text":"

        Checks for calls to pickle functions or modules that wrap them.

        ","tags":["S301"]},{"location":"rules/suspicious-pickle-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Deserializing untrusted data with pickle and other deserialization modules is insecure as it can allow for the creation of arbitrary objects, which can then be used to achieve arbitrary code execution and otherwise unexpected behavior.

        Avoid deserializing untrusted data with pickle and other deserialization modules. Instead, consider safer formats, such as JSON.

        If you must deserialize untrusted data with pickle, consider signing the data with a secret key and verifying the signature before deserializing the payload, This will prevent an attacker from injecting arbitrary objects into the serialized data.

        In preview, this rule will also flag references to pickle functions.

        ","tags":["S301"]},{"location":"rules/suspicious-pickle-usage/#example","title":"Example","text":"
        import pickle\n\nwith open(\"foo.pickle\", \"rb\") as file:\n    foo = pickle.load(file)\n

        Use instead:

        import json\n\nwith open(\"foo.json\", \"rb\") as file:\n    foo = json.load(file)\n
        ","tags":["S301"]},{"location":"rules/suspicious-pickle-usage/#references","title":"References","text":"
        • Python documentation: pickle \u2014 Python object serialization
        • Common Weakness Enumeration: CWE-502
        ","tags":["S301"]},{"location":"rules/suspicious-pycrypto-import/","title":"suspicious-pycrypto-import (S413)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S413"]},{"location":"rules/suspicious-pycrypto-import/#what-it-does","title":"What it does","text":"

        Checks for imports of several unsafe cryptography modules.

        ","tags":["S413"]},{"location":"rules/suspicious-pycrypto-import/#why-is-this-bad","title":"Why is this bad?","text":"

        The pycrypto library is known to have a publicly disclosed buffer overflow vulnerability. It is no longer actively maintained and has been deprecated in favor of the pyca/cryptography library.

        ","tags":["S413"]},{"location":"rules/suspicious-pycrypto-import/#example","title":"Example","text":"
        import Crypto.Random\n
        ","tags":["S413"]},{"location":"rules/suspicious-pycrypto-import/#references","title":"References","text":"
        • Buffer Overflow Issue
        ","tags":["S413"]},{"location":"rules/suspicious-pyghmi-import/","title":"suspicious-pyghmi-import (S415)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S415"]},{"location":"rules/suspicious-pyghmi-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the pyghmi module.

        ","tags":["S415"]},{"location":"rules/suspicious-pyghmi-import/#why-is-this-bad","title":"Why is this bad?","text":"

        pyghmi is an IPMI-related module, but IPMI is considered insecure. Instead, use an encrypted protocol.

        ","tags":["S415"]},{"location":"rules/suspicious-pyghmi-import/#example","title":"Example","text":"
        import pyghmi\n
        ","tags":["S415"]},{"location":"rules/suspicious-pyghmi-import/#references","title":"References","text":"
        • Buffer Overflow Issue
        ","tags":["S415"]},{"location":"rules/suspicious-subprocess-import/","title":"suspicious-subprocess-import (S404)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S404"]},{"location":"rules/suspicious-subprocess-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the subprocess module.

        ","tags":["S404"]},{"location":"rules/suspicious-subprocess-import/#why-is-this-bad","title":"Why is this bad?","text":"

        It is possible to inject malicious commands into subprocess calls. Consider possible security implications associated with this module.

        ","tags":["S404"]},{"location":"rules/suspicious-subprocess-import/#example","title":"Example","text":"
        import subprocess\n
        ","tags":["S404"]},{"location":"rules/suspicious-telnet-usage/","title":"suspicious-telnet-usage (S312)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S312"]},{"location":"rules/suspicious-telnet-usage/#what-it-does","title":"What it does","text":"

        Checks for the use of Telnet-related functions.

        ","tags":["S312"]},{"location":"rules/suspicious-telnet-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Telnet is considered insecure because it does not encrypt data sent over the connection and is vulnerable to numerous attacks.

        Instead, consider using a more secure protocol such as SSH.

        In preview, this rule will also flag references to Telnet-related functions.

        ","tags":["S312"]},{"location":"rules/suspicious-telnet-usage/#references","title":"References","text":"
        • Python documentation: telnetlib \u2014 Telnet client
        ","tags":["S312"]},{"location":"rules/suspicious-telnetlib-import/","title":"suspicious-telnetlib-import (S401)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S401"]},{"location":"rules/suspicious-telnetlib-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the telnetlib module.

        ","tags":["S401"]},{"location":"rules/suspicious-telnetlib-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Telnet is considered insecure. It is deprecated since version 3.11, and was removed in version 3.13. Instead, use SSH or another encrypted protocol.

        ","tags":["S401"]},{"location":"rules/suspicious-telnetlib-import/#example","title":"Example","text":"
        import telnetlib\n
        ","tags":["S401"]},{"location":"rules/suspicious-telnetlib-import/#references","title":"References","text":"
        • Python documentation: telnetlib - Telnet client
        • PEP 594: telnetlib
        ","tags":["S401"]},{"location":"rules/suspicious-unverified-context-usage/","title":"suspicious-unverified-context-usage (S323)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S323"]},{"location":"rules/suspicious-unverified-context-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of ssl._create_unverified_context.

        ","tags":["S323"]},{"location":"rules/suspicious-unverified-context-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 476 enabled certificate and hostname validation by default in Python standard library HTTP clients. Previously, Python did not validate certificates by default, which could allow an attacker to perform a \"man in the middle\" attack by intercepting and modifying traffic between client and server.

        To support legacy environments, ssl._create_unverified_context reverts to the previous behavior that does perform verification. Otherwise, use ssl.create_default_context to create a secure context.

        In preview, this rule will also flag references to ssl._create_unverified_context.

        ","tags":["S323"]},{"location":"rules/suspicious-unverified-context-usage/#example","title":"Example","text":"
        import ssl\n\ncontext = ssl._create_unverified_context()\n

        Use instead:

        import ssl\n\ncontext = ssl.create_default_context()\n
        ","tags":["S323"]},{"location":"rules/suspicious-unverified-context-usage/#references","title":"References","text":"
        • PEP 476 \u2013 Enabling certificate verification by default for stdlib http clients: Opting out
        • Python documentation: ssl \u2014 TLS/SSL wrapper for socket objects
        ","tags":["S323"]},{"location":"rules/suspicious-url-open-usage/","title":"suspicious-url-open-usage (S310)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S310"]},{"location":"rules/suspicious-url-open-usage/#what-it-does","title":"What it does","text":"

        Checks for instances where URL open functions are used with unexpected schemes.

        ","tags":["S310"]},{"location":"rules/suspicious-url-open-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Some URL open functions allow the use of file: or custom schemes (for use instead of http: or https:). An attacker may be able to use these schemes to access or modify unauthorized resources, and cause unexpected behavior.

        To mitigate this risk, audit all uses of URL open functions and ensure that only permitted schemes are used (e.g., allowing http: and https:, and disallowing file: and ftp:).

        In preview, this rule will also flag references to URL open functions.

        ","tags":["S310"]},{"location":"rules/suspicious-url-open-usage/#example","title":"Example","text":"
        from urllib.request import urlopen\n\nurl = input(\"Enter a URL: \")\n\nwith urlopen(url) as response:\n    ...\n

        Use instead:

        from urllib.request import urlopen\n\nurl = input(\"Enter a URL: \")\n\nif not url.startswith((\"http:\", \"https:\")):\n    raise ValueError(\"URL must start with 'http:' or 'https:'\")\n\nwith urlopen(url) as response:\n    ...\n
        ","tags":["S310"]},{"location":"rules/suspicious-url-open-usage/#references","title":"References","text":"
        • Python documentation: urlopen
        ","tags":["S310"]},{"location":"rules/suspicious-xml-element-tree-usage/","title":"suspicious-xml-element-tree-usage (S314)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S314"]},{"location":"rules/suspicious-xml-element-tree-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S314"]},{"location":"rules/suspicious-xml-element-tree-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S314"]},{"location":"rules/suspicious-xml-element-tree-usage/#example","title":"Example","text":"
        from xml.etree.ElementTree import parse\n\ntree = parse(\"untrusted.xml\")  # Vulnerable to XML attacks.\n

        Use instead:

        from defusedxml.ElementTree import parse\n\ntree = parse(\"untrusted.xml\")\n
        ","tags":["S314"]},{"location":"rules/suspicious-xml-element-tree-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S314"]},{"location":"rules/suspicious-xml-etree-import/","title":"suspicious-xml-etree-import (S405)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S405"]},{"location":"rules/suspicious-xml-etree-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xml.etree.cElementTree and xml.etree.ElementTree modules

        ","tags":["S405"]},{"location":"rules/suspicious-xml-etree-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from these modules to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called before parsing XML data.

        ","tags":["S405"]},{"location":"rules/suspicious-xml-etree-import/#example","title":"Example","text":"
        import xml.etree.cElementTree\n
        ","tags":["S405"]},{"location":"rules/suspicious-xml-expat-builder-usage/","title":"suspicious-xml-expat-builder-usage (S316)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S316"]},{"location":"rules/suspicious-xml-expat-builder-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S316"]},{"location":"rules/suspicious-xml-expat-builder-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S316"]},{"location":"rules/suspicious-xml-expat-builder-usage/#example","title":"Example","text":"
        from xml.dom.expatbuilder import parse\n\nparse(\"untrusted.xml\")\n

        Use instead:

        from defusedxml.expatbuilder import parse\n\ntree = parse(\"untrusted.xml\")\n
        ","tags":["S316"]},{"location":"rules/suspicious-xml-expat-builder-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S316"]},{"location":"rules/suspicious-xml-expat-import/","title":"suspicious-xml-expat-import (S407)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S407"]},{"location":"rules/suspicious-xml-expat-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xml.dom.expatbuilder module.

        ","tags":["S407"]},{"location":"rules/suspicious-xml-expat-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from these modules to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called before parsing XML data.

        ","tags":["S407"]},{"location":"rules/suspicious-xml-expat-import/#example","title":"Example","text":"
        import xml.dom.expatbuilder\n
        ","tags":["S407"]},{"location":"rules/suspicious-xml-expat-reader-usage/","title":"suspicious-xml-expat-reader-usage (S315)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S315"]},{"location":"rules/suspicious-xml-expat-reader-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S315"]},{"location":"rules/suspicious-xml-expat-reader-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S315"]},{"location":"rules/suspicious-xml-expat-reader-usage/#example","title":"Example","text":"
        from xml.sax.expatreader import create_parser\n\nparser = create_parser()\n

        Use instead:

        from defusedxml.sax import create_parser\n\nparser = create_parser()\n
        ","tags":["S315"]},{"location":"rules/suspicious-xml-expat-reader-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S315"]},{"location":"rules/suspicious-xml-mini-dom-usage/","title":"suspicious-xml-mini-dom-usage (S318)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S318"]},{"location":"rules/suspicious-xml-mini-dom-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S318"]},{"location":"rules/suspicious-xml-mini-dom-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S318"]},{"location":"rules/suspicious-xml-mini-dom-usage/#example","title":"Example","text":"
        from xml.dom.minidom import parse\n\ncontent = parse(\"untrusted.xml\")\n

        Use instead:

        from defusedxml.minidom import parse\n\ncontent = parse(\"untrusted.xml\")\n
        ","tags":["S318"]},{"location":"rules/suspicious-xml-mini-dom-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S318"]},{"location":"rules/suspicious-xml-minidom-import/","title":"suspicious-xml-minidom-import (S408)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S408"]},{"location":"rules/suspicious-xml-minidom-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xml.dom.minidom module.

        ","tags":["S408"]},{"location":"rules/suspicious-xml-minidom-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from these modules to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called before parsing XML data.

        ","tags":["S408"]},{"location":"rules/suspicious-xml-minidom-import/#example","title":"Example","text":"
        import xml.dom.minidom\n
        ","tags":["S408"]},{"location":"rules/suspicious-xml-pull-dom-usage/","title":"suspicious-xml-pull-dom-usage (S319)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S319"]},{"location":"rules/suspicious-xml-pull-dom-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S319"]},{"location":"rules/suspicious-xml-pull-dom-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S319"]},{"location":"rules/suspicious-xml-pull-dom-usage/#example","title":"Example","text":"
        from xml.dom.pulldom import parse\n\ncontent = parse(\"untrusted.xml\")\n

        Use instead:

        from defusedxml.pulldom import parse\n\ncontent = parse(\"untrusted.xml\")\n
        ","tags":["S319"]},{"location":"rules/suspicious-xml-pull-dom-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S319"]},{"location":"rules/suspicious-xml-pulldom-import/","title":"suspicious-xml-pulldom-import (S409)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S409"]},{"location":"rules/suspicious-xml-pulldom-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xml.dom.pulldom module.

        ","tags":["S409"]},{"location":"rules/suspicious-xml-pulldom-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from these modules to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called before parsing XML data.

        ","tags":["S409"]},{"location":"rules/suspicious-xml-pulldom-import/#example","title":"Example","text":"
        import xml.dom.pulldom\n
        ","tags":["S409"]},{"location":"rules/suspicious-xml-sax-import/","title":"suspicious-xml-sax-import (S406)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S406"]},{"location":"rules/suspicious-xml-sax-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xml.sax module.

        ","tags":["S406"]},{"location":"rules/suspicious-xml-sax-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Using various methods from these modules to parse untrusted XML data is known to be vulnerable to XML attacks. Replace vulnerable imports with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called before parsing XML data.

        ","tags":["S406"]},{"location":"rules/suspicious-xml-sax-import/#example","title":"Example","text":"
        import xml.sax\n
        ","tags":["S406"]},{"location":"rules/suspicious-xml-sax-usage/","title":"suspicious-xml-sax-usage (S317)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S317"]},{"location":"rules/suspicious-xml-sax-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S317"]},{"location":"rules/suspicious-xml-sax-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S317"]},{"location":"rules/suspicious-xml-sax-usage/#example","title":"Example","text":"
        from xml.sax import make_parser\n\nmake_parser()\n

        Use instead:

        from defusedxml.sax import make_parser\n\nmake_parser()\n
        ","tags":["S317"]},{"location":"rules/suspicious-xml-sax-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S317"]},{"location":"rules/suspicious-xmlc-element-tree-usage/","title":"suspicious-xmlc-element-tree-usage (S313)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S313"]},{"location":"rules/suspicious-xmlc-element-tree-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S313"]},{"location":"rules/suspicious-xmlc-element-tree-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        Consider using the defusedxml package when parsing untrusted XML data, to protect against XML attacks.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S313"]},{"location":"rules/suspicious-xmlc-element-tree-usage/#example","title":"Example","text":"
        from xml.etree.cElementTree import parse\n\ntree = parse(\"untrusted.xml\")  # Vulnerable to XML attacks.\n

        Use instead:

        from defusedxml.cElementTree import parse\n\ntree = parse(\"untrusted.xml\")\n
        ","tags":["S313"]},{"location":"rules/suspicious-xmlc-element-tree-usage/#references","title":"References","text":"
        • Python documentation: xml \u2014 XML processing modules
        • PyPI: defusedxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S313"]},{"location":"rules/suspicious-xmle-tree-usage/","title":"suspicious-xmle-tree-usage (S320)","text":"

        Derived from the flake8-bandit linter.

        Warning: This rule is deprecated and will be removed in a future release.

        ","tags":["S320"]},{"location":"rules/suspicious-xmle-tree-usage/#deprecation","title":"Deprecation","text":"

        This rule was deprecated as the lxml library has been modified to address known vulnerabilities and unsafe defaults. As such, the defusedxml library is no longer necessary, defusedxml has deprecated its lxml module.

        ","tags":["S320"]},{"location":"rules/suspicious-xmle-tree-usage/#what-it-does","title":"What it does","text":"

        Checks for uses of insecure XML parsers.

        ","tags":["S320"]},{"location":"rules/suspicious-xmle-tree-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Many XML parsers are vulnerable to XML attacks (such as entity expansion), which cause excessive memory and CPU usage by exploiting recursion. An attacker could use such methods to access unauthorized resources.

        In preview, this rule will also flag references to insecure XML parsers.

        ","tags":["S320"]},{"location":"rules/suspicious-xmle-tree-usage/#example","title":"Example","text":"
        from lxml import etree\n\ncontent = etree.parse(\"untrusted.xml\")\n
        ","tags":["S320"]},{"location":"rules/suspicious-xmle-tree-usage/#references","title":"References","text":"
        • PyPI: lxml
        • Common Weakness Enumeration: CWE-400
        • Common Weakness Enumeration: CWE-776
        ","tags":["S320"]},{"location":"rules/suspicious-xmlrpc-import/","title":"suspicious-xmlrpc-import (S411)","text":"

        Derived from the flake8-bandit linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["S411"]},{"location":"rules/suspicious-xmlrpc-import/#what-it-does","title":"What it does","text":"

        Checks for imports of the xmlrpc module.

        ","tags":["S411"]},{"location":"rules/suspicious-xmlrpc-import/#why-is-this-bad","title":"Why is this bad?","text":"

        XMLRPC is a particularly dangerous XML module, as it is also concerned with communicating data over a network. Use the defused.xmlrpc.monkey_patch() function to monkey-patch the xmlrpclib module and mitigate remote XML attacks.

        ","tags":["S411"]},{"location":"rules/suspicious-xmlrpc-import/#example","title":"Example","text":"
        import xmlrpc\n
        ","tags":["S411"]},{"location":"rules/syntax-error/","title":"syntax-error (E999)","text":"

        Derived from the pycodestyle linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["E999"]},{"location":"rules/syntax-error/#removed","title":"Removed","text":"

        This rule has been removed. Syntax errors will always be shown regardless of whether this rule is selected or not.

        ","tags":["E999"]},{"location":"rules/syntax-error/#what-it-does","title":"What it does","text":"

        Checks for code that contains syntax errors.

        ","tags":["E999"]},{"location":"rules/syntax-error/#why-is-this-bad","title":"Why is this bad?","text":"

        Code with syntax errors cannot be executed. Such errors are likely a mistake.

        ","tags":["E999"]},{"location":"rules/syntax-error/#example","title":"Example","text":"
        x =\n

        Use instead:

        x = 1\n
        ","tags":["E999"]},{"location":"rules/syntax-error/#references","title":"References","text":"
        • Python documentation: Syntax Errors
        ","tags":["E999"]},{"location":"rules/sys-exit-alias/","title":"sys-exit-alias (PLR1722)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLR1722"]},{"location":"rules/sys-exit-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of the exit() and quit().

        ","tags":["PLR1722"]},{"location":"rules/sys-exit-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        exit and quit come from the site module, which is typically imported automatically during startup. However, it is not guaranteed to be imported, and so using these functions may result in a NameError at runtime. Generally, these constants are intended to be used in an interactive interpreter, and not in programs.

        Prefer sys.exit(), as the sys module is guaranteed to exist in all contexts.

        ","tags":["PLR1722"]},{"location":"rules/sys-exit-alias/#fix-safety","title":"Fix safety","text":"

        This fix is always unsafe. When replacing exit or quit with sys.exit, the behavior can change in the following ways:

        1. If the code runs in an environment where the site module is not imported (e.g., with python -S), the original code would raise a NameError, while the fixed code would execute normally.

        2. site.exit and sys.exit handle tuple arguments differently. site.exit treats tuples as regular objects and always returns exit code 1, while sys.exit interprets tuple contents to determine the exit code: an empty tuple () results in exit code 0, and a single-element tuple like (2,) uses that element's value (2) as the exit code.

        ","tags":["PLR1722"]},{"location":"rules/sys-exit-alias/#example","title":"Example","text":"
        if __name__ == \"__main__\":\n    exit()\n

        Use instead:

        import sys\n\nif __name__ == \"__main__\":\n    sys.exit()\n
        ","tags":["PLR1722"]},{"location":"rules/sys-exit-alias/#references","title":"References","text":"
        • Python documentation: Constants added by the site module
        ","tags":["PLR1722"]},{"location":"rules/sys-version-cmp-str10/","title":"sys-version-cmp-str10 (YTT302)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT302"]},{"location":"rules/sys-version-cmp-str10/#what-it-does","title":"What it does","text":"

        Checks for comparisons that test sys.version against string literals, such that the comparison would fail if the major version number were ever incremented to Python 10 or higher.

        ","tags":["YTT302"]},{"location":"rules/sys-version-cmp-str10/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing sys.version to a string is error-prone and may cause subtle bugs, as the comparison will be performed lexicographically, not semantically.

        Instead, use sys.version_info to access the current major and minor version numbers as a tuple, which can be compared to other tuples without issue.

        ","tags":["YTT302"]},{"location":"rules/sys-version-cmp-str10/#example","title":"Example","text":"
        import sys\n\nsys.version >= \"3\"  # `False` on Python 10.\n

        Use instead:

        import sys\n\nsys.version_info >= (3,)  # `True` on Python 10.\n
        ","tags":["YTT302"]},{"location":"rules/sys-version-cmp-str10/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT302"]},{"location":"rules/sys-version-cmp-str3/","title":"sys-version-cmp-str3 (YTT103)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT103"]},{"location":"rules/sys-version-cmp-str3/#what-it-does","title":"What it does","text":"

        Checks for comparisons that test sys.version against string literals, such that the comparison will evaluate to False on Python 3.10 or later.

        ","tags":["YTT103"]},{"location":"rules/sys-version-cmp-str3/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparing sys.version to a string is error-prone and may cause subtle bugs, as the comparison will be performed lexicographically, not semantically. For example, sys.version > \"3.9\" will evaluate to False when using Python 3.10, as \"3.10\" is lexicographically \"less\" than \"3.9\".

        Instead, use sys.version_info to access the current major and minor version numbers as a tuple, which can be compared to other tuples without issue.

        ","tags":["YTT103"]},{"location":"rules/sys-version-cmp-str3/#example","title":"Example","text":"
        import sys\n\nsys.version > \"3.9\"  # `False` on Python 3.10.\n

        Use instead:

        import sys\n\nsys.version_info > (3, 9)  # `True` on Python 3.10.\n
        ","tags":["YTT103"]},{"location":"rules/sys-version-cmp-str3/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT103"]},{"location":"rules/sys-version-info-minor-cmp-int/","title":"sys-version-info-minor-cmp-int (YTT204)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT204"]},{"location":"rules/sys-version-info-minor-cmp-int/#what-it-does","title":"What it does","text":"

        Checks for comparisons that test sys.version_info.minor against an integer.

        ","tags":["YTT204"]},{"location":"rules/sys-version-info-minor-cmp-int/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparisons based on the current minor version number alone can cause subtle bugs and would likely lead to unintended effects if the Python major version number were ever incremented (e.g., to Python 4).

        Instead, compare sys.version_info to a tuple, including the major and minor version numbers, to future-proof the code.

        ","tags":["YTT204"]},{"location":"rules/sys-version-info-minor-cmp-int/#example","title":"Example","text":"
        import sys\n\nif sys.version_info.minor < 7:\n    print(\"Python 3.6 or earlier.\")  # This will be printed on Python 4.0.\n

        Use instead:

        import sys\n\nif sys.version_info < (3, 7):\n    print(\"Python 3.6 or earlier.\")\n
        ","tags":["YTT204"]},{"location":"rules/sys-version-info-minor-cmp-int/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT204"]},{"location":"rules/sys-version-info0-eq3/","title":"sys-version-info0-eq3 (YTT201)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT201"]},{"location":"rules/sys-version-info0-eq3/#what-it-does","title":"What it does","text":"

        Checks for equality comparisons against the major version returned by sys.version_info (e.g., sys.version_info[0] == 3).

        ","tags":["YTT201"]},{"location":"rules/sys-version-info0-eq3/#why-is-this-bad","title":"Why is this bad?","text":"

        Using sys.version_info[0] == 3 to verify that the major version is Python 3 or greater will fail if the major version number is ever incremented (e.g., to Python 4). This is likely unintended, as code that uses this comparison is likely intended to be run on Python 2, but would now run on Python 4 too.

        Instead, use >= to check if the major version number is 3 or greater, to future-proof the code.

        ","tags":["YTT201"]},{"location":"rules/sys-version-info0-eq3/#example","title":"Example","text":"
        import sys\n\nif sys.version_info[0] == 3:\n    ...\nelse:\n    print(\"Python 2\")  # This will be printed on Python 4.\n

        Use instead:

        import sys\n\nif sys.version_info >= (3,):\n    ...\nelse:\n    print(\"Python 2\")  # This will not be printed on Python 4.\n
        ","tags":["YTT201"]},{"location":"rules/sys-version-info0-eq3/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT201"]},{"location":"rules/sys-version-info1-cmp-int/","title":"sys-version-info1-cmp-int (YTT203)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT203"]},{"location":"rules/sys-version-info1-cmp-int/#what-it-does","title":"What it does","text":"

        Checks for comparisons that test sys.version_info[1] against an integer.

        ","tags":["YTT203"]},{"location":"rules/sys-version-info1-cmp-int/#why-is-this-bad","title":"Why is this bad?","text":"

        Comparisons based on the current minor version number alone can cause subtle bugs and would likely lead to unintended effects if the Python major version number were ever incremented (e.g., to Python 4).

        Instead, compare sys.version_info to a tuple, including the major and minor version numbers, to future-proof the code.

        ","tags":["YTT203"]},{"location":"rules/sys-version-info1-cmp-int/#example","title":"Example","text":"
        import sys\n\nif sys.version_info[1] < 7:\n    print(\"Python 3.6 or earlier.\")  # This will be printed on Python 4.0.\n

        Use instead:

        import sys\n\nif sys.version_info < (3, 7):\n    print(\"Python 3.6 or earlier.\")\n
        ","tags":["YTT203"]},{"location":"rules/sys-version-info1-cmp-int/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT203"]},{"location":"rules/sys-version-slice1/","title":"sys-version-slice1 (YTT303)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT303"]},{"location":"rules/sys-version-slice1/#what-it-does","title":"What it does","text":"

        Checks for uses of sys.version[:1].

        ","tags":["YTT303"]},{"location":"rules/sys-version-slice1/#why-is-this-bad","title":"Why is this bad?","text":"

        If the major version number consists of more than one digit, this will select the first digit of the major version number only (e.g., \"10.0\" would evaluate to \"1\"). This is likely unintended, and can lead to subtle bugs in future versions of Python if the version string is used to test against a specific major version number.

        Instead, use sys.version_info.major to access the current major version number.

        ","tags":["YTT303"]},{"location":"rules/sys-version-slice1/#example","title":"Example","text":"
        import sys\n\nsys.version[:1]  # If using Python 10, this evaluates to \"1\".\n

        Use instead:

        import sys\n\nf\"{sys.version_info.major}\"  # If using Python 10, this evaluates to \"10\".\n
        ","tags":["YTT303"]},{"location":"rules/sys-version-slice1/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT303"]},{"location":"rules/sys-version-slice3/","title":"sys-version-slice3 (YTT101)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT101"]},{"location":"rules/sys-version-slice3/#what-it-does","title":"What it does","text":"

        Checks for uses of sys.version[:3].

        ","tags":["YTT101"]},{"location":"rules/sys-version-slice3/#why-is-this-bad","title":"Why is this bad?","text":"

        If the current major or minor version consists of multiple digits, sys.version[:3] will truncate the version number (e.g., \"3.10\" would become \"3.1\"). This is likely unintended, and can lead to subtle bugs if the version string is used to test against a specific Python version.

        Instead, use sys.version_info to access the current major and minor version numbers as a tuple, which can be compared to other tuples without issue.

        ","tags":["YTT101"]},{"location":"rules/sys-version-slice3/#example","title":"Example","text":"
        import sys\n\nsys.version[:3]  # Evaluates to \"3.1\" on Python 3.10.\n

        Use instead:

        import sys\n\nsys.version_info[:2]  # Evaluates to (3, 10) on Python 3.10.\n
        ","tags":["YTT101"]},{"location":"rules/sys-version-slice3/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT101"]},{"location":"rules/sys-version0/","title":"sys-version0 (YTT301)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT301"]},{"location":"rules/sys-version0/#what-it-does","title":"What it does","text":"

        Checks for uses of sys.version[0].

        ","tags":["YTT301"]},{"location":"rules/sys-version0/#why-is-this-bad","title":"Why is this bad?","text":"

        If the current major or minor version consists of multiple digits, sys.version[0] will select the first digit of the major version number only (e.g., \"10.2\" would evaluate to \"1\"). This is likely unintended, and can lead to subtle bugs if the version string is used to test against a major version number.

        Instead, use sys.version_info.major to access the current major version number.

        ","tags":["YTT301"]},{"location":"rules/sys-version0/#example","title":"Example","text":"
        import sys\n\nsys.version[0]  # If using Python 10, this evaluates to \"1\".\n

        Use instead:

        import sys\n\nf\"{sys.version_info.major}\"  # If using Python 10, this evaluates to \"10\".\n
        ","tags":["YTT301"]},{"location":"rules/sys-version0/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT301"]},{"location":"rules/sys-version2/","title":"sys-version2 (YTT102)","text":"

        Derived from the flake8-2020 linter.

        ","tags":["YTT102"]},{"location":"rules/sys-version2/#what-it-does","title":"What it does","text":"

        Checks for uses of sys.version[2].

        ","tags":["YTT102"]},{"location":"rules/sys-version2/#why-is-this-bad","title":"Why is this bad?","text":"

        If the current major or minor version consists of multiple digits, sys.version[2] will select the first digit of the minor number only (e.g., \"3.10\" would evaluate to \"1\"). This is likely unintended, and can lead to subtle bugs if the version is used to test against a minor version number.

        Instead, use sys.version_info.minor to access the current minor version number.

        ","tags":["YTT102"]},{"location":"rules/sys-version2/#example","title":"Example","text":"
        import sys\n\nsys.version[2]  # Evaluates to \"1\" on Python 3.10.\n

        Use instead:

        import sys\n\nf\"{sys.version_info.minor}\"  # Evaluates to \"10\" on Python 3.10.\n
        ","tags":["YTT102"]},{"location":"rules/sys-version2/#references","title":"References","text":"
        • Python documentation: sys.version
        • Python documentation: sys.version_info
        ","tags":["YTT102"]},{"location":"rules/t-suffixed-type-alias/","title":"t-suffixed-type-alias (PYI043)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI043"]},{"location":"rules/t-suffixed-type-alias/#what-it-does","title":"What it does","text":"

        Checks for private type alias definitions suffixed with 'T'.

        ","tags":["PYI043"]},{"location":"rules/t-suffixed-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        It's conventional to use the 'T' suffix for type variables; the use of such a suffix implies that the object is a TypeVar.

        Adding the 'T' suffix to a non-TypeVar, it can be misleading and should be avoided.

        ","tags":["PYI043"]},{"location":"rules/t-suffixed-type-alias/#example","title":"Example","text":"
        from typing import TypeAlias\n\n_MyTypeT: TypeAlias = int\n

        Use instead:

        from typing import TypeAlias\n\n_MyType: TypeAlias = int\n
        ","tags":["PYI043"]},{"location":"rules/t-suffixed-type-alias/#references","title":"References","text":"
        • PEP 484: Type Aliases
        ","tags":["PYI043"]},{"location":"rules/tab-after-comma/","title":"tab-after-comma (E242)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E242"]},{"location":"rules/tab-after-comma/#what-it-does","title":"What it does","text":"

        Checks for extraneous tabs after a comma.

        ","tags":["E242"]},{"location":"rules/tab-after-comma/#why-is-this-bad","title":"Why is this bad?","text":"

        Commas should be followed by one space, never tabs.

        ","tags":["E242"]},{"location":"rules/tab-after-comma/#example","title":"Example","text":"
        a = 4,\\t5\n

        Use instead:

        a = 4, 5\n
        ","tags":["E242"]},{"location":"rules/tab-after-keyword/","title":"tab-after-keyword (E273)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E273"]},{"location":"rules/tab-after-keyword/#what-it-does","title":"What it does","text":"

        Checks for extraneous tabs after keywords.

        ","tags":["E273"]},{"location":"rules/tab-after-keyword/#why-is-this-bad","title":"Why is this bad?","text":"","tags":["E273"]},{"location":"rules/tab-after-keyword/#example","title":"Example","text":"
        True and\\tFalse\n

        Use instead:

        True and False\n
        ","tags":["E273"]},{"location":"rules/tab-after-operator/","title":"tab-after-operator (E224)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E224"]},{"location":"rules/tab-after-operator/#what-it-does","title":"What it does","text":"

        Checks for extraneous tabs after an operator.

        ","tags":["E224"]},{"location":"rules/tab-after-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, operators should be surrounded by at most a single space on either side.

        ","tags":["E224"]},{"location":"rules/tab-after-operator/#example","title":"Example","text":"
        a = 4 +\\t5\n

        Use instead:

        a = 4 + 5\n
        ","tags":["E224"]},{"location":"rules/tab-before-keyword/","title":"tab-before-keyword (E274)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E274"]},{"location":"rules/tab-before-keyword/#what-it-does","title":"What it does","text":"

        Checks for extraneous tabs before keywords.

        ","tags":["E274"]},{"location":"rules/tab-before-keyword/#why-is-this-bad","title":"Why is this bad?","text":"","tags":["E274"]},{"location":"rules/tab-before-keyword/#example","title":"Example","text":"
        True\\tand False\n

        Use instead:

        True and False\n
        ","tags":["E274"]},{"location":"rules/tab-before-operator/","title":"tab-before-operator (E223)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E223"]},{"location":"rules/tab-before-operator/#what-it-does","title":"What it does","text":"

        Checks for extraneous tabs before an operator.

        ","tags":["E223"]},{"location":"rules/tab-before-operator/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, operators should be surrounded by at most a single space on either side.

        ","tags":["E223"]},{"location":"rules/tab-before-operator/#example","title":"Example","text":"
        a = 4\\t+ 5\n

        Use instead:

        a = 4 + 5\n
        ","tags":["E223"]},{"location":"rules/tab-indentation/","title":"tab-indentation (W191)","text":"

        Derived from the pycodestyle linter.

        ","tags":["W191"]},{"location":"rules/tab-indentation/#what-it-does","title":"What it does","text":"

        Checks for indentation that uses tabs.

        ","tags":["W191"]},{"location":"rules/tab-indentation/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, spaces are preferred over tabs (unless used to remain consistent with code that is already indented with tabs).

        ","tags":["W191"]},{"location":"rules/tab-indentation/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        The rule is also incompatible with the formatter when using format.indent-style=\"tab\".

        ","tags":["W191"]},{"location":"rules/tarfile-unsafe-members/","title":"tarfile-unsafe-members (S202)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S202"]},{"location":"rules/tarfile-unsafe-members/#what-it-does","title":"What it does","text":"

        Checks for uses of tarfile.extractall.

        ","tags":["S202"]},{"location":"rules/tarfile-unsafe-members/#why-is-this-bad","title":"Why is this bad?","text":"

        Extracting archives from untrusted sources without prior inspection is a security risk, as maliciously crafted archives may contain files that will be written outside of the target directory. For example, the archive could include files with absolute paths (e.g., /etc/passwd), or relative paths with parent directory references (e.g., ../etc/passwd).

        On Python 3.12 and later, use filter='data' to prevent the most dangerous security issues (see: PEP 706). On earlier versions, set the members argument to a trusted subset of the archive's members.

        ","tags":["S202"]},{"location":"rules/tarfile-unsafe-members/#example","title":"Example","text":"
        import tarfile\nimport tempfile\n\ntar = tarfile.open(filename)\ntar.extractall(path=tempfile.mkdtemp())\ntar.close()\n
        ","tags":["S202"]},{"location":"rules/tarfile-unsafe-members/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-22
        • Python documentation: TarFile.extractall
        • Python documentation: Extraction filters
        ","tags":["S202"]},{"location":"rules/timeout-error-alias/","title":"timeout-error-alias (UP041)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP041"]},{"location":"rules/timeout-error-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of exceptions that alias TimeoutError.

        ","tags":["UP041"]},{"location":"rules/timeout-error-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        TimeoutError is the builtin error type used for exceptions when a system function timed out at the system level.

        In Python 3.10, socket.timeout was aliased to TimeoutError. In Python 3.11, asyncio.TimeoutError was aliased to TimeoutError.

        These aliases remain in place for compatibility with older versions of Python, but may be removed in future versions.

        Prefer using TimeoutError directly, as it is more idiomatic and future-proof.

        ","tags":["UP041"]},{"location":"rules/timeout-error-alias/#example","title":"Example","text":"
        raise asyncio.TimeoutError\n

        Use instead:

        raise TimeoutError\n
        ","tags":["UP041"]},{"location":"rules/timeout-error-alias/#references","title":"References","text":"
        • Python documentation: TimeoutError
        ","tags":["UP041"]},{"location":"rules/too-few-spaces-before-inline-comment/","title":"too-few-spaces-before-inline-comment (E261)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E261"]},{"location":"rules/too-few-spaces-before-inline-comment/#what-it-does","title":"What it does","text":"

        Checks if inline comments are separated by at least two spaces.

        ","tags":["E261"]},{"location":"rules/too-few-spaces-before-inline-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        An inline comment is a comment on the same line as a statement.

        Per PEP 8, inline comments should be separated by at least two spaces from the preceding statement.

        ","tags":["E261"]},{"location":"rules/too-few-spaces-before-inline-comment/#example","title":"Example","text":"
        x = x + 1 # Increment x\n

        Use instead:

        x = x + 1  # Increment x\nx = x + 1    # Increment x\n
        ","tags":["E261"]},{"location":"rules/too-many-arguments/","title":"too-many-arguments (PLR0913)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0913"]},{"location":"rules/too-many-arguments/#what-it-does","title":"What it does","text":"

        Checks for function definitions that include too many arguments.

        By default, this rule allows up to five arguments, as configured by the lint.pylint.max-args option.

        ","tags":["PLR0913"]},{"location":"rules/too-many-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions with many arguments are harder to understand, maintain, and call. Consider refactoring functions with many arguments into smaller functions with fewer arguments, or using objects to group related arguments.

        ","tags":["PLR0913"]},{"location":"rules/too-many-arguments/#example","title":"Example","text":"
        def calculate_position(x_pos, y_pos, z_pos, x_vel, y_vel, z_vel, time):\n    new_x = x_pos + x_vel * time\n    new_y = y_pos + y_vel * time\n    new_z = z_pos + z_vel * time\n    return new_x, new_y, new_z\n

        Use instead:

        from typing import NamedTuple\n\n\nclass Vector(NamedTuple):\n    x: float\n    y: float\n    z: float\n\n\ndef calculate_position(pos: Vector, vel: Vector, time: float) -> Vector:\n    return Vector(*(p + v * time for p, v in zip(pos, vel)))\n
        ","tags":["PLR0913"]},{"location":"rules/too-many-arguments/#options","title":"Options","text":"
        • lint.pylint.max-args
        ","tags":["PLR0913"]},{"location":"rules/too-many-blank-lines/","title":"too-many-blank-lines (E303)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#what-it-does","title":"What it does","text":"

        Checks for extraneous blank lines.

        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends using blank lines as follows:

        • No more than two blank lines between top-level statements.
        • No more than one blank line between non-top-level statements.
        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#example","title":"Example","text":"
        def func1():\n    pass\n\n\n\ndef func2():\n    pass\n

        Use instead:

        def func1():\n    pass\n\n\ndef func2():\n    pass\n
        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#typing-stub-files-pyi","title":"Typing stub files (.pyi)","text":"

        The rule allows at most one blank line in typing stub files in accordance to the typing style guide recommendation.

        Note: The rule respects the following isort settings when determining the maximum number of blank lines allowed between two statements:

        • lint.isort.lines-after-imports: For top-level statements directly following an import statement.
        • lint.isort.lines-between-types: For import statements directly following a from ... import ... statement or vice versa.
        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#options","title":"Options","text":"
        • lint.isort.lines-after-imports
        • lint.isort.lines-between-types
        ","tags":["E303"]},{"location":"rules/too-many-blank-lines/#references","title":"References","text":"
        • PEP 8: Blank Lines
        • Flake 8 rule
        • Typing Style Guide
        ","tags":["E303"]},{"location":"rules/too-many-boolean-expressions/","title":"too-many-boolean-expressions (PLR0916)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0916"]},{"location":"rules/too-many-boolean-expressions/#what-it-does","title":"What it does","text":"

        Checks for too many Boolean expressions in an if statement.

        By default, this rule allows up to 5 expressions. This can be configured using the lint.pylint.max-bool-expr option.

        ","tags":["PLR0916"]},{"location":"rules/too-many-boolean-expressions/#why-is-this-bad","title":"Why is this bad?","text":"

        if statements with many Boolean expressions are harder to understand and maintain. Consider assigning the result of the Boolean expression, or any of its sub-expressions, to a variable.

        ","tags":["PLR0916"]},{"location":"rules/too-many-boolean-expressions/#example","title":"Example","text":"
        if a and b and c and d and e and f and g and h:\n    ...\n
        ","tags":["PLR0916"]},{"location":"rules/too-many-boolean-expressions/#options","title":"Options","text":"
        • lint.pylint.max-bool-expr
        ","tags":["PLR0916"]},{"location":"rules/too-many-branches/","title":"too-many-branches (PLR0912)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0912"]},{"location":"rules/too-many-branches/#what-it-does","title":"What it does","text":"

        Checks for functions or methods with too many branches, including (nested) if, elif, and else branches, for loops, try-except clauses, and match and case statements.

        By default, this rule allows up to 12 branches. This can be configured using the lint.pylint.max-branches option.

        ","tags":["PLR0912"]},{"location":"rules/too-many-branches/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions or methods with many branches are harder to understand and maintain than functions or methods with fewer branches.

        ","tags":["PLR0912"]},{"location":"rules/too-many-branches/#example","title":"Example","text":"

        Given:

        def capital(country):\n    if country == \"Australia\":\n        return \"Canberra\"\n    elif country == \"Brazil\":\n        return \"Brasilia\"\n    elif country == \"Canada\":\n        return \"Ottawa\"\n    elif country == \"England\":\n        return \"London\"\n    elif country == \"France\":\n        return \"Paris\"\n    elif country == \"Germany\":\n        return \"Berlin\"\n    elif country == \"Poland\":\n        return \"Warsaw\"\n    elif country == \"Romania\":\n        return \"Bucharest\"\n    elif country == \"Spain\":\n        return \"Madrid\"\n    elif country == \"Thailand\":\n        return \"Bangkok\"\n    elif country == \"Turkey\":\n        return \"Ankara\"\n    elif country == \"United States\":\n        return \"Washington\"\n    else:\n        return \"Unknown\"  # 13th branch\n

        Use instead:

        def capital(country):\n    capitals = {\n        \"Australia\": \"Canberra\",\n        \"Brazil\": \"Brasilia\",\n        \"Canada\": \"Ottawa\",\n        \"England\": \"London\",\n        \"France\": \"Paris\",\n        \"Germany\": \"Berlin\",\n        \"Poland\": \"Warsaw\",\n        \"Romania\": \"Bucharest\",\n        \"Spain\": \"Madrid\",\n        \"Thailand\": \"Bangkok\",\n        \"Turkey\": \"Ankara\",\n        \"United States\": \"Washington\",\n    }\n    city = capitals.get(country, \"Unknown\")\n    return city\n

        Given:

        def grades_to_average_number(grades):\n    numbers = []\n    for grade in grades:  # 1st branch\n        if len(grade) not in {1, 2}:\n            raise ValueError(f\"Invalid grade: {grade}\")\n\n        if len(grade) == 2 and grade[1] not in {\"+\", \"-\"}:\n            raise ValueError(f\"Invalid grade: {grade}\")\n\n        letter = grade[0]\n\n        if letter in {\"F\", \"E\"}:\n            number = 0.0\n        elif letter == \"D\":\n            number = 1.0\n        elif letter == \"C\":\n            number = 2.0\n        elif letter == \"B\":\n            number = 3.0\n        elif letter == \"A\":\n            number = 4.0\n        else:\n            raise ValueError(f\"Invalid grade: {grade}\")\n\n        modifier = 0.0\n        if letter != \"F\" and grade[-1] == \"+\":\n            modifier = 0.3\n        elif letter != \"F\" and grade[-1] == \"-\":\n            modifier = -0.3\n\n        numbers.append(max(0.0, min(number + modifier, 4.0)))\n\n    try:\n        return sum(numbers) / len(numbers)\n    except ZeroDivisionError:  # 13th branch\n        return 0\n

        Use instead:

        def grades_to_average_number(grades):\n    grade_values = {\"F\": 0.0, \"E\": 0.0, \"D\": 1.0, \"C\": 2.0, \"B\": 3.0, \"A\": 4.0}\n    modifier_values = {\"+\": 0.3, \"-\": -0.3}\n\n    numbers = []\n    for grade in grades:\n        if len(grade) not in {1, 2}:\n            raise ValueError(f\"Invalid grade: {grade}\")\n\n        letter = grade[0]\n        if letter not in grade_values:\n            raise ValueError(f\"Invalid grade: {grade}\")\n        number = grade_values[letter]\n\n        if len(grade) == 2 and grade[1] not in modifier_values:\n            raise ValueError(f\"Invalid grade: {grade}\")\n        modifier = modifier_values.get(grade[-1], 0.0)\n\n        if letter == \"F\":\n            numbers.append(0.0)\n        else:\n            numbers.append(max(0.0, min(number + modifier, 4.0)))\n\n    try:\n        return sum(numbers) / len(numbers)\n    except ZeroDivisionError:\n        return 0\n
        ","tags":["PLR0912"]},{"location":"rules/too-many-branches/#options","title":"Options","text":"
        • lint.pylint.max-branches
        ","tags":["PLR0912"]},{"location":"rules/too-many-locals/","title":"too-many-locals (PLR0914)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0914"]},{"location":"rules/too-many-locals/#what-it-does","title":"What it does","text":"

        Checks for functions that include too many local variables.

        By default, this rule allows up to fifteen locals, as configured by the lint.pylint.max-locals option.

        ","tags":["PLR0914"]},{"location":"rules/too-many-locals/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions with many local variables are harder to understand and maintain.

        Consider refactoring functions with many local variables into smaller functions with fewer assignments.

        ","tags":["PLR0914"]},{"location":"rules/too-many-locals/#options","title":"Options","text":"
        • lint.pylint.max-locals
        ","tags":["PLR0914"]},{"location":"rules/too-many-nested-blocks/","title":"too-many-nested-blocks (PLR1702)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR1702"]},{"location":"rules/too-many-nested-blocks/#what-it-does","title":"What it does","text":"

        Checks for functions or methods with too many nested blocks.

        By default, this rule allows up to five nested blocks. This can be configured using the lint.pylint.max-nested-blocks option.

        ","tags":["PLR1702"]},{"location":"rules/too-many-nested-blocks/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions or methods with too many nested blocks are harder to understand and maintain.

        ","tags":["PLR1702"]},{"location":"rules/too-many-nested-blocks/#options","title":"Options","text":"
        • lint.pylint.max-nested-blocks
        ","tags":["PLR1702"]},{"location":"rules/too-many-newlines-at-end-of-file/","title":"too-many-newlines-at-end-of-file (W391)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["W391"]},{"location":"rules/too-many-newlines-at-end-of-file/#what-it-does","title":"What it does","text":"

        Checks for files with multiple trailing blank lines.

        In the case of notebooks, this check is applied to each cell separately.

        ","tags":["W391"]},{"location":"rules/too-many-newlines-at-end-of-file/#why-is-this-bad","title":"Why is this bad?","text":"

        Trailing blank lines in a file are superfluous.

        However, the last line of the file should end with a newline.

        ","tags":["W391"]},{"location":"rules/too-many-newlines-at-end-of-file/#example","title":"Example","text":"
        spam(1)\\n\\n\\n\n

        Use instead:

        spam(1)\\n\n
        ","tags":["W391"]},{"location":"rules/too-many-positional-arguments/","title":"too-many-positional-arguments (PLR0917)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0917"]},{"location":"rules/too-many-positional-arguments/#what-it-does","title":"What it does","text":"

        Checks for function definitions that include too many positional arguments.

        By default, this rule allows up to five arguments, as configured by the lint.pylint.max-positional-args option.

        ","tags":["PLR0917"]},{"location":"rules/too-many-positional-arguments/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions with many arguments are harder to understand, maintain, and call. This is especially true for functions with many positional arguments, as providing arguments positionally is more error-prone and less clear to readers than providing arguments by name.

        Consider refactoring functions with many arguments into smaller functions with fewer arguments, using objects to group related arguments, or migrating to keyword-only arguments.

        ","tags":["PLR0917"]},{"location":"rules/too-many-positional-arguments/#example","title":"Example","text":"
        def plot(x, y, z, color, mark, add_trendline): ...\n\n\nplot(1, 2, 3, \"r\", \"*\", True)\n

        Use instead:

        def plot(x, y, z, *, color, mark, add_trendline): ...\n\n\nplot(1, 2, 3, color=\"r\", mark=\"*\", add_trendline=True)\n
        ","tags":["PLR0917"]},{"location":"rules/too-many-positional-arguments/#options","title":"Options","text":"
        • lint.pylint.max-positional-args
        ","tags":["PLR0917"]},{"location":"rules/too-many-public-methods/","title":"too-many-public-methods (PLR0904)","text":"

        Derived from the Pylint linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR0904"]},{"location":"rules/too-many-public-methods/#what-it-does","title":"What it does","text":"

        Checks for classes with too many public methods

        By default, this rule allows up to 20 public methods, as configured by the lint.pylint.max-public-methods option.

        ","tags":["PLR0904"]},{"location":"rules/too-many-public-methods/#why-is-this-bad","title":"Why is this bad?","text":"

        Classes with many public methods are harder to understand and maintain.

        Instead, consider refactoring the class into separate classes.

        ","tags":["PLR0904"]},{"location":"rules/too-many-public-methods/#example","title":"Example","text":"

        Assuming that lint.pylint.max-public-methods is set to 5:

        class Linter:\n    def __init__(self):\n        pass\n\n    def pylint(self):\n        pass\n\n    def pylint_settings(self):\n        pass\n\n    def flake8(self):\n        pass\n\n    def flake8_settings(self):\n        pass\n\n    def pydocstyle(self):\n        pass\n\n    def pydocstyle_settings(self):\n        pass\n

        Use instead:

        class Linter:\n    def __init__(self):\n        self.pylint = Pylint()\n        self.flake8 = Flake8()\n        self.pydocstyle = Pydocstyle()\n\n    def lint(self):\n        pass\n\n\nclass Pylint:\n    def lint(self):\n        pass\n\n    def settings(self):\n        pass\n\n\nclass Flake8:\n    def lint(self):\n        pass\n\n    def settings(self):\n        pass\n\n\nclass Pydocstyle:\n    def lint(self):\n        pass\n\n    def settings(self):\n        pass\n
        ","tags":["PLR0904"]},{"location":"rules/too-many-public-methods/#options","title":"Options","text":"
        • lint.pylint.max-public-methods
        ","tags":["PLR0904"]},{"location":"rules/too-many-return-statements/","title":"too-many-return-statements (PLR0911)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0911"]},{"location":"rules/too-many-return-statements/#what-it-does","title":"What it does","text":"

        Checks for functions or methods with too many return statements.

        By default, this rule allows up to six return statements, as configured by the lint.pylint.max-returns option.

        ","tags":["PLR0911"]},{"location":"rules/too-many-return-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions or methods with many return statements are harder to understand and maintain, and often indicative of complex logic.

        ","tags":["PLR0911"]},{"location":"rules/too-many-return-statements/#example","title":"Example","text":"
        def capital(country: str) -> str | None:\n    if country == \"England\":\n        return \"London\"\n    elif country == \"France\":\n        return \"Paris\"\n    elif country == \"Poland\":\n        return \"Warsaw\"\n    elif country == \"Romania\":\n        return \"Bucharest\"\n    elif country == \"Spain\":\n        return \"Madrid\"\n    elif country == \"Thailand\":\n        return \"Bangkok\"\n    else:\n        return None\n

        Use instead:

        def capital(country: str) -> str | None:\n    capitals = {\n        \"England\": \"London\",\n        \"France\": \"Paris\",\n        \"Poland\": \"Warsaw\",\n        \"Romania\": \"Bucharest\",\n        \"Spain\": \"Madrid\",\n        \"Thailand\": \"Bangkok\",\n    }\n    return capitals.get(country)\n
        ","tags":["PLR0911"]},{"location":"rules/too-many-return-statements/#options","title":"Options","text":"
        • lint.pylint.max-returns
        ","tags":["PLR0911"]},{"location":"rules/too-many-statements/","title":"too-many-statements (PLR0915)","text":"

        Derived from the Pylint linter.

        ","tags":["PLR0915"]},{"location":"rules/too-many-statements/#what-it-does","title":"What it does","text":"

        Checks for functions or methods with too many statements.

        By default, this rule allows up to 50 statements, as configured by the lint.pylint.max-statements option.

        ","tags":["PLR0915"]},{"location":"rules/too-many-statements/#why-is-this-bad","title":"Why is this bad?","text":"

        Functions or methods with many statements are harder to understand and maintain.

        Instead, consider refactoring the function or method into smaller functions or methods, or identifying generalizable patterns and replacing them with generic logic or abstractions.

        ","tags":["PLR0915"]},{"location":"rules/too-many-statements/#example","title":"Example","text":"
        def is_even(number: int) -> bool:\n    if number == 0:\n        return True\n    elif number == 1:\n        return False\n    elif number == 2:\n        return True\n    elif number == 3:\n        return False\n    elif number == 4:\n        return True\n    elif number == 5:\n        return False\n    else:\n        ...\n

        Use instead:

        def is_even(number: int) -> bool:\n    return number % 2 == 0\n
        ","tags":["PLR0915"]},{"location":"rules/too-many-statements/#options","title":"Options","text":"
        • lint.pylint.max-statements
        ","tags":["PLR0915"]},{"location":"rules/trailing-comma-on-bare-tuple/","title":"trailing-comma-on-bare-tuple (COM818)","text":"

        Derived from the flake8-commas linter.

        ","tags":["COM818"]},{"location":"rules/trailing-comma-on-bare-tuple/#what-it-does","title":"What it does","text":"

        Checks for the presence of trailing commas on bare (i.e., unparenthesized) tuples.

        ","tags":["COM818"]},{"location":"rules/trailing-comma-on-bare-tuple/#why-is-this-bad","title":"Why is this bad?","text":"

        The presence of a misplaced comma will cause Python to interpret the value as a tuple, which can lead to unexpected behaviour.

        ","tags":["COM818"]},{"location":"rules/trailing-comma-on-bare-tuple/#example","title":"Example","text":"
        import json\n\n\nfoo = json.dumps({\"bar\": 1}),\n

        Use instead:

        import json\n\n\nfoo = json.dumps({\"bar\": 1})\n

        In the event that a tuple is intended, then use instead:

        import json\n\n\nfoo = (json.dumps({\"bar\": 1}),)\n
        ","tags":["COM818"]},{"location":"rules/trailing-whitespace/","title":"trailing-whitespace (W291)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["W291"]},{"location":"rules/trailing-whitespace/#what-it-does","title":"What it does","text":"

        Checks for superfluous trailing whitespace.

        ","tags":["W291"]},{"location":"rules/trailing-whitespace/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, \"avoid trailing whitespace anywhere. Because it\u2019s usually invisible, it can be confusing\"

        ","tags":["W291"]},{"location":"rules/trailing-whitespace/#example","title":"Example","text":"
        spam(1) \\n#\n

        Use instead:

        spam(1)\\n#\n
        ","tags":["W291"]},{"location":"rules/trio-sync-call/","title":"trio-sync-call (ASYNC105)","text":"

        Derived from the flake8-async linter.

        Fix is sometimes available.

        ","tags":["ASYNC105"]},{"location":"rules/trio-sync-call/#what-it-does","title":"What it does","text":"

        Checks for calls to trio functions that are not immediately awaited.

        ","tags":["ASYNC105"]},{"location":"rules/trio-sync-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Many of the functions exposed by trio are asynchronous, and must be awaited to take effect. Calling a trio function without an await can lead to RuntimeWarning diagnostics and unexpected behaviour.

        ","tags":["ASYNC105"]},{"location":"rules/trio-sync-call/#example","title":"Example","text":"
        async def double_sleep(x):\n    trio.sleep(2 * x)\n

        Use instead:

        async def double_sleep(x):\n    await trio.sleep(2 * x)\n
        ","tags":["ASYNC105"]},{"location":"rules/trio-sync-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as adding an await to a function call changes its semantics and runtime behavior.

        ","tags":["ASYNC105"]},{"location":"rules/triple-single-quotes/","title":"triple-single-quotes (D300)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D300"]},{"location":"rules/triple-single-quotes/#what-it-does","title":"What it does","text":"

        Checks for docstrings that use '''triple single quotes''' instead of \"\"\"triple double quotes\"\"\".

        ","tags":["D300"]},{"location":"rules/triple-single-quotes/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends the use of \"\"\"triple double quotes\"\"\" for docstrings, to ensure consistency.

        ","tags":["D300"]},{"location":"rules/triple-single-quotes/#example","title":"Example","text":"
        def kos_root():\n    '''Return the pathname of the KOS root directory.'''\n

        Use instead:

        def kos_root():\n    \"\"\"Return the pathname of the KOS root directory.\"\"\"\n
        ","tags":["D300"]},{"location":"rules/triple-single-quotes/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent quotes, making the rule redundant.

        ","tags":["D300"]},{"location":"rules/triple-single-quotes/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D300"]},{"location":"rules/true-false-comparison/","title":"true-false-comparison (E712)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["E712"]},{"location":"rules/true-false-comparison/#what-it-does","title":"What it does","text":"

        Checks for equality comparisons to boolean literals.

        ","tags":["E712"]},{"location":"rules/true-false-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends against using the equality operators == and != to compare values to True or False.

        Instead, use if cond: or if not cond: to check for truth values.

        If you intend to check if a value is the boolean literal True or False, consider using is or is not to check for identity instead.

        ","tags":["E712"]},{"location":"rules/true-false-comparison/#example","title":"Example","text":"
        if foo == True:\n    ...\n\nif bar == False:\n    ...\n

        Use instead:

        if foo:\n    ...\n\nif not bar:\n    ...\n
        ","tags":["E712"]},{"location":"rules/true-false-comparison/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may alter runtime behavior when used with libraries that override the ==/__eq__ or !=/__ne__ operators. In these cases, is/is not may not be equivalent to ==/!=. For more information, see this issue.

        ","tags":["E712"]},{"location":"rules/try-consider-else/","title":"try-consider-else (TRY300)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY300"]},{"location":"rules/try-consider-else/#what-it-does","title":"What it does","text":"

        Checks for return statements in try blocks.

        ","tags":["TRY300"]},{"location":"rules/try-consider-else/#why-is-this-bad","title":"Why is this bad?","text":"

        The try-except statement has an else clause for code that should run only if no exceptions were raised. Returns in try blocks may exhibit confusing or unwanted behavior, such as being overridden by control flow in except and finally blocks, or unintentionally suppressing an exception.

        ","tags":["TRY300"]},{"location":"rules/try-consider-else/#example","title":"Example","text":"
        import logging\n\n\ndef reciprocal(n):\n    try:\n        rec = 1 / n\n        print(f\"reciprocal of {n} is {rec}\")\n        return rec\n    except ZeroDivisionError:\n        logging.exception(\"Exception occurred\")\n

        Use instead:

        import logging\n\n\ndef reciprocal(n):\n    try:\n        rec = 1 / n\n    except ZeroDivisionError:\n        logging.exception(\"Exception occurred\")\n    else:\n        print(f\"reciprocal of {n} is {rec}\")\n        return rec\n
        ","tags":["TRY300"]},{"location":"rules/try-consider-else/#references","title":"References","text":"
        • Python documentation: Errors and Exceptions
        ","tags":["TRY300"]},{"location":"rules/try-except-continue/","title":"try-except-continue (S112)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S112"]},{"location":"rules/try-except-continue/#what-it-does","title":"What it does","text":"

        Checks for uses of the try-except-continue pattern.

        ","tags":["S112"]},{"location":"rules/try-except-continue/#why-is-this-bad","title":"Why is this bad?","text":"

        The try-except-continue pattern suppresses all exceptions. Suppressing exceptions may hide errors that could otherwise reveal unexpected behavior, security vulnerabilities, or malicious activity. Instead, consider logging the exception.

        ","tags":["S112"]},{"location":"rules/try-except-continue/#example","title":"Example","text":"
        import logging\n\nwhile predicate:\n    try:\n        ...\n    except Exception:\n        continue\n

        Use instead:

        import logging\n\nwhile predicate:\n    try:\n        ...\n    except Exception as exc:\n        logging.exception(\"Error occurred\")\n
        ","tags":["S112"]},{"location":"rules/try-except-continue/#options","title":"Options","text":"
        • lint.flake8-bandit.check-typed-exception
        ","tags":["S112"]},{"location":"rules/try-except-continue/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-703
        • Python documentation: logging
        ","tags":["S112"]},{"location":"rules/try-except-in-loop/","title":"try-except-in-loop (PERF203)","text":"

        Derived from the Perflint linter.

        ","tags":["PERF203"]},{"location":"rules/try-except-in-loop/#what-it-does","title":"What it does","text":"

        Checks for uses of except handling via try-except within for and while loops.

        ","tags":["PERF203"]},{"location":"rules/try-except-in-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        Exception handling via try-except blocks incurs some performance overhead, regardless of whether an exception is raised.

        To optimize your code, two techniques are possible:

        1. Refactor your code to put the entire loop into the try-except block, rather than wrapping each iteration in a separate try-except block.
        2. Use \"Look Before You Leap\" idioms that attempt to avoid exceptions being raised in the first place, avoiding the need to use try-except blocks in the first place.

        This rule is only enforced for Python versions prior to 3.11, which introduced \"zero-cost\" exception handling. However, note that even on Python 3.11 and newer, refactoring your code to avoid exception handling in tight loops can provide a significant speedup in some cases, as zero-cost exception handling is only zero-cost in the \"happy path\" where no exception is raised in the try-except block.

        As with all perflint rules, this is only intended as a micro-optimization. In many cases, it will have a negligible impact on performance.

        ","tags":["PERF203"]},{"location":"rules/try-except-in-loop/#example","title":"Example","text":"
        string_numbers: list[str] = [\"1\", \"2\", \"three\", \"4\", \"5\"]\n\n# `try`/`except` that could be moved out of the loop:\nint_numbers: list[int] = []\nfor num in string_numbers:\n    try:\n        int_numbers.append(int(num))\n    except ValueError as e:\n        print(f\"Couldn't convert to integer: {e}\")\n        break\n\n# `try`/`except` used when \"look before you leap\" idioms could be used:\nnumber_names: dict[int, str] = {1: \"one\", 3: \"three\", 4: \"four\"}\nfor number in range(5):\n    try:\n        name = number_names[number]\n    except KeyError:\n        continue\n    else:\n        print(f\"The name of {number} is {name}\")\n

        Use instead:

        string_numbers: list[str] = [\"1\", \"2\", \"three\", \"4\", \"5\"]\n\nint_numbers: list[int] = []\ntry:\n    for num in string_numbers:\n        int_numbers.append(int(num))\nexcept ValueError as e:\n    print(f\"Couldn't convert to integer: {e}\")\n\nnumber_names: dict[int, str] = {1: \"one\", 3: \"three\", 4: \"four\"}\nfor number in range(5):\n    name = number_names.get(number)\n    if name is not None:\n        print(f\"The name of {number} is {name}\")\n
        ","tags":["PERF203"]},{"location":"rules/try-except-in-loop/#options","title":"Options","text":"
        • target-version
        ","tags":["PERF203"]},{"location":"rules/try-except-pass/","title":"try-except-pass (S110)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S110"]},{"location":"rules/try-except-pass/#what-it-does","title":"What it does","text":"

        Checks for uses of the try-except-pass pattern.

        ","tags":["S110"]},{"location":"rules/try-except-pass/#why-is-this-bad","title":"Why is this bad?","text":"

        The try-except-pass pattern suppresses all exceptions. Suppressing exceptions may hide errors that could otherwise reveal unexpected behavior, security vulnerabilities, or malicious activity. Instead, consider logging the exception.

        ","tags":["S110"]},{"location":"rules/try-except-pass/#example","title":"Example","text":"
        try:\n    ...\nexcept Exception:\n    pass\n

        Use instead:

        import logging\n\ntry:\n    ...\nexcept Exception as exc:\n    logging.exception(\"Exception occurred\")\n
        ","tags":["S110"]},{"location":"rules/try-except-pass/#options","title":"Options","text":"
        • lint.flake8-bandit.check-typed-exception
        ","tags":["S110"]},{"location":"rules/try-except-pass/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-703
        • Python documentation: logging
        ","tags":["S110"]},{"location":"rules/type-alias-without-annotation/","title":"type-alias-without-annotation (PYI026)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI026"]},{"location":"rules/type-alias-without-annotation/#what-it-does","title":"What it does","text":"

        Checks for type alias definitions that are not annotated with typing.TypeAlias.

        ","tags":["PYI026"]},{"location":"rules/type-alias-without-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, a type alias is defined by assigning a type to a variable (e.g., Vector = list[float]).

        It's best to annotate type aliases with the typing.TypeAlias type to make it clear that the statement is a type alias declaration, as opposed to a normal variable assignment.

        ","tags":["PYI026"]},{"location":"rules/type-alias-without-annotation/#example","title":"Example","text":"
        Vector = list[float]\n

        Use instead:

        from typing import TypeAlias\n\nVector: TypeAlias = list[float]\n
        ","tags":["PYI026"]},{"location":"rules/type-alias-without-annotation/#availability","title":"Availability","text":"

        Because this rule relies on the third-party typing_extensions module for Python versions before 3.10, its diagnostic will not be emitted, and no fix will be offered, if typing_extensions imports have been disabled by the lint.typing-extensions linter option.

        ","tags":["PYI026"]},{"location":"rules/type-alias-without-annotation/#options","title":"Options","text":"
        • lint.typing-extensions
        ","tags":["PYI026"]},{"location":"rules/type-bivariance/","title":"type-bivariance (PLC0131)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC0131"]},{"location":"rules/type-bivariance/#what-it-does","title":"What it does","text":"

        Checks for TypeVar and ParamSpec definitions in which the type is both covariant and contravariant.

        ","tags":["PLC0131"]},{"location":"rules/type-bivariance/#why-is-this-bad","title":"Why is this bad?","text":"

        By default, Python's generic types are invariant, but can be marked as either covariant or contravariant via the covariant and contravariant keyword arguments. While the API does allow you to mark a type as both covariant and contravariant, this is not supported by the type system, and should be avoided.

        Instead, change the variance of the type to be either covariant, contravariant, or invariant. If you want to describe both covariance and contravariance, consider using two separate type parameters.

        For context: an \"invariant\" generic type only accepts values that exactly match the type parameter; for example, list[Dog] accepts only list[Dog], not list[Animal] (superclass) or list[Bulldog] (subclass). This is the default behavior for Python's generic types.

        A \"covariant\" generic type accepts subclasses of the type parameter; for example, Sequence[Animal] accepts Sequence[Dog]. A \"contravariant\" generic type accepts superclasses of the type parameter; for example, Callable[Dog] accepts Callable[Animal].

        ","tags":["PLC0131"]},{"location":"rules/type-bivariance/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"T\", covariant=True, contravariant=True)\n

        Use instead:

        from typing import TypeVar\n\nT_co = TypeVar(\"T_co\", covariant=True)\nT_contra = TypeVar(\"T_contra\", contravariant=True)\n
        ","tags":["PLC0131"]},{"location":"rules/type-bivariance/#references","title":"References","text":"
        • Python documentation: typing \u2014 Support for type hints
        • PEP 483 \u2013 The Theory of Type Hints: Covariance and Contravariance
        • PEP 484 \u2013 Type Hints: Covariance and contravariance
        ","tags":["PLC0131"]},{"location":"rules/type-check-without-type-error/","title":"type-check-without-type-error (TRY004)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY004"]},{"location":"rules/type-check-without-type-error/#what-it-does","title":"What it does","text":"

        Checks for type checks that do not raise TypeError.

        ","tags":["TRY004"]},{"location":"rules/type-check-without-type-error/#why-is-this-bad","title":"Why is this bad?","text":"

        The Python documentation states that TypeError should be raised upon encountering an inappropriate type.

        ","tags":["TRY004"]},{"location":"rules/type-check-without-type-error/#example","title":"Example","text":"
        def foo(n: int):\n    if isinstance(n, int):\n        pass\n    else:\n        raise ValueError(\"n must be an integer\")\n

        Use instead:

        def foo(n: int):\n    if isinstance(n, int):\n        pass\n    else:\n        raise TypeError(\"n must be an integer\")\n
        ","tags":["TRY004"]},{"location":"rules/type-check-without-type-error/#references","title":"References","text":"
        • Python documentation: TypeError
        ","tags":["TRY004"]},{"location":"rules/type-comment-in-stub/","title":"type-comment-in-stub (PYI033)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI033"]},{"location":"rules/type-comment-in-stub/#what-it-does","title":"What it does","text":"

        Checks for the use of type comments (e.g., x = 1 # type: int) in stub files.

        ","tags":["PYI033"]},{"location":"rules/type-comment-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub (.pyi) files should use type annotations directly, rather than type comments, even if they're intended to support Python 2, since stub files are not executed at runtime. The one exception is # type: ignore.

        ","tags":["PYI033"]},{"location":"rules/type-comment-in-stub/#example","title":"Example","text":"
        x = 1  # type: int\n

        Use instead:

        x: int = 1\n
        ","tags":["PYI033"]},{"location":"rules/type-comparison/","title":"type-comparison (E721)","text":"

        Derived from the pycodestyle linter.

        ","tags":["E721"]},{"location":"rules/type-comparison/#what-it-does","title":"What it does","text":"

        Checks for object type comparisons using == and other comparison operators.

        ","tags":["E721"]},{"location":"rules/type-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Unlike a direct type comparison, isinstance will also check if an object is an instance of a class or a subclass thereof.

        If you want to check for an exact type match, use is or is not.

        ","tags":["E721"]},{"location":"rules/type-comparison/#known-problems","title":"Known problems","text":"

        When using libraries that override the == (__eq__) operator (such as NumPy, Pandas, and SQLAlchemy), this rule may produce false positives, as converting from == to is or is not will change the behavior of the code.

        For example, the following operations are not equivalent:

        import numpy as np\n\nnp.array([True, False]) == False\n# array([False,  True])\n\nnp.array([True, False]) is False\n# False\n
        ","tags":["E721"]},{"location":"rules/type-comparison/#example","title":"Example","text":"
        if type(obj) == type(1):\n    pass\n\nif type(obj) == int:\n    pass\n

        Use instead:

        if isinstance(obj, int):\n    pass\n
        ","tags":["E721"]},{"location":"rules/type-name-incorrect-variance/","title":"type-name-incorrect-variance (PLC0105)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC0105"]},{"location":"rules/type-name-incorrect-variance/#what-it-does","title":"What it does","text":"

        Checks for type names that do not match the variance of their associated type parameter.

        ","tags":["PLC0105"]},{"location":"rules/type-name-incorrect-variance/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 484 recommends the use of the _co and _contra suffixes for covariant and contravariant type parameters, respectively (while invariant type parameters should not have any such suffix).

        ","tags":["PLC0105"]},{"location":"rules/type-name-incorrect-variance/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"T\", covariant=True)\nU = TypeVar(\"U\", contravariant=True)\nV_co = TypeVar(\"V_co\")\n

        Use instead:

        from typing import TypeVar\n\nT_co = TypeVar(\"T_co\", covariant=True)\nU_contra = TypeVar(\"U_contra\", contravariant=True)\nV = TypeVar(\"V\")\n
        ","tags":["PLC0105"]},{"location":"rules/type-name-incorrect-variance/#references","title":"References","text":"
        • Python documentation: typing \u2014 Support for type hints
        • PEP 483 \u2013 The Theory of Type Hints: Covariance and Contravariance
        • PEP 484 \u2013 Type Hints: Covariance and contravariance
        ","tags":["PLC0105"]},{"location":"rules/type-none-comparison/","title":"type-none-comparison (FURB169)","text":"

        Derived from the refurb linter.

        Fix is always available.

        ","tags":["FURB169"]},{"location":"rules/type-none-comparison/#what-it-does","title":"What it does","text":"

        Checks for uses of type that compare the type of an object to the type of None.

        ","tags":["FURB169"]},{"location":"rules/type-none-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        There is only ever one instance of None, so it is more efficient and readable to use the is operator to check if an object is None.

        ","tags":["FURB169"]},{"location":"rules/type-none-comparison/#example","title":"Example","text":"
        type(obj) is type(None)\n

        Use instead:

        obj is None\n
        ","tags":["FURB169"]},{"location":"rules/type-none-comparison/#fix-safety","title":"Fix safety","text":"

        If the fix might remove comments, it will be marked as unsafe.

        ","tags":["FURB169"]},{"location":"rules/type-none-comparison/#references","title":"References","text":"
        • Python documentation: isinstance
        • Python documentation: None
        • Python documentation: type
        • Python documentation: Identity comparisons
        ","tags":["FURB169"]},{"location":"rules/type-of-primitive/","title":"type-of-primitive (UP003)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP003"]},{"location":"rules/type-of-primitive/#what-it-does","title":"What it does","text":"

        Checks for uses of type that take a primitive as an argument.

        ","tags":["UP003"]},{"location":"rules/type-of-primitive/#why-is-this-bad","title":"Why is this bad?","text":"

        type() returns the type of a given object. A type of a primitive can always be known in advance and accessed directly, which is more concise and explicit than using type().

        ","tags":["UP003"]},{"location":"rules/type-of-primitive/#example","title":"Example","text":"
        type(1)\n

        Use instead:

        int\n
        ","tags":["UP003"]},{"location":"rules/type-of-primitive/#references","title":"References","text":"
        • Python documentation: type()
        • Python documentation: Built-in types
        ","tags":["UP003"]},{"location":"rules/type-param-name-mismatch/","title":"type-param-name-mismatch (PLC0132)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC0132"]},{"location":"rules/type-param-name-mismatch/#what-it-does","title":"What it does","text":"

        Checks for TypeVar, TypeVarTuple, ParamSpec, and NewType definitions in which the name of the type parameter does not match the name of the variable to which it is assigned.

        ","tags":["PLC0132"]},{"location":"rules/type-param-name-mismatch/#why-is-this-bad","title":"Why is this bad?","text":"

        When defining a TypeVar or a related type parameter, Python allows you to provide a name for the type parameter. According to PEP 484, the name provided to the TypeVar constructor must be equal to the name of the variable to which it is assigned.

        ","tags":["PLC0132"]},{"location":"rules/type-param-name-mismatch/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"U\")\n

        Use instead:

        from typing import TypeVar\n\nT = TypeVar(\"T\")\n
        ","tags":["PLC0132"]},{"location":"rules/type-param-name-mismatch/#references","title":"References","text":"
        • Python documentation: typing \u2014 Support for type hints
        • PEP 484 \u2013 Type Hints: Generics
        ","tags":["PLC0132"]},{"location":"rules/typed-argument-default-in-stub/","title":"typed-argument-default-in-stub (PYI011)","text":"

        Derived from the flake8-pyi linter.

        Fix is always available.

        ","tags":["PYI011"]},{"location":"rules/typed-argument-default-in-stub/#what-it-does","title":"What it does","text":"

        Checks for typed function arguments in stubs with complex default values.

        ","tags":["PYI011"]},{"location":"rules/typed-argument-default-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub (.pyi) files exist as \"data files\" for static analysis tools, and are not evaluated at runtime. While simple default values may be useful for some tools that consume stubs, such as IDEs, they are ignored by type checkers.

        Instead of including and reproducing a complex value, use ... to indicate that the assignment has a default value, but that the value is \"complex\" or varies according to the current platform or Python version. For the purposes of this rule, any default value counts as \"complex\" unless it is a literal int, float, complex, bytes, str, bool, None, ..., or a simple container literal.

        ","tags":["PYI011"]},{"location":"rules/typed-argument-default-in-stub/#example","title":"Example","text":"
        def foo(arg: list[int] = list(range(10_000))) -> None: ...\n

        Use instead:

        def foo(arg: list[int] = ...) -> None: ...\n
        ","tags":["PYI011"]},{"location":"rules/typed-argument-default-in-stub/#references","title":"References","text":"
        • flake8-pyi
        ","tags":["PYI011"]},{"location":"rules/typing-only-first-party-import/","title":"typing-only-first-party-import (TC001)","text":"

        Derived from the flake8-type-checking linter.

        Fix is sometimes available.

        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#what-it-does","title":"What it does","text":"

        Checks for first-party imports that are only used for type annotations, but aren't defined in a type-checking block.

        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused imports add a performance overhead at runtime, and risk creating import cycles. If an import is only used in typing-only contexts, it can instead be imported conditionally under an if TYPE_CHECKING: block to minimize runtime overhead.

        If lint.flake8-type-checking.quote-annotations is set to true, annotations will be wrapped in quotes if doing so would enable the corresponding import to be moved into an if TYPE_CHECKING: block.

        If a class requires that type annotations be available at runtime (as is the case for Pydantic, SQLAlchemy, and other libraries), consider using the lint.flake8-type-checking.runtime-evaluated-base-classes and lint.flake8-type-checking.runtime-evaluated-decorators settings to mark them as such.

        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#example","title":"Example","text":"
        from __future__ import annotations\n\nimport local_module\n\n\ndef func(sized: local_module.Container) -> int:\n    return len(sized)\n

        Use instead:

        from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    import local_module\n\n\ndef func(sized: local_module.Container) -> int:\n    return len(sized)\n
        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#preview","title":"Preview","text":"

        When preview is enabled, the criterion for determining whether an import is first-party is stricter, which could affect whether this lint is triggered vs TC001. See this FAQ section for more details.

        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#options","title":"Options","text":"
        • lint.flake8-type-checking.quote-annotations
        • lint.flake8-type-checking.runtime-evaluated-base-classes
        • lint.flake8-type-checking.runtime-evaluated-decorators
        • lint.flake8-type-checking.strict
        • lint.typing-modules
        ","tags":["TC001"]},{"location":"rules/typing-only-first-party-import/#references","title":"References","text":"
        • PEP 563: Runtime annotation resolution and TYPE_CHECKING
        ","tags":["TC001"]},{"location":"rules/typing-only-standard-library-import/","title":"typing-only-standard-library-import (TC003)","text":"

        Derived from the flake8-type-checking linter.

        Fix is sometimes available.

        ","tags":["TC003"]},{"location":"rules/typing-only-standard-library-import/#what-it-does","title":"What it does","text":"

        Checks for standard library imports that are only used for type annotations, but aren't defined in a type-checking block.

        ","tags":["TC003"]},{"location":"rules/typing-only-standard-library-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused imports add a performance overhead at runtime, and risk creating import cycles. If an import is only used in typing-only contexts, it can instead be imported conditionally under an if TYPE_CHECKING: block to minimize runtime overhead.

        If lint.flake8-type-checking.quote-annotations is set to true, annotations will be wrapped in quotes if doing so would enable the corresponding import to be moved into an if TYPE_CHECKING: block.

        If a class requires that type annotations be available at runtime (as is the case for Pydantic, SQLAlchemy, and other libraries), consider using the lint.flake8-type-checking.runtime-evaluated-base-classes and lint.flake8-type-checking.runtime-evaluated-decorators settings to mark them as such.

        ","tags":["TC003"]},{"location":"rules/typing-only-standard-library-import/#example","title":"Example","text":"
        from __future__ import annotations\n\nfrom pathlib import Path\n\n\ndef func(path: Path) -> str:\n    return str(path)\n

        Use instead:

        from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from pathlib import Path\n\n\ndef func(path: Path) -> str:\n    return str(path)\n
        ","tags":["TC003"]},{"location":"rules/typing-only-standard-library-import/#options","title":"Options","text":"
        • lint.flake8-type-checking.quote-annotations
        • lint.flake8-type-checking.runtime-evaluated-base-classes
        • lint.flake8-type-checking.runtime-evaluated-decorators
        • lint.flake8-type-checking.strict
        • lint.typing-modules
        ","tags":["TC003"]},{"location":"rules/typing-only-standard-library-import/#references","title":"References","text":"
        • PEP 563: Runtime annotation resolution and TYPE_CHECKING
        ","tags":["TC003"]},{"location":"rules/typing-only-third-party-import/","title":"typing-only-third-party-import (TC002)","text":"

        Derived from the flake8-type-checking linter.

        Fix is sometimes available.

        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#what-it-does","title":"What it does","text":"

        Checks for third-party imports that are only used for type annotations, but aren't defined in a type-checking block.

        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused imports add a performance overhead at runtime, and risk creating import cycles. If an import is only used in typing-only contexts, it can instead be imported conditionally under an if TYPE_CHECKING: block to minimize runtime overhead.

        If lint.flake8-type-checking.quote-annotations is set to true, annotations will be wrapped in quotes if doing so would enable the corresponding import to be moved into an if TYPE_CHECKING: block.

        If a class requires that type annotations be available at runtime (as is the case for Pydantic, SQLAlchemy, and other libraries), consider using the lint.flake8-type-checking.runtime-evaluated-base-classes and lint.flake8-type-checking.runtime-evaluated-decorators settings to mark them as such.

        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#example","title":"Example","text":"
        from __future__ import annotations\n\nimport pandas as pd\n\n\ndef func(df: pd.DataFrame) -> int:\n    return len(df)\n

        Use instead:

        from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    import pandas as pd\n\n\ndef func(df: pd.DataFrame) -> int:\n    return len(df)\n
        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#preview","title":"Preview","text":"

        When preview is enabled, the criterion for determining whether an import is first-party is stricter, which could affect whether this lint is triggered vs TC001. See this FAQ section for more details.

        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#options","title":"Options","text":"
        • lint.flake8-type-checking.quote-annotations
        • lint.flake8-type-checking.runtime-evaluated-base-classes
        • lint.flake8-type-checking.runtime-evaluated-decorators
        • lint.flake8-type-checking.strict
        • lint.typing-modules
        ","tags":["TC002"]},{"location":"rules/typing-only-third-party-import/#references","title":"References","text":"
        • PEP 563: Runtime annotation resolution and TYPE_CHECKING
        ","tags":["TC002"]},{"location":"rules/typing-text-str-alias/","title":"typing-text-str-alias (UP019)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP019"]},{"location":"rules/typing-text-str-alias/#what-it-does","title":"What it does","text":"

        Checks for uses of typing.Text.

        ","tags":["UP019"]},{"location":"rules/typing-text-str-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        typing.Text is an alias for str, and only exists for Python 2 compatibility. As of Python 3.11, typing.Text is deprecated. Use str instead.

        ","tags":["UP019"]},{"location":"rules/typing-text-str-alias/#example","title":"Example","text":"
        from typing import Text\n\nfoo: Text = \"bar\"\n

        Use instead:

        foo: str = \"bar\"\n
        ","tags":["UP019"]},{"location":"rules/typing-text-str-alias/#references","title":"References","text":"
        • Python documentation: typing.Text
        ","tags":["UP019"]},{"location":"rules/unaliased-collections-abc-set-import/","title":"unaliased-collections-abc-set-import (PYI025)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI025"]},{"location":"rules/unaliased-collections-abc-set-import/#what-it-does","title":"What it does","text":"

        Checks for from collections.abc import Set imports that do not alias Set to AbstractSet.

        ","tags":["PYI025"]},{"location":"rules/unaliased-collections-abc-set-import/#why-is-this-bad","title":"Why is this bad?","text":"

        The Set type in collections.abc is an abstract base class for set-like types. It is easily confused with, and not equivalent to, the set builtin.

        To avoid confusion, Set should be aliased to AbstractSet when imported. This makes it clear that the imported type is an abstract base class, and not the set builtin.

        ","tags":["PYI025"]},{"location":"rules/unaliased-collections-abc-set-import/#example","title":"Example","text":"
        from collections.abc import Set\n

        Use instead:

        from collections.abc import Set as AbstractSet\n
        ","tags":["PYI025"]},{"location":"rules/unaliased-collections-abc-set-import/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for Set imports defined at the top-level of a .py module. Top-level symbols are implicitly exported by the module, and so renaming a top-level symbol may break downstream modules that import it.

        The same is not true for .pyi files, where imported symbols are only re-exported if they are included in __all__, use a \"redundant\" import foo as foo alias, or are imported via a * import. As such, the fix is marked as safe in more cases for .pyi files.

        ","tags":["PYI025"]},{"location":"rules/unannotated-assignment-in-stub/","title":"unannotated-assignment-in-stub (PYI052)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI052"]},{"location":"rules/unannotated-assignment-in-stub/#what-it-does","title":"What it does","text":"

        Checks for unannotated assignments in stub (.pyi) files.

        ","tags":["PYI052"]},{"location":"rules/unannotated-assignment-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files exist to provide type hints, and are never executed. As such, all assignments in stub files should be annotated with a type.

        ","tags":["PYI052"]},{"location":"rules/unary-prefix-increment-decrement/","title":"unary-prefix-increment-decrement (B002)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B002"]},{"location":"rules/unary-prefix-increment-decrement/#what-it-does","title":"What it does","text":"

        Checks for the attempted use of the unary prefix increment (++) or decrement operator (--).

        ","tags":["B002"]},{"location":"rules/unary-prefix-increment-decrement/#why-is-this-bad","title":"Why is this bad?","text":"

        Python does not support the unary prefix increment or decrement operator. Writing ++n is equivalent to +(+(n)) and writing --n is equivalent to -(-(n)). In both cases, it is equivalent to n.

        ","tags":["B002"]},{"location":"rules/unary-prefix-increment-decrement/#example","title":"Example","text":"
        ++x\n--y\n

        Use instead:

        x += 1\ny -= 1\n
        ","tags":["B002"]},{"location":"rules/unary-prefix-increment-decrement/#references","title":"References","text":"
        • Python documentation: Unary arithmetic and bitwise operations
        • Python documentation: Augmented assignment statements
        ","tags":["B002"]},{"location":"rules/unassigned-special-variable-in-stub/","title":"unassigned-special-variable-in-stub (PYI035)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI035"]},{"location":"rules/unassigned-special-variable-in-stub/#what-it-does","title":"What it does","text":"

        Checks that __all__, __match_args__, and __slots__ variables are assigned to values when defined in stub files.

        ","tags":["PYI035"]},{"location":"rules/unassigned-special-variable-in-stub/#why-is-this-bad","title":"Why is this bad?","text":"

        Special variables like __all__ have the same semantics in stub files as they do in Python modules, and so should be consistent with their runtime counterparts.

        ","tags":["PYI035"]},{"location":"rules/unassigned-special-variable-in-stub/#example","title":"Example","text":"
        __all__: list[str]\n

        Use instead:

        __all__: list[str] = [\"foo\", \"bar\"]\n
        ","tags":["PYI035"]},{"location":"rules/uncapitalized-environment-variables/","title":"uncapitalized-environment-variables (SIM112)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM112"]},{"location":"rules/uncapitalized-environment-variables/#what-it-does","title":"What it does","text":"

        Check for environment variables that are not capitalized.

        ","tags":["SIM112"]},{"location":"rules/uncapitalized-environment-variables/#why-is-this-bad","title":"Why is this bad?","text":"

        By convention, environment variables should be capitalized.

        On Windows, environment variables are case-insensitive and are converted to uppercase, so using lowercase environment variables can lead to subtle bugs.

        ","tags":["SIM112"]},{"location":"rules/uncapitalized-environment-variables/#example","title":"Example","text":"
        import os\n\nos.environ[\"foo\"]\n

        Use instead:

        import os\n\nos.environ[\"FOO\"]\n
        ","tags":["SIM112"]},{"location":"rules/uncapitalized-environment-variables/#fix-safety","title":"Fix safety","text":"

        This fix is always marked as unsafe because automatically capitalizing environment variable names can change program behavior in environments where the variable names are case-sensitive, such as most Unix-like systems.

        ","tags":["SIM112"]},{"location":"rules/uncapitalized-environment-variables/#references","title":"References","text":"
        • Python documentation: os.environ
        ","tags":["SIM112"]},{"location":"rules/unconventional-import-alias/","title":"unconventional-import-alias (ICN001)","text":"

        Derived from the flake8-import-conventions linter.

        Fix is sometimes available.

        ","tags":["ICN001"]},{"location":"rules/unconventional-import-alias/#what-it-does","title":"What it does","text":"

        Checks for imports that are typically imported using a common convention, like import pandas as pd, and enforces that convention.

        ","tags":["ICN001"]},{"location":"rules/unconventional-import-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use a common convention for imports to make your code more readable and idiomatic.

        For example, import pandas as pd is a common convention for importing the pandas library, and users typically expect Pandas to be aliased as pd.

        ","tags":["ICN001"]},{"location":"rules/unconventional-import-alias/#example","title":"Example","text":"
        import pandas\n

        Use instead:

        import pandas as pd\n
        ","tags":["ICN001"]},{"location":"rules/unconventional-import-alias/#options","title":"Options","text":"
        • lint.flake8-import-conventions.aliases
        • lint.flake8-import-conventions.extend-aliases
        ","tags":["ICN001"]},{"location":"rules/undefined-export/","title":"undefined-export (F822)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F822"]},{"location":"rules/undefined-export/#what-it-does","title":"What it does","text":"

        Checks for undefined names in __all__.

        ","tags":["F822"]},{"location":"rules/undefined-export/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the __all__ variable is used to define the names that are exported when a module is imported as a wildcard (e.g., from foo import *). The names in __all__ must be defined in the module, but are included as strings.

        Including an undefined name in __all__ is likely to raise NameError at runtime, when the module is imported.

        In preview, this rule will flag undefined names in __init__.py file, even if those names implicitly refer to other modules in the package. Users that rely on implicit exports should disable this rule in __init__.py files via lint.per-file-ignores.

        ","tags":["F822"]},{"location":"rules/undefined-export/#example","title":"Example","text":"
        from foo import bar\n\n\n__all__ = [\"bar\", \"baz\"]  # undefined name `baz` in `__all__`\n

        Use instead:

        from foo import bar, baz\n\n\n__all__ = [\"bar\", \"baz\"]\n
        ","tags":["F822"]},{"location":"rules/undefined-export/#references","title":"References","text":"
        • Python documentation: __all__
        ","tags":["F822"]},{"location":"rules/undefined-local-with-import-star-usage/","title":"undefined-local-with-import-star-usage (F405)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F405"]},{"location":"rules/undefined-local-with-import-star-usage/#what-it-does","title":"What it does","text":"

        Checks for names that might be undefined, but may also be defined in a wildcard import.

        ","tags":["F405"]},{"location":"rules/undefined-local-with-import-star-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        Wildcard imports (e.g., from module import *) make it hard to determine which symbols are available in the current namespace. If a module contains a wildcard import, and a name in the current namespace has not been explicitly defined or imported, then it's unclear whether the name is undefined or was imported by the wildcard import.

        If the name is defined in via a wildcard import, that member should be imported explicitly to avoid confusion.

        If the name is not defined in a wildcard import, it should be defined or imported.

        ","tags":["F405"]},{"location":"rules/undefined-local-with-import-star-usage/#example","title":"Example","text":"
        from math import *\n\n\ndef area(radius):\n    return pi * radius**2\n

        Use instead:

        from math import pi\n\n\ndef area(radius):\n    return pi * radius**2\n
        ","tags":["F405"]},{"location":"rules/undefined-local-with-import-star/","title":"undefined-local-with-import-star (F403)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F403"]},{"location":"rules/undefined-local-with-import-star/#what-it-does","title":"What it does","text":"

        Checks for the use of wildcard imports.

        ","tags":["F403"]},{"location":"rules/undefined-local-with-import-star/#why-is-this-bad","title":"Why is this bad?","text":"

        Wildcard imports (e.g., from module import *) make it hard to determine which symbols are available in the current namespace, and from which module they were imported. They're also discouraged by PEP 8.

        ","tags":["F403"]},{"location":"rules/undefined-local-with-import-star/#example","title":"Example","text":"
        from math import *\n\n\ndef area(radius):\n    return pi * radius**2\n

        Use instead:

        from math import pi\n\n\ndef area(radius):\n    return pi * radius**2\n
        ","tags":["F403"]},{"location":"rules/undefined-local-with-nested-import-star-usage/","title":"undefined-local-with-nested-import-star-usage (F406)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F406"]},{"location":"rules/undefined-local-with-nested-import-star-usage/#what-it-does","title":"What it does","text":"

        Check for the use of wildcard imports outside of the module namespace.

        ","tags":["F406"]},{"location":"rules/undefined-local-with-nested-import-star-usage/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of wildcard imports outside of the module namespace (e.g., within functions) can lead to confusion, as the import can shadow local variables.

        Though wildcard imports are discouraged by PEP 8, when necessary, they should be placed in the module namespace (i.e., at the top-level of a module).

        ","tags":["F406"]},{"location":"rules/undefined-local-with-nested-import-star-usage/#example","title":"Example","text":"
        def foo():\n    from math import *\n

        Use instead:

        from math import *\n\n\ndef foo(): ...\n
        ","tags":["F406"]},{"location":"rules/undefined-local/","title":"undefined-local (F823)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F823"]},{"location":"rules/undefined-local/#what-it-does","title":"What it does","text":"

        Checks for undefined local variables.

        ","tags":["F823"]},{"location":"rules/undefined-local/#why-is-this-bad","title":"Why is this bad?","text":"

        Referencing a local variable before it has been assigned will raise an UnboundLocalError at runtime.

        ","tags":["F823"]},{"location":"rules/undefined-local/#example","title":"Example","text":"
        x = 1\n\n\ndef foo():\n    x += 1\n

        Use instead:

        x = 1\n\n\ndef foo():\n    global x\n    x += 1\n
        ","tags":["F823"]},{"location":"rules/undefined-name/","title":"undefined-name (F821)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F821"]},{"location":"rules/undefined-name/#what-it-does","title":"What it does","text":"

        Checks for uses of undefined names.

        ","tags":["F821"]},{"location":"rules/undefined-name/#why-is-this-bad","title":"Why is this bad?","text":"

        An undefined name is likely to raise NameError at runtime.

        ","tags":["F821"]},{"location":"rules/undefined-name/#example","title":"Example","text":"
        def double():\n    return n * 2  # raises `NameError` if `n` is undefined when `double` is called\n

        Use instead:

        def double(n):\n    return n * 2\n
        ","tags":["F821"]},{"location":"rules/undefined-name/#options","title":"Options","text":"
        • target-version: Can be used to configure which symbols Ruff will understand as being available in the builtins namespace.
        ","tags":["F821"]},{"location":"rules/undefined-name/#references","title":"References","text":"
        • Python documentation: Naming and binding
        ","tags":["F821"]},{"location":"rules/under-indentation/","title":"under-indentation (D207)","text":"

        Derived from the pydocstyle linter.

        Fix is always available.

        ","tags":["D207"]},{"location":"rules/under-indentation/#what-it-does","title":"What it does","text":"

        Checks for under-indented docstrings.

        ","tags":["D207"]},{"location":"rules/under-indentation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that docstrings be indented to the same level as their opening quotes. Avoid under-indenting docstrings, for consistency.

        ","tags":["D207"]},{"location":"rules/under-indentation/#example","title":"Example","text":"
        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\nSort the list in ascending order and return a copy of the result using the bubble sort\nalgorithm.\n    \"\"\"\n

        Use instead:

        def sort_list(l: list[int]) -> list[int]:\n    \"\"\"Return a sorted copy of the list.\n\n    Sort the list in ascending order and return a copy of the result using the bubble\n    sort algorithm.\n    \"\"\"\n
        ","tags":["D207"]},{"location":"rules/under-indentation/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter enforces consistent indentation, making the rule redundant.

        ","tags":["D207"]},{"location":"rules/under-indentation/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D207"]},{"location":"rules/undocumented-magic-method/","title":"undocumented-magic-method (D105)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D105"]},{"location":"rules/undocumented-magic-method/#what-it-does","title":"What it does","text":"

        Checks for undocumented magic method definitions.

        ","tags":["D105"]},{"location":"rules/undocumented-magic-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Magic methods (methods with names that start and end with double underscores) are used to implement operator overloading and other special behavior. Such methods should be documented via docstrings to outline their behavior.

        Generally, magic method docstrings should describe the method's behavior, arguments, side effects, exceptions, return values, and any other information that may be relevant to the user.

        If the codebase adheres to a standard format for method docstrings, follow that format for consistency.

        ","tags":["D105"]},{"location":"rules/undocumented-magic-method/#example","title":"Example","text":"
        class Cat(Animal):\n    def __str__(self) -> str:\n        return f\"Cat: {self.name}\"\n\n\ncat = Cat(\"Dusty\")\nprint(cat)  # \"Cat: Dusty\"\n

        Use instead:

        class Cat(Animal):\n    def __str__(self) -> str:\n        \"\"\"Return a string representation of the cat.\"\"\"\n        return f\"Cat: {self.name}\"\n\n\ncat = Cat(\"Dusty\")\nprint(cat)  # \"Cat: Dusty\"\n
        ","tags":["D105"]},{"location":"rules/undocumented-magic-method/#options","title":"Options","text":"
        • lint.pydocstyle.ignore-decorators
        ","tags":["D105"]},{"location":"rules/undocumented-magic-method/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Python Docstrings
        ","tags":["D105"]},{"location":"rules/undocumented-param/","title":"undocumented-param (D417)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D417"]},{"location":"rules/undocumented-param/#what-it-does","title":"What it does","text":"

        Checks for function docstrings that do not include documentation for all parameters in the function.

        ","tags":["D417"]},{"location":"rules/undocumented-param/#why-is-this-bad","title":"Why is this bad?","text":"

        This rule helps prevent you from leaving Google-style docstrings unfinished or incomplete. Multiline Google-style docstrings should describe all parameters for the function they are documenting.

        Multiline docstrings are typically composed of a summary line, followed by a blank line, followed by a series of sections, each with a section header and a section body. Function docstrings often include a section for function arguments; this rule is concerned with that section only. Note that this rule only checks docstrings with an arguments (e.g. Args) section.

        This rule is enabled when using the google convention, and disabled when using the pep257 and numpy conventions.

        ","tags":["D417"]},{"location":"rules/undocumented-param/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D417"]},{"location":"rules/undocumented-param/#options","title":"Options","text":"
        • lint.pydocstyle.convention
        • lint.pydocstyle.ignore-var-parameters
        ","tags":["D417"]},{"location":"rules/undocumented-param/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • Google Python Style Guide - Docstrings
        ","tags":["D417"]},{"location":"rules/undocumented-public-class/","title":"undocumented-public-class (D101)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D101"]},{"location":"rules/undocumented-public-class/#what-it-does","title":"What it does","text":"

        Checks for undocumented public class definitions.

        ","tags":["D101"]},{"location":"rules/undocumented-public-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Public classes should be documented via docstrings to outline their purpose and behavior.

        Generally, a class docstring should describe the class's purpose and list its public attributes and methods.

        If the codebase adheres to a standard format for class docstrings, follow that format for consistency.

        ","tags":["D101"]},{"location":"rules/undocumented-public-class/#example","title":"Example","text":"
        class Player:\n    def __init__(self, name: str, points: int = 0) -> None:\n        self.name: str = name\n        self.points: int = points\n\n    def add_points(self, points: int) -> None:\n        self.points += points\n

        Use instead (in the NumPy docstring format):

        class Player:\n    \"\"\"A player in the game.\n\n    Attributes\n    ----------\n    name : str\n        The name of the player.\n    points : int\n        The number of points the player has.\n\n    Methods\n    -------\n    add_points(points: int) -> None\n        Add points to the player's score.\n    \"\"\"\n\n    def __init__(self, name: str, points: int = 0) -> None:\n        self.name: str = name\n        self.points: int = points\n\n    def add_points(self, points: int) -> None:\n        self.points += points\n

        Or (in the Google docstring format):

        class Player:\n    \"\"\"A player in the game.\n\n    Attributes:\n        name: The name of the player.\n        points: The number of points the player has.\n    \"\"\"\n\n    def __init__(self, name: str, points: int = 0) -> None:\n        self.name: str = name\n        self.points: int = points\n\n    def add_points(self, points: int) -> None:\n        self.points += points\n
        ","tags":["D101"]},{"location":"rules/undocumented-public-class/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D101"]},{"location":"rules/undocumented-public-function/","title":"undocumented-public-function (D103)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D103"]},{"location":"rules/undocumented-public-function/#what-it-does","title":"What it does","text":"

        Checks for undocumented public function definitions.

        ","tags":["D103"]},{"location":"rules/undocumented-public-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Public functions should be documented via docstrings to outline their purpose and behavior.

        Generally, a function docstring should describe the function's behavior, arguments, side effects, exceptions, return values, and any other information that may be relevant to the user.

        If the codebase adheres to a standard format for function docstrings, follow that format for consistency.

        ","tags":["D103"]},{"location":"rules/undocumented-public-function/#example","title":"Example","text":"
        def calculate_speed(distance: float, time: float) -> float:\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Use instead (using the NumPy docstring format):

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Parameters\n    ----------\n    distance : float\n        Distance traveled.\n    time : float\n        Time spent traveling.\n\n    Returns\n    -------\n    float\n        Speed as distance divided by time.\n\n    Raises\n    ------\n    FasterThanLightError\n        If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n

        Or, using the Google docstring format:

        def calculate_speed(distance: float, time: float) -> float:\n    \"\"\"Calculate speed as distance divided by time.\n\n    Args:\n        distance: Distance traveled.\n        time: Time spent traveling.\n\n    Returns:\n        Speed as distance divided by time.\n\n    Raises:\n        FasterThanLightError: If speed is greater than the speed of light.\n    \"\"\"\n    try:\n        return distance / time\n    except ZeroDivisionError as exc:\n        raise FasterThanLightError from exc\n
        ","tags":["D103"]},{"location":"rules/undocumented-public-function/#options","title":"Options","text":"
        • lint.pydocstyle.ignore-decorators
        ","tags":["D103"]},{"location":"rules/undocumented-public-function/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Python Docstrings
        ","tags":["D103"]},{"location":"rules/undocumented-public-init/","title":"undocumented-public-init (D107)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D107"]},{"location":"rules/undocumented-public-init/#what-it-does","title":"What it does","text":"

        Checks for public __init__ method definitions that are missing docstrings.

        ","tags":["D107"]},{"location":"rules/undocumented-public-init/#why-is-this-bad","title":"Why is this bad?","text":"

        Public __init__ methods are used to initialize objects. __init__ methods should be documented via docstrings to describe the method's behavior, arguments, side effects, exceptions, and any other information that may be relevant to the user.

        If the codebase adheres to a standard format for __init__ method docstrings, follow that format for consistency.

        ","tags":["D107"]},{"location":"rules/undocumented-public-init/#example","title":"Example","text":"
        class City:\n    def __init__(self, name: str, population: int) -> None:\n        self.name: str = name\n        self.population: int = population\n

        Use instead:

        class City:\n    def __init__(self, name: str, population: int) -> None:\n        \"\"\"Initialize a city with a name and population.\"\"\"\n        self.name: str = name\n        self.population: int = population\n
        ","tags":["D107"]},{"location":"rules/undocumented-public-init/#options","title":"Options","text":"
        • lint.pydocstyle.ignore-decorators
        ","tags":["D107"]},{"location":"rules/undocumented-public-init/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Python Docstrings
        ","tags":["D107"]},{"location":"rules/undocumented-public-method/","title":"undocumented-public-method (D102)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D102"]},{"location":"rules/undocumented-public-method/#what-it-does","title":"What it does","text":"

        Checks for undocumented public method definitions.

        ","tags":["D102"]},{"location":"rules/undocumented-public-method/#why-is-this-bad","title":"Why is this bad?","text":"

        Public methods should be documented via docstrings to outline their purpose and behavior.

        Generally, a method docstring should describe the method's behavior, arguments, side effects, exceptions, return values, and any other information that may be relevant to the user.

        If the codebase adheres to a standard format for method docstrings, follow that format for consistency.

        ","tags":["D102"]},{"location":"rules/undocumented-public-method/#example","title":"Example","text":"
        class Cat(Animal):\n    def greet(self, happy: bool = True):\n        if happy:\n            print(\"Meow!\")\n        else:\n            raise ValueError(\"Tried to greet an unhappy cat.\")\n

        Use instead (in the NumPy docstring format):

        class Cat(Animal):\n    def greet(self, happy: bool = True):\n        \"\"\"Print a greeting from the cat.\n\n        Parameters\n        ----------\n        happy : bool, optional\n            Whether the cat is happy, is True by default.\n\n        Raises\n        ------\n        ValueError\n            If the cat is not happy.\n        \"\"\"\n        if happy:\n            print(\"Meow!\")\n        else:\n            raise ValueError(\"Tried to greet an unhappy cat.\")\n

        Or (in the Google docstring format):

        class Cat(Animal):\n    def greet(self, happy: bool = True):\n        \"\"\"Print a greeting from the cat.\n\n        Args:\n            happy: Whether the cat is happy, is True by default.\n\n        Raises:\n            ValueError: If the cat is not happy.\n        \"\"\"\n        if happy:\n            print(\"Meow!\")\n        else:\n            raise ValueError(\"Tried to greet an unhappy cat.\")\n
        ","tags":["D102"]},{"location":"rules/undocumented-public-method/#options","title":"Options","text":"
        • lint.pydocstyle.ignore-decorators
        ","tags":["D102"]},{"location":"rules/undocumented-public-method/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D102"]},{"location":"rules/undocumented-public-module/","title":"undocumented-public-module (D100)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D100"]},{"location":"rules/undocumented-public-module/#what-it-does","title":"What it does","text":"

        Checks for undocumented public module definitions.

        ","tags":["D100"]},{"location":"rules/undocumented-public-module/#why-is-this-bad","title":"Why is this bad?","text":"

        Public modules should be documented via docstrings to outline their purpose and contents.

        Generally, module docstrings should describe the purpose of the module and list the classes, exceptions, functions, and other objects that are exported by the module, alongside a one-line summary of each.

        If the module is a script, the docstring should be usable as its \"usage\" message.

        If the codebase adheres to a standard format for module docstrings, follow that format for consistency.

        ","tags":["D100"]},{"location":"rules/undocumented-public-module/#example","title":"Example","text":"
        class FasterThanLightError(ZeroDivisionError): ...\n\n\ndef calculate_speed(distance: float, time: float) -> float: ...\n

        Use instead:

        \"\"\"Utility functions and classes for calculating speed.\n\nThis module provides:\n- FasterThanLightError: exception when FTL speed is calculated;\n- calculate_speed: calculate speed given distance and time.\n\"\"\"\n\n\nclass FasterThanLightError(ZeroDivisionError): ...\n\n\ndef calculate_speed(distance: float, time: float) -> float: ...\n
        ","tags":["D100"]},{"location":"rules/undocumented-public-module/#notebook-behavior","title":"Notebook behavior","text":"

        This rule is ignored for Jupyter Notebooks.

        ","tags":["D100"]},{"location":"rules/undocumented-public-module/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Python Style Guide - Docstrings
        ","tags":["D100"]},{"location":"rules/undocumented-public-nested-class/","title":"undocumented-public-nested-class (D106)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D106"]},{"location":"rules/undocumented-public-nested-class/#what-it-does","title":"What it does","text":"

        Checks for undocumented public class definitions, for nested classes.

        ","tags":["D106"]},{"location":"rules/undocumented-public-nested-class/#why-is-this-bad","title":"Why is this bad?","text":"

        Public classes should be documented via docstrings to outline their purpose and behavior.

        Nested classes do not inherit the docstring of their enclosing class, so they should have their own docstrings.

        If the codebase adheres to a standard format for class docstrings, follow that format for consistency.

        ","tags":["D106"]},{"location":"rules/undocumented-public-nested-class/#example","title":"Example","text":"
        class Foo:\n    \"\"\"Class Foo.\"\"\"\n\n    class Bar: ...\n\n\nbar = Foo.Bar()\nbar.__doc__  # None\n

        Use instead:

        class Foo:\n    \"\"\"Class Foo.\"\"\"\n\n    class Bar:\n        \"\"\"Class Bar.\"\"\"\n\n\nbar = Foo.Bar()\nbar.__doc__  # \"Class Bar.\"\n
        ","tags":["D106"]},{"location":"rules/undocumented-public-nested-class/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Python Docstrings
        ","tags":["D106"]},{"location":"rules/undocumented-public-package/","title":"undocumented-public-package (D104)","text":"

        Derived from the pydocstyle linter.

        ","tags":["D104"]},{"location":"rules/undocumented-public-package/#what-it-does","title":"What it does","text":"

        Checks for undocumented public package definitions.

        ","tags":["D104"]},{"location":"rules/undocumented-public-package/#why-is-this-bad","title":"Why is this bad?","text":"

        Public packages should be documented via docstrings to outline their purpose and contents.

        Generally, package docstrings should list the modules and subpackages that are exported by the package.

        If the codebase adheres to a standard format for package docstrings, follow that format for consistency.

        ","tags":["D104"]},{"location":"rules/undocumented-public-package/#example","title":"Example","text":"
        __all__ = [\"Player\", \"Game\"]\n

        Use instead:

        \"\"\"Game and player management package.\n\nThis package provides classes for managing players and games.\n\"\"\"\n\n__all__ = [\"player\", \"game\"]\n
        ","tags":["D104"]},{"location":"rules/undocumented-public-package/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        • PEP 287 \u2013 reStructuredText Docstring Format
        • NumPy Style Guide
        • Google Style Python Docstrings
        ","tags":["D104"]},{"location":"rules/undocumented-warn/","title":"undocumented-warn (LOG009)","text":"

        Derived from the flake8-logging linter.

        Fix is sometimes available.

        ","tags":["LOG009"]},{"location":"rules/undocumented-warn/#what-it-does","title":"What it does","text":"

        Checks for uses of logging.WARN.

        ","tags":["LOG009"]},{"location":"rules/undocumented-warn/#why-is-this-bad","title":"Why is this bad?","text":"

        The logging.WARN constant is an undocumented alias for logging.WARNING.

        Although it\u2019s not explicitly deprecated, logging.WARN is not mentioned in the logging documentation. Prefer logging.WARNING instead.

        ","tags":["LOG009"]},{"location":"rules/undocumented-warn/#example","title":"Example","text":"
        import logging\n\n\nlogging.basicConfig(level=logging.WARN)\n

        Use instead:

        import logging\n\n\nlogging.basicConfig(level=logging.WARNING)\n
        ","tags":["LOG009"]},{"location":"rules/unexpected-indentation-comment/","title":"unexpected-indentation-comment (E116)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E116"]},{"location":"rules/unexpected-indentation-comment/#what-it-does","title":"What it does","text":"

        Checks for unexpected indentation of comment.

        ","tags":["E116"]},{"location":"rules/unexpected-indentation-comment/#why-is-this-bad","title":"Why is this bad?","text":"

        Comments should match the indentation of the containing code block.

        ","tags":["E116"]},{"location":"rules/unexpected-indentation-comment/#example","title":"Example","text":"
        a = 1\n    # b = 2\n

        Use instead:

        a = 1\n# b = 2\n
        ","tags":["E116"]},{"location":"rules/unexpected-indentation/","title":"unexpected-indentation (E113)","text":"

        Derived from the pycodestyle linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E113"]},{"location":"rules/unexpected-indentation/#what-it-does","title":"What it does","text":"

        Checks for unexpected indentation.

        ","tags":["E113"]},{"location":"rules/unexpected-indentation/#why-is-this-bad","title":"Why is this bad?","text":"

        Indentation outside of a code block is not valid Python syntax.

        ","tags":["E113"]},{"location":"rules/unexpected-indentation/#example","title":"Example","text":"
        a = 1\n    b = 2\n

        Use instead:

        a = 1\nb = 2\n
        ","tags":["E113"]},{"location":"rules/unexpected-spaces-around-keyword-parameter-equals/","title":"unexpected-spaces-around-keyword-parameter-equals (E251)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E251"]},{"location":"rules/unexpected-spaces-around-keyword-parameter-equals/#what-it-does","title":"What it does","text":"

        Checks for missing whitespace around the equals sign in an unannotated function keyword parameter.

        ","tags":["E251"]},{"location":"rules/unexpected-spaces-around-keyword-parameter-equals/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, there should be no spaces around the equals sign in a keyword parameter, if it is unannotated:

        Don\u2019t use spaces around the = sign when used to indicate a keyword argument, or when used to indicate a default value for an unannotated function parameter.

        ","tags":["E251"]},{"location":"rules/unexpected-spaces-around-keyword-parameter-equals/#example","title":"Example","text":"
        def add(a = 0) -> int:\n    return a + 1\n

        Use instead:

        def add(a=0) -> int:\n    return a + 1\n
        ","tags":["E251"]},{"location":"rules/unexpected-special-method-signature/","title":"unexpected-special-method-signature (PLE0302)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0302"]},{"location":"rules/unexpected-special-method-signature/#what-it-does","title":"What it does","text":"

        Checks for \"special\" methods that have an unexpected method signature.

        ","tags":["PLE0302"]},{"location":"rules/unexpected-special-method-signature/#why-is-this-bad","title":"Why is this bad?","text":"

        \"Special\" methods, like __len__, are expected to adhere to a specific, standard function signature. Implementing a \"special\" method using a non-standard function signature can lead to unexpected and surprising behavior for users of a given class.

        ","tags":["PLE0302"]},{"location":"rules/unexpected-special-method-signature/#example","title":"Example","text":"
        class Bookshelf:\n    def __init__(self):\n        self._books = [\"Foo\", \"Bar\", \"Baz\"]\n\n    def __len__(self, index):  # __len__ does not except an index parameter\n        return len(self._books)\n\n    def __getitem__(self, index):\n        return self._books[index]\n

        Use instead:

        class Bookshelf:\n    def __init__(self):\n        self._books = [\"Foo\", \"Bar\", \"Baz\"]\n\n    def __len__(self):\n        return len(self._books)\n\n    def __getitem__(self, index):\n        return self._books[index]\n
        ","tags":["PLE0302"]},{"location":"rules/unexpected-special-method-signature/#references","title":"References","text":"
        • Python documentation: Data model
        ","tags":["PLE0302"]},{"location":"rules/unicode-kind-prefix/","title":"unicode-kind-prefix (UP025)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP025"]},{"location":"rules/unicode-kind-prefix/#what-it-does","title":"What it does","text":"

        Checks for uses of the Unicode kind prefix (u) in strings.

        ","tags":["UP025"]},{"location":"rules/unicode-kind-prefix/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python 3, all strings are Unicode by default. The Unicode kind prefix is unnecessary and should be removed to avoid confusion.

        ","tags":["UP025"]},{"location":"rules/unicode-kind-prefix/#example","title":"Example","text":"
        u\"foo\"\n

        Use instead:

        \"foo\"\n
        ","tags":["UP025"]},{"location":"rules/unicode-kind-prefix/#references","title":"References","text":"
        • Python documentation: Unicode HOWTO
        ","tags":["UP025"]},{"location":"rules/unintentional-type-annotation/","title":"unintentional-type-annotation (B032)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B032"]},{"location":"rules/unintentional-type-annotation/#what-it-does","title":"What it does","text":"

        Checks for the unintentional use of type annotations.

        ","tags":["B032"]},{"location":"rules/unintentional-type-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of a colon (:) in lieu of an assignment (=) can be syntactically valid, but is almost certainly a mistake when used in a subscript or attribute assignment.

        ","tags":["B032"]},{"location":"rules/unintentional-type-annotation/#example","title":"Example","text":"
        a[\"b\"]: 1\n

        Use instead:

        a[\"b\"] = 1\n
        ","tags":["B032"]},{"location":"rules/unix-command-wildcard-injection/","title":"unix-command-wildcard-injection (S609)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S609"]},{"location":"rules/unix-command-wildcard-injection/#what-it-does","title":"What it does","text":"

        Checks for possible wildcard injections in calls to subprocess.Popen().

        ","tags":["S609"]},{"location":"rules/unix-command-wildcard-injection/#why-is-this-bad","title":"Why is this bad?","text":"

        Wildcard injections can lead to unexpected behavior if unintended files are matched by the wildcard. Consider using a more specific path instead.

        ","tags":["S609"]},{"location":"rules/unix-command-wildcard-injection/#example","title":"Example","text":"
        import subprocess\n\nsubprocess.Popen([\"chmod\", \"777\", \"*.py\"])\n

        Use instead:

        import subprocess\n\nsubprocess.Popen([\"chmod\", \"777\", \"main.py\"])\n
        ","tags":["S609"]},{"location":"rules/unix-command-wildcard-injection/#references","title":"References","text":"
        • Common Weakness Enumeration: CWE-78
        ","tags":["S609"]},{"location":"rules/unnecessary-assign/","title":"unnecessary-assign (RET504)","text":"

        Derived from the flake8-return linter.

        Fix is always available.

        ","tags":["RET504"]},{"location":"rules/unnecessary-assign/#what-it-does","title":"What it does","text":"

        Checks for variable assignments that immediately precede a return of the assigned variable.

        ","tags":["RET504"]},{"location":"rules/unnecessary-assign/#why-is-this-bad","title":"Why is this bad?","text":"

        The variable assignment is not necessary, as the value can be returned directly.

        ","tags":["RET504"]},{"location":"rules/unnecessary-assign/#example","title":"Example","text":"
        def foo():\n    bar = 1\n    return bar\n

        Use instead:

        def foo():\n    return 1\n
        ","tags":["RET504"]},{"location":"rules/unnecessary-builtin-import/","title":"unnecessary-builtin-import (UP029)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP029"]},{"location":"rules/unnecessary-builtin-import/#what-it-does","title":"What it does","text":"

        Checks for unnecessary imports of builtins.

        ","tags":["UP029"]},{"location":"rules/unnecessary-builtin-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Builtins are always available. Importing them is unnecessary and should be removed to avoid confusion.

        ","tags":["UP029"]},{"location":"rules/unnecessary-builtin-import/#example","title":"Example","text":"
        from builtins import str\n\nstr(1)\n

        Use instead:

        str(1)\n
        ","tags":["UP029"]},{"location":"rules/unnecessary-builtin-import/#references","title":"References","text":"
        • Python documentation: The Python Standard Library
        ","tags":["UP029"]},{"location":"rules/unnecessary-call-around-sorted/","title":"unnecessary-call-around-sorted (C413)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C413"]},{"location":"rules/unnecessary-call-around-sorted/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list() or reversed() calls around sorted() calls.

        ","tags":["C413"]},{"location":"rules/unnecessary-call-around-sorted/#why-is-this-bad","title":"Why is this bad?","text":"

        It is unnecessary to use list() around sorted(), as the latter already returns a list.

        It is also unnecessary to use reversed() around sorted(), as the latter has a reverse argument that can be used in lieu of an additional reversed() call.

        In both cases, it's clearer and more efficient to avoid the redundant call.

        ","tags":["C413"]},{"location":"rules/unnecessary-call-around-sorted/#example","title":"Example","text":"
        reversed(sorted(iterable))\n

        Use instead:

        sorted(iterable, reverse=True)\n
        ","tags":["C413"]},{"location":"rules/unnecessary-call-around-sorted/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as reversed() and reverse=True will yield different results in the event of custom sort keys or equality functions. Specifically, reversed() will reverse the order of the collection, while sorted() with reverse=True will perform a stable reverse sort, which will preserve the order of elements that compare as equal.

        ","tags":["C413"]},{"location":"rules/unnecessary-cast-to-int/","title":"unnecessary-cast-to-int (RUF046)","text":"

        Fix is always available.

        ","tags":["RUF046"]},{"location":"rules/unnecessary-cast-to-int/#what-it-does","title":"What it does","text":"

        Checks for int conversions of values that are already integers.

        ","tags":["RUF046"]},{"location":"rules/unnecessary-cast-to-int/#why-is-this-bad","title":"Why is this bad?","text":"

        Such a conversion is unnecessary.

        ","tags":["RUF046"]},{"location":"rules/unnecessary-cast-to-int/#known-problems","title":"Known problems","text":"

        This rule may produce false positives for round, math.ceil, math.floor, and math.trunc calls when values override the __round__, __ceil__, __floor__, or __trunc__ operators such that they don't return an integer.

        ","tags":["RUF046"]},{"location":"rules/unnecessary-cast-to-int/#example","title":"Example","text":"
        int(len([]))\nint(round(foo, None))\n

        Use instead:

        len([])\nround(foo)\n
        ","tags":["RUF046"]},{"location":"rules/unnecessary-cast-to-int/#fix-safety","title":"Fix safety","text":"

        The fix for round, math.ceil, math.floor, and math.truncate is unsafe because removing the int conversion can change the semantics for values overriding the __round__, __ceil__, __floor__, or __trunc__ dunder methods such that they don't return an integer.

        ","tags":["RUF046"]},{"location":"rules/unnecessary-class-parentheses/","title":"unnecessary-class-parentheses (UP039)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP039"]},{"location":"rules/unnecessary-class-parentheses/#what-it-does","title":"What it does","text":"

        Checks for class definitions that include unnecessary parentheses after the class name.

        ","tags":["UP039"]},{"location":"rules/unnecessary-class-parentheses/#why-is-this-bad","title":"Why is this bad?","text":"

        If a class definition doesn't have any bases, the parentheses are unnecessary.

        ","tags":["UP039"]},{"location":"rules/unnecessary-class-parentheses/#example","title":"Example","text":"
        class Foo():\n    ...\n

        Use instead:

        class Foo:\n    ...\n
        ","tags":["UP039"]},{"location":"rules/unnecessary-collection-call/","title":"unnecessary-collection-call (C408)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C408"]},{"location":"rules/unnecessary-collection-call/#what-it-does","title":"What it does","text":"

        Checks for unnecessary dict(), list() or tuple() calls that can be rewritten as empty literals.

        ","tags":["C408"]},{"location":"rules/unnecessary-collection-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to call, e.g., dict() as opposed to using an empty literal ({}). The former is slower because the name dict must be looked up in the global scope in case it has been rebound.

        ","tags":["C408"]},{"location":"rules/unnecessary-collection-call/#example","title":"Example","text":"
        dict()\ndict(a=1, b=2)\nlist()\ntuple()\n

        Use instead:

        {}\n{\"a\": 1, \"b\": 2}\n[]\n()\n
        ","tags":["C408"]},{"location":"rules/unnecessary-collection-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C408"]},{"location":"rules/unnecessary-collection-call/#options","title":"Options","text":"
        • lint.flake8-comprehensions.allow-dict-calls-with-keyword-arguments
        ","tags":["C408"]},{"location":"rules/unnecessary-comprehension-in-call/","title":"unnecessary-comprehension-in-call (C419)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is sometimes available.

        ","tags":["C419"]},{"location":"rules/unnecessary-comprehension-in-call/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list or set comprehensions passed to builtin functions that take an iterable.

        Set comprehensions are only a violation in the case where the builtin function does not care about duplication of elements in the passed iterable.

        ","tags":["C419"]},{"location":"rules/unnecessary-comprehension-in-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Many builtin functions (this rule currently covers any and all in stable, along with min, max, and sum in preview) accept any iterable, including a generator. Constructing a temporary list via list comprehension is unnecessary and wastes memory for large iterables.

        any and all can also short-circuit iteration, saving a lot of time. The unnecessary comprehension forces a full iteration of the input iterable, giving up the benefits of short-circuiting. For example, compare the performance of all with a list comprehension against that of a generator in a case where an early short-circuit is possible (almost 40x faster):

        In [1]: %timeit all([i for i in range(1000)])\n8.14 \u00b5s \u00b1 25.4 ns per loop (mean \u00b1 std. dev. of 7 runs, 100,000 loops each)\n\nIn [2]: %timeit all(i for i in range(1000))\n212 ns \u00b1 0.892 ns per loop (mean \u00b1 std. dev. of 7 runs, 1,000,000 loops each)\n

        This performance improvement is due to short-circuiting. If the entire iterable has to be traversed, the comprehension version may even be a bit faster: list allocation overhead is not necessarily greater than generator overhead.

        Applying this rule simplifies the code and will usually save memory, but in the absence of short-circuiting it may not improve performance. (It may even slightly regress performance, though the difference will usually be small.)

        ","tags":["C419"]},{"location":"rules/unnecessary-comprehension-in-call/#example","title":"Example","text":"
        any([x.id for x in bar])\nall([x.id for x in bar])\nsum([x.val for x in bar])\nmin([x.val for x in bar])\nmax([x.val for x in bar])\n

        Use instead:

        any(x.id for x in bar)\nall(x.id for x in bar)\nsum(x.val for x in bar)\nmin(x.val for x in bar)\nmax(x.val for x in bar)\n
        ","tags":["C419"]},{"location":"rules/unnecessary-comprehension-in-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it can change the behavior of the code if the iteration has side effects (due to laziness and short-circuiting). The fix may also drop comments when rewriting some comprehensions.

        ","tags":["C419"]},{"location":"rules/unnecessary-comprehension/","title":"unnecessary-comprehension (C416)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C416"]},{"location":"rules/unnecessary-comprehension/#what-it-does","title":"What it does","text":"

        Checks for unnecessary dict, list, and set comprehension.

        ","tags":["C416"]},{"location":"rules/unnecessary-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a dict/list/set comprehension to build a data structure if the elements are unchanged. Wrap the iterable with dict(), list(), or set() instead.

        ","tags":["C416"]},{"location":"rules/unnecessary-comprehension/#example","title":"Example","text":"
        {a: b for a, b in iterable}\n[x for x in iterable]\n{x for x in iterable}\n

        Use instead:

        dict(iterable)\nlist(iterable)\nset(iterable)\n
        ","tags":["C416"]},{"location":"rules/unnecessary-comprehension/#known-problems","title":"Known problems","text":"

        This rule may produce false positives for dictionary comprehensions that iterate over a mapping. The dict constructor behaves differently depending on if it receives a sequence (e.g., a list) or a mapping (e.g., a dict). When a comprehension iterates over the keys of a mapping, replacing it with a dict() constructor call will give a different result.

        For example:

        >>> d1 = {(1, 2): 3, (4, 5): 6}\n>>> {x: y for x, y in d1}  # Iterates over the keys of a mapping\n{1: 2, 4: 5}\n>>> dict(d1)               # Ruff's incorrect suggested fix\n(1, 2): 3, (4, 5): 6}\n>>> dict(d1.keys())        # Correct fix\n{1: 2, 4: 5}\n

        When the comprehension iterates over a sequence, Ruff's suggested fix is correct. However, Ruff cannot consistently infer if the iterable type is a sequence or a mapping and cannot suggest the correct fix for mappings.

        ","tags":["C416"]},{"location":"rules/unnecessary-comprehension/#fix-safety","title":"Fix safety","text":"

        Due to the known problem with dictionary comprehensions, this fix is marked as unsafe.

        Additionally, this fix may drop comments when rewriting the comprehension.

        ","tags":["C416"]},{"location":"rules/unnecessary-default-type-args/","title":"unnecessary-default-type-args (UP043)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#what-it-does","title":"What it does","text":"

        Checks for unnecessary default type arguments for Generator and AsyncGenerator on Python 3.13+.

        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#why-is-this-bad","title":"Why is this bad?","text":"

        Python 3.13 introduced the ability for type parameters to specify default values. Following this change, several standard-library classes were updated to add default values for some of their type parameters. For example, Generator[int] is now equivalent to Generator[int, None, None], as the second and third type parameters of Generator now default to None.

        Omitting type arguments that match the default values can make the code more concise and easier to read.

        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#example","title":"Example","text":"
        from collections.abc import Generator, AsyncGenerator\n\n\ndef sync_gen() -> Generator[int, None, None]:\n    yield 42\n\n\nasync def async_gen() -> AsyncGenerator[int, None]:\n    yield 42\n

        Use instead:

        from collections.abc import Generator, AsyncGenerator\n\n\ndef sync_gen() -> Generator[int]:\n    yield 42\n\n\nasync def async_gen() -> AsyncGenerator[int]:\n    yield 42\n
        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the type annotation contains comments.

        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#options","title":"Options","text":"
        • target-version
        ","tags":["UP043"]},{"location":"rules/unnecessary-default-type-args/#references","title":"References","text":"
        • PEP 696 \u2013 Type Defaults for Type Parameters
        • Annotating generators and coroutines
        • Python documentation: typing.Generator
        • Python documentation: typing.AsyncGenerator
        ","tags":["UP043"]},{"location":"rules/unnecessary-dict-comprehension-for-iterable/","title":"unnecessary-dict-comprehension-for-iterable (C420)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is sometimes available.

        ","tags":["C420"]},{"location":"rules/unnecessary-dict-comprehension-for-iterable/#what-it-does","title":"What it does","text":"

        Checks for unnecessary dict comprehension when creating a dictionary from an iterable.

        ","tags":["C420"]},{"location":"rules/unnecessary-dict-comprehension-for-iterable/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a dict comprehension to build a dictionary from an iterable when the value is static.

        Prefer dict.fromkeys(iterable) over {value: None for value in iterable}, as dict.fromkeys is more readable and efficient.

        ","tags":["C420"]},{"location":"rules/unnecessary-dict-comprehension-for-iterable/#example","title":"Example","text":"
        {a: None for a in iterable}\n{a: 1 for a in iterable}\n

        Use instead:

        dict.fromkeys(iterable)\ndict.fromkeys(iterable, 1)\n
        ","tags":["C420"]},{"location":"rules/unnecessary-dict-comprehension-for-iterable/#references","title":"References","text":"
        • Python documentation: dict.fromkeys
        ","tags":["C420"]},{"location":"rules/unnecessary-dict-index-lookup/","title":"unnecessary-dict-index-lookup (PLR1733)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLR1733"]},{"location":"rules/unnecessary-dict-index-lookup/#what-it-does","title":"What it does","text":"

        Checks for key-based dict accesses during .items() iterations.

        ","tags":["PLR1733"]},{"location":"rules/unnecessary-dict-index-lookup/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over a dict via .items(), the current value is already available alongside its key. Using the key to look up the value is unnecessary.

        ","tags":["PLR1733"]},{"location":"rules/unnecessary-dict-index-lookup/#example","title":"Example","text":"
        FRUITS = {\"apple\": 1, \"orange\": 10, \"berry\": 22}\n\nfor fruit_name, fruit_count in FRUITS.items():\n    print(FRUITS[fruit_name])\n

        Use instead:

        FRUITS = {\"apple\": 1, \"orange\": 10, \"berry\": 22}\n\nfor fruit_name, fruit_count in FRUITS.items():\n    print(fruit_count)\n
        ","tags":["PLR1733"]},{"location":"rules/unnecessary-dict-kwargs/","title":"unnecessary-dict-kwargs (PIE804)","text":"

        Derived from the flake8-pie linter.

        Fix is sometimes available.

        ","tags":["PIE804"]},{"location":"rules/unnecessary-dict-kwargs/#what-it-does","title":"What it does","text":"

        Checks for unnecessary dict kwargs.

        ","tags":["PIE804"]},{"location":"rules/unnecessary-dict-kwargs/#why-is-this-bad","title":"Why is this bad?","text":"

        If the dict keys are valid identifiers, they can be passed as keyword arguments directly.

        ","tags":["PIE804"]},{"location":"rules/unnecessary-dict-kwargs/#example","title":"Example","text":"
        def foo(bar):\n    return bar + 1\n\n\nprint(foo(**{\"bar\": 2}))  # prints 3\n

        Use instead:

        def foo(bar):\n    return bar + 1\n\n\nprint(foo(bar=2))  # prints 3\n
        ","tags":["PIE804"]},{"location":"rules/unnecessary-dict-kwargs/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for dictionaries with comments interleaved between the items, as comments may be removed.

        For example, the fix would be marked as unsafe in the following case:

        foo(\n    **{\n        # comment\n        \"x\": 1.0,\n        # comment\n        \"y\": 2.0,\n    }\n)\n

        as this is converted to foo(x=1.0, y=2.0) without any of the comments.

        ","tags":["PIE804"]},{"location":"rules/unnecessary-dict-kwargs/#references","title":"References","text":"
        • Python documentation: Dictionary displays
        • Python documentation: Calls
        ","tags":["PIE804"]},{"location":"rules/unnecessary-direct-lambda-call/","title":"unnecessary-direct-lambda-call (PLC3002)","text":"

        Derived from the Pylint linter.

        ","tags":["PLC3002"]},{"location":"rules/unnecessary-direct-lambda-call/#what-it-does","title":"What it does","text":"

        Checks for unnecessary direct calls to lambda expressions.

        ","tags":["PLC3002"]},{"location":"rules/unnecessary-direct-lambda-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling a lambda expression directly is unnecessary. The expression can be executed inline instead to improve readability.

        ","tags":["PLC3002"]},{"location":"rules/unnecessary-direct-lambda-call/#example","title":"Example","text":"
        area = (lambda r: 3.14 * r**2)(radius)\n

        Use instead:

        area = 3.14 * radius**2\n
        ","tags":["PLC3002"]},{"location":"rules/unnecessary-direct-lambda-call/#references","title":"References","text":"
        • Python documentation: Lambdas
        ","tags":["PLC3002"]},{"location":"rules/unnecessary-double-cast-or-process/","title":"unnecessary-double-cast-or-process (C414)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C414"]},{"location":"rules/unnecessary-double-cast-or-process/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list(), reversed(), set(), sorted(), and tuple() call within list(), set(), sorted(), and tuple() calls.

        ","tags":["C414"]},{"location":"rules/unnecessary-double-cast-or-process/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to double-cast or double-process iterables by wrapping the listed functions within an additional list(), set(), sorted(), or tuple() call. Doing so is redundant and can be confusing for readers.

        ","tags":["C414"]},{"location":"rules/unnecessary-double-cast-or-process/#example","title":"Example","text":"
        list(tuple(iterable))\n

        Use instead:

        list(iterable)\n

        This rule applies to a variety of functions, including list(), reversed(), set(), sorted(), and tuple(). For example:

        • Instead of list(list(iterable)), use list(iterable).
        • Instead of list(tuple(iterable)), use list(iterable).
        • Instead of tuple(list(iterable)), use tuple(iterable).
        • Instead of tuple(tuple(iterable)), use tuple(iterable).
        • Instead of set(set(iterable)), use set(iterable).
        • Instead of set(list(iterable)), use set(iterable).
        • Instead of set(tuple(iterable)), use set(iterable).
        • Instead of set(sorted(iterable)), use set(iterable).
        • Instead of set(reversed(iterable)), use set(iterable).
        • Instead of sorted(list(iterable)), use sorted(iterable).
        • Instead of sorted(tuple(iterable)), use sorted(iterable).
        • Instead of sorted(sorted(iterable)), use sorted(iterable).
        • Instead of sorted(reversed(iterable)), use sorted(iterable).
        ","tags":["C414"]},{"location":"rules/unnecessary-double-cast-or-process/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C414"]},{"location":"rules/unnecessary-dunder-call/","title":"unnecessary-dunder-call (PLC2801)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLC2801"]},{"location":"rules/unnecessary-dunder-call/#what-it-does","title":"What it does","text":"

        Checks for explicit use of dunder methods, like __str__ and __add__.

        ","tags":["PLC2801"]},{"location":"rules/unnecessary-dunder-call/#why-is-this-bad","title":"Why is this bad?","text":"

        Dunder names are not meant to be called explicitly and, in most cases, can be replaced with builtins or operators.

        ","tags":["PLC2801"]},{"location":"rules/unnecessary-dunder-call/#fix-safety","title":"Fix safety","text":"

        This fix is always unsafe. When replacing dunder method calls with operators or builtins, the behavior can change in the following ways:

        1. Types may implement only a subset of related dunder methods. Calling a missing dunder method directly returns NotImplemented, but using the equivalent operator raises a TypeError.

          class C: pass\nc = C()\nc.__gt__(1)  # before fix: NotImplemented\nc > 1        # after fix: raises TypeError\n
        2. Instance-assigned dunder methods are ignored by operators and builtins.

          class C: pass\nc = C()\nc.__bool__ = lambda: False\nc.__bool__() # before fix: False\nbool(c)      # after fix: True\n
        3. Even with built-in types, behavior can differ.

          (1).__gt__(1.0)  # before fix: NotImplemented\n1 > 1.0          # after fix: False\n
        ","tags":["PLC2801"]},{"location":"rules/unnecessary-dunder-call/#example","title":"Example","text":"
        three = (3.0).__str__()\ntwelve = \"1\".__add__(\"2\")\n\n\ndef is_greater_than_two(x: int) -> bool:\n    return x.__gt__(2)\n

        Use instead:

        three = str(3.0)\ntwelve = \"1\" + \"2\"\n\n\ndef is_greater_than_two(x: int) -> bool:\n    return x > 2\n
        ","tags":["PLC2801"]},{"location":"rules/unnecessary-empty-iterable-within-deque-call/","title":"unnecessary-empty-iterable-within-deque-call (RUF037)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF037"]},{"location":"rules/unnecessary-empty-iterable-within-deque-call/#what-it-does","title":"What it does","text":"

        Checks for usages of collections.deque that have an empty iterable as the first argument.

        ","tags":["RUF037"]},{"location":"rules/unnecessary-empty-iterable-within-deque-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use an empty literal as a deque's iterable, since this is already the default behavior.

        ","tags":["RUF037"]},{"location":"rules/unnecessary-empty-iterable-within-deque-call/#example","title":"Example","text":"
        from collections import deque\n\nqueue = deque(set())\nqueue = deque([], 10)\n

        Use instead:

        from collections import deque\n\nqueue = deque()\nqueue = deque(maxlen=10)\n
        ","tags":["RUF037"]},{"location":"rules/unnecessary-empty-iterable-within-deque-call/#references","title":"References","text":"
        • Python documentation: collections.deque
        ","tags":["RUF037"]},{"location":"rules/unnecessary-encode-utf8/","title":"unnecessary-encode-utf8 (UP012)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP012"]},{"location":"rules/unnecessary-encode-utf8/#what-it-does","title":"What it does","text":"

        Checks for unnecessary calls to encode as UTF-8.

        ","tags":["UP012"]},{"location":"rules/unnecessary-encode-utf8/#why-is-this-bad","title":"Why is this bad?","text":"

        UTF-8 is the default encoding in Python, so there is no need to call encode when UTF-8 is the desired encoding. Instead, use a bytes literal.

        ","tags":["UP012"]},{"location":"rules/unnecessary-encode-utf8/#example","title":"Example","text":"
        \"foo\".encode(\"utf-8\")\n

        Use instead:

        b\"foo\"\n
        ","tags":["UP012"]},{"location":"rules/unnecessary-encode-utf8/#references","title":"References","text":"
        • Python documentation: str.encode
        ","tags":["UP012"]},{"location":"rules/unnecessary-enumerate/","title":"unnecessary-enumerate (FURB148)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB148"]},{"location":"rules/unnecessary-enumerate/#what-it-does","title":"What it does","text":"

        Checks for uses of enumerate that discard either the index or the value when iterating over a sequence.

        ","tags":["FURB148"]},{"location":"rules/unnecessary-enumerate/#why-is-this-bad","title":"Why is this bad?","text":"

        The built-in enumerate function is useful when you need both the index and value of a sequence.

        If you only need the index or values of a sequence, you should iterate over range(len(...)) or the sequence itself, respectively, instead. This is more efficient and communicates the intent of the code more clearly.

        ","tags":["FURB148"]},{"location":"rules/unnecessary-enumerate/#known-problems","title":"Known problems","text":"

        This rule is prone to false negatives due to type inference limitations; namely, it will only suggest a fix using the len builtin function if the sequence passed to enumerate is an instantiated as a list, set, dict, or tuple literal, or annotated as such with a type annotation.

        The len builtin function is not defined for all object types (such as generators), and so refactoring to use len over enumerate is not always safe.

        ","tags":["FURB148"]},{"location":"rules/unnecessary-enumerate/#example","title":"Example","text":"
        for index, _ in enumerate(sequence):\n    print(index)\n\nfor _, value in enumerate(sequence):\n    print(value)\n

        Use instead:

        for index in range(len(sequence)):\n    print(index)\n\nfor value in sequence:\n    print(value)\n
        ","tags":["FURB148"]},{"location":"rules/unnecessary-enumerate/#references","title":"References","text":"
        • Python documentation: enumerate
        • Python documentation: range
        • Python documentation: len
        ","tags":["FURB148"]},{"location":"rules/unnecessary-escaped-quote/","title":"unnecessary-escaped-quote (Q004)","text":"

        Derived from the flake8-quotes linter.

        Fix is always available.

        ","tags":["Q004"]},{"location":"rules/unnecessary-escaped-quote/#what-it-does","title":"What it does","text":"

        Checks for strings that include unnecessarily escaped quotes.

        ","tags":["Q004"]},{"location":"rules/unnecessary-escaped-quote/#why-is-this-bad","title":"Why is this bad?","text":"

        If a string contains an escaped quote that doesn't match the quote character used for the string, it's unnecessary and can be removed.

        ","tags":["Q004"]},{"location":"rules/unnecessary-escaped-quote/#example","title":"Example","text":"
        foo = \"bar\\'s\"\n

        Use instead:

        foo = \"bar's\"\n
        ","tags":["Q004"]},{"location":"rules/unnecessary-escaped-quote/#formatter-compatibility","title":"Formatter compatibility","text":"

        We recommend against using this rule alongside the formatter. The formatter automatically removes unnecessary escapes, making the rule redundant.

        ","tags":["Q004"]},{"location":"rules/unnecessary-from-float/","title":"unnecessary-from-float (FURB164)","text":"

        Derived from the refurb linter.

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB164"]},{"location":"rules/unnecessary-from-float/#what-it-does","title":"What it does","text":"

        Checks for unnecessary from_float and from_decimal usages to construct Decimal and Fraction instances.

        ","tags":["FURB164"]},{"location":"rules/unnecessary-from-float/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3.2, the Fraction and Decimal classes can be constructed by passing float or decimal instances to the constructor directly. As such, the use of from_float and from_decimal methods is unnecessary, and should be avoided in favor of the more concise constructor syntax.

        ","tags":["FURB164"]},{"location":"rules/unnecessary-from-float/#example","title":"Example","text":"
        Decimal.from_float(4.2)\nDecimal.from_float(float(\"inf\"))\nFraction.from_float(4.2)\nFraction.from_decimal(Decimal(\"4.2\"))\n

        Use instead:

        Decimal(4.2)\nDecimal(\"inf\")\nFraction(4.2)\nFraction(Decimal(4.2))\n
        ","tags":["FURB164"]},{"location":"rules/unnecessary-from-float/#references","title":"References","text":"
        • Python documentation: decimal
        • Python documentation: fractions
        ","tags":["FURB164"]},{"location":"rules/unnecessary-future-import/","title":"unnecessary-future-import (UP010)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP010"]},{"location":"rules/unnecessary-future-import/#what-it-does","title":"What it does","text":"

        Checks for unnecessary __future__ imports.

        ","tags":["UP010"]},{"location":"rules/unnecessary-future-import/#why-is-this-bad","title":"Why is this bad?","text":"

        The __future__ module is used to enable features that are not yet available in the current Python version. If a feature is already available in the minimum supported Python version, importing it from __future__ is unnecessary and should be removed to avoid confusion.

        ","tags":["UP010"]},{"location":"rules/unnecessary-future-import/#example","title":"Example","text":"
        from __future__ import print_function\n\nprint(\"Hello, world!\")\n

        Use instead:

        print(\"Hello, world!\")\n
        ","tags":["UP010"]},{"location":"rules/unnecessary-future-import/#options","title":"Options","text":"
        • target-version
        ","tags":["UP010"]},{"location":"rules/unnecessary-future-import/#references","title":"References","text":"
        • Python documentation: __future__ \u2014 Future statement definitions
        ","tags":["UP010"]},{"location":"rules/unnecessary-generator-dict/","title":"unnecessary-generator-dict (C402)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C402"]},{"location":"rules/unnecessary-generator-dict/#what-it-does","title":"What it does","text":"

        Checks for unnecessary generators that can be rewritten as dict comprehensions.

        ","tags":["C402"]},{"location":"rules/unnecessary-generator-dict/#why-is-this-bad","title":"Why is this bad?","text":"

        It is unnecessary to use dict() around a generator expression, since there are equivalent comprehensions for these types. Using a comprehension is clearer and more idiomatic.

        ","tags":["C402"]},{"location":"rules/unnecessary-generator-dict/#example","title":"Example","text":"
        dict((x, f(x)) for x in foo)\n

        Use instead:

        {x: f(x) for x in foo}\n
        ","tags":["C402"]},{"location":"rules/unnecessary-generator-dict/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C402"]},{"location":"rules/unnecessary-generator-list/","title":"unnecessary-generator-list (C400)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C400"]},{"location":"rules/unnecessary-generator-list/#what-it-does","title":"What it does","text":"

        Checks for unnecessary generators that can be rewritten as list comprehensions (or with list() directly).

        ","tags":["C400"]},{"location":"rules/unnecessary-generator-list/#why-is-this-bad","title":"Why is this bad?","text":"

        It is unnecessary to use list() around a generator expression, since there are equivalent comprehensions for these types. Using a comprehension is clearer and more idiomatic.

        Further, if the comprehension can be removed entirely, as in the case of list(x for x in foo), it's better to use list(foo) directly, since it's even more direct.

        ","tags":["C400"]},{"location":"rules/unnecessary-generator-list/#example","title":"Example","text":"
        list(f(x) for x in foo)\nlist(x for x in foo)\nlist((x for x in foo))\n

        Use instead:

        [f(x) for x in foo]\nlist(foo)\nlist(foo)\n
        ","tags":["C400"]},{"location":"rules/unnecessary-generator-list/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C400"]},{"location":"rules/unnecessary-generator-set/","title":"unnecessary-generator-set (C401)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C401"]},{"location":"rules/unnecessary-generator-set/#what-it-does","title":"What it does","text":"

        Checks for unnecessary generators that can be rewritten as set comprehensions (or with set() directly).

        ","tags":["C401"]},{"location":"rules/unnecessary-generator-set/#why-is-this-bad","title":"Why is this bad?","text":"

        It is unnecessary to use set around a generator expression, since there are equivalent comprehensions for these types. Using a comprehension is clearer and more idiomatic.

        Further, if the comprehension can be removed entirely, as in the case of set(x for x in foo), it's better to use set(foo) directly, since it's even more direct.

        ","tags":["C401"]},{"location":"rules/unnecessary-generator-set/#example","title":"Example","text":"
        set(f(x) for x in foo)\nset(x for x in foo)\nset((x for x in foo))\n

        Use instead:

        {f(x) for x in foo}\nset(foo)\nset(foo)\n
        ","tags":["C401"]},{"location":"rules/unnecessary-generator-set/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C401"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/","title":"unnecessary-iterable-allocation-for-first-element (RUF015)","text":"

        Fix is always available.

        ","tags":["RUF015"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/#what-it-does","title":"What it does","text":"

        Checks the following constructs, all of which can be replaced by next(iter(...)):

        • list(...)[0]
        • tuple(...)[0]
        • list(i for i in ...)[0]
        • [i for i in ...][0]
        • list(...).pop(0)
        ","tags":["RUF015"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/#why-is-this-bad","title":"Why is this bad?","text":"

        Calling e.g. list(...) will create a new list of the entire collection, which can be very expensive for large collections. If you only need the first element of the collection, you can use next(...) or next(iter(...) to lazily fetch the first element. The same is true for the other constructs.

        ","tags":["RUF015"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/#example","title":"Example","text":"
        head = list(x)[0]\nhead = [x * x for x in range(10)][0]\n

        Use instead:

        head = next(iter(x))\nhead = next(x * x for x in range(10))\n
        ","tags":["RUF015"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as migrating from (e.g.) list(...)[0] to next(iter(...)) can change the behavior of your program in two ways:

        1. First, all above-mentioned constructs will eagerly evaluate the entire collection, while next(iter(...)) will only evaluate the first element. As such, any side effects that occur during iteration will be delayed.
        2. Second, accessing members of a collection via square bracket notation [0] of the pop() function will raise IndexError if the collection is empty, while next(iter(...)) will raise StopIteration.
        ","tags":["RUF015"]},{"location":"rules/unnecessary-iterable-allocation-for-first-element/#references","title":"References","text":"
        • Iterators and Iterables in Python: Run Efficient Iterations
        ","tags":["RUF015"]},{"location":"rules/unnecessary-key-check/","title":"unnecessary-key-check (RUF019)","text":"

        Fix is always available.

        ","tags":["RUF019"]},{"location":"rules/unnecessary-key-check/#what-it-does","title":"What it does","text":"

        Checks for unnecessary key checks prior to accessing a dictionary.

        ","tags":["RUF019"]},{"location":"rules/unnecessary-key-check/#why-is-this-bad","title":"Why is this bad?","text":"

        When working with dictionaries, the get can be used to access a value without having to check if the dictionary contains the relevant key, returning None if the key is not present.

        ","tags":["RUF019"]},{"location":"rules/unnecessary-key-check/#example","title":"Example","text":"
        if \"key\" in dct and dct[\"key\"]:\n    ...\n

        Use instead:

        if dct.get(\"key\"):\n    ...\n
        ","tags":["RUF019"]},{"location":"rules/unnecessary-lambda/","title":"unnecessary-lambda (PLW0108)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW0108"]},{"location":"rules/unnecessary-lambda/#what-it-does","title":"What it does","text":"

        Checks for lambda definitions that consist of a single function call with the same arguments as the lambda itself.

        ","tags":["PLW0108"]},{"location":"rules/unnecessary-lambda/#why-is-this-bad","title":"Why is this bad?","text":"

        When a lambda is used to wrap a function call, and merely propagates the lambda arguments to that function, it can typically be replaced with the function itself, removing a level of indirection.

        ","tags":["PLW0108"]},{"location":"rules/unnecessary-lambda/#example","title":"Example","text":"
        df.apply(lambda x: str(x))\n

        Use instead:

        df.apply(str)\n
        ","tags":["PLW0108"]},{"location":"rules/unnecessary-lambda/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for two primary reasons.

        First, the lambda body itself could contain an effect.

        For example, replacing lambda x, y: (func()(x, y)) with func() would lead to a change in behavior, as func() would be evaluated eagerly when defining the lambda, rather than when the lambda is called.

        However, even when the lambda body itself is pure, the lambda may change the argument names, which can lead to a change in behavior when callers pass arguments by name.

        For example, replacing foo = lambda x, y: func(x, y) with foo = func, where func is defined as def func(a, b): return a + b, would be a breaking change for callers that execute the lambda by passing arguments by name, as in: foo(x=1, y=2). Since func does not define the arguments x and y, unlike the lambda, the call would raise a TypeError.

        ","tags":["PLW0108"]},{"location":"rules/unnecessary-list-call/","title":"unnecessary-list-call (C411)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C411"]},{"location":"rules/unnecessary-list-call/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list() calls around list comprehensions.

        ","tags":["C411"]},{"location":"rules/unnecessary-list-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It is redundant to use a list() call around a list comprehension.

        ","tags":["C411"]},{"location":"rules/unnecessary-list-call/#example","title":"Example","text":"
        list([f(x) for x in foo])\n

        Use instead

        [f(x) for x in foo]\n
        ","tags":["C411"]},{"location":"rules/unnecessary-list-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C411"]},{"location":"rules/unnecessary-list-cast/","title":"unnecessary-list-cast (PERF101)","text":"

        Derived from the Perflint linter.

        Fix is always available.

        ","tags":["PERF101"]},{"location":"rules/unnecessary-list-cast/#what-it-does","title":"What it does","text":"

        Checks for explicit casts to list on for-loop iterables.

        ","tags":["PERF101"]},{"location":"rules/unnecessary-list-cast/#why-is-this-bad","title":"Why is this bad?","text":"

        Using a list() call to eagerly iterate over an already-iterable type (like a tuple, list, or set) is inefficient, as it forces Python to create a new list unnecessarily.

        Removing the list() call will not change the behavior of the code, but may improve performance.

        Note that, as with all perflint rules, this is only intended as a micro-optimization, and will have a negligible impact on performance in most cases.

        ","tags":["PERF101"]},{"location":"rules/unnecessary-list-cast/#example","title":"Example","text":"
        items = (1, 2, 3)\nfor i in list(items):\n    print(i)\n

        Use instead:

        items = (1, 2, 3)\nfor i in items:\n    print(i)\n
        ","tags":["PERF101"]},{"location":"rules/unnecessary-list-comprehension-dict/","title":"unnecessary-list-comprehension-dict (C404)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C404"]},{"location":"rules/unnecessary-list-comprehension-dict/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list comprehensions.

        ","tags":["C404"]},{"location":"rules/unnecessary-list-comprehension-dict/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list comprehension inside a call to dict(), since there is an equivalent comprehension for this type.

        ","tags":["C404"]},{"location":"rules/unnecessary-list-comprehension-dict/#example","title":"Example","text":"
        dict([(x, f(x)) for x in foo])\n

        Use instead:

        {x: f(x) for x in foo}\n
        ","tags":["C404"]},{"location":"rules/unnecessary-list-comprehension-dict/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C404"]},{"location":"rules/unnecessary-list-comprehension-set/","title":"unnecessary-list-comprehension-set (C403)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C403"]},{"location":"rules/unnecessary-list-comprehension-set/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list comprehensions.

        ","tags":["C403"]},{"location":"rules/unnecessary-list-comprehension-set/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list comprehension inside a call to set(), since there is an equivalent comprehension for this type.

        ","tags":["C403"]},{"location":"rules/unnecessary-list-comprehension-set/#example","title":"Example","text":"
        set([f(x) for x in foo])\n

        Use instead:

        {f(x) for x in foo}\n
        ","tags":["C403"]},{"location":"rules/unnecessary-list-comprehension-set/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C403"]},{"location":"rules/unnecessary-list-index-lookup/","title":"unnecessary-list-index-lookup (PLR1736)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLR1736"]},{"location":"rules/unnecessary-list-index-lookup/#what-it-does","title":"What it does","text":"

        Checks for index-based list accesses during enumerate iterations.

        ","tags":["PLR1736"]},{"location":"rules/unnecessary-list-index-lookup/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over a list with enumerate, the current item is already available alongside its index. Using the index to look up the item is unnecessary.

        ","tags":["PLR1736"]},{"location":"rules/unnecessary-list-index-lookup/#example","title":"Example","text":"
        letters = [\"a\", \"b\", \"c\"]\n\nfor index, letter in enumerate(letters):\n    print(letters[index])\n

        Use instead:

        letters = [\"a\", \"b\", \"c\"]\n\nfor index, letter in enumerate(letters):\n    print(letter)\n
        ","tags":["PLR1736"]},{"location":"rules/unnecessary-literal-dict/","title":"unnecessary-literal-dict (C406)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C406"]},{"location":"rules/unnecessary-literal-dict/#what-it-does","title":"What it does","text":"

        Checks for unnecessary list or tuple literals.

        ","tags":["C406"]},{"location":"rules/unnecessary-literal-dict/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list or tuple literal within a call to dict(). It can be rewritten as a dict literal ({}).

        ","tags":["C406"]},{"location":"rules/unnecessary-literal-dict/#example","title":"Example","text":"
        dict([(1, 2), (3, 4)])\ndict(((1, 2), (3, 4)))\ndict([])\n

        Use instead:

        {1: 2, 3: 4}\n{1: 2, 3: 4}\n{}\n
        ","tags":["C406"]},{"location":"rules/unnecessary-literal-dict/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C406"]},{"location":"rules/unnecessary-literal-set/","title":"unnecessary-literal-set (C405)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C405"]},{"location":"rules/unnecessary-literal-set/#what-it-does","title":"What it does","text":"

        Checks for set() calls that take unnecessary list or tuple literals as arguments.

        ","tags":["C405"]},{"location":"rules/unnecessary-literal-set/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list or tuple literal within a call to set(). Instead, the expression can be rewritten as a set literal.

        ","tags":["C405"]},{"location":"rules/unnecessary-literal-set/#example","title":"Example","text":"
        set([1, 2])\nset((1, 2))\nset([])\n

        Use instead:

        {1, 2}\n{1, 2}\nset()\n
        ","tags":["C405"]},{"location":"rules/unnecessary-literal-set/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C405"]},{"location":"rules/unnecessary-literal-union/","title":"unnecessary-literal-union (PYI030)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-union/#what-it-does","title":"What it does","text":"

        Checks for the presence of multiple literal types in a union.

        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-union/#why-is-this-bad","title":"Why is this bad?","text":"

        Literal[\"foo\", 42] has identical semantics to Literal[\"foo\"] | Literal[42], but is clearer and more concise.

        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-union/#example","title":"Example","text":"
        from typing import Literal\n\nfield: Literal[1] | Literal[2] | str\n

        Use instead:

        from typing import Literal\n\nfield: Literal[1, 2] | str\n
        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-union/#fix-safety","title":"Fix safety","text":"

        This fix is marked unsafe if it would delete any comments within the replacement range.

        An example to illustrate where comments are preserved and where they are not:

        from typing import Literal\n\nfield: (\n    # deleted comment\n    Literal[\"a\", \"b\"]  # deleted comment\n    # deleted comment\n    | Literal[\"c\", \"d\"]  # preserved comment\n)\n
        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-union/#references","title":"References","text":"
        • Python documentation: typing.Literal
        ","tags":["PYI030"]},{"location":"rules/unnecessary-literal-within-dict-call/","title":"unnecessary-literal-within-dict-call (C418)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C418"]},{"location":"rules/unnecessary-literal-within-dict-call/#what-it-does","title":"What it does","text":"

        Checks for dict() calls that take unnecessary dict literals or dict comprehensions as arguments.

        ","tags":["C418"]},{"location":"rules/unnecessary-literal-within-dict-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to wrap a dict literal or comprehension within a dict() call, since the literal or comprehension syntax already returns a dictionary.

        ","tags":["C418"]},{"location":"rules/unnecessary-literal-within-dict-call/#example","title":"Example","text":"
        dict({})\ndict({\"a\": 1})\n

        Use instead:

        {}\n{\"a\": 1}\n
        ","tags":["C418"]},{"location":"rules/unnecessary-literal-within-dict-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C418"]},{"location":"rules/unnecessary-literal-within-list-call/","title":"unnecessary-literal-within-list-call (C410)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C410"]},{"location":"rules/unnecessary-literal-within-list-call/#what-it-does","title":"What it does","text":"

        Checks for list() calls that take unnecessary list or tuple literals as arguments.

        ","tags":["C410"]},{"location":"rules/unnecessary-literal-within-list-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list or tuple literal within a list() call, since there is a literal syntax for these types.

        If a list literal is passed in, then the outer call to list() should be removed. Otherwise, if a tuple literal is passed in, then it should be rewritten as a list literal.

        ","tags":["C410"]},{"location":"rules/unnecessary-literal-within-list-call/#example","title":"Example","text":"
        list([1, 2])\nlist((1, 2))\n

        Use instead:

        [1, 2]\n[1, 2]\n
        ","tags":["C410"]},{"location":"rules/unnecessary-literal-within-list-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C410"]},{"location":"rules/unnecessary-literal-within-tuple-call/","title":"unnecessary-literal-within-tuple-call (C409)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is always available.

        ","tags":["C409"]},{"location":"rules/unnecessary-literal-within-tuple-call/#what-it-does","title":"What it does","text":"

        Checks for tuple calls that take unnecessary list or tuple literals as arguments. In preview, this also includes unnecessary list comprehensions within tuple calls.

        ","tags":["C409"]},{"location":"rules/unnecessary-literal-within-tuple-call/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to use a list or tuple literal within a tuple() call, since there is a literal syntax for these types.

        If a list literal was passed, then it should be rewritten as a tuple literal. Otherwise, if a tuple literal was passed, then the outer call to tuple() should be removed.

        In preview, this rule also checks for list comprehensions within tuple() calls. If a list comprehension is found, it should be rewritten as a generator expression.

        ","tags":["C409"]},{"location":"rules/unnecessary-literal-within-tuple-call/#example","title":"Example","text":"
        tuple([1, 2])\ntuple((1, 2))\ntuple([x for x in range(10)])\n

        Use instead:

        (1, 2)\n(1, 2)\ntuple(x for x in range(10))\n
        ","tags":["C409"]},{"location":"rules/unnecessary-literal-within-tuple-call/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C409"]},{"location":"rules/unnecessary-map/","title":"unnecessary-map (C417)","text":"

        Derived from the flake8-comprehensions linter.

        Fix is sometimes available.

        ","tags":["C417"]},{"location":"rules/unnecessary-map/#what-it-does","title":"What it does","text":"

        Checks for unnecessary map() calls with lambda functions.

        ","tags":["C417"]},{"location":"rules/unnecessary-map/#why-is-this-bad","title":"Why is this bad?","text":"

        Using map(func, iterable) when func is a lambda is slower than using a generator expression or a comprehension, as the latter approach avoids the function call overhead, in addition to being more readable.

        This rule also applies to map() calls within list(), set(), and dict() calls. For example:

        • Instead of list(map(lambda num: num * 2, nums)), use [num * 2 for num in nums].
        • Instead of set(map(lambda num: num % 2 == 0, nums)), use {num % 2 == 0 for num in nums}.
        • Instead of dict(map(lambda v: (v, v ** 2), values)), use {v: v ** 2 for v in values}.
        ","tags":["C417"]},{"location":"rules/unnecessary-map/#example","title":"Example","text":"
        map(lambda x: x + 1, iterable)\n

        Use instead:

        (x + 1 for x in iterable)\n
        ","tags":["C417"]},{"location":"rules/unnecessary-map/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it may occasionally drop comments when rewriting the call. In most cases, though, comments will be preserved.

        ","tags":["C417"]},{"location":"rules/unnecessary-multiline-docstring/","title":"unnecessary-multiline-docstring (D200)","text":"

        Derived from the pydocstyle linter.

        Fix is sometimes available.

        ","tags":["D200"]},{"location":"rules/unnecessary-multiline-docstring/#what-it-does","title":"What it does","text":"

        Checks for single-line docstrings that are broken across multiple lines.

        ","tags":["D200"]},{"location":"rules/unnecessary-multiline-docstring/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 257 recommends that docstrings that can fit on one line should be formatted on a single line, for consistency and readability.

        ","tags":["D200"]},{"location":"rules/unnecessary-multiline-docstring/#example","title":"Example","text":"
        def average(values: list[float]) -> float:\n    \"\"\"\n    Return the mean of the given values.\n    \"\"\"\n

        Use instead:

        def average(values: list[float]) -> float:\n    \"\"\"Return the mean of the given values.\"\"\"\n
        ","tags":["D200"]},{"location":"rules/unnecessary-multiline-docstring/#fix-safety","title":"Fix safety","text":"

        The fix is marked as unsafe because it could affect tools that parse docstrings, documentation generators, or custom introspection utilities that rely on specific docstring formatting.

        ","tags":["D200"]},{"location":"rules/unnecessary-multiline-docstring/#references","title":"References","text":"
        • PEP 257 \u2013 Docstring Conventions
        ","tags":["D200"]},{"location":"rules/unnecessary-nested-literal/","title":"unnecessary-nested-literal (RUF041)","text":"

        Fix is sometimes available.

        ","tags":["RUF041"]},{"location":"rules/unnecessary-nested-literal/#what-it-does","title":"What it does","text":"

        Checks for unnecessary nested Literal.

        ","tags":["RUF041"]},{"location":"rules/unnecessary-nested-literal/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefer using a single Literal, which is equivalent and more concise.

        Parameterization of literals by other literals is supported as an ergonomic feature as proposed in [PEP 586], to enable patterns such as:

        ReadOnlyMode         = Literal[\"r\", \"r+\"]\nWriteAndTruncateMode = Literal[\"w\", \"w+\", \"wt\", \"w+t\"]\nWriteNoTruncateMode  = Literal[\"r+\", \"r+t\"]\nAppendMode           = Literal[\"a\", \"a+\", \"at\", \"a+t\"]\n\nAllModes = Literal[ReadOnlyMode, WriteAndTruncateMode,\n                  WriteNoTruncateMode, AppendMode]\n

        As a consequence, type checkers also support nesting of literals which is less readable than a flat Literal:

        AllModes = Literal[Literal[\"r\", \"r+\"], Literal[\"w\", \"w+\", \"wt\", \"w+t\"],\n                  Literal[\"r+\", \"r+t\"], Literal[\"a\", \"a+\", \"at\", \"a+t\"]]\n
        ","tags":["RUF041"]},{"location":"rules/unnecessary-nested-literal/#example","title":"Example","text":"
        AllModes = Literal[\n    Literal[\"r\", \"r+\"],\n    Literal[\"w\", \"w+\", \"wt\", \"w+t\"],\n    Literal[\"r+\", \"r+t\"],\n    Literal[\"a\", \"a+\", \"at\", \"a+t\"],\n]\n

        Use instead:

        AllModes = Literal[\n    \"r\", \"r+\", \"w\", \"w+\", \"wt\", \"w+t\", \"r+\", \"r+t\", \"a\", \"a+\", \"at\", \"a+t\"\n]\n

        or assign the literal to a variable as in the first example.

        ","tags":["RUF041"]},{"location":"rules/unnecessary-nested-literal/#fix-safety","title":"Fix safety","text":"

        The fix for this rule is marked as unsafe when the Literal slice is split across multiple lines and some of the lines have trailing comments.

        ","tags":["RUF041"]},{"location":"rules/unnecessary-nested-literal/#references","title":"References","text":"
        • Typing documentation: Legal parameters for Literal at type check time

        PEP 586

        ","tags":["RUF041"]},{"location":"rules/unnecessary-paren-on-raise-exception/","title":"unnecessary-paren-on-raise-exception (RSE102)","text":"

        Derived from the flake8-raise linter.

        Fix is always available.

        ","tags":["RSE102"]},{"location":"rules/unnecessary-paren-on-raise-exception/#what-it-does","title":"What it does","text":"

        Checks for unnecessary parentheses on raised exceptions.

        ","tags":["RSE102"]},{"location":"rules/unnecessary-paren-on-raise-exception/#why-is-this-bad","title":"Why is this bad?","text":"

        If an exception is raised without any arguments, parentheses are not required, as the raise statement accepts either an exception instance or an exception class (which is then implicitly instantiated).

        Removing the parentheses makes the code more concise.

        ","tags":["RSE102"]},{"location":"rules/unnecessary-paren-on-raise-exception/#known-problems","title":"Known problems","text":"

        Parentheses can only be omitted if the exception is a class, as opposed to a function call. This rule isn't always capable of distinguishing between the two.

        For example, if you import a function module.get_exception from another module, and module.get_exception returns an exception object, this rule will incorrectly mark the parentheses in raise module.get_exception() as unnecessary.

        ","tags":["RSE102"]},{"location":"rules/unnecessary-paren-on-raise-exception/#example","title":"Example","text":"
        raise TypeError()\n

        Use instead:

        raise TypeError\n
        ","tags":["RSE102"]},{"location":"rules/unnecessary-paren-on-raise-exception/#references","title":"References","text":"
        • Python documentation: The raise statement
        ","tags":["RSE102"]},{"location":"rules/unnecessary-placeholder/","title":"unnecessary-placeholder (PIE790)","text":"

        Derived from the flake8-pie linter.

        Fix is always available.

        ","tags":["PIE790"]},{"location":"rules/unnecessary-placeholder/#what-it-does","title":"What it does","text":"

        Checks for unnecessary pass statements and ellipsis (...) literals in functions, classes, and other blocks.

        ","tags":["PIE790"]},{"location":"rules/unnecessary-placeholder/#why-is-this-bad","title":"Why is this bad?","text":"

        In Python, the pass statement and ellipsis (...) literal serve as placeholders, allowing for syntactically correct empty code blocks. The primary purpose of these nodes is to avoid syntax errors in situations where a statement or expression is syntactically required, but no code needs to be executed.

        If a pass or ellipsis is present in a code block that includes at least one other statement (even, e.g., a docstring), it is unnecessary and should be removed.

        ","tags":["PIE790"]},{"location":"rules/unnecessary-placeholder/#example","title":"Example","text":"
        def func():\n    \"\"\"Placeholder docstring.\"\"\"\n    pass\n

        Use instead:

        def func():\n    \"\"\"Placeholder docstring.\"\"\"\n

        Or, given:

        def func():\n    \"\"\"Placeholder docstring.\"\"\"\n    ...\n

        Use instead:

        def func():\n    \"\"\"Placeholder docstring.\"\"\"\n
        ","tags":["PIE790"]},{"location":"rules/unnecessary-placeholder/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe in the rare case that the pass or ellipsis is followed by a string literal, since removal of the placeholder would convert the subsequent string literal into a docstring.

        ","tags":["PIE790"]},{"location":"rules/unnecessary-placeholder/#references","title":"References","text":"
        • Python documentation: The pass statement
        ","tags":["PIE790"]},{"location":"rules/unnecessary-range-start/","title":"unnecessary-range-start (PIE808)","text":"

        Derived from the flake8-pie linter.

        Fix is always available.

        ","tags":["PIE808"]},{"location":"rules/unnecessary-range-start/#what-it-does","title":"What it does","text":"

        Checks for range calls with an unnecessary start argument.

        ","tags":["PIE808"]},{"location":"rules/unnecessary-range-start/#why-is-this-bad","title":"Why is this bad?","text":"

        range(0, x) is equivalent to range(x), as 0 is the default value for the start argument. Omitting the start argument makes the code more concise and idiomatic.

        ","tags":["PIE808"]},{"location":"rules/unnecessary-range-start/#example","title":"Example","text":"
        range(0, 3)\n

        Use instead:

        range(3)\n
        ","tags":["PIE808"]},{"location":"rules/unnecessary-range-start/#references","title":"References","text":"
        • Python documentation: range
        ","tags":["PIE808"]},{"location":"rules/unnecessary-regular-expression/","title":"unnecessary-regular-expression (RUF055)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#what-it-does","title":"What it does","text":"

        Checks for uses of the re module that can be replaced with builtin str methods.

        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#why-is-this-bad","title":"Why is this bad?","text":"

        Performing checks on strings directly can make the code simpler, may require less escaping, and will often be faster.

        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#example","title":"Example","text":"
        re.sub(\"abc\", \"\", s)\n

        Use instead:

        s.replace(\"abc\", \"\")\n
        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#details","title":"Details","text":"

        The rule reports the following calls when the first argument to the call is a plain string literal, and no additional flags are passed:

        • re.sub
        • re.match
        • re.search
        • re.fullmatch
        • re.split

        For re.sub, the repl (replacement) argument must also be a string literal, not a function. For re.match, re.search, and re.fullmatch, the return value must also be used only for its truth value.

        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe if the affected expression contains comments. Otherwise, the fix can be applied safely.

        ","tags":["RUF055"]},{"location":"rules/unnecessary-regular-expression/#references","title":"References","text":"
        • Python Regular Expression HOWTO: Common Problems - Use String Methods
        ","tags":["RUF055"]},{"location":"rules/unnecessary-return-none/","title":"unnecessary-return-none (RET501)","text":"

        Derived from the flake8-return linter.

        Fix is always available.

        ","tags":["RET501"]},{"location":"rules/unnecessary-return-none/#what-it-does","title":"What it does","text":"

        Checks for the presence of a return None statement when None is the only possible return value.

        ","tags":["RET501"]},{"location":"rules/unnecessary-return-none/#why-is-this-bad","title":"Why is this bad?","text":"

        Python implicitly assumes return None if an explicit return value is omitted. Therefore, explicitly returning None is redundant and should be avoided when it is the only possible return value across all code paths in a given function.

        ","tags":["RET501"]},{"location":"rules/unnecessary-return-none/#example","title":"Example","text":"
        def foo(bar):\n    if not bar:\n        return\n    return None\n

        Use instead:

        def foo(bar):\n    if not bar:\n        return\n    return\n
        ","tags":["RET501"]},{"location":"rules/unnecessary-round/","title":"unnecessary-round (RUF057)","text":"

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF057"]},{"location":"rules/unnecessary-round/#what-it-does","title":"What it does","text":"

        Checks for round() calls that have no effect on the input.

        ","tags":["RUF057"]},{"location":"rules/unnecessary-round/#why-is-this-bad","title":"Why is this bad?","text":"

        Rounding a value that's already an integer is unnecessary. It's clearer to use the value directly.

        ","tags":["RUF057"]},{"location":"rules/unnecessary-round/#example","title":"Example","text":"
        a = round(1, 0)\n

        Use instead:

        a = 1\n
        ","tags":["RUF057"]},{"location":"rules/unnecessary-round/#fix-safety","title":"Fix safety","text":"

        The fix is marked unsafe if it is not possible to guarantee that the first argument of round() is of type int, or if the fix deletes comments.

        ","tags":["RUF057"]},{"location":"rules/unnecessary-spread/","title":"unnecessary-spread (PIE800)","text":"

        Derived from the flake8-pie linter.

        Fix is sometimes available.

        ","tags":["PIE800"]},{"location":"rules/unnecessary-spread/#what-it-does","title":"What it does","text":"

        Checks for unnecessary dictionary unpacking operators (**).

        ","tags":["PIE800"]},{"location":"rules/unnecessary-spread/#why-is-this-bad","title":"Why is this bad?","text":"

        Unpacking a dictionary into another dictionary is redundant. The unpacking operator can be removed, making the code more readable.

        ","tags":["PIE800"]},{"location":"rules/unnecessary-spread/#example","title":"Example","text":"
        foo = {\"A\": 1, \"B\": 2}\nbar = {**foo, **{\"C\": 3}}\n

        Use instead:

        foo = {\"A\": 1, \"B\": 2}\nbar = {**foo, \"C\": 3}\n
        ","tags":["PIE800"]},{"location":"rules/unnecessary-spread/#references","title":"References","text":"
        • Python documentation: Dictionary displays
        ","tags":["PIE800"]},{"location":"rules/unnecessary-subscript-reversal/","title":"unnecessary-subscript-reversal (C415)","text":"

        Derived from the flake8-comprehensions linter.

        ","tags":["C415"]},{"location":"rules/unnecessary-subscript-reversal/#what-it-does","title":"What it does","text":"

        Checks for unnecessary subscript reversal of iterable.

        ","tags":["C415"]},{"location":"rules/unnecessary-subscript-reversal/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to reverse the order of an iterable when passing it into reversed(), set() or sorted() functions as they will change the order of the elements again.

        ","tags":["C415"]},{"location":"rules/unnecessary-subscript-reversal/#example","title":"Example","text":"
        sorted(iterable[::-1])\nset(iterable[::-1])\nreversed(iterable[::-1])\n

        Use instead:

        sorted(iterable)\nset(iterable)\niterable\n
        ","tags":["C415"]},{"location":"rules/unnecessary-type-union/","title":"unnecessary-type-union (PYI055)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI055"]},{"location":"rules/unnecessary-type-union/#what-it-does","title":"What it does","text":"

        Checks for the presence of multiple types in a union.

        ","tags":["PYI055"]},{"location":"rules/unnecessary-type-union/#why-is-this-bad","title":"Why is this bad?","text":"

        type[T | S] has identical semantics to type[T] | type[S] in a type annotation, but is cleaner and more concise.

        ","tags":["PYI055"]},{"location":"rules/unnecessary-type-union/#example","title":"Example","text":"
        field: type[int] | type[float] | str\n

        Use instead:

        field: type[int | float] | str\n
        ","tags":["PYI055"]},{"location":"rules/unnecessary-type-union/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as safe, unless the type annotation contains comments.

        Note that while the fix may flatten nested unions into a single top-level union, the semantics of the annotation will remain unchanged.

        ","tags":["PYI055"]},{"location":"rules/unpacked-list-comprehension/","title":"unpacked-list-comprehension (UP027)","text":"

        Derived from the pyupgrade linter.

        Warning: This rule has been removed and its documentation is only available for historical reasons.

        ","tags":["UP027"]},{"location":"rules/unpacked-list-comprehension/#removed","title":"Removed","text":"

        There's no evidence that generators are meaningfully faster than list comprehensions when combined with unpacking.

        ","tags":["UP027"]},{"location":"rules/unpacked-list-comprehension/#what-it-does","title":"What it does","text":"

        Checks for list comprehensions that are immediately unpacked.

        ","tags":["UP027"]},{"location":"rules/unpacked-list-comprehension/#why-is-this-bad","title":"Why is this bad?","text":"

        There is no reason to use a list comprehension if the result is immediately unpacked. Instead, use a generator expression, which avoids allocating an intermediary list.

        ","tags":["UP027"]},{"location":"rules/unpacked-list-comprehension/#example","title":"Example","text":"
        a, b, c = [foo(x) for x in items]\n

        Use instead:

        a, b, c = (foo(x) for x in items)\n
        ","tags":["UP027"]},{"location":"rules/unpacked-list-comprehension/#references","title":"References","text":"
        • Python documentation: Generator expressions
        • Python documentation: List comprehensions
        ","tags":["UP027"]},{"location":"rules/unprefixed-type-param/","title":"unprefixed-type-param (PYI001)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI001"]},{"location":"rules/unprefixed-type-param/#what-it-does","title":"What it does","text":"

        Checks that type TypeVars, ParamSpecs, and TypeVarTuples in stubs have names prefixed with _.

        ","tags":["PYI001"]},{"location":"rules/unprefixed-type-param/#why-is-this-bad","title":"Why is this bad?","text":"

        Prefixing type parameters with _ avoids accidentally exposing names internal to the stub.

        ","tags":["PYI001"]},{"location":"rules/unprefixed-type-param/#example","title":"Example","text":"
        from typing import TypeVar\n\nT = TypeVar(\"T\")\n

        Use instead:

        from typing import TypeVar\n\n_T = TypeVar(\"_T\")\n
        ","tags":["PYI001"]},{"location":"rules/unquoted-type-alias/","title":"unquoted-type-alias (TC007)","text":"

        Derived from the flake8-type-checking linter.

        Fix is sometimes available.

        ","tags":["TC007"]},{"location":"rules/unquoted-type-alias/#what-it-does","title":"What it does","text":"

        Checks if PEP 613 explicit type aliases contain references to symbols that are not available at runtime.

        ","tags":["TC007"]},{"location":"rules/unquoted-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        Referencing type-checking only symbols results in a NameError at runtime.

        ","tags":["TC007"]},{"location":"rules/unquoted-type-alias/#example","title":"Example","text":"
        from typing import TYPE_CHECKING, TypeAlias\n\nif TYPE_CHECKING:\n    from foo import Foo\nOptFoo: TypeAlias = Foo | None\n

        Use instead:

        from typing import TYPE_CHECKING, TypeAlias\n\nif TYPE_CHECKING:\n    from foo import Foo\nOptFoo: TypeAlias = \"Foo | None\"\n
        ","tags":["TC007"]},{"location":"rules/unquoted-type-alias/#fix-safety","title":"Fix safety","text":"

        This rule's fix is currently always marked as unsafe, since runtime typing libraries may try to access/resolve the type alias in a way that we can't statically determine during analysis and relies on the type alias not containing any forward references.

        ","tags":["TC007"]},{"location":"rules/unquoted-type-alias/#references","title":"References","text":"
        • PEP 613 \u2013 Explicit Type Aliases
        ","tags":["TC007"]},{"location":"rules/unraw-re-pattern/","title":"unraw-re-pattern (RUF039)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF039"]},{"location":"rules/unraw-re-pattern/#what-it-does","title":"What it does","text":"

        Reports the following re and regex calls when their first arguments are not raw strings:

        • For regex and re: compile, findall, finditer, fullmatch, match, search, split, sub, subn.
        • regex-specific: splititer, subf, subfn, template.
        ","tags":["RUF039"]},{"location":"rules/unraw-re-pattern/#why-is-this-bad","title":"Why is this bad?","text":"

        Regular expressions should be written using raw strings to avoid double escaping.

        ","tags":["RUF039"]},{"location":"rules/unraw-re-pattern/#example","title":"Example","text":"
        re.compile(\"foo\\\\bar\")\n

        Use instead:

        re.compile(r\"foo\\bar\")\n
        ","tags":["RUF039"]},{"location":"rules/unrecognized-platform-check/","title":"unrecognized-platform-check (PYI007)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI007"]},{"location":"rules/unrecognized-platform-check/#what-it-does","title":"What it does","text":"

        Check for unrecognized sys.platform checks. Platform checks should be simple string comparisons.

        Note: this rule is only enabled in .pyi stub files.

        ","tags":["PYI007"]},{"location":"rules/unrecognized-platform-check/#why-is-this-bad","title":"Why is this bad?","text":"

        Some sys.platform checks are too complex for type checkers to understand, and thus result in incorrect inferences by these tools. sys.platform checks should be simple string comparisons, like if sys.platform == \"linux\".

        ","tags":["PYI007"]},{"location":"rules/unrecognized-platform-check/#example","title":"Example","text":"
        if sys.platform.startswith(\"linux\"):\n    # Linux specific definitions\n    ...\nelse:\n    # Posix specific definitions\n    ...\n

        Instead, use a simple string comparison, such as == or !=:

        if sys.platform == \"linux\":\n    # Linux specific definitions\n    ...\nelse:\n    # Posix specific definitions\n    ...\n
        ","tags":["PYI007"]},{"location":"rules/unrecognized-platform-check/#references","title":"References","text":"
        • Typing documentation: Version and Platform checking
        ","tags":["PYI007"]},{"location":"rules/unrecognized-platform-name/","title":"unrecognized-platform-name (PYI008)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI008"]},{"location":"rules/unrecognized-platform-name/#what-it-does","title":"What it does","text":"

        Check for unrecognized platform names in sys.platform checks.

        Note: this rule is only enabled in .pyi stub files.

        ","tags":["PYI008"]},{"location":"rules/unrecognized-platform-name/#why-is-this-bad","title":"Why is this bad?","text":"

        If a sys.platform check compares to a platform name outside of a small set of known platforms (e.g. \"linux\", \"win32\", etc.), it's likely a typo or a platform name that is not recognized by type checkers.

        The list of known platforms is: \"linux\", \"win32\", \"cygwin\", \"darwin\".

        ","tags":["PYI008"]},{"location":"rules/unrecognized-platform-name/#example","title":"Example","text":"
        if sys.platform == \"linus\": ...\n

        Use instead:

        if sys.platform == \"linux\": ...\n
        ","tags":["PYI008"]},{"location":"rules/unrecognized-platform-name/#references","title":"References","text":"
        • Typing documentation: Version and Platform checking
        ","tags":["PYI008"]},{"location":"rules/unrecognized-version-info-check/","title":"unrecognized-version-info-check (PYI003)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI003"]},{"location":"rules/unrecognized-version-info-check/#what-it-does","title":"What it does","text":"

        Checks for problematic sys.version_info-related conditions in stubs.

        ","tags":["PYI003"]},{"location":"rules/unrecognized-version-info-check/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files support simple conditionals to test for differences in Python versions using sys.version_info. However, there are a number of common mistakes involving sys.version_info comparisons that should be avoided. For example, comparing against a string can lead to unexpected behavior.

        ","tags":["PYI003"]},{"location":"rules/unrecognized-version-info-check/#example","title":"Example","text":"
        import sys\n\nif sys.version_info[0] == \"2\": ...\n

        Use instead:

        import sys\n\nif sys.version_info[0] == 2: ...\n
        ","tags":["PYI003"]},{"location":"rules/unrecognized-version-info-check/#references","title":"References","text":"
        • Typing documentation: Version and Platform checking
        ","tags":["PYI003"]},{"location":"rules/unreliable-callable-check/","title":"unreliable-callable-check (B004)","text":"

        Derived from the flake8-bugbear linter.

        Fix is sometimes available.

        ","tags":["B004"]},{"location":"rules/unreliable-callable-check/#what-it-does","title":"What it does","text":"

        Checks for uses of hasattr to test if an object is callable (e.g., hasattr(obj, \"__call__\")).

        ","tags":["B004"]},{"location":"rules/unreliable-callable-check/#why-is-this-bad","title":"Why is this bad?","text":"

        Using hasattr is an unreliable mechanism for testing if an object is callable. If obj implements a custom __getattr__, or if its __call__ is itself not callable, you may get misleading results.

        Instead, use callable(obj) to test if obj is callable.

        ","tags":["B004"]},{"location":"rules/unreliable-callable-check/#example","title":"Example","text":"
        hasattr(obj, \"__call__\")\n

        Use instead:

        callable(obj)\n
        ","tags":["B004"]},{"location":"rules/unreliable-callable-check/#references","title":"References","text":"
        • Python documentation: callable
        • Python documentation: hasattr
        • Python documentation: __getattr__
        • Python documentation: __call__
        ","tags":["B004"]},{"location":"rules/unsafe-markup-use/","title":"unsafe-markup-use (S704)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S704"]},{"location":"rules/unsafe-markup-use/#what-it-does","title":"What it does","text":"

        Checks for non-literal strings being passed to markupsafe.Markup.

        ","tags":["S704"]},{"location":"rules/unsafe-markup-use/#why-is-this-bad","title":"Why is this bad?","text":"

        [markupsafe.Markup][markupsafe.Markup] does not perform any escaping, so passing dynamic content, like f-strings, variables or interpolated strings will potentially lead to XSS vulnerabilities.

        Instead you should interpolate the Markup object.

        Using lint.flake8-bandit.extend-markup-names additional objects can be treated like Markup.

        This rule was originally inspired by flake8-markupsafe but doesn't carve out any exceptions for i18n related calls by default.

        You can use lint.flake8-bandit.allowed-markup-calls to specify exceptions.

        ","tags":["S704"]},{"location":"rules/unsafe-markup-use/#example","title":"Example","text":"

        Given:

        from markupsafe import Markup\n\ncontent = \"<script>alert('Hello, world!')</script>\"\nhtml = Markup(f\"<b>{content}</b>\")  # XSS\n

        Use instead:

        from markupsafe import Markup\n\ncontent = \"<script>alert('Hello, world!')</script>\"\nhtml = Markup(\"<b>{}</b>\").format(content)  # Safe\n

        Given:

        from markupsafe import Markup\n\nlines = [\n    Markup(\"<b>heading</b>\"),\n    \"<script>alert('XSS attempt')</script>\",\n]\nhtml = Markup(\"<br>\".join(lines))  # XSS\n

        Use instead:

        from markupsafe import Markup\n\nlines = [\n    Markup(\"<b>heading</b>\"),\n    \"<script>alert('XSS attempt')</script>\",\n]\nhtml = Markup(\"<br>\").join(lines)  # Safe\n
        ","tags":["S704"]},{"location":"rules/unsafe-markup-use/#options","title":"Options","text":"
        • lint.flake8-bandit.extend-markup-names
        • lint.flake8-bandit.allowed-markup-calls
        ","tags":["S704"]},{"location":"rules/unsafe-markup-use/#references","title":"References","text":"
        • MarkupSafe on PyPI
        • markupsafe.Markup API documentation
        ","tags":["S704"]},{"location":"rules/unsafe-yaml-load/","title":"unsafe-yaml-load (S506)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S506"]},{"location":"rules/unsafe-yaml-load/#what-it-does","title":"What it does","text":"

        Checks for uses of the yaml.load function.

        ","tags":["S506"]},{"location":"rules/unsafe-yaml-load/#why-is-this-bad","title":"Why is this bad?","text":"

        Running the yaml.load function over untrusted YAML files is insecure, as yaml.load allows for the creation of arbitrary Python objects, which can then be used to execute arbitrary code.

        Instead, consider using yaml.safe_load, which allows for the creation of simple Python objects like integers and lists, but prohibits the creation of more complex objects like functions and classes.

        ","tags":["S506"]},{"location":"rules/unsafe-yaml-load/#example","title":"Example","text":"
        import yaml\n\nyaml.load(untrusted_yaml)\n

        Use instead:

        import yaml\n\nyaml.safe_load(untrusted_yaml)\n
        ","tags":["S506"]},{"location":"rules/unsafe-yaml-load/#references","title":"References","text":"
        • PyYAML documentation: Loading YAML
        • Common Weakness Enumeration: CWE-20
        ","tags":["S506"]},{"location":"rules/unsorted-dunder-all/","title":"unsorted-dunder-all (RUF022)","text":"

        Fix is sometimes available.

        ","tags":["RUF022"]},{"location":"rules/unsorted-dunder-all/#what-it-does","title":"What it does","text":"

        Checks for __all__ definitions that are not ordered according to an \"isort-style\" sort.

        An isort-style sort orders items first according to their casing: SCREAMING_SNAKE_CASE names (conventionally used for global constants) come first, followed by CamelCase names (conventionally used for classes), followed by anything else. Within each category, a natural sort is used to order the elements.

        ","tags":["RUF022"]},{"location":"rules/unsorted-dunder-all/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use a common convention for __all__ to make your code more readable and idiomatic.

        ","tags":["RUF022"]},{"location":"rules/unsorted-dunder-all/#example","title":"Example","text":"
        import sys\n\n__all__ = [\n    \"b\",\n    \"c\",\n    \"a\",\n]\n\nif sys.platform == \"win32\":\n    __all__ += [\"z\", \"y\"]\n

        Use instead:

        import sys\n\n__all__ = [\n    \"a\",\n    \"b\",\n    \"c\",\n]\n\nif sys.platform == \"win32\":\n    __all__ += [\"y\", \"z\"]\n
        ","tags":["RUF022"]},{"location":"rules/unsorted-dunder-all/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe if there are any comments that take up a whole line by themselves inside the __all__ definition, for example:

        __all__ = [\n    # eggy things\n    \"duck_eggs\",\n    \"chicken_eggs\",\n    # hammy things\n    \"country_ham\",\n    \"parma_ham\",\n]\n

        This is a common pattern used to delimit categories within a module's API, but it would be out of the scope of this rule to attempt to maintain these categories when alphabetically sorting the items of __all__.

        The fix is also marked as unsafe if there are more than two __all__ items on a single line and that line also has a trailing comment, since here it is impossible to accurately gauge which item the comment should be moved with when sorting __all__:

        __all__ = [\n    \"a\", \"c\", \"e\",  # a comment\n    \"b\", \"d\", \"f\",  # a second  comment\n]\n

        Other than this, the rule's fix is marked as always being safe, in that it should very rarely alter the semantics of any Python code. However, note that (although it's rare) the value of __all__ could be read by code elsewhere that depends on the exact iteration order of the items in __all__, in which case this rule's fix could theoretically cause breakage.

        ","tags":["RUF022"]},{"location":"rules/unsorted-dunder-slots/","title":"unsorted-dunder-slots (RUF023)","text":"

        Fix is sometimes available.

        ","tags":["RUF023"]},{"location":"rules/unsorted-dunder-slots/#what-it-does","title":"What it does","text":"

        Checks for __slots__ definitions that are not ordered according to a natural sort.

        ","tags":["RUF023"]},{"location":"rules/unsorted-dunder-slots/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use a common convention for this special variable to make your code more readable and idiomatic.

        ","tags":["RUF023"]},{"location":"rules/unsorted-dunder-slots/#example","title":"Example","text":"
        class Dog:\n    __slots__ = \"name\", \"breed\"\n

        Use instead:

        class Dog:\n    __slots__ = \"breed\", \"name\"\n
        ","tags":["RUF023"]},{"location":"rules/unsorted-dunder-slots/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe in three situations.

        Firstly, the fix is unsafe if there are any comments that take up a whole line by themselves inside the __slots__ definition, for example:

        class Foo:\n    __slots__ = [\n        # eggy things\n        \"duck_eggs\",\n        \"chicken_eggs\",\n        # hammy things\n        \"country_ham\",\n        \"parma_ham\",\n    ]\n

        This is a common pattern used to delimit categories within a class's slots, but it would be out of the scope of this rule to attempt to maintain these categories when applying a natural sort to the items of __slots__.

        Secondly, the fix is also marked as unsafe if there are more than two __slots__ items on a single line and that line also has a trailing comment, since here it is impossible to accurately gauge which item the comment should be moved with when sorting __slots__:

        class Bar:\n    __slots__ = [\n        \"a\", \"c\", \"e\",  # a comment\n        \"b\", \"d\", \"f\",  # a second  comment\n    ]\n

        Lastly, this rule's fix is marked as unsafe whenever Ruff can detect that code elsewhere in the same file reads the __slots__ variable in some way and the __slots__ variable is not assigned to a set. This is because the order of the items in __slots__ may have semantic significance if the __slots__ of a class is being iterated over, or being assigned to another value.

        In the vast majority of other cases, this rule's fix is unlikely to cause breakage; as such, Ruff will otherwise mark this rule's fix as safe. However, note that (although it's rare) the value of __slots__ could still be read by code outside of the module in which the __slots__ definition occurs, in which case this rule's fix could theoretically cause breakage.

        ","tags":["RUF023"]},{"location":"rules/unsorted-imports/","title":"unsorted-imports (I001)","text":"

        Derived from the isort linter.

        Fix is sometimes available.

        ","tags":["I001"]},{"location":"rules/unsorted-imports/#what-it-does","title":"What it does","text":"

        De-duplicates, groups, and sorts imports based on the provided isort settings.

        ","tags":["I001"]},{"location":"rules/unsorted-imports/#why-is-this-bad","title":"Why is this bad?","text":"

        Consistency is good. Use a common convention for imports to make your code more readable and idiomatic.

        ","tags":["I001"]},{"location":"rules/unsorted-imports/#example","title":"Example","text":"
        import pandas\nimport numpy as np\n

        Use instead:

        import numpy as np\nimport pandas\n
        ","tags":["I001"]},{"location":"rules/unsorted-imports/#preview","title":"Preview","text":"

        When preview mode is enabled, Ruff applies a stricter criterion for determining whether an import should be classified as first-party. Specifically, for an import of the form import foo.bar.baz, Ruff will check that foo/bar, relative to a user-specified src directory, contains either the directory baz or else a file with the name baz.py or baz.pyi.

        ","tags":["I001"]},{"location":"rules/unspecified-encoding/","title":"unspecified-encoding (PLW1514)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["PLW1514"]},{"location":"rules/unspecified-encoding/#what-it-does","title":"What it does","text":"

        Checks for uses of open and related calls without an explicit encoding argument.

        ","tags":["PLW1514"]},{"location":"rules/unspecified-encoding/#why-is-this-bad","title":"Why is this bad?","text":"

        Using open in text mode without an explicit encoding can lead to non-portable code, with differing behavior across platforms. While readers may assume that UTF-8 is the default encoding, in reality, the default is locale-specific.

        Instead, consider using the encoding parameter to enforce a specific encoding. PEP 597 recommends the use of encoding=\"utf-8\" as a default, and suggests that it may become the default in future versions of Python.

        If a locale-specific encoding is intended, use encoding=\"locale\" on Python 3.10 and later, or locale.getpreferredencoding() on earlier versions, to make the encoding explicit.

        ","tags":["PLW1514"]},{"location":"rules/unspecified-encoding/#fix-safety","title":"Fix safety","text":"

        This fix is always unsafe and may change the program's behavior. It forces encoding=\"utf-8\" as the default, regardless of the platform\u2019s actual default encoding, which may cause UnicodeDecodeError on non-UTF-8 systems.

        with open(\"test.txt\") as f:\n    print(f.read()) # before fix (on UTF-8 systems): \u4f60\u597d\uff0c\u4e16\u754c\uff01\nwith open(\"test.txt\", encoding=\"utf-8\") as f:\n    print(f.read()) # after fix (on Windows): UnicodeDecodeError\n
        ","tags":["PLW1514"]},{"location":"rules/unspecified-encoding/#example","title":"Example","text":"
        open(\"file.txt\")\n

        Use instead:

        open(\"file.txt\", encoding=\"utf-8\")\n
        ","tags":["PLW1514"]},{"location":"rules/unspecified-encoding/#references","title":"References","text":"
        • Python documentation: open
        ","tags":["PLW1514"]},{"location":"rules/unsupported-method-call-on-all/","title":"unsupported-method-call-on-all (PYI056)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI056"]},{"location":"rules/unsupported-method-call-on-all/#what-it-does","title":"What it does","text":"

        Checks that append, extend and remove methods are not called on __all__.

        ","tags":["PYI056"]},{"location":"rules/unsupported-method-call-on-all/#why-is-this-bad","title":"Why is this bad?","text":"

        Different type checkers have varying levels of support for calling these methods on __all__. Instead, use the += operator to add items to __all__, which is known to be supported by all major type checkers.

        ","tags":["PYI056"]},{"location":"rules/unsupported-method-call-on-all/#example","title":"Example","text":"
        import sys\n\n__all__ = [\"A\", \"B\"]\n\nif sys.version_info >= (3, 10):\n    __all__.append(\"C\")\n\nif sys.version_info >= (3, 11):\n    __all__.remove(\"B\")\n

        Use instead:

        import sys\n\n__all__ = [\"A\"]\n\nif sys.version_info < (3, 11):\n    __all__ += [\"B\"]\n\nif sys.version_info >= (3, 10):\n    __all__ += [\"C\"]\n
        ","tags":["PYI056"]},{"location":"rules/unused-annotation/","title":"unused-annotation (F842)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F842"]},{"location":"rules/unused-annotation/#what-it-does","title":"What it does","text":"

        Checks for local variables that are annotated but never used.

        ","tags":["F842"]},{"location":"rules/unused-annotation/#why-is-this-bad","title":"Why is this bad?","text":"

        Annotations are used to provide type hints to static type checkers. If a variable is annotated but never used, the annotation is unnecessary.

        ","tags":["F842"]},{"location":"rules/unused-annotation/#example","title":"Example","text":"
        def foo():\n    bar: int\n
        ","tags":["F842"]},{"location":"rules/unused-annotation/#references","title":"References","text":"
        • PEP 484 \u2013 Type Hints
        ","tags":["F842"]},{"location":"rules/unused-async/","title":"unused-async (RUF029)","text":"

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF029"]},{"location":"rules/unused-async/#what-it-does","title":"What it does","text":"

        Checks for functions declared async that do not await or otherwise use features requiring the function to be declared async.

        ","tags":["RUF029"]},{"location":"rules/unused-async/#why-is-this-bad","title":"Why is this bad?","text":"

        Declaring a function async when it's not is usually a mistake, and will artificially limit the contexts where that function may be called. In some cases, labeling a function async is semantically meaningful (e.g. with the trio library).

        ","tags":["RUF029"]},{"location":"rules/unused-async/#example","title":"Example","text":"
        async def foo():\n    bar()\n

        Use instead:

        def foo():\n    bar()\n
        ","tags":["RUF029"]},{"location":"rules/unused-class-method-argument/","title":"unused-class-method-argument (ARG003)","text":"

        Derived from the flake8-unused-arguments linter.

        ","tags":["ARG003"]},{"location":"rules/unused-class-method-argument/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused arguments in class method definitions.

        ","tags":["ARG003"]},{"location":"rules/unused-class-method-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An argument that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["ARG003"]},{"location":"rules/unused-class-method-argument/#example","title":"Example","text":"
        class Class:\n    @classmethod\n    def foo(cls, arg1, arg2):\n        print(arg1)\n

        Use instead:

        class Class:\n    @classmethod\n    def foo(cls, arg1):\n        print(arg1)\n
        ","tags":["ARG003"]},{"location":"rules/unused-class-method-argument/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["ARG003"]},{"location":"rules/unused-function-argument/","title":"unused-function-argument (ARG001)","text":"

        Derived from the flake8-unused-arguments linter.

        ","tags":["ARG001"]},{"location":"rules/unused-function-argument/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused arguments in function definitions.

        ","tags":["ARG001"]},{"location":"rules/unused-function-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An argument that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["ARG001"]},{"location":"rules/unused-function-argument/#example","title":"Example","text":"
        def foo(bar, baz):\n    return bar * 2\n

        Use instead:

        def foo(bar):\n    return bar * 2\n
        ","tags":["ARG001"]},{"location":"rules/unused-function-argument/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["ARG001"]},{"location":"rules/unused-import/","title":"unused-import (F401)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F401"]},{"location":"rules/unused-import/#what-it-does","title":"What it does","text":"

        Checks for unused imports.

        ","tags":["F401"]},{"location":"rules/unused-import/#why-is-this-bad","title":"Why is this bad?","text":"

        Unused imports add a performance overhead at runtime, and risk creating import cycles. They also increase the cognitive load of reading the code.

        If an import statement is used to check for the availability or existence of a module, consider using importlib.util.find_spec instead.

        If an import statement is used to re-export a symbol as part of a module's public interface, consider using a \"redundant\" import alias, which instructs Ruff (and other tools) to respect the re-export, and avoid marking it as unused, as in:

        from module import member as member\n

        Alternatively, you can use __all__ to declare a symbol as part of the module's interface, as in:

        # __init__.py\nimport some_module\n\n__all__ = [\"some_module\"]\n
        ","tags":["F401"]},{"location":"rules/unused-import/#fix-safety","title":"Fix safety","text":"

        Fixes to remove unused imports are safe, except in __init__.py files.

        Applying fixes to __init__.py files is currently in preview. The fix offered depends on the type of the unused import. Ruff will suggest a safe fix to export first-party imports with either a redundant alias or, if already present in the file, an __all__ entry. If multiple __all__ declarations are present, Ruff will not offer a fix. Ruff will suggest an unsafe fix to remove third-party and standard library imports -- the fix is unsafe because the module's interface changes.

        ","tags":["F401"]},{"location":"rules/unused-import/#example","title":"Example","text":"
        import numpy as np  # unused import\n\n\ndef area(radius):\n    return 3.14 * radius**2\n

        Use instead:

        def area(radius):\n    return 3.14 * radius**2\n

        To check the availability of a module, use importlib.util.find_spec:

        from importlib.util import find_spec\n\nif find_spec(\"numpy\") is not None:\n    print(\"numpy is installed\")\nelse:\n    print(\"numpy is not installed\")\n
        ","tags":["F401"]},{"location":"rules/unused-import/#preview","title":"Preview","text":"

        When preview is enabled, the criterion for determining whether an import is first-party is stricter, which could affect the suggested fix. See this FAQ section for more details.

        ","tags":["F401"]},{"location":"rules/unused-import/#options","title":"Options","text":"
        • lint.ignore-init-module-imports
        • lint.pyflakes.allowed-unused-imports
        ","tags":["F401"]},{"location":"rules/unused-import/#references","title":"References","text":"
        • Python documentation: import
        • Python documentation: importlib.util.find_spec
        • Typing documentation: interface conventions
        ","tags":["F401"]},{"location":"rules/unused-lambda-argument/","title":"unused-lambda-argument (ARG005)","text":"

        Derived from the flake8-unused-arguments linter.

        ","tags":["ARG005"]},{"location":"rules/unused-lambda-argument/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused arguments in lambda expression definitions.

        ","tags":["ARG005"]},{"location":"rules/unused-lambda-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An argument that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["ARG005"]},{"location":"rules/unused-lambda-argument/#example","title":"Example","text":"
        my_list = [1, 2, 3, 4, 5]\nsquares = map(lambda x, y: x**2, my_list)\n

        Use instead:

        my_list = [1, 2, 3, 4, 5]\nsquares = map(lambda x: x**2, my_list)\n
        ","tags":["ARG005"]},{"location":"rules/unused-lambda-argument/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["ARG005"]},{"location":"rules/unused-loop-control-variable/","title":"unused-loop-control-variable (B007)","text":"

        Derived from the flake8-bugbear linter.

        Fix is sometimes available.

        ","tags":["B007"]},{"location":"rules/unused-loop-control-variable/#what-it-does","title":"What it does","text":"

        Checks for unused variables in loops (e.g., for and while statements).

        ","tags":["B007"]},{"location":"rules/unused-loop-control-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        Defining a variable in a loop statement that is never used can confuse readers.

        If the variable is intended to be unused (e.g., to facilitate destructuring of a tuple or other object), prefix it with an underscore to indicate the intent. Otherwise, remove the variable entirely.

        ","tags":["B007"]},{"location":"rules/unused-loop-control-variable/#example","title":"Example","text":"
        for i, j in foo:\n    bar(i)\n

        Use instead:

        for i, _j in foo:\n    bar(i)\n
        ","tags":["B007"]},{"location":"rules/unused-loop-control-variable/#references","title":"References","text":"
        • PEP 8: Naming Conventions
        ","tags":["B007"]},{"location":"rules/unused-method-argument/","title":"unused-method-argument (ARG002)","text":"

        Derived from the flake8-unused-arguments linter.

        ","tags":["ARG002"]},{"location":"rules/unused-method-argument/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused arguments in instance method definitions.

        ","tags":["ARG002"]},{"location":"rules/unused-method-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An argument that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["ARG002"]},{"location":"rules/unused-method-argument/#example","title":"Example","text":"
        class Class:\n    def foo(self, arg1, arg2):\n        print(arg1)\n

        Use instead:

        class Class:\n    def foo(self, arg1):\n        print(arg1)\n
        ","tags":["ARG002"]},{"location":"rules/unused-method-argument/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["ARG002"]},{"location":"rules/unused-noqa/","title":"unused-noqa (RUF100)","text":"

        Fix is always available.

        ","tags":["RUF100"]},{"location":"rules/unused-noqa/#what-it-does","title":"What it does","text":"

        Checks for noqa directives that are no longer applicable.

        ","tags":["RUF100"]},{"location":"rules/unused-noqa/#why-is-this-bad","title":"Why is this bad?","text":"

        A noqa directive that no longer matches any diagnostic violations is likely included by mistake, and should be removed to avoid confusion.

        ","tags":["RUF100"]},{"location":"rules/unused-noqa/#example","title":"Example","text":"
        import foo  # noqa: F401\n\n\ndef bar():\n    foo.bar()\n

        Use instead:

        import foo\n\n\ndef bar():\n    foo.bar()\n
        ","tags":["RUF100"]},{"location":"rules/unused-noqa/#options","title":"Options","text":"
        • lint.external
        ","tags":["RUF100"]},{"location":"rules/unused-noqa/#references","title":"References","text":"
        • Ruff error suppression
        ","tags":["RUF100"]},{"location":"rules/unused-private-protocol/","title":"unused-private-protocol (PYI046)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI046"]},{"location":"rules/unused-private-protocol/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused private typing.Protocol definitions.

        ","tags":["PYI046"]},{"location":"rules/unused-private-protocol/#why-is-this-bad","title":"Why is this bad?","text":"

        A private typing.Protocol that is defined but not used is likely a mistake. It should either be used, made public, or removed to avoid confusion.

        ","tags":["PYI046"]},{"location":"rules/unused-private-protocol/#example","title":"Example","text":"
        import typing\n\nclass _PrivateProtocol(typing.Protocol):\n    foo: int\n

        Use instead:

        import typing\n\nclass _PrivateProtocol(typing.Protocol):\n    foo: int\n\ndef func(arg: _PrivateProtocol) -> None: ...\n
        ","tags":["PYI046"]},{"location":"rules/unused-private-type-alias/","title":"unused-private-type-alias (PYI047)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI047"]},{"location":"rules/unused-private-type-alias/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused private type aliases.

        ","tags":["PYI047"]},{"location":"rules/unused-private-type-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        A private type alias that is defined but not used is likely a mistake. It should either be used, made public, or removed to avoid confusion.

        ","tags":["PYI047"]},{"location":"rules/unused-private-type-alias/#example","title":"Example","text":"
        import typing\n\n_UnusedTypeAlias: typing.TypeAlias = int\n

        Use instead:

        import typing\n\n_UsedTypeAlias: typing.TypeAlias = int\n\ndef func(arg: _UsedTypeAlias) -> _UsedTypeAlias: ...\n
        ","tags":["PYI047"]},{"location":"rules/unused-private-type-var/","title":"unused-private-type-var (PYI018)","text":"

        Derived from the flake8-pyi linter.

        Fix is sometimes available.

        ","tags":["PYI018"]},{"location":"rules/unused-private-type-var/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused private TypeVar, ParamSpec or TypeVarTuple declarations.

        ","tags":["PYI018"]},{"location":"rules/unused-private-type-var/#why-is-this-bad","title":"Why is this bad?","text":"

        A private TypeVar that is defined but not used is likely a mistake. It should either be used, made public, or removed to avoid confusion. A type variable is considered \"private\" if its name starts with an underscore.

        ","tags":["PYI018"]},{"location":"rules/unused-private-type-var/#example","title":"Example","text":"
        import typing\nimport typing_extensions\n\n_T = typing.TypeVar(\"_T\")\n_Ts = typing_extensions.TypeVarTuple(\"_Ts\")\n
        ","tags":["PYI018"]},{"location":"rules/unused-private-type-var/#fix-safety","title":"Fix safety","text":"

        The fix is always marked as unsafe, as it would break your code if the type variable is imported by another module.

        ","tags":["PYI018"]},{"location":"rules/unused-private-typed-dict/","title":"unused-private-typed-dict (PYI049)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI049"]},{"location":"rules/unused-private-typed-dict/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused private typing.TypedDict definitions.

        ","tags":["PYI049"]},{"location":"rules/unused-private-typed-dict/#why-is-this-bad","title":"Why is this bad?","text":"

        A private typing.TypedDict that is defined but not used is likely a mistake. It should either be used, made public, or removed to avoid confusion.

        ","tags":["PYI049"]},{"location":"rules/unused-private-typed-dict/#example","title":"Example","text":"
        import typing\n\nclass _UnusedPrivateTypedDict(typing.TypedDict):\n    foo: list[int]\n

        Use instead:

        import typing\n\nclass _UsedPrivateTypedDict(typing.TypedDict):\n    foo: set[str]\n\ndef func(arg: _UsedPrivateTypedDict) -> _UsedPrivateTypedDict: ...\n
        ","tags":["PYI049"]},{"location":"rules/unused-static-method-argument/","title":"unused-static-method-argument (ARG004)","text":"

        Derived from the flake8-unused-arguments linter.

        ","tags":["ARG004"]},{"location":"rules/unused-static-method-argument/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused arguments in static method definitions.

        ","tags":["ARG004"]},{"location":"rules/unused-static-method-argument/#why-is-this-bad","title":"Why is this bad?","text":"

        An argument that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["ARG004"]},{"location":"rules/unused-static-method-argument/#example","title":"Example","text":"
        class Class:\n    @staticmethod\n    def foo(arg1, arg2):\n        print(arg1)\n

        Use instead:

        class Class:\n    @staticmethod\n    def foo(arg1):\n        print(arg1)\n
        ","tags":["ARG004"]},{"location":"rules/unused-static-method-argument/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["ARG004"]},{"location":"rules/unused-unpacked-variable/","title":"unused-unpacked-variable (RUF059)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF059"]},{"location":"rules/unused-unpacked-variable/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused variables in unpacked assignments.

        ","tags":["RUF059"]},{"location":"rules/unused-unpacked-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        A variable that is defined but never used can confuse readers.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["RUF059"]},{"location":"rules/unused-unpacked-variable/#example","title":"Example","text":"
        def get_pair():\n    return 1, 2\n\n\ndef foo():\n    x, y = get_pair()\n    return x\n

        Use instead:

        def foo():\n    x, _ = get_pair()\n    return x\n
        ","tags":["RUF059"]},{"location":"rules/unused-unpacked-variable/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["RUF059"]},{"location":"rules/unused-variable/","title":"unused-variable (F841)","text":"

        Derived from the Pyflakes linter.

        Fix is sometimes available.

        ","tags":["F841"]},{"location":"rules/unused-variable/#what-it-does","title":"What it does","text":"

        Checks for the presence of unused variables in function scopes.

        ","tags":["F841"]},{"location":"rules/unused-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        A variable that is defined but not used is likely a mistake, and should be removed to avoid confusion.

        If a variable is intentionally defined-but-not-used, it should be prefixed with an underscore, or some other value that adheres to the lint.dummy-variable-rgx pattern.

        ","tags":["F841"]},{"location":"rules/unused-variable/#example","title":"Example","text":"
        def foo():\n    x = 1\n    y = 2\n    return x\n

        Use instead:

        def foo():\n    x = 1\n    return x\n
        ","tags":["F841"]},{"location":"rules/unused-variable/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe because removing an unused variable assignment may delete comments that are attached to the assignment.

        ","tags":["F841"]},{"location":"rules/unused-variable/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["F841"]},{"location":"rules/used-dummy-variable/","title":"used-dummy-variable (RUF052)","text":"

        Fix is sometimes available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#what-it-does","title":"What it does","text":"

        Checks for \"dummy variables\" (variables that are named as if to indicate they are unused) that are in fact used.

        By default, \"dummy variables\" are any variables with names that start with leading underscores. However, this is customisable using the lint.dummy-variable-rgx setting).

        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#why-is-this-bad","title":"Why is this bad?","text":"

        Marking a variable with a leading underscore conveys that it is intentionally unused within the function or method. When these variables are later referenced in the code, it causes confusion and potential misunderstandings about the code's intention. If a variable marked as \"unused\" is subsequently used, it suggests that either the variable could be given a clearer name, or that the code is accidentally making use of the wrong variable.

        Sometimes leading underscores are used to avoid variables shadowing other variables, Python builtins, or Python keywords. However, PEP 8 recommends to use trailing underscores for this rather than leading underscores.

        Dunder variables are ignored by this rule, as are variables named _. Only local variables in function scopes are flagged by the rule.

        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#example","title":"Example","text":"
        def function():\n    _variable = 3\n    # important: avoid shadowing the builtin `id()` function!\n    _id = 4\n    return _variable + _id\n

        Use instead:

        def function():\n    variable = 3\n    # important: avoid shadowing the builtin `id()` function!\n    id_ = 4\n    return variable + id_\n
        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#fix-availability","title":"Fix availability","text":"

        The rule's fix is only available for variables that start with leading underscores. It will also only be available if the \"obvious\" new name for the variable would not shadow any other known variables already accessible from the scope in which the variable is defined.

        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe.

        For this rule's fix, Ruff renames the variable and fixes up all known references to it so they point to the renamed variable. However, some renamings also require other changes such as different arguments to constructor calls or alterations to comments. Ruff is aware of some of these cases: _T = TypeVar(\"_T\") will be fixed to T = TypeVar(\"T\") if the _T binding is flagged by this rule. However, in general, cases like these are hard to detect and hard to automatically fix.

        ","tags":["RUF052"]},{"location":"rules/used-dummy-variable/#options","title":"Options","text":"
        • lint.dummy-variable-rgx
        ","tags":["RUF052"]},{"location":"rules/useless-comparison/","title":"useless-comparison (B015)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B015"]},{"location":"rules/useless-comparison/#what-it-does","title":"What it does","text":"

        Checks for useless comparisons.

        ","tags":["B015"]},{"location":"rules/useless-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Useless comparisons have no effect on the program, and are often included by mistake. If the comparison is intended to enforce an invariant, prepend the comparison with an assert. Otherwise, remove it entirely.

        ","tags":["B015"]},{"location":"rules/useless-comparison/#example","title":"Example","text":"
        foo == bar\n

        Use instead:

        assert foo == bar, \"`foo` and `bar` should be equal.\"\n
        ","tags":["B015"]},{"location":"rules/useless-comparison/#notebook-behavior","title":"Notebook behavior","text":"

        For Jupyter Notebooks, this rule is not applied to the last top-level expression in a cell. This is because it's common to have a notebook cell that ends with an expression, which will result in the repr of the evaluated expression being printed as the cell's output.

        ","tags":["B015"]},{"location":"rules/useless-comparison/#references","title":"References","text":"
        • Python documentation: assert statement
        ","tags":["B015"]},{"location":"rules/useless-contextlib-suppress/","title":"useless-contextlib-suppress (B022)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B022"]},{"location":"rules/useless-contextlib-suppress/#what-it-does","title":"What it does","text":"

        Checks for contextlib.suppress without arguments.

        ","tags":["B022"]},{"location":"rules/useless-contextlib-suppress/#why-is-this-bad","title":"Why is this bad?","text":"

        contextlib.suppress is a context manager that suppresses exceptions. It takes, as arguments, the exceptions to suppress within the enclosed block. If no exceptions are specified, then the context manager won't suppress any exceptions, and is thus redundant.

        Consider adding exceptions to the contextlib.suppress call, or removing the context manager entirely.

        ","tags":["B022"]},{"location":"rules/useless-contextlib-suppress/#example","title":"Example","text":"
        import contextlib\n\nwith contextlib.suppress():\n    foo()\n

        Use instead:

        import contextlib\n\nwith contextlib.suppress(Exception):\n    foo()\n
        ","tags":["B022"]},{"location":"rules/useless-contextlib-suppress/#references","title":"References","text":"
        • Python documentation: contextlib.suppress
        ","tags":["B022"]},{"location":"rules/useless-else-on-loop/","title":"useless-else-on-loop (PLW0120)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLW0120"]},{"location":"rules/useless-else-on-loop/#what-it-does","title":"What it does","text":"

        Checks for else clauses on loops without a break statement.

        ","tags":["PLW0120"]},{"location":"rules/useless-else-on-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        When a loop includes an else statement, the code inside the else clause will be executed if the loop terminates \"normally\" (i.e., without a break).

        If a loop always terminates \"normally\" (i.e., does not contain a break), then the else clause is redundant, as the code inside the else clause will always be executed.

        In such cases, the code inside the else clause can be moved outside the loop entirely, and the else clause can be removed.

        ","tags":["PLW0120"]},{"location":"rules/useless-else-on-loop/#example","title":"Example","text":"
        for item in items:\n    print(item)\nelse:\n    print(\"All items printed\")\n

        Use instead:

        for item in items:\n    print(item)\nprint(\"All items printed\")\n
        ","tags":["PLW0120"]},{"location":"rules/useless-else-on-loop/#references","title":"References","text":"
        • Python documentation: break and continue Statements, and else Clauses on Loops
        ","tags":["PLW0120"]},{"location":"rules/useless-exception-statement/","title":"useless-exception-statement (PLW0133)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLW0133"]},{"location":"rules/useless-exception-statement/#what-it-does","title":"What it does","text":"

        Checks for an exception that is not raised.

        ","tags":["PLW0133"]},{"location":"rules/useless-exception-statement/#why-is-this-bad","title":"Why is this bad?","text":"

        It's unnecessary to create an exception without raising it. For example, ValueError(\"...\") on its own will have no effect (unlike raise ValueError(\"...\")) and is likely a mistake.

        ","tags":["PLW0133"]},{"location":"rules/useless-exception-statement/#known-problems","title":"Known problems","text":"

        This rule only detects built-in exceptions, like ValueError, and does not catch user-defined exceptions.

        ","tags":["PLW0133"]},{"location":"rules/useless-exception-statement/#example","title":"Example","text":"
        ValueError(\"...\")\n

        Use instead:

        raise ValueError(\"...\")\n
        ","tags":["PLW0133"]},{"location":"rules/useless-exception-statement/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as converting a useless exception statement to a raise statement will change the program's behavior.

        ","tags":["PLW0133"]},{"location":"rules/useless-expression/","title":"useless-expression (B018)","text":"

        Derived from the flake8-bugbear linter.

        ","tags":["B018"]},{"location":"rules/useless-expression/#what-it-does","title":"What it does","text":"

        Checks for useless expressions.

        ","tags":["B018"]},{"location":"rules/useless-expression/#why-is-this-bad","title":"Why is this bad?","text":"

        Useless expressions have no effect on the program, and are often included by mistake. Assign a useless expression to a variable, or remove it entirely.

        ","tags":["B018"]},{"location":"rules/useless-expression/#example","title":"Example","text":"
        1 + 1\n

        Use instead:

        foo = 1 + 1\n
        ","tags":["B018"]},{"location":"rules/useless-expression/#notebook-behavior","title":"Notebook behavior","text":"

        For Jupyter Notebooks, this rule is not applied to the last top-level expression in a cell. This is because it's common to have a notebook cell that ends with an expression, which will result in the repr of the evaluated expression being printed as the cell's output.

        ","tags":["B018"]},{"location":"rules/useless-expression/#known-problems","title":"Known problems","text":"

        This rule ignores expression types that are commonly used for their side effects, such as function calls.

        However, if a seemingly useless expression (like an attribute access) is needed to trigger a side effect, consider assigning it to an anonymous variable, to indicate that the return value is intentionally ignored.

        For example, given:

        with errors.ExceptionRaisedContext():\n    obj.attribute\n

        Use instead:

        with errors.ExceptionRaisedContext():\n    _ = obj.attribute\n
        ","tags":["B018"]},{"location":"rules/useless-if-else/","title":"useless-if-else (RUF034)","text":"","tags":["RUF034"]},{"location":"rules/useless-if-else/#what-it-does","title":"What it does","text":"

        Checks for useless if-else conditions with identical arms.

        ","tags":["RUF034"]},{"location":"rules/useless-if-else/#why-is-this-bad","title":"Why is this bad?","text":"

        Useless if-else conditions add unnecessary complexity to the code without providing any logical benefit. Assigning the value directly is clearer.

        ","tags":["RUF034"]},{"location":"rules/useless-if-else/#example","title":"Example","text":"
        foo = x if y else x\n

        Use instead:

        foo = x\n
        ","tags":["RUF034"]},{"location":"rules/useless-import-alias/","title":"useless-import-alias (PLC0414)","text":"

        Derived from the Pylint linter.

        Fix is sometimes available.

        ","tags":["PLC0414"]},{"location":"rules/useless-import-alias/#what-it-does","title":"What it does","text":"

        Checks for import aliases that do not rename the original package.

        ","tags":["PLC0414"]},{"location":"rules/useless-import-alias/#why-is-this-bad","title":"Why is this bad?","text":"

        The import alias is redundant and should be removed to avoid confusion.

        ","tags":["PLC0414"]},{"location":"rules/useless-import-alias/#fix-safety","title":"Fix safety","text":"

        This fix is marked as always unsafe because the user may be intentionally re-exporting the import. While statements like import numpy as numpy appear redundant, they can have semantic meaning in certain contexts.

        ","tags":["PLC0414"]},{"location":"rules/useless-import-alias/#example","title":"Example","text":"
        import numpy as numpy\n

        Use instead:

        import numpy as np\n

        or

        import numpy\n
        ","tags":["PLC0414"]},{"location":"rules/useless-metaclass-type/","title":"useless-metaclass-type (UP001)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP001"]},{"location":"rules/useless-metaclass-type/#what-it-does","title":"What it does","text":"

        Checks for the use of __metaclass__ = type in class definitions.

        ","tags":["UP001"]},{"location":"rules/useless-metaclass-type/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3, __metaclass__ = type is implied and can thus be omitted.

        ","tags":["UP001"]},{"location":"rules/useless-metaclass-type/#example","title":"Example","text":"
        class Foo:\n    __metaclass__ = type\n

        Use instead:

        class Foo: ...\n
        ","tags":["UP001"]},{"location":"rules/useless-metaclass-type/#references","title":"References","text":"
        • PEP 3115 \u2013 Metaclasses in Python 3000
        ","tags":["UP001"]},{"location":"rules/useless-object-inheritance/","title":"useless-object-inheritance (UP004)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP004"]},{"location":"rules/useless-object-inheritance/#what-it-does","title":"What it does","text":"

        Checks for classes that inherit from object.

        ","tags":["UP004"]},{"location":"rules/useless-object-inheritance/#why-is-this-bad","title":"Why is this bad?","text":"

        Since Python 3, all classes inherit from object by default, so object can be omitted from the list of base classes.

        ","tags":["UP004"]},{"location":"rules/useless-object-inheritance/#example","title":"Example","text":"
        class Foo(object): ...\n

        Use instead:

        class Foo: ...\n
        ","tags":["UP004"]},{"location":"rules/useless-object-inheritance/#references","title":"References","text":"
        • PEP 3115 \u2013 Metaclasses in Python 3000
        ","tags":["UP004"]},{"location":"rules/useless-return/","title":"useless-return (PLR1711)","text":"

        Derived from the Pylint linter.

        Fix is always available.

        ","tags":["PLR1711"]},{"location":"rules/useless-return/#what-it-does","title":"What it does","text":"

        Checks for functions that end with an unnecessary return or return None, and contain no other return statements.

        ","tags":["PLR1711"]},{"location":"rules/useless-return/#why-is-this-bad","title":"Why is this bad?","text":"

        Python implicitly assumes a None return at the end of a function, making it unnecessary to explicitly write return None.

        ","tags":["PLR1711"]},{"location":"rules/useless-return/#example","title":"Example","text":"
        def f():\n    print(5)\n    return None\n

        Use instead:

        def f():\n    print(5)\n
        ","tags":["PLR1711"]},{"location":"rules/useless-semicolon/","title":"useless-semicolon (E703)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        ","tags":["E703"]},{"location":"rules/useless-semicolon/#what-it-does","title":"What it does","text":"

        Checks for statements that end with an unnecessary semicolon.

        ","tags":["E703"]},{"location":"rules/useless-semicolon/#why-is-this-bad","title":"Why is this bad?","text":"

        A trailing semicolon is unnecessary and should be removed.

        ","tags":["E703"]},{"location":"rules/useless-semicolon/#example","title":"Example","text":"
        do_four();  # useless semicolon\n

        Use instead:

        do_four()\n
        ","tags":["E703"]},{"location":"rules/useless-try-except/","title":"useless-try-except (TRY203)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY203"]},{"location":"rules/useless-try-except/#what-it-does","title":"What it does","text":"

        Checks for immediate uses of raise within exception handlers.

        ","tags":["TRY203"]},{"location":"rules/useless-try-except/#why-is-this-bad","title":"Why is this bad?","text":"

        Capturing an exception, only to immediately reraise it, has no effect. Instead, remove the error-handling code and let the exception propagate upwards without the unnecessary try-except block.

        ","tags":["TRY203"]},{"location":"rules/useless-try-except/#example","title":"Example","text":"
        def foo():\n    try:\n        bar()\n    except NotImplementedError:\n        raise\n

        Use instead:

        def foo():\n    bar()\n
        ","tags":["TRY203"]},{"location":"rules/useless-with-lock/","title":"useless-with-lock (PLW2101)","text":"

        Derived from the Pylint linter.

        ","tags":["PLW2101"]},{"location":"rules/useless-with-lock/#what-it-does","title":"What it does","text":"

        Checks for lock objects that are created and immediately discarded in with statements.

        ","tags":["PLW2101"]},{"location":"rules/useless-with-lock/#why-is-this-bad","title":"Why is this bad?","text":"

        Creating a lock (via threading.Lock or similar) in a with statement has no effect, as locks are only relevant when shared between threads.

        Instead, assign the lock to a variable outside the with statement, and share that variable between threads.

        ","tags":["PLW2101"]},{"location":"rules/useless-with-lock/#example","title":"Example","text":"
        import threading\n\ncounter = 0\n\n\ndef increment():\n    global counter\n\n    with threading.Lock():\n        counter += 1\n

        Use instead:

        import threading\n\ncounter = 0\nlock = threading.Lock()\n\n\ndef increment():\n    global counter\n\n    with lock:\n        counter += 1\n
        ","tags":["PLW2101"]},{"location":"rules/useless-with-lock/#references","title":"References","text":"
        • Python documentation: Lock Objects
        ","tags":["PLW2101"]},{"location":"rules/utf8-encoding-declaration/","title":"utf8-encoding-declaration (UP009)","text":"

        Derived from the pyupgrade linter.

        Fix is always available.

        ","tags":["UP009"]},{"location":"rules/utf8-encoding-declaration/#what-it-does","title":"What it does","text":"

        Checks for unnecessary UTF-8 encoding declarations.

        ","tags":["UP009"]},{"location":"rules/utf8-encoding-declaration/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 3120 makes UTF-8 the default encoding, so a UTF-8 encoding declaration is unnecessary.

        ","tags":["UP009"]},{"location":"rules/utf8-encoding-declaration/#example","title":"Example","text":"
        # -*- coding: utf-8 -*-\nprint(\"Hello, world!\")\n

        Use instead:

        print(\"Hello, world!\")\n
        ","tags":["UP009"]},{"location":"rules/verbose-decimal-constructor/","title":"verbose-decimal-constructor (FURB157)","text":"

        Derived from the refurb linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB157"]},{"location":"rules/verbose-decimal-constructor/#what-it-does","title":"What it does","text":"

        Checks for unnecessary string literal or float casts in Decimal constructors.

        ","tags":["FURB157"]},{"location":"rules/verbose-decimal-constructor/#why-is-this-bad","title":"Why is this bad?","text":"

        The Decimal constructor accepts a variety of arguments, including integers, floats, and strings. However, it's not necessary to cast integer literals to strings when passing them to the Decimal.

        Similarly, Decimal accepts inf, -inf, and nan as string literals, so there's no need to wrap those values in a float call when passing them to the Decimal constructor.

        Prefer the more concise form of argument passing for Decimal constructors, as it's more readable and idiomatic.

        ","tags":["FURB157"]},{"location":"rules/verbose-decimal-constructor/#example","title":"Example","text":"
        Decimal(\"0\")\nDecimal(float(\"Infinity\"))\n

        Use instead:

        Decimal(0)\nDecimal(\"Infinity\")\n
        ","tags":["FURB157"]},{"location":"rules/verbose-decimal-constructor/#references","title":"References","text":"
        • Python documentation: decimal
        ","tags":["FURB157"]},{"location":"rules/verbose-log-message/","title":"verbose-log-message (TRY401)","text":"

        Derived from the tryceratops linter.

        ","tags":["TRY401"]},{"location":"rules/verbose-log-message/#what-it-does","title":"What it does","text":"

        Checks for excessive logging of exception objects.

        ","tags":["TRY401"]},{"location":"rules/verbose-log-message/#why-is-this-bad","title":"Why is this bad?","text":"

        When logging exceptions via logging.exception, the exception object is logged automatically. Including the exception object in the log message is redundant and can lead to excessive logging.

        ","tags":["TRY401"]},{"location":"rules/verbose-log-message/#example","title":"Example","text":"
        try:\n    ...\nexcept ValueError as e:\n    logger.exception(f\"Found an error: {e}\")\n

        Use instead:

        try:\n    ...\nexcept ValueError:\n    logger.exception(\"Found an error\")\n
        ","tags":["TRY401"]},{"location":"rules/verbose-raise/","title":"verbose-raise (TRY201)","text":"

        Derived from the tryceratops linter.

        Fix is always available.

        ","tags":["TRY201"]},{"location":"rules/verbose-raise/#what-it-does","title":"What it does","text":"

        Checks for needless exception names in raise statements.

        ","tags":["TRY201"]},{"location":"rules/verbose-raise/#why-is-this-bad","title":"Why is this bad?","text":"

        It's redundant to specify the exception name in a raise statement if the exception is being re-raised.

        ","tags":["TRY201"]},{"location":"rules/verbose-raise/#example","title":"Example","text":"
        def foo():\n    try:\n        ...\n    except ValueError as exc:\n        raise exc\n

        Use instead:

        def foo():\n    try:\n        ...\n    except ValueError:\n        raise\n
        ","tags":["TRY201"]},{"location":"rules/verbose-raise/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as it doesn't properly handle bound exceptions that are shadowed between the except and raise statements.

        ","tags":["TRY201"]},{"location":"rules/wait-for-process-in-async-function/","title":"wait-for-process-in-async-function (ASYNC222)","text":"

        Derived from the flake8-async linter.

        ","tags":["ASYNC222"]},{"location":"rules/wait-for-process-in-async-function/#what-it-does","title":"What it does","text":"

        Checks that async functions do not wait on processes with blocking methods.

        ","tags":["ASYNC222"]},{"location":"rules/wait-for-process-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Blocking an async function via a blocking call will block the entire event loop, preventing it from executing other tasks while waiting for the call to complete, negating the benefits of asynchronous programming.

        Instead of making a blocking call, use an equivalent asynchronous library or function, like trio.to_thread.run_sync() or anyio.to_thread.run_sync().

        ","tags":["ASYNC222"]},{"location":"rules/wait-for-process-in-async-function/#example","title":"Example","text":"
        async def foo():\n    os.waitpid(0)\n

        Use instead:

        def wait_for_process():\n    os.waitpid(0)\n\n\nasync def foo():\n    await asyncio.loop.run_in_executor(None, wait_for_process)\n
        ","tags":["ASYNC222"]},{"location":"rules/weak-cryptographic-key/","title":"weak-cryptographic-key (S505)","text":"

        Derived from the flake8-bandit linter.

        ","tags":["S505"]},{"location":"rules/weak-cryptographic-key/#what-it-does","title":"What it does","text":"

        Checks for uses of cryptographic keys with vulnerable key sizes.

        ","tags":["S505"]},{"location":"rules/weak-cryptographic-key/#why-is-this-bad","title":"Why is this bad?","text":"

        Small keys are easily breakable. For DSA and RSA, keys should be at least 2048 bits long. For EC, keys should be at least 224 bits long.

        ","tags":["S505"]},{"location":"rules/weak-cryptographic-key/#example","title":"Example","text":"
        from cryptography.hazmat.primitives.asymmetric import dsa, ec\n\ndsa.generate_private_key(key_size=512)\nec.generate_private_key(curve=ec.SECT163K1())\n

        Use instead:

        from cryptography.hazmat.primitives.asymmetric import dsa, ec\n\ndsa.generate_private_key(key_size=4096)\nec.generate_private_key(curve=ec.SECP384R1())\n
        ","tags":["S505"]},{"location":"rules/weak-cryptographic-key/#references","title":"References","text":"
        • CSRC: Transitioning the Use of Cryptographic Algorithms and Key Lengths
        ","tags":["S505"]},{"location":"rules/whitespace-after-decorator/","title":"whitespace-after-decorator (E204)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E204"]},{"location":"rules/whitespace-after-decorator/#what-it-does","title":"What it does","text":"

        Checks for trailing whitespace after a decorator's opening @.

        ","tags":["E204"]},{"location":"rules/whitespace-after-decorator/#why-is-this-bad","title":"Why is this bad?","text":"

        Including whitespace after the @ symbol is not compliant with PEP 8.

        ","tags":["E204"]},{"location":"rules/whitespace-after-decorator/#example","title":"Example","text":"
        @ decorator\ndef func():\n   pass\n

        Use instead:

        @decorator\ndef func():\n  pass\n
        ","tags":["E204"]},{"location":"rules/whitespace-after-open-bracket/","title":"whitespace-after-open-bracket (E201)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E201"]},{"location":"rules/whitespace-after-open-bracket/#what-it-does","title":"What it does","text":"

        Checks for the use of extraneous whitespace after \"(\", \"[\" or \"{\".

        ","tags":["E201"]},{"location":"rules/whitespace-after-open-bracket/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the omission of whitespace in the following cases:

        • \"Immediately inside parentheses, brackets or braces.\"
        • \"Immediately before a comma, semicolon, or colon.\"
        ","tags":["E201"]},{"location":"rules/whitespace-after-open-bracket/#example","title":"Example","text":"
        spam( ham[1], {eggs: 2})\nspam(ham[ 1], {eggs: 2})\nspam(ham[1], { eggs: 2})\n

        Use instead:

        spam(ham[1], {eggs: 2})\n
        ","tags":["E201"]},{"location":"rules/whitespace-before-close-bracket/","title":"whitespace-before-close-bracket (E202)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E202"]},{"location":"rules/whitespace-before-close-bracket/#what-it-does","title":"What it does","text":"

        Checks for the use of extraneous whitespace before \")\", \"]\" or \"}\".

        ","tags":["E202"]},{"location":"rules/whitespace-before-close-bracket/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the omission of whitespace in the following cases:

        • \"Immediately inside parentheses, brackets or braces.\"
        • \"Immediately before a comma, semicolon, or colon.\"
        ","tags":["E202"]},{"location":"rules/whitespace-before-close-bracket/#example","title":"Example","text":"
        spam(ham[1], {eggs: 2} )\nspam(ham[1 ], {eggs: 2})\nspam(ham[1], {eggs: 2 })\n

        Use instead:

        spam(ham[1], {eggs: 2})\n
        ","tags":["E202"]},{"location":"rules/whitespace-before-parameters/","title":"whitespace-before-parameters (E211)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E211"]},{"location":"rules/whitespace-before-parameters/#what-it-does","title":"What it does","text":"

        Checks for extraneous whitespace immediately preceding an open parenthesis or bracket.

        ","tags":["E211"]},{"location":"rules/whitespace-before-parameters/#why-is-this-bad","title":"Why is this bad?","text":"

        According to PEP 8, open parentheses and brackets should not be preceded by any trailing whitespace.

        ","tags":["E211"]},{"location":"rules/whitespace-before-parameters/#example","title":"Example","text":"
        spam (1)\n

        Use instead:

        spam(1)\n
        ","tags":["E211"]},{"location":"rules/whitespace-before-punctuation/","title":"whitespace-before-punctuation (E203)","text":"

        Derived from the pycodestyle linter.

        Fix is always available.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["E203"]},{"location":"rules/whitespace-before-punctuation/#what-it-does","title":"What it does","text":"

        Checks for the use of extraneous whitespace before \",\", \";\" or \":\".

        ","tags":["E203"]},{"location":"rules/whitespace-before-punctuation/#why-is-this-bad","title":"Why is this bad?","text":"

        PEP 8 recommends the omission of whitespace in the following cases:

        • \"Immediately inside parentheses, brackets or braces.\"
        • \"Immediately before a comma, semicolon, or colon.\"
        ","tags":["E203"]},{"location":"rules/whitespace-before-punctuation/#example","title":"Example","text":"
        if x == 4: print(x, y); x, y = y , x\n

        Use instead:

        if x == 4: print(x, y); x, y = y, x\n
        ","tags":["E203"]},{"location":"rules/write-whole-file/","title":"write-whole-file (FURB103)","text":"

        Derived from the refurb linter.

        This rule is unstable and in preview. The --preview flag is required for use.

        ","tags":["FURB103"]},{"location":"rules/write-whole-file/#what-it-does","title":"What it does","text":"

        Checks for uses of open and write that can be replaced by pathlib methods, like Path.write_text and Path.write_bytes.

        ","tags":["FURB103"]},{"location":"rules/write-whole-file/#why-is-this-bad","title":"Why is this bad?","text":"

        When writing a single string to a file, it's simpler and more concise to use pathlib methods like Path.write_text and Path.write_bytes instead of open and write calls via with statements.

        ","tags":["FURB103"]},{"location":"rules/write-whole-file/#example","title":"Example","text":"
        with open(filename, \"w\") as f:\n    f.write(contents)\n

        Use instead:

        from pathlib import Path\n\nPath(filename).write_text(contents)\n
        ","tags":["FURB103"]},{"location":"rules/write-whole-file/#references","title":"References","text":"
        • Python documentation: Path.write_bytes
        • Python documentation: Path.write_text
        ","tags":["FURB103"]},{"location":"rules/wrong-tuple-length-version-comparison/","title":"wrong-tuple-length-version-comparison (PYI005)","text":"

        Derived from the flake8-pyi linter.

        ","tags":["PYI005"]},{"location":"rules/wrong-tuple-length-version-comparison/#what-it-does","title":"What it does","text":"

        Checks for Python version comparisons that compare against a tuple of the wrong length.

        ","tags":["PYI005"]},{"location":"rules/wrong-tuple-length-version-comparison/#why-is-this-bad","title":"Why is this bad?","text":"

        Stub files support simple conditionals to test for differences in Python versions and platforms. When comparing against sys.version_info, avoid comparing against tuples of the wrong length, which can lead to unexpected behavior.

        ","tags":["PYI005"]},{"location":"rules/wrong-tuple-length-version-comparison/#example","title":"Example","text":"
        import sys\n\nif sys.version_info[:2] == (3,): ...\n

        Use instead:

        import sys\n\nif sys.version_info[0] == 3: ...\n
        ","tags":["PYI005"]},{"location":"rules/wrong-tuple-length-version-comparison/#references","title":"References","text":"
        • Typing documentation: Version and Platform checking
        ","tags":["PYI005"]},{"location":"rules/yield-from-in-async-function/","title":"yield-from-in-async-function (PLE1700)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE1700"]},{"location":"rules/yield-from-in-async-function/#what-it-does","title":"What it does","text":"

        Checks for uses of yield from in async functions.

        ","tags":["PLE1700"]},{"location":"rules/yield-from-in-async-function/#why-is-this-bad","title":"Why is this bad?","text":"

        Python doesn't support the use of yield from in async functions, and will raise a SyntaxError in such cases.

        Instead, considering refactoring the code to use an async for loop instead.

        ","tags":["PLE1700"]},{"location":"rules/yield-from-in-async-function/#example","title":"Example","text":"
        async def numbers():\n    yield from [1, 2, 3, 4, 5]\n

        Use instead:

        async def numbers():\n    async for number in [1, 2, 3, 4, 5]:\n        yield number\n
        ","tags":["PLE1700"]},{"location":"rules/yield-in-for-loop/","title":"yield-in-for-loop (UP028)","text":"

        Derived from the pyupgrade linter.

        Fix is sometimes available.

        ","tags":["UP028"]},{"location":"rules/yield-in-for-loop/#what-it-does","title":"What it does","text":"

        Checks for for loops that can be replaced with yield from expressions.

        ","tags":["UP028"]},{"location":"rules/yield-in-for-loop/#why-is-this-bad","title":"Why is this bad?","text":"

        If a for loop only contains a yield statement, it can be replaced with a yield from expression, which is more concise and idiomatic.

        ","tags":["UP028"]},{"location":"rules/yield-in-for-loop/#example","title":"Example","text":"
        for x in foo:\n    yield x\n\nglobal y\nfor y in foo:\n    yield y\n

        Use instead:

        yield from foo\n\nfor _element in foo:\n    y = _element\n    yield y\n
        ","tags":["UP028"]},{"location":"rules/yield-in-for-loop/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe, as converting a for loop to a yield from expression can change the behavior of the program in rare cases. For example, if a generator is being sent values via send, then rewriting to a yield from could lead to an attribute error if the underlying generator does not implement the send method.

        Additionally, if at least one target is global or nonlocal, no fix will be offered.

        In most cases, however, the fix is safe, and such a modification should have no effect on the behavior of the program.

        ","tags":["UP028"]},{"location":"rules/yield-in-for-loop/#references","title":"References","text":"
        • Python documentation: The yield statement
        • PEP 380 \u2013 Syntax for Delegating to a Subgenerator
        ","tags":["UP028"]},{"location":"rules/yield-in-init/","title":"yield-in-init (PLE0100)","text":"

        Derived from the Pylint linter.

        ","tags":["PLE0100"]},{"location":"rules/yield-in-init/#what-it-does","title":"What it does","text":"

        Checks for __init__ methods that are turned into generators by the inclusion of yield or yield from expressions.

        ","tags":["PLE0100"]},{"location":"rules/yield-in-init/#why-is-this-bad","title":"Why is this bad?","text":"

        The __init__ method is the constructor for a given Python class, responsible for initializing, rather than creating, new objects.

        The __init__ method has to return None. By including a yield or yield from expression in an __init__, the method will return a generator object when called at runtime, resulting in a runtime error.

        ","tags":["PLE0100"]},{"location":"rules/yield-in-init/#example","title":"Example","text":"
        class InitIsGenerator:\n    def __init__(self, i):\n        yield i\n
        ","tags":["PLE0100"]},{"location":"rules/yield-in-init/#references","title":"References","text":"
        • CodeQL: py-init-method-is-generator
        ","tags":["PLE0100"]},{"location":"rules/yield-outside-function/","title":"yield-outside-function (F704)","text":"

        Derived from the Pyflakes linter.

        ","tags":["F704"]},{"location":"rules/yield-outside-function/#what-it-does","title":"What it does","text":"

        Checks for yield, yield from, and await usages outside of functions.

        ","tags":["F704"]},{"location":"rules/yield-outside-function/#why-is-this-bad","title":"Why is this bad?","text":"

        The use of yield, yield from, or await outside of a function will raise a SyntaxError.

        ","tags":["F704"]},{"location":"rules/yield-outside-function/#example","title":"Example","text":"
        class Foo:\n    yield 1\n
        ","tags":["F704"]},{"location":"rules/yield-outside-function/#notebook-behavior","title":"Notebook behavior","text":"

        As an exception, await is allowed at the top level of a Jupyter notebook (see: autoawait).

        ","tags":["F704"]},{"location":"rules/yield-outside-function/#references","title":"References","text":"
        • Python documentation: yield
        ","tags":["F704"]},{"location":"rules/yoda-conditions/","title":"yoda-conditions (SIM300)","text":"

        Derived from the flake8-simplify linter.

        Fix is sometimes available.

        ","tags":["SIM300"]},{"location":"rules/yoda-conditions/#what-it-does","title":"What it does","text":"

        Checks for conditions that position a constant on the left-hand side of the comparison operator, rather than the right-hand side.

        ","tags":["SIM300"]},{"location":"rules/yoda-conditions/#why-is-this-bad","title":"Why is this bad?","text":"

        These conditions (sometimes referred to as \"Yoda conditions\") are less readable than conditions that place the variable on the left-hand side of the comparison operator.

        In some languages, Yoda conditions are used to prevent accidental assignment in conditions (i.e., accidental uses of the = operator, instead of the == operator). However, Python does not allow assignments in conditions unless using the := operator, so Yoda conditions provide no benefit in this regard.

        ","tags":["SIM300"]},{"location":"rules/yoda-conditions/#example","title":"Example","text":"
        if \"Foo\" == foo:\n    ...\n

        Use instead:

        if foo == \"Foo\":\n    ...\n
        ","tags":["SIM300"]},{"location":"rules/yoda-conditions/#references","title":"References","text":"
        • Python documentation: Comparisons
        • Python documentation: Assignment statements
        ","tags":["SIM300"]},{"location":"rules/zip-dict-keys-and-values/","title":"zip-dict-keys-and-values (SIM911)","text":"

        Derived from the flake8-simplify linter.

        Fix is always available.

        ","tags":["SIM911"]},{"location":"rules/zip-dict-keys-and-values/#what-it-does","title":"What it does","text":"

        Checks for use of zip() to iterate over keys and values of a dictionary at once.

        ","tags":["SIM911"]},{"location":"rules/zip-dict-keys-and-values/#why-is-this-bad","title":"Why is this bad?","text":"

        The dict type provides an .items() method which is faster and more readable.

        ","tags":["SIM911"]},{"location":"rules/zip-dict-keys-and-values/#example","title":"Example","text":"
        flag_stars = {\"USA\": 50, \"Slovenia\": 3, \"Panama\": 2, \"Australia\": 6}\n\nfor country, stars in zip(flag_stars.keys(), flag_stars.values()):\n    print(f\"{country}'s flag has {stars} stars.\")\n

        Use instead:

        flag_stars = {\"USA\": 50, \"Slovenia\": 3, \"Panama\": 2, \"Australia\": 6}\n\nfor country, stars in flag_stars.items():\n    print(f\"{country}'s flag has {stars} stars.\")\n
        ","tags":["SIM911"]},{"location":"rules/zip-dict-keys-and-values/#references","title":"References","text":"
        • Python documentation: dict.items
        ","tags":["SIM911"]},{"location":"rules/zip-instead-of-pairwise/","title":"zip-instead-of-pairwise (RUF007)","text":"

        Fix is sometimes available.

        ","tags":["RUF007"]},{"location":"rules/zip-instead-of-pairwise/#what-it-does","title":"What it does","text":"

        Checks for use of zip() to iterate over successive pairs of elements.

        ","tags":["RUF007"]},{"location":"rules/zip-instead-of-pairwise/#why-is-this-bad","title":"Why is this bad?","text":"

        When iterating over successive pairs of elements, prefer itertools.pairwise() over zip().

        itertools.pairwise() is more readable and conveys the intent of the code more clearly.

        ","tags":["RUF007"]},{"location":"rules/zip-instead-of-pairwise/#example","title":"Example","text":"
        letters = \"ABCD\"\nzip(letters, letters[1:])  # (\"A\", \"B\"), (\"B\", \"C\"), (\"C\", \"D\")\n

        Use instead:

        from itertools import pairwise\n\nletters = \"ABCD\"\npairwise(letters)  # (\"A\", \"B\"), (\"B\", \"C\"), (\"C\", \"D\")\n
        ","tags":["RUF007"]},{"location":"rules/zip-instead-of-pairwise/#fix-safety","title":"Fix safety","text":"

        The fix is always marked unsafe because it assumes that slicing an object (e.g., obj[1:]) produces a value with the same type and iteration behavior as the original object, which is not guaranteed for user-defined types that override __getitem__ without properly handling slices. Moreover, the fix could delete comments.

        ","tags":["RUF007"]},{"location":"rules/zip-instead-of-pairwise/#references","title":"References","text":"
        • Python documentation: itertools.pairwise
        ","tags":["RUF007"]},{"location":"rules/zip-without-explicit-strict/","title":"zip-without-explicit-strict (B905)","text":"

        Derived from the flake8-bugbear linter.

        Fix is always available.

        ","tags":["B905"]},{"location":"rules/zip-without-explicit-strict/#what-it-does","title":"What it does","text":"

        Checks for zip calls without an explicit strict parameter.

        ","tags":["B905"]},{"location":"rules/zip-without-explicit-strict/#why-is-this-bad","title":"Why is this bad?","text":"

        By default, if the iterables passed to zip are of different lengths, the resulting iterator will be silently truncated to the length of the shortest iterable. This can lead to subtle bugs.

        Pass strict=True to raise a ValueError if the iterables are of non-uniform length. Alternatively, if the iterables are deliberately of different lengths, pass strict=False to make the intention explicit.

        ","tags":["B905"]},{"location":"rules/zip-without-explicit-strict/#example","title":"Example","text":"
        zip(a, b)\n

        Use instead:

        zip(a, b, strict=True)\n
        ","tags":["B905"]},{"location":"rules/zip-without-explicit-strict/#fix-safety","title":"Fix safety","text":"

        This rule's fix is marked as unsafe for zip calls that contain **kwargs, as adding a strict keyword argument to such a call may lead to a duplicate keyword argument error.

        ","tags":["B905"]},{"location":"rules/zip-without-explicit-strict/#references","title":"References","text":"
        • Python documentation: zip
        ","tags":["B905"]}]} \ No newline at end of file diff --git a/site/ruff/sitemap.xml b/site/ruff/sitemap.xml index 8430f340..9ac76910 100644 --- a/site/ruff/sitemap.xml +++ b/site/ruff/sitemap.xml @@ -2,3762 +2,3762 @@ https://docs.astral.sh/ruff/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/configuration/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/contributing/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/faq/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/formatter/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/installation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/integrations/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/linter/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/preview/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/settings/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/tutorial/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/versioning/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/editors/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/editors/features/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/editors/migration/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/editors/settings/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/editors/setup/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/formatter/black/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/abstract-base-class-without-abstract-method/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/airflow-dag-no-schedule-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/airflow-variable-name-task-id-mismatch/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/airflow3-moved-to-provider/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/airflow3-removal/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/airflow3-suggested-to-move-to-provider/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/airflow3-suggested-update/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ambiguous-class-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ambiguous-function-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ambiguous-unicode-character-comment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ambiguous-unicode-character-docstring/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ambiguous-unicode-character-string/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ambiguous-variable-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/and-or-ternary/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/any-eq-ne-annotation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/any-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/argument-default-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/assert-false/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/assert-on-string-literal/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/assert-raises-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/assert-tuple/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/assert-with-print-message/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/assert/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/assignment-default-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/assignment-in-assert/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/assignment-to-os-environ/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/async-busy-wait/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/async-function-with-timeout/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/async-zero-sleep/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/asyncio-dangling-task/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/avoidable-escaped-quote/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/await-outside-async/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-dunder-method-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-exit-annotation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-file-permissions/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-open-mode/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-quotes-docstring/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-quotes-inline-string/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-quotes-multiline-string/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-staticmethod-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-str-strip-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-string-format-character/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-string-format-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-version-info-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bad-version-info-order/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/banned-api/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/banned-import-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/banned-import-from/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/banned-module-level-imports/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bare-except/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/batched-without-explicit-strict/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bidirectional-unicode/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/binary-op-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/bit-count/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blank-line-after-decorator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blank-line-after-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blank-line-before-class/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blank-line-before-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blank-line-between-methods/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blank-line-with-whitespace/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blank-lines-after-function-or-class/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blank-lines-before-nested-definition/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blank-lines-between-header-and-content/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blank-lines-top-level/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blanket-noqa/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blanket-type-ignore/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blind-except/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blocking-http-call-in-async-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blocking-open-call-in-async-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/blocking-sleep-in-async-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/boolean-chained-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/boolean-default-value-positional-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/boolean-positional-value-in-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/boolean-type-hint-positional-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/break-outside-loop/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/builtin-argument-shadowing/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/builtin-attribute-shadowing/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/builtin-import-shadowing/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/builtin-lambda-argument-shadowing/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/builtin-open/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/builtin-variable-shadowing/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/byte-string-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/cached-instance-method/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/call-date-fromtimestamp/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/call-date-today/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/call-datetime-fromtimestamp/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/call-datetime-now-without-tzinfo/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/call-datetime-strptime-without-zone/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/call-datetime-today/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/call-datetime-utcfromtimestamp/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/call-datetime-utcnow/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/call-datetime-without-tzinfo/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/call-with-shell-equals-true/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/camelcase-imported-as-acronym/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/camelcase-imported-as-constant/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/camelcase-imported-as-lowercase/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/cancel-scope-no-checkpoint/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/check-and-remove-from-set/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/class-as-data-structure/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/class-with-mixed-type-vars/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/collapsible-else-if/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/collapsible-if/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/collection-literal-concatenation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/collections-named-tuple/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/commented-out-code/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/compare-to-empty-string/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/compare-with-tuple/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/comparison-of-constant/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/comparison-with-itself/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/complex-assignment-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/complex-if-statement-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/complex-structure/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/constant-imported-as-non-constant/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/continue-in-finally/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/continue-outside-loop/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/convert-named-tuple-functional-to-class/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/convert-typed-dict-functional-to-class/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/create-subprocess-in-async-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/custom-type-var-for-self/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/dataclass-enum/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/datetime-min-max/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/datetime-timezone-utc/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/debugger/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/decimal-from-float-literal/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/default-except-not-last/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/default-factory-kwarg/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/delete-full-slice/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/deprecated-c-element-tree/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/deprecated-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/deprecated-log-warn/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/deprecated-mock-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/deprecated-unittest-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/dict-get-with-none-default/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/dict-index-missing-items/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/dict-iter-missing-items/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/direct-logger-instantiation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/django-all-with-model-form/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/django-exclude-with-model-form/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/django-extra/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/django-locals-in-render-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/django-model-without-dunder-str/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/django-non-leading-receiver-decorator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/django-nullable-model-string-field/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/django-raw-sql/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/django-unordered-body-content-in-model/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/doc-line-too-long/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/docstring-extraneous-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/docstring-extraneous-returns/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/docstring-extraneous-yields/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/docstring-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/docstring-missing-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/docstring-missing-returns/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/docstring-missing-yields/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/docstring-starts-with-this/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/docstring-tab-indentation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/dot-format-in-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/double-negation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/dunder-function-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/duplicate-bases/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/duplicate-class-field-definition/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/duplicate-handler-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/duplicate-isinstance-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/duplicate-literal-member/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/duplicate-try-block-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/duplicate-union-member/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/duplicate-value/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ellipsis-in-non-empty-class-body/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/empty-comment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/empty-docstring-section/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/empty-docstring/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/empty-method-without-abstract-decorator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/empty-type-checking-block/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/enumerate-for-loop/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/eq-without-hash/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/error-instead-of-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/error-suffix-on-exception-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/escape-sequence-in-docstring/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/eval/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/exc-info-outside-except-handler/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/except-with-empty-tuple/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/except-with-non-exception-classes/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/exception-without-exc-info/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/exec-builtin/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/explicit-f-string-type-conversion/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/explicit-string-concatenation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/expr-and-false/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/expr-and-not-expr/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/expr-or-not-expr/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/expr-or-true/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/expressions-in-star-assignment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/extraneous-parentheses/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/f-string-docstring/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/f-string-in-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/f-string-in-get-text-func-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/f-string-missing-placeholders/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/f-string-number-format/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/f-string/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/falsy-dict-get-fallback/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/fast-api-non-annotated-dependency/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/fast-api-redundant-response-model/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/fast-api-unused-path-parameter/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/first-word-uncapitalized/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/flask-debug-true/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/for-loop-set-mutations/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/for-loop-writes/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/format-in-get-text-func-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/format-literals/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/forward-annotation-syntax-error/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/fromisoformat-replace-z/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/function-call-in-dataclass-default-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/function-call-in-default-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/function-uses-loop-variable/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/future-annotations-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/future-feature-not-defined/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/future-required-type-annotation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/future-rewritable-type-annotation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/generator-return-from-iter-method/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/generic-not-last-base-class/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/get-attr-with-constant/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/glob/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/global-at-module-level/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/global-statement/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/global-variable-not-assigned/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/hardcoded-bind-all-interfaces/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/hardcoded-password-default/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/hardcoded-password-func-arg/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/hardcoded-password-string/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/hardcoded-sql-expression/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/hardcoded-string-charset/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/hardcoded-temp-file/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/hashlib-digest-hex/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/hashlib-insecure-hash-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-else-block-instead-of-dict-get/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-else-block-instead-of-dict-lookup/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-else-block-instead-of-if-exp/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-exp-instead-of-or-operator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-expr-min-max/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-expr-with-false-true/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-expr-with-true-false/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-expr-with-twisted-arms/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-key-in-dict-del/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-stmt-min-max/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-tuple/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/if-with-same-arms/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/implicit-class-var-in-dataclass/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/implicit-cwd/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/implicit-namespace-package/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/implicit-optional/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/implicit-return-value/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/implicit-return/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/import-outside-top-level/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/import-private-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/import-self/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/import-shadowed-by-loop-var/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/in-dict-keys/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/in-empty-collection/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/incorrect-blank-line-after-class/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/incorrect-blank-line-before-class/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/incorrect-dict-iterator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/incorrectly-parenthesized-tuple-in-subscript/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/indentation-with-invalid-multiple-comment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/indentation-with-invalid-multiple/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/indented-form-feed/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/int-on-sliced-str/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-all-format/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-all-object/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-argument-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-assert-message-literal-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-bool-return-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-bytes-return-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-character-backspace/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-character-esc/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-character-nul/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-character-sub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-character-zero-width-space/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-class-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-envvar-default/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-envvar-value/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-escape-sequence/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-first-argument-name-for-class-method/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-first-argument-name-for-method/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-formatter-suppression-comment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-function-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-get-logger-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-hash-return-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-index-return-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-index-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-length-return-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-mock-access/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-module-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-pathlib-with-suffix/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-print-syntax/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-pyproject-toml/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-rule-code/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-str-return-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-todo-capitalization/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/invalid-todo-tag/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/io-error/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/is-literal/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/isinstance-type-none/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/iter-method-return-iterable/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/iteration-over-set/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/jinja2-autoescape-false/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/jump-statement-in-finally/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/lambda-assignment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/late-future-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/len-test/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/line-contains-fixme/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/line-contains-hack/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/line-contains-todo/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/line-contains-xxx/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/line-too-long/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/list-reverse-copy/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/literal-membership/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/load-before-global-declaration/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/log-exception-outside-except-handler/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/logging-config-insecure-listen/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/logging-exc-info/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/logging-extra-attr-clash/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/logging-f-string/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/logging-percent-format/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/logging-redundant-exc-info/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/logging-string-concat/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/logging-string-format/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/logging-too-few-args/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/logging-too-many-args/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/logging-warn/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/long-sleep-not-forever/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/loop-iterator-mutation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/loop-variable-overrides-iterator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/lowercase-imported-as-non-lowercase/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/lru-cache-with-maxsize-none/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/lru-cache-without-parameters/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/magic-value-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/mako-templates/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/manual-dict-comprehension/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/manual-from-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/manual-list-comprehension/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/manual-list-copy/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/map-int-version-parsing/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/math-constant/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/meta-class-abc-meta/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/mismatched-section-underline-length/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/misplaced-bare-raise/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-blank-line-after-last-section/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-blank-line-after-summary/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-copyright-notice/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-dashed-underline-after-section/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-f-string-syntax/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-new-line-after-section-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-newline-at-end-of-file/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-required-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-return-type-class-method/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-return-type-private-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-return-type-special-method/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-return-type-static-method/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-return-type-undocumented-public-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-section-name-colon/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-section-underline-after-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-space-after-todo-colon/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-terminal-punctuation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-todo-author/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-todo-colon/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-todo-description/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-todo-link/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-trailing-comma/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-trailing-period/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-type-args/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-type-cls/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-type-function-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-type-kwargs/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-type-self/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-whitespace-after-keyword/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-whitespace-around-arithmetic-operator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-whitespace-around-bitwise-or-shift-operator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-whitespace-around-modulo-operator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-whitespace-around-operator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-whitespace-around-parameter-equals/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/missing-whitespace/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/mixed-case-variable-in-class-scope/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/mixed-case-variable-in-global-scope/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/mixed-spaces-and-tabs/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/modified-iterating-set/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/module-import-not-at-top-of-file/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multi-line-implicit-string-concatenation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multi-line-summary-first-line/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multi-line-summary-second-line/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multi-value-repeated-key-literal/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multi-value-repeated-key-variable/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-imports-on-one-line/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-leading-hashes-for-block-comment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-spaces-after-comma/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-spaces-after-keyword/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-spaces-after-operator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-spaces-before-keyword/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-spaces-before-operator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-starred-expressions/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-starts-ends-with/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-statements-on-one-line-colon/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-statements-on-one-line-semicolon/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/multiple-with-statements/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/mutable-argument-default/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/mutable-class-default/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/mutable-contextvar-default/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/mutable-dataclass-default/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/mutable-fromkeys-value/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/named-expr-without-context/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/nan-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/native-literals/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/needless-bool/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/needless-else/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/negate-equal-op/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/negate-not-equal-op/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/nested-min-max/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/never-union/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/new-line-after-last-paragraph/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-blank-line-after-section/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-blank-line-before-section/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-classmethod-decorator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-explicit-stacklevel/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-indented-block-comment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-indented-block/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-return-argument-annotation-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-self-use/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-slots-in-namedtuple-subclass/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-slots-in-str-subclass/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-slots-in-tuple-subclass/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-space-after-block-comment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-space-after-inline-comment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/no-staticmethod-decorator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-ascii-import-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-ascii-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-augmented-assignment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-capitalized-section-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-empty-stub-body/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-imperative-mood/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-lowercase-variable-in-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-pep585-annotation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-pep604-annotation-optional/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-pep604-annotation-union/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-pep604-isinstance/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-pep646-unpack/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-pep695-generic-class/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-pep695-generic-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-pep695-type-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-self-return-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-slot-assignment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/non-unique-enums/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/none-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/none-not-at-end-of-union/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/nonlocal-and-global/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/nonlocal-without-binding/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/not-in-test/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/not-is-test/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/numeric-literal-too-long/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/numpy-deprecated-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/numpy-deprecated-type-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/numpy-legacy-random/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/numpy2-deprecation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/open-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/open-file-with-context-handler/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-chmod/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-error-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-getcwd/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-listdir/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-makedirs/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-mkdir/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-abspath/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-basename/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-dirname/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-exists/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-expanduser/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-getatime/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-getctime/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-getmtime/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-getsize/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-isabs/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-isdir/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-isfile/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-islink/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-join/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-samefile/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-path-splitext/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-readlink/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-remove/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-rename/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-replace/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-rmdir/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-sep-split/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-stat/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/os-unlink/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/outdated-version-block/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/over-indentation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/over-indented/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/overindented-section-underline/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/overindented-section/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/overload-with-docstring/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/p-print/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-df-variable-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-nunique-constant-series-check/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-use-of-dot-at/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-use-of-dot-iat/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-use-of-dot-is-null/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-use-of-dot-ix/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-use-of-dot-not-null/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-use-of-dot-pivot-or-unstack/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-use-of-dot-read-table/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-use-of-dot-stack/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-use-of-dot-values/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-use-of-inplace-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pandas-use-of-pd-merge/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/paramiko-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/parenthesize-chained-operators/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pass-in-class-body/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pass-statement-stub-body/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/patch-version-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/path-constructor-current-directory/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pep484-style-positional-only-parameter/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/percent-format-expected-mapping/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/percent-format-expected-sequence/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/percent-format-extra-named-arguments/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/percent-format-invalid-format/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/percent-format-missing-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/percent-format-mixed-positional-and-named/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/percent-format-positional-count-mismatch/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/percent-format-star-requires-sequence/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/percent-format-unsupported-format-character/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/post-init-default/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/potential-index-error/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/print-empty-string/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/print/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/printf-in-get-text-func-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/printf-string-formatting/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/private-member-access/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/private-type-parameter/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/prohibited-trailing-comma/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/property-with-parameters/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/py-path/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-assert-always-false/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-assert-in-except/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-composite-assertion/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-deprecated-yield-fixture/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-duplicate-parametrize-test-cases/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-erroneous-use-fixtures-on-fixture/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-extraneous-scope-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-fail-without-message/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-fixture-finalizer-callback/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-fixture-incorrect-parentheses-style/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-fixture-param-without-value/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-fixture-positional-args/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-incorrect-fixture-name-underscore/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-incorrect-mark-parentheses-style/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-incorrect-pytest-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-missing-fixture-name-underscore/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-parameter-with-default-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-parametrize-names-wrong-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-parametrize-values-wrong-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-patch-with-lambda/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-raises-ambiguous-pattern/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-raises-too-broad/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-raises-with-multiple-statements/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-raises-without-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-unittest-assertion/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-unittest-raises-assertion/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-unnecessary-asyncio-mark-on-fixture/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-use-fixtures-without-parameters/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-useless-yield-fixture/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-warns-too-broad/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-warns-with-multiple-statements/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/pytest-warns-without-warning/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/quadratic-list-summation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/quoted-annotation-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/quoted-annotation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/quoted-type-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/raise-literal/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/raise-not-implemented/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/raise-vanilla-args/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/raise-vanilla-class/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/raise-within-try/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/raise-without-from-inside-except/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/raw-string-in-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/re-sub-positional-args/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/read-whole-file/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/readlines-in-for/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redeclared-assigned-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redefined-argument-from-local/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redefined-loop-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redefined-slots-in-subclass/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redefined-while-unused/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redirected-noqa/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redundant-backslash/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redundant-bool-literal/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redundant-final-literal/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redundant-literal-union/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redundant-log-base/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redundant-none-literal/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redundant-numeric-union/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redundant-open-modes/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/redundant-tuple-in-exception-handler/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/regex-flag-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/reimplemented-builtin/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/reimplemented-container-builtin/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/reimplemented-operator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/reimplemented-starmap/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/relative-imports/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/repeated-append/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/repeated-equality-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/repeated-global/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/repeated-isinstance-calls/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/repeated-keyword-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/replace-stdout-stderr/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/replace-str-enum/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/replace-universal-newlines/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/request-with-no-cert-validation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/request-without-timeout/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/reraise-no-cause/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/return-in-generator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/return-in-init/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/return-in-try-except-finally/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/return-outside-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/reuse-of-groupby-generator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/root-logger-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ruff-static-key-dict-comprehension/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ruff-unsafe-markup-use/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/run-process-in-async-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/runtime-cast-value/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/runtime-import-in-type-checking-block/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/runtime-string-union/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/self-assigning-variable/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/self-or-cls-assignment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/set-attr-with-constant/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/shallow-copy-environ/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/shebang-leading-whitespace/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/shebang-missing-executable-file/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/shebang-missing-python/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/shebang-not-executable/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/shebang-not-first-line/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/signature-in-docstring/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/single-item-membership-test/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/single-line-implicit-string-concatenation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/single-string-slots/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/singledispatch-method/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/singledispatchmethod-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/six-py3/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/slice-copy/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/slice-to-remove-prefix-or-suffix/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/snake-case-type-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/snmp-insecure-version/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/snmp-weak-cryptography/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/sorted-min-max/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/split-static-string/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ssh-no-host-key-verification/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ssl-insecure-version/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ssl-with-bad-defaults/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/ssl-with-no-version/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/star-arg-unpacking-after-keyword-arg/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/starmap-zip/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/start-process-with-a-shell/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/start-process-with-no-shell/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/start-process-with-partial-path/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/static-join-to-f-string/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/static-key-dict-comprehension/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/stdlib-module-shadowing/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/str-or-repr-defined-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/string-dot-format-extra-named-arguments/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/string-dot-format-extra-positional-arguments/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/string-dot-format-invalid-format/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/string-dot-format-missing-arguments/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/string-dot-format-mixing-automatic/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/string-or-bytes-too-long/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/strip-with-multi-characters/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/stub-body-multiple-statements/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/subclass-builtin/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/subprocess-popen-preexec-fn/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/subprocess-popen-with-shell-equals-true/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/subprocess-run-without-check/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/subprocess-without-shell-equals-true/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/super-call-with-parameters/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/super-without-brackets/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/superfluous-else-break/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/superfluous-else-continue/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/superfluous-else-raise/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/superfluous-else-return/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suppressible-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/surrounding-whitespace/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-eval-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-ftp-lib-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-ftplib-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-httpoxy-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-insecure-cipher-mode-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-insecure-cipher-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-insecure-hash-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-lxml-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-mark-safe-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-marshal-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-mktemp-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-non-cryptographic-random-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-pickle-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-pickle-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-pycrypto-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-pyghmi-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-subprocess-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-telnet-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-telnetlib-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-unverified-context-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-url-open-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xml-element-tree-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xml-etree-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xml-expat-builder-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xml-expat-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xml-expat-reader-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xml-mini-dom-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xml-minidom-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xml-pull-dom-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xml-pulldom-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xml-sax-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xml-sax-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xmlc-element-tree-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xmle-tree-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/suspicious-xmlrpc-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/syntax-error/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/sys-exit-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/sys-version-cmp-str10/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/sys-version-cmp-str3/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/sys-version-info-minor-cmp-int/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/sys-version-info0-eq3/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/sys-version-info1-cmp-int/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/sys-version-slice1/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/sys-version-slice3/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/sys-version0/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/sys-version2/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/t-suffixed-type-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/tab-after-comma/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/tab-after-keyword/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/tab-after-operator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/tab-before-keyword/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/tab-before-operator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/tab-indentation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/tarfile-unsafe-members/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/timeout-error-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-few-spaces-before-inline-comment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-many-arguments/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-many-blank-lines/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-many-boolean-expressions/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-many-branches/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-many-locals/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-many-nested-blocks/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-many-newlines-at-end-of-file/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-many-positional-arguments/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-many-public-methods/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-many-return-statements/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/too-many-statements/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/trailing-comma-on-bare-tuple/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/trailing-whitespace/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/trio-sync-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/triple-single-quotes/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/true-false-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/try-consider-else/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/try-except-continue/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/try-except-in-loop/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/try-except-pass/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/type-alias-without-annotation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/type-bivariance/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/type-check-without-type-error/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/type-comment-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/type-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/type-name-incorrect-variance/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/type-none-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/type-of-primitive/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/type-param-name-mismatch/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/typed-argument-default-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/typing-only-first-party-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/typing-only-standard-library-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/typing-only-third-party-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/typing-text-str-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unaliased-collections-abc-set-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unannotated-assignment-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unary-prefix-increment-decrement/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unassigned-special-variable-in-stub/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/uncapitalized-environment-variables/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unconventional-import-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undefined-export/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undefined-local-with-import-star-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undefined-local-with-import-star/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undefined-local-with-nested-import-star-usage/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undefined-local/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undefined-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/under-indentation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undocumented-magic-method/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undocumented-param/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undocumented-public-class/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undocumented-public-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undocumented-public-init/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undocumented-public-method/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undocumented-public-module/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undocumented-public-nested-class/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undocumented-public-package/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/undocumented-warn/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unexpected-indentation-comment/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unexpected-indentation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unexpected-spaces-around-keyword-parameter-equals/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unexpected-special-method-signature/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unicode-kind-prefix/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unintentional-type-annotation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unix-command-wildcard-injection/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-assign/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-builtin-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-call-around-sorted/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-cast-to-int/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-class-parentheses/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-collection-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-comprehension-in-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-comprehension/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-default-type-args/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-dict-comprehension-for-iterable/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-dict-index-lookup/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-dict-kwargs/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-direct-lambda-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-double-cast-or-process/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-dunder-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-empty-iterable-within-deque-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-encode-utf8/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-enumerate/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-escaped-quote/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-from-float/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-future-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-generator-dict/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-generator-list/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-generator-set/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-iterable-allocation-for-first-element/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-key-check/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-lambda/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-list-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-list-cast/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-list-comprehension-dict/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-list-comprehension-set/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-list-index-lookup/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-literal-dict/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-literal-set/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-literal-union/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-literal-within-dict-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-literal-within-list-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-literal-within-tuple-call/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-map/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-multiline-docstring/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-nested-literal/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-paren-on-raise-exception/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-placeholder/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-range-start/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-regular-expression/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-return-none/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-round/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-spread/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-subscript-reversal/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unnecessary-type-union/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unpacked-list-comprehension/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unprefixed-type-param/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unquoted-type-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unraw-re-pattern/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unrecognized-platform-check/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unrecognized-platform-name/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unrecognized-version-info-check/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unreliable-callable-check/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unsafe-markup-use/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unsafe-yaml-load/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unsorted-dunder-all/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unsorted-dunder-slots/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unsorted-imports/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unspecified-encoding/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unsupported-method-call-on-all/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-annotation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-async/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-class-method-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-function-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-import/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-lambda-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-loop-control-variable/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-method-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-noqa/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-private-protocol/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-private-type-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-private-type-var/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-private-typed-dict/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-static-method-argument/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-unpacked-variable/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/unused-variable/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/used-dummy-variable/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-contextlib-suppress/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-else-on-loop/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-exception-statement/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-expression/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-if-else/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-import-alias/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-metaclass-type/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-object-inheritance/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-return/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-semicolon/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-try-except/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/useless-with-lock/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/utf8-encoding-declaration/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/verbose-decimal-constructor/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/verbose-log-message/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/verbose-raise/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/wait-for-process-in-async-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/weak-cryptographic-key/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/whitespace-after-decorator/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/whitespace-after-open-bracket/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/whitespace-before-close-bracket/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/whitespace-before-parameters/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/whitespace-before-punctuation/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/write-whole-file/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/wrong-tuple-length-version-comparison/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/yield-from-in-async-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/yield-in-for-loop/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/yield-in-init/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/yield-outside-function/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/yoda-conditions/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/zip-dict-keys-and-values/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/zip-instead-of-pairwise/ - 2025-05-15 + 2025-05-22 https://docs.astral.sh/ruff/rules/zip-without-explicit-strict/ - 2025-05-15 + 2025-05-22 \ No newline at end of file diff --git a/site/ruff/sitemap.xml.gz b/site/ruff/sitemap.xml.gz index b067062e..7ac53514 100644 Binary files a/site/ruff/sitemap.xml.gz and b/site/ruff/sitemap.xml.gz differ diff --git a/site/ruff/tutorial/index.html b/site/ruff/tutorial/index.html index e82ed7c7..eba8d1a9 100644 --- a/site/ruff/tutorial/index.html +++ b/site/ruff/tutorial/index.html @@ -1255,7 +1255,7 @@

        Integrationspre-commit hook via ruff-pre-commit:

        - repo: https://github.com/astral-sh/ruff-pre-commit
           # Ruff version.
        -  rev: v0.11.10
        +  rev: v0.11.11
           hooks:
             # Run the linter.
             - id: ruff