From cf6d3fe0c6faf7a8a3835ba97edac3238c8b1edc Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 24 Nov 2022 16:28:16 -0500 Subject: [PATCH 01/92] remove MANIFEST.in packagers: please package from the github tgz --- MANIFEST.in | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 74b090b..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,9 +0,0 @@ -include *.rst -include CONTRIBUTORS.txt -include LICENSE -include *.ini -global-exclude *.pyc -recursive-include docs *.rst *.py -recursive-include tests *.py *.ini *.rst *_diff -recursive-include src *.py -prune docs/build/ From 5fde644640496af61b580193178e34c8aafefc86 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 04:04:15 +0000 Subject: [PATCH 02/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.3.0 → v4.4.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.3.0...v4.4.0) - [github.com/PyCQA/flake8: 5.0.4 → 6.0.0](https://github.com/PyCQA/flake8/compare/5.0.4...6.0.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 13c4a0f..ad9c62b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.4.0 hooks: - id: check-yaml - id: debug-statements @@ -27,7 +27,7 @@ repos: - id: black args: [--line-length=79] - repo: https://github.com/PyCQA/flake8 - rev: 5.0.4 + rev: 6.0.0 hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy From c0d0ced5b83ca5f72d438ea86d0cc0fdf2dd8345 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 6 Dec 2022 02:21:54 +0000 Subject: [PATCH 03/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.2.2 → v3.3.0](https://github.com/asottile/pyupgrade/compare/v3.2.2...v3.3.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ad9c62b..f2ca587 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.2.2 + rev: v3.3.0 hooks: - id: pyupgrade args: [--py38-plus] From 00fbfd7774aca3d3fa36e5b3c8e1ac6080edf88c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 Dec 2022 03:27:50 +0000 Subject: [PATCH 04/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.3.0 → v3.3.1](https://github.com/asottile/pyupgrade/compare/v3.3.0...v3.3.1) - [github.com/psf/black: 22.10.0 → 22.12.0](https://github.com/psf/black/compare/22.10.0...22.12.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f2ca587..1796476 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,12 +17,12 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.3.0 + rev: v3.3.1 hooks: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/psf/black - rev: 22.10.0 + rev: 22.12.0 hooks: - id: black args: [--line-length=79] From 837e81948bdf81da1193584dfbb98ca16a2dc997 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Wed, 14 Dec 2022 12:55:37 -0500 Subject: [PATCH 05/92] communicate that --select is usually unnecessary --- docs/source/user/options.rst | 8 ++++++-- src/flake8/defaults.py | 1 - src/flake8/main/options.py | 14 +++++++++----- src/flake8/style_guide.py | 2 +- tests/unit/test_decision_engine.py | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/source/user/options.rst b/docs/source/user/options.rst index f9e8b86..8db2df8 100644 --- a/docs/source/user/options.rst +++ b/docs/source/user/options.rst @@ -607,13 +607,14 @@ Options and their Descriptions :ref:`Go back to index ` + **You usually do not need to specify this option as the default includes + all installed plugin codes.** + Specify the list of error codes you wish |Flake8| to report. Similarly to :option:`--ignore`. You can specify a portion of an error code to get all that start with that string. For example, you can use ``E``, ``E4``, ``E43``, and ``E431``. - This defaults to: ``E,F,W,C90`` - Command-line example: .. prompt:: bash @@ -649,6 +650,9 @@ Options and their Descriptions .. versionadded:: 4.0.0 + **You usually do not need to specify this option as the default includes + all installed plugin codes.** + Specify a list of codes to add to the list of selected ones. Similar considerations as in :option:`--select` apply here with regard to the value. diff --git a/src/flake8/defaults.py b/src/flake8/defaults.py index e3edf32..8add695 100644 --- a/src/flake8/defaults.py +++ b/src/flake8/defaults.py @@ -16,7 +16,6 @@ EXCLUDE = ( "*.egg", ) IGNORE = ("E121", "E123", "E126", "E226", "E24", "E704", "W503", "W504") -SELECT = ("E", "F", "W", "C90") MAX_LINE_LENGTH = 79 INDENT_SIZE = 4 diff --git a/src/flake8/main/options.py b/src/flake8/main/options.py index 891bae9..9d57321 100644 --- a/src/flake8/main/options.py +++ b/src/flake8/main/options.py @@ -297,9 +297,11 @@ def register_default_options(option_manager: OptionManager) -> None: parse_from_config=True, comma_separated_list=True, help=( - f"Comma-separated list of error codes to enable. " - f"For example, ``--select=E4,E51,W234``. " - f"(Default: {','.join(defaults.SELECT)})" + "Limit the reported error codes to codes prefix-matched by this " + "list. " + "You usually do not need to specify this option as the default " + "includes all installed plugin codes. " + "For example, ``--select=E4,E51,W234``." ), ) @@ -309,8 +311,10 @@ def register_default_options(option_manager: OptionManager) -> None: parse_from_config=True, comma_separated_list=True, help=( - "Comma-separated list of error codes to add to the list " - "of selected ones. For example, ``--extend-select=E4,E51,W234``." + "Add additional error codes to the default ``--select``. " + "You usually do not need to specify this option as the default " + "includes all installed plugin codes. " + "For example, ``--extend-select=E4,E51,W234``." ), ) diff --git a/src/flake8/style_guide.py b/src/flake8/style_guide.py index 8431650..a409484 100644 --- a/src/flake8/style_guide.py +++ b/src/flake8/style_guide.py @@ -88,7 +88,7 @@ class DecisionEngine: self.selected = _select_ignore( option=options.select, - default=defaults.SELECT, + default=(), extended_default=options.extended_default_select, extend=options.extend_select, ) diff --git a/tests/unit/test_decision_engine.py b/tests/unit/test_decision_engine.py index 27ced3f..d543d5e 100644 --- a/tests/unit/test_decision_engine.py +++ b/tests/unit/test_decision_engine.py @@ -14,7 +14,7 @@ def create_options(**kwargs): kwargs.setdefault("ignore", None) kwargs.setdefault("extend_select", None) kwargs.setdefault("extend_ignore", None) - kwargs.setdefault("extended_default_select", []) + kwargs.setdefault("extended_default_select", ["C90", "F", "E", "W"]) kwargs.setdefault("extended_default_ignore", []) kwargs.setdefault("disable_noqa", False) return argparse.Namespace(**kwargs) From 4778fe9643e94123f93a306f1ed63b52323eee35 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Wed, 14 Dec 2022 13:25:35 -0500 Subject: [PATCH 06/92] deprecate --include-in-doctest --exclude-from-doctest --- src/flake8/plugins/pyflakes.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/flake8/plugins/pyflakes.py b/src/flake8/plugins/pyflakes.py index a9dbc4c..f165c95 100644 --- a/src/flake8/plugins/pyflakes.py +++ b/src/flake8/plugins/pyflakes.py @@ -3,6 +3,7 @@ from __future__ import annotations import argparse import ast +import logging import os from typing import Any from typing import Generator @@ -12,6 +13,8 @@ import pyflakes.checker from flake8 import utils from flake8.options.manager import OptionManager +LOG = logging.getLogger(__name__) + FLAKE8_PYFLAKES_CODES = { "UnusedImport": "F401", "ImportShadowedByLoopVar": "F402", @@ -137,6 +140,12 @@ class FlakesChecker(pyflakes.checker.Checker): cls.builtIns = cls.builtIns.union(options.builtins) cls.with_doctest = options.doctests + if options.include_in_doctest or options.exclude_from_doctest: + LOG.warning( + "--include-in-doctest / --exclude-from-doctest will be " + "removed in a future version. see PyCQA/flake8#1747" + ) + included_files = [] for included_file in options.include_in_doctest: if included_file == "": From 61138f1f4b00ae9e00b3262c566de9b2afdc5584 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 2 Jan 2023 10:25:13 -0500 Subject: [PATCH 07/92] correct tidelift link --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 7267456..1ac2512 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,2 @@ github: asottile -tidelift: pypi/pre-commit +tidelift: pypi/flake8 From bc6e08723541125b0340bd6b6f72fdd3e30e9ca9 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 2 Jan 2023 07:41:47 -0800 Subject: [PATCH 08/92] use pypy3.9 to work around coverage issue --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e5799e1..7f28cf9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,7 +13,7 @@ jobs: include: # linux - os: ubuntu-latest - python: pypy-3.8 + python: pypy-3.9 toxenv: py - os: ubuntu-latest python: 3.8 From 0be0ae784269a96c3022c47ead652ec93e07bf63 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Wed, 11 Jan 2023 09:19:54 -0500 Subject: [PATCH 09/92] add myself to maintenance --- README.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index f2a6d43..1ea6096 100644 --- a/README.rst +++ b/README.rst @@ -85,5 +85,6 @@ Links Maintenance =========== -Flake8 was created by Tarek Ziadé and is currently maintained by `Ian Cordasco +Flake8 was created by Tarek Ziadé and is currently maintained by `anthony sottile +`_ and `Ian Cordasco `_ From e6f9db5039a79d0776e416314e1e331c611d7319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastien=20G=C3=A9rard?= Date: Sat, 21 Jan 2023 21:37:35 +0100 Subject: [PATCH 10/92] Update python-api.rst Fix minor typo in doc --- docs/source/user/python-api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/user/python-api.rst b/docs/source/user/python-api.rst index ed7e5e5..f51b146 100644 --- a/docs/source/user/python-api.rst +++ b/docs/source/user/python-api.rst @@ -70,7 +70,7 @@ namely .. warning:: These are not *perfectly* backwards compatible. Not all arguments are - respsected, and some of the types necessary for something to work have + respected, and some of the types necessary for something to work have changed. Most people, we observed, were using From 50755610d2161e8d6b15d37ca3c9a651eca7a443 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 Feb 2023 07:21:58 +0000 Subject: [PATCH 11/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 22.12.0 → 23.1.0](https://github.com/psf/black/compare/22.12.0...23.1.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1796476..4fa1718 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/psf/black - rev: 22.12.0 + rev: 23.1.0 hooks: - id: black args: [--line-length=79] From b0d7912f7e4232cbaa87d9ba26df3cbd583b0ea0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 Feb 2023 07:22:49 +0000 Subject: [PATCH 12/92] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/flake8/checker.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flake8/checker.py b/src/flake8/checker.py index 2cae545..8d70034 100644 --- a/src/flake8/checker.py +++ b/src/flake8/checker.py @@ -160,7 +160,7 @@ class Manager: def _handle_results(self, filename: str, results: Results) -> int: style_guide = self.style_guide reported_results_count = 0 - for (error_code, line_number, column, text, physical_line) in results: + for error_code, line_number, column, text, physical_line in results: reported_results_count += style_guide.handle_error( code=error_code, filename=filename, @@ -423,7 +423,7 @@ class FileChecker: runner = checker.run() except AttributeError: runner = checker - for (line_number, offset, text, _) in runner: + for line_number, offset, text, _ in runner: self.report( error_code=None, line_number=line_number, From 77e075c66a4f2642d1168da307f6fe42c5348ba8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 14 Feb 2023 05:36:21 +0000 Subject: [PATCH 13/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v0.991 → v1.0.0](https://github.com/pre-commit/mirrors-mypy/compare/v0.991...v1.0.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4fa1718..6387b06 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.991 + rev: v1.0.0 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From 2615d21a5bb19d7c6df0172cb3f536cf4c2fec72 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 21 Feb 2023 05:18:56 +0000 Subject: [PATCH 14/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.0.0 → v1.0.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.0.0...v1.0.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6387b06..123eb87 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.0.0 + rev: v1.0.1 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From f096f853c26bc8db75a0c096251122d27262f099 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 06:44:36 +0000 Subject: [PATCH 15/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.0.1 → v1.1.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.0.1...v1.1.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 123eb87..059562b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.0.1 + rev: v1.1.1 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From 050d0dcf4d9c4ff1b1083f02eb946eca6eab5988 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 09:38:50 +0000 Subject: [PATCH 16/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.1.0 → 23.3.0](https://github.com/psf/black/compare/23.1.0...23.3.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 059562b..f0303bd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/psf/black - rev: 23.1.0 + rev: 23.3.0 hooks: - id: black args: [--line-length=79] From 426f952fc89d9cf9b8f0ad9fa5fd4d28ef96b13c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 06:25:16 +0000 Subject: [PATCH 17/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.1.1 → v1.2.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.1.1...v1.2.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f0303bd..e2b95f5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.1.1 + rev: v1.2.0 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From cabc45abab39e136290f1c93ab36177cf2151eba Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 25 Apr 2023 07:12:41 +0000 Subject: [PATCH 18/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.3.1 → v3.3.2](https://github.com/asottile/pyupgrade/compare/v3.3.1...v3.3.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e2b95f5..5994d20 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.3.1 + rev: v3.3.2 hooks: - id: pyupgrade args: [--py38-plus] From 0c3cf066d301a140eb87d3b0681d32c60f0139a5 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sun, 30 Apr 2023 15:03:01 -0400 Subject: [PATCH 19/92] remove regex link --- src/flake8/defaults.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/flake8/defaults.py b/src/flake8/defaults.py index 8add695..57abda1 100644 --- a/src/flake8/defaults.py +++ b/src/flake8/defaults.py @@ -36,7 +36,6 @@ NOQA_INLINE_REGEXP = re.compile( # We do not want to capture the ``: `` that follows ``noqa`` # We do not care about the casing of ``noqa`` # We want a comma-separated list of errors - # https://regex101.com/r/4XUuax/2 full explanation of the regex r"# noqa(?::[\s]?(?P([A-Z]+[0-9]+(?:[,\s]+)?)+))?", re.IGNORECASE, ) From a466e461e5cb45b0c0d8c41a75c77f9bbf29786b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 9 May 2023 08:00:29 +0000 Subject: [PATCH 20/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - https://github.com/asottile/reorder_python_imports → https://github.com/asottile/reorder-python-imports - [github.com/asottile/pyupgrade: v3.3.2 → v3.4.0](https://github.com/asottile/pyupgrade/compare/v3.3.2...v3.4.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5994d20..2214c16 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace exclude: ^tests/fixtures/ -- repo: https://github.com/asottile/reorder_python_imports +- repo: https://github.com/asottile/reorder-python-imports rev: v3.9.0 hooks: - id: reorder-python-imports @@ -17,7 +17,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.3.2 + rev: v3.4.0 hooks: - id: pyupgrade args: [--py38-plus] From 4b7ede13fb64288ccc3a361a8fd4560c955cf13a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 07:06:03 +0000 Subject: [PATCH 21/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.2.0 → v1.3.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.2.0...v1.3.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2214c16..7047121 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.2.0 + rev: v1.3.0 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From 9b6887762bbde293f1e0807fafd997d6213775ff Mon Sep 17 00:00:00 2001 From: Abdulfatai Aka <32123313+abdulfataiaka@users.noreply.github.com> Date: Tue, 16 May 2023 14:44:14 +0100 Subject: [PATCH 22/92] Update invocation.rst file --- docs/source/user/invocation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/user/invocation.rst b/docs/source/user/invocation.rst index 0049ec9..61cef97 100644 --- a/docs/source/user/invocation.rst +++ b/docs/source/user/invocation.rst @@ -51,7 +51,7 @@ Or This is the last time we will show both versions of an invocation. From now on, we'll simply use ``flake8`` and assume that the user - knows they can instead use ``python -m flake8`` instead. + knows they can instead use ``python -m flake8``. It's also possible to narrow what |Flake8| will try to check by specifying exactly the paths and directories you want it to check. Let's assume that From 43266a2e26ec49a55b866c78b295deaebb1debf7 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 12 Jun 2023 22:02:26 -0400 Subject: [PATCH 23/92] mute FSTRING_MIDDLE tokens --- src/flake8/processor.py | 8 +++++++- tests/integration/test_plugins.py | 32 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/flake8/processor.py b/src/flake8/processor.py index 16fa16b..c9c9e5d 100644 --- a/src/flake8/processor.py +++ b/src/flake8/processor.py @@ -5,6 +5,7 @@ import argparse import ast import contextlib import logging +import sys import tokenize from typing import Any from typing import Generator @@ -178,7 +179,7 @@ class FileProcessor: self.blank_lines = 0 self.tokens = [] - def build_logical_line_tokens(self) -> _Logical: + def build_logical_line_tokens(self) -> _Logical: # noqa: C901 """Build the mapping, comments, and logical line lists.""" logical = [] comments = [] @@ -195,6 +196,11 @@ class FileProcessor: continue if token_type == tokenize.STRING: text = mutate_string(text) + elif ( + sys.version_info >= (3, 12) + and token_type == tokenize.FSTRING_MIDDLE + ): + text = "x" * len(text) if previous_row: (start_row, start_column) = start if previous_row != start_row: diff --git a/tests/integration/test_plugins.py b/tests/integration/test_plugins.py index edba048..b67e6d6 100644 --- a/tests/integration/test_plugins.py +++ b/tests/integration/test_plugins.py @@ -197,3 +197,35 @@ t.py:3:1: T001 '"""\\n' ''' out, err = capsys.readouterr() assert out == expected + + +def yields_logical_line(logical_line): + yield 0, f"T001 {logical_line!r}" + + +def test_logical_line_plugin(tmpdir, capsys): + cfg_s = f"""\ +[flake8] +extend-ignore = F +[flake8:local-plugins] +extension = + T = {yields_logical_line.__module__}:{yields_logical_line.__name__} +""" + + cfg = tmpdir.join("tox.ini") + cfg.write(cfg_s) + + src = """\ +f'hello world' +""" + t_py = tmpdir.join("t.py") + t_py.write_binary(src.encode()) + + with tmpdir.as_cwd(): + assert main(("t.py", "--config", str(cfg))) == 1 + + expected = """\ +t.py:1:1: T001 "f'xxxxxxxxxxx'" +""" + out, err = capsys.readouterr() + assert out == expected From 4d0c97d7afd3c76cbf99f027896c3e93f963136a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 Jun 2023 08:00:37 +0000 Subject: [PATCH 24/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.4.0 → v3.6.0](https://github.com/asottile/pyupgrade/compare/v3.4.0...v3.6.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7047121..75b58c0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.4.0 + rev: v3.6.0 hooks: - id: pyupgrade args: [--py38-plus] From ad03ede045ce35a8390f4d41b62992de381d28e8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 08:45:09 +0000 Subject: [PATCH 25/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/reorder-python-imports: v3.9.0 → v3.10.0](https://github.com/asottile/reorder-python-imports/compare/v3.9.0...v3.10.0) - [github.com/asottile/pyupgrade: v3.6.0 → v3.7.0](https://github.com/asottile/pyupgrade/compare/v3.6.0...v3.7.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 75b58c0..f15bf88 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ repos: - id: trailing-whitespace exclude: ^tests/fixtures/ - repo: https://github.com/asottile/reorder-python-imports - rev: v3.9.0 + rev: v3.10.0 hooks: - id: reorder-python-imports args: [ @@ -17,7 +17,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.6.0 + rev: v3.7.0 hooks: - id: pyupgrade args: [--py38-plus] From 24999ec87e6e8cd5ddaa815f575467f6ed8bb33e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 Jun 2023 07:48:29 +0000 Subject: [PATCH 26/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.3.0 → v1.4.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.3.0...v1.4.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f15bf88..6d2b716 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.3.0 + rev: v1.4.1 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From fa42096dfe62fc6d4059b70042e27e4e59353984 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 09:39:09 +0000 Subject: [PATCH 27/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.7.0 → v3.8.0](https://github.com/asottile/pyupgrade/compare/v3.7.0...v3.8.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6d2b716..d8c9662 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.7.0 + rev: v3.8.0 hooks: - id: pyupgrade args: [--py38-plus] From 73825ae81c9e0085efc7d10cdec7eb2917d81b9e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:15:18 +0000 Subject: [PATCH 28/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.8.0 → v3.9.0](https://github.com/asottile/pyupgrade/compare/v3.8.0...v3.9.0) - [github.com/psf/black: 23.3.0 → 23.7.0](https://github.com/psf/black/compare/23.3.0...23.7.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d8c9662..dbe6918 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,12 +17,12 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.8.0 + rev: v3.9.0 hooks: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 23.7.0 hooks: - id: black args: [--line-length=79] From 5bd63bc5528cf0c89ed93c353e65b1089836c105 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Jul 2023 13:03:38 -0400 Subject: [PATCH 29/92] upgrade pyflakes to 3.1.x --- docs/source/user/error-codes.rst | 2 -- setup.cfg | 2 +- src/flake8/plugins/pyflakes.py | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/source/user/error-codes.rst b/docs/source/user/error-codes.rst index d12a07f..2a91413 100644 --- a/docs/source/user/error-codes.rst +++ b/docs/source/user/error-codes.rst @@ -81,8 +81,6 @@ generates its own :term:`error code`\ s for ``pyflakes``: +------+---------------------------------------------------------------------+ | F702 | a ``continue`` statement outside of a ``while`` or ``for`` loop | +------+---------------------------------------------------------------------+ -| F703 | a ``continue`` statement in a ``finally`` block in a loop | -+------+---------------------------------------------------------------------+ | F704 | a ``yield`` or ``yield from`` statement outside of a function | +------+---------------------------------------------------------------------+ | F706 | a ``return`` statement outside of a function/method | diff --git a/setup.cfg b/setup.cfg index 6c28b90..15dcfeb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,7 +36,7 @@ package_dir = install_requires = mccabe>=0.7.0,<0.8.0 pycodestyle>=2.10.0,<2.11.0 - pyflakes>=3.0.0,<3.1.0 + pyflakes>=3.1.0,<3.2.0 # 3.8.0's importlib.metadata is broken python_requires = >=3.8.1 diff --git a/src/flake8/plugins/pyflakes.py b/src/flake8/plugins/pyflakes.py index f165c95..f62527e 100644 --- a/src/flake8/plugins/pyflakes.py +++ b/src/flake8/plugins/pyflakes.py @@ -48,7 +48,6 @@ FLAKE8_PYFLAKES_CODES = { "IfTuple": "F634", "BreakOutsideLoop": "F701", "ContinueOutsideLoop": "F702", - "ContinueInFinally": "F703", "YieldOutsideFunction": "F704", "ReturnOutsideFunction": "F706", "DefaultExceptNotLast": "F707", From 9786562feb573d30c73f18e1a0a6685c8584e9b5 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Jul 2023 13:23:01 -0400 Subject: [PATCH 30/92] upgrade to pycodestyle 2.11.x --- setup.cfg | 2 +- src/flake8/plugins/pycodestyle.py | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/setup.cfg b/setup.cfg index 15dcfeb..593c2e1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -35,7 +35,7 @@ package_dir = # https://flake8.pycqa.org/en/latest/internal/releases.html#releasing-flake8 install_requires = mccabe>=0.7.0,<0.8.0 - pycodestyle>=2.10.0,<2.11.0 + pycodestyle>=2.11.0,<2.12.0 pyflakes>=3.1.0,<3.2.0 # 3.8.0's importlib.metadata is broken python_requires = >=3.8.1 diff --git a/src/flake8/plugins/pycodestyle.py b/src/flake8/plugins/pycodestyle.py index 7eb90e1..9e1d2bb 100644 --- a/src/flake8/plugins/pycodestyle.py +++ b/src/flake8/plugins/pycodestyle.py @@ -23,9 +23,7 @@ from pycodestyle import maximum_doc_length as _maximum_doc_length from pycodestyle import maximum_line_length as _maximum_line_length from pycodestyle import missing_whitespace as _missing_whitespace from pycodestyle import missing_whitespace_after_keyword as _missing_whitespace_after_keyword # noqa: E501 -from pycodestyle import missing_whitespace_around_operator as _missing_whitespace_around_operator # noqa: E501 from pycodestyle import module_imports_on_top_of_file as _module_imports_on_top_of_file # noqa: E501 -from pycodestyle import python_3000_async_await_keywords as _python_3000_async_await_keywords # noqa: E501 from pycodestyle import python_3000_invalid_escape_sequence as _python_3000_invalid_escape_sequence # noqa: E501 from pycodestyle import tabs_obsolete as _tabs_obsolete from pycodestyle import tabs_or_spaces as _tabs_or_spaces @@ -74,11 +72,9 @@ def pycodestyle_logical( yield from _imports_on_separate_lines(logical_line) yield from _indentation(logical_line, previous_logical, indent_char, indent_level, previous_indent_level, indent_size) # noqa: E501 yield from _maximum_doc_length(logical_line, max_doc_length, noqa, tokens) - yield from _missing_whitespace(logical_line) + yield from _missing_whitespace(logical_line, tokens) yield from _missing_whitespace_after_keyword(logical_line, tokens) - yield from _missing_whitespace_around_operator(logical_line, tokens) yield from _module_imports_on_top_of_file(logical_line, indent_level, checker_state, noqa) # noqa: E501 - yield from _python_3000_async_await_keywords(logical_line, tokens) yield from _python_3000_invalid_escape_sequence(logical_line, tokens, noqa) yield from _whitespace_around_comma(logical_line) yield from _whitespace_around_keywords(logical_line) From acca35b8006e2760ceed58c1fbec34fbac024ff2 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Jul 2023 14:30:55 -0400 Subject: [PATCH 31/92] add 3.12 to ci matrix --- .github/workflows/main.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7f28cf9..e210204 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,6 +27,9 @@ jobs: - os: ubuntu-latest python: '3.11' toxenv: py + - os: ubuntu-latest + python: '3.12-dev' + toxenv: py # windows - os: windows-latest python: 3.8 From 1ed78d592a355ece4edfee2884185dccaa732dbc Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Jul 2023 14:25:54 -0400 Subject: [PATCH 32/92] handle multiline fstrings in 3.12 --- src/flake8/_compat.py | 11 +++++++ src/flake8/checker.py | 15 +++++---- src/flake8/processor.py | 53 +++++++++++++++---------------- tests/integration/test_plugins.py | 32 +++++++++++++++++++ tests/unit/test_file_processor.py | 25 ++++----------- 5 files changed, 83 insertions(+), 53 deletions(-) create mode 100644 src/flake8/_compat.py diff --git a/src/flake8/_compat.py b/src/flake8/_compat.py new file mode 100644 index 0000000..f4a0903 --- /dev/null +++ b/src/flake8/_compat.py @@ -0,0 +1,11 @@ +from __future__ import annotations + +import sys +import tokenize + +if sys.version_info >= (3, 12): + FSTRING_START = tokenize.FSTRING_START + FSTRING_MIDDLE = tokenize.FSTRING_MIDDLE + FSTRING_END = tokenize.FSTRING_END +else: + FSTRING_START = FSTRING_MIDDLE = FSTRING_END = -1 diff --git a/src/flake8/checker.py b/src/flake8/checker.py index 8d70034..6c4caef 100644 --- a/src/flake8/checker.py +++ b/src/flake8/checker.py @@ -20,6 +20,7 @@ from flake8 import defaults from flake8 import exceptions from flake8 import processor from flake8 import utils +from flake8._compat import FSTRING_START from flake8.discover_files import expand_paths from flake8.options.parse_args import parse_args from flake8.plugins.finder import Checkers @@ -551,15 +552,17 @@ class FileChecker: ) -> None: """Run physical checks if and only if it is at the end of the line.""" assert self.processor is not None + if token.type == FSTRING_START: # pragma: >=3.12 cover + self.processor.fstring_start(token.start[0]) # a newline token ends a single physical line. - if processor.is_eol_token(token): + elif processor.is_eol_token(token): # if the file does not end with a newline, the NEWLINE # token is inserted by the parser, but it does not contain # the previous physical line in `token[4]` - if token[4] == "": + if token.line == "": self.run_physical_checks(prev_physical) else: - self.run_physical_checks(token[4]) + self.run_physical_checks(token.line) elif processor.is_multiline_string(token): # Less obviously, a string that contains newlines is a # multiline string, either triple-quoted or with internal @@ -572,10 +575,8 @@ class FileChecker: # - have to wind self.line_number back because initially it # points to the last line of the string, and we want # check_physical() to give accurate feedback - line_no = token[2][0] - with self.processor.inside_multiline(line_number=line_no): - for line in self.processor.split_line(token): - self.run_physical_checks(line) + for line in self.processor.multiline_string(token): + self.run_physical_checks(line) def _try_initialize_processpool( diff --git a/src/flake8/processor.py b/src/flake8/processor.py index c9c9e5d..2eea88f 100644 --- a/src/flake8/processor.py +++ b/src/flake8/processor.py @@ -3,9 +3,7 @@ from __future__ import annotations import argparse import ast -import contextlib import logging -import sys import tokenize from typing import Any from typing import Generator @@ -14,6 +12,8 @@ from typing import Tuple from flake8 import defaults from flake8 import utils +from flake8._compat import FSTRING_END +from flake8._compat import FSTRING_MIDDLE from flake8.plugins.finder import LoadedPlugin LOG = logging.getLogger(__name__) @@ -117,6 +117,7 @@ class FileProcessor: self._file_tokens: list[tokenize.TokenInfo] | None = None # map from line number to the line we'll search for `noqa` in self._noqa_line_mapping: dict[int, str] | None = None + self._fstring_start = -1 @property def file_tokens(self) -> list[tokenize.TokenInfo]: @@ -129,14 +130,26 @@ class FileProcessor: return self._file_tokens - @contextlib.contextmanager - def inside_multiline( - self, line_number: int - ) -> Generator[None, None, None]: - """Context-manager to toggle the multiline attribute.""" - self.line_number = line_number + def fstring_start(self, lineno: int) -> None: + """Signal the beginning of an fstring.""" + self._fstring_start = lineno + + def multiline_string( + self, token: tokenize.TokenInfo + ) -> Generator[str, None, None]: + """Iterate through the lines of a multiline string.""" + if token.type == FSTRING_END: + start = self._fstring_start + else: + start = token.start[0] + self.multiline = True - yield + self.line_number = start + # intentionally don't include the last line, that line will be + # terminated later by a future end-of-line + for _ in range(start, token.end[0]): + yield self.lines[self.line_number - 1] + self.line_number += 1 self.multiline = False def reset_blank_before(self) -> None: @@ -196,10 +209,7 @@ class FileProcessor: continue if token_type == tokenize.STRING: text = mutate_string(text) - elif ( - sys.version_info >= (3, 12) - and token_type == tokenize.FSTRING_MIDDLE - ): + elif token_type == FSTRING_MIDDLE: text = "x" * len(text) if previous_row: (start_row, start_column) = start @@ -231,19 +241,6 @@ class FileProcessor: self.statistics["logical lines"] += 1 return joined_comments, self.logical_line, mapping_list - def split_line( - self, token: tokenize.TokenInfo - ) -> Generator[str, None, None]: - """Split a physical line's line based on new-lines. - - This also auto-increments the line number for the caller. - """ - # intentionally don't include the last line, that line will be - # terminated later by a future end-of-line - for line_no in range(token.start[0], token.end[0]): - yield self.lines[line_no - 1] - self.line_number += 1 - def keyword_arguments_for( self, parameters: dict[str, bool], @@ -398,7 +395,9 @@ def is_eol_token(token: tokenize.TokenInfo) -> bool: def is_multiline_string(token: tokenize.TokenInfo) -> bool: """Check if this is a multiline string.""" - return token[0] == tokenize.STRING and "\n" in token[1] + return token.type == FSTRING_END or ( + token.type == tokenize.STRING and "\n" in token.string + ) def token_is_newline(token: tokenize.TokenInfo) -> bool: diff --git a/tests/integration/test_plugins.py b/tests/integration/test_plugins.py index b67e6d6..d4c22b0 100644 --- a/tests/integration/test_plugins.py +++ b/tests/integration/test_plugins.py @@ -199,6 +199,38 @@ t.py:3:1: T001 '"""\\n' assert out == expected +def test_physical_line_plugin_multiline_fstring(tmpdir, capsys): + cfg_s = f"""\ +[flake8:local-plugins] +extension = + T = {yields_physical_line.__module__}:{yields_physical_line.__name__} +""" + + cfg = tmpdir.join("tox.ini") + cfg.write(cfg_s) + + src = '''\ +y = 1 +x = f""" +hello {y} +""" +''' + t_py = tmpdir.join("t.py") + t_py.write_binary(src.encode()) + + with tmpdir.as_cwd(): + assert main(("t.py", "--config", str(cfg))) == 1 + + expected = '''\ +t.py:1:1: T001 'y = 1\\n' +t.py:2:1: T001 'x = f"""\\n' +t.py:3:1: T001 'hello {y}\\n' +t.py:4:1: T001 '"""\\n' +''' + out, err = capsys.readouterr() + assert out == expected + + def yields_logical_line(logical_line): yield 0, f"T001 {logical_line!r}" diff --git a/tests/unit/test_file_processor.py b/tests/unit/test_file_processor.py index bd693b3..a90c628 100644 --- a/tests/unit/test_file_processor.py +++ b/tests/unit/test_file_processor.py @@ -275,13 +275,15 @@ def test_processor_split_line(default_options): (3, 3), 'x = """\ncontents\n"""\n', ) - expected = [('x = """\n', 0), ("contents\n", 1)] + expected = [('x = """\n', 1, True), ("contents\n", 2, True)] + assert file_processor.multiline is False actual = [ - (line, file_processor.line_number) - for line in file_processor.split_line(token) + (line, file_processor.line_number, file_processor.multiline) + for line in file_processor.multiline_string(token) ] + assert file_processor.multiline is False assert expected == actual - assert file_processor.line_number == 2 + assert file_processor.line_number == 3 def test_build_ast(default_options): @@ -321,21 +323,6 @@ def test_visited_new_blank_line(default_options): assert file_processor.blank_lines == 1 -def test_inside_multiline(default_options): - """Verify we update the line number and reset multiline.""" - file_processor = processor.FileProcessor( - "-", default_options, lines=["a = 1\n"] - ) - - assert file_processor.multiline is False - assert file_processor.line_number == 0 - with file_processor.inside_multiline(10): - assert file_processor.multiline is True - assert file_processor.line_number == 10 - - assert file_processor.multiline is False - - @pytest.mark.parametrize( "string, expected", [ From cc301ed499511c56ceca3262a2302364dc146b06 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Jul 2023 14:36:44 -0400 Subject: [PATCH 33/92] fix pylintrc warnings --- .pylintrc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.pylintrc b/.pylintrc index a23de97..92ea2a4 100644 --- a/.pylintrc +++ b/.pylintrc @@ -365,10 +365,3 @@ ext-import-graph= # Create a graph of internal dependencies in the given file (report RP0402 must # not be disabled) int-import-graph= - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=Exception From 5233d880696a6867b53fabf0c9d4419d83f372ad Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Jul 2023 14:39:06 -0400 Subject: [PATCH 34/92] use setup-cfg-fmt --- .pre-commit-config.yaml | 4 ++++ setup.cfg | 11 +++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dbe6918..6de9c1b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,6 +7,10 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace exclude: ^tests/fixtures/ +- repo: https://github.com/asottile/setup-cfg-fmt + rev: v2.4.0 + hooks: + - id: setup-cfg-fmt - repo: https://github.com/asottile/reorder-python-imports rev: v3.10.0 hooks: diff --git a/setup.cfg b/setup.cfg index 593c2e1..ebf4355 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,7 @@ author_email = tarek@ziade.org maintainer = Ian Stapleton Cordasco maintainer_email = graffatcolmingov@gmail.com license = MIT -license_file = LICENSE +license_files = LICENSE classifiers = Development Status :: 5 - Production/Stable Environment :: Console @@ -27,18 +27,13 @@ classifiers = [options] packages = find: -package_dir = - =src -# We document the reasoning for using ranges here: -# https://flake8.pycqa.org/en/latest/faq.html#why-does-flake8-use-ranges-for-its-dependencies -# And in which releases we will update those ranges here: -# https://flake8.pycqa.org/en/latest/internal/releases.html#releasing-flake8 install_requires = mccabe>=0.7.0,<0.8.0 pycodestyle>=2.11.0,<2.12.0 pyflakes>=3.1.0,<3.2.0 -# 3.8.0's importlib.metadata is broken python_requires = >=3.8.1 +package_dir = + =src [options.packages.find] where = src From 7ef0350a439c93166bc8ba89fcc3de6a9a664e6c Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Jul 2023 15:04:17 -0400 Subject: [PATCH 35/92] Release 6.1.0 --- docs/source/internal/releases.rst | 4 ++-- docs/source/release-notes/6.1.0.rst | 22 ++++++++++++++++++++++ docs/source/release-notes/index.rst | 1 + src/flake8/__init__.py | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 docs/source/release-notes/6.1.0.rst diff --git a/docs/source/internal/releases.rst b/docs/source/internal/releases.rst index 39fbdf7..fc29bd3 100644 --- a/docs/source/internal/releases.rst +++ b/docs/source/internal/releases.rst @@ -81,9 +81,9 @@ for users. Before releasing, the following tox test environments must pass: -- Python 3.6 (a.k.a., ``tox -e py36``) +- Python 3.8 (a.k.a., ``tox -e py38``) -- Python 3.7 (a.k.a., ``tox -e py37``) +- Python 3.12 (a.k.a., ``tox -e py312``) - PyPy 3 (a.k.a., ``tox -e pypy3``) diff --git a/docs/source/release-notes/6.1.0.rst b/docs/source/release-notes/6.1.0.rst new file mode 100644 index 0000000..a2244a9 --- /dev/null +++ b/docs/source/release-notes/6.1.0.rst @@ -0,0 +1,22 @@ +6.1.0 -- 2023-07-29 +------------------- + +You can view the `6.1.0 milestone`_ on GitHub for more details. + +New Dependency Information +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Pyflakes has been updated to >= 3.1.0, < 3.2.0 (See also :pull:`1847`). +- pycodestyle has been updated to >= 2.11.0, < 2.12.0 (See also :pull:`1848`). + +Features +~~~~~~~~ + +- Deprecate ``--include-in-doctest``, ``--exclude-from-doctest`` (See also + :issue:`1747`, :pull:`1768`). +- Add support for python 3.12 (See also :pull:`1832`, :pull:`1849`, + :pull:`1850`). + +.. all links +.. _6.1.0 milestone: + https://github.com/PyCQA/flake8/milestone/48 diff --git a/docs/source/release-notes/index.rst b/docs/source/release-notes/index.rst index a9eff5f..8cd7573 100644 --- a/docs/source/release-notes/index.rst +++ b/docs/source/release-notes/index.rst @@ -10,6 +10,7 @@ with the newest releases first. .. toctree:: 6.0.0 + 6.1.0 5.x Release Series ================== diff --git a/src/flake8/__init__.py b/src/flake8/__init__.py index c6d48b7..171b1db 100644 --- a/src/flake8/__init__.py +++ b/src/flake8/__init__.py @@ -17,7 +17,7 @@ import sys LOG = logging.getLogger(__name__) LOG.addHandler(logging.NullHandler()) -__version__ = "6.0.0" +__version__ = "6.1.0" __version_info__ = tuple(int(i) for i in __version__.split(".") if i.isdigit()) _VERBOSITY_TO_LOG_LEVEL = { From 4a47bab979b251324aa31fc3db61e64c8ed3d15d Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Jul 2023 15:43:21 -0400 Subject: [PATCH 36/92] improve coverage --- .coveragerc | 26 ------------- setup.cfg | 9 +++++ src/flake8/_compat.py | 4 +- src/flake8/processor.py | 81 +++++++++++++++++------------------------ tox.ini | 1 + 5 files changed, 45 insertions(+), 76 deletions(-) delete mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index d74ca19..0000000 --- a/.coveragerc +++ /dev/null @@ -1,26 +0,0 @@ -[run] -branch = True -source = - flake8 - tests -omit = - # Don't complain if non-runnable code isn't run - */__main__.py - -[report] -show_missing = True -skip_covered = True -exclude_lines = - # Have to re-enable the standard pragma - \#\s*pragma: no cover - - # Don't complain if tests don't hit defensive assertion code: - ^\s*raise AssertionError\b - ^\s*raise NotImplementedError\b - ^\s*return NotImplemented\b - ^\s*raise$ - - # Don't complain if non-runnable code isn't run: - ^if __name__ == ['"]__main__['"]:$ - ^\s*if False: - ^\s*if TYPE_CHECKING: diff --git a/setup.cfg b/setup.cfg index ebf4355..70c2b8d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -54,6 +54,15 @@ flake8.report = [bdist_wheel] universal = 1 +[coverage:run] +source = + flake8 + tests +plugins = covdefaults + +[coverage:report] +fail_under = 97 + [mypy] check_untyped_defs = true disallow_any_generics = true diff --git a/src/flake8/_compat.py b/src/flake8/_compat.py index f4a0903..e8a3ccd 100644 --- a/src/flake8/_compat.py +++ b/src/flake8/_compat.py @@ -3,9 +3,9 @@ from __future__ import annotations import sys import tokenize -if sys.version_info >= (3, 12): +if sys.version_info >= (3, 12): # pragma: >=3.12 cover FSTRING_START = tokenize.FSTRING_START FSTRING_MIDDLE = tokenize.FSTRING_MIDDLE FSTRING_END = tokenize.FSTRING_END -else: +else: # pragma: <3.12 cover FSTRING_START = FSTRING_MIDDLE = FSTRING_END = -1 diff --git a/src/flake8/processor.py b/src/flake8/processor.py index 2eea88f..21a25e0 100644 --- a/src/flake8/processor.py +++ b/src/flake8/processor.py @@ -3,6 +3,7 @@ from __future__ import annotations import argparse import ast +import functools import logging import tokenize from typing import Any @@ -114,23 +115,15 @@ class FileProcessor: self.verbose = options.verbose #: Statistics dictionary self.statistics = {"logical lines": 0} - self._file_tokens: list[tokenize.TokenInfo] | None = None - # map from line number to the line we'll search for `noqa` in - self._noqa_line_mapping: dict[int, str] | None = None self._fstring_start = -1 - @property + @functools.cached_property def file_tokens(self) -> list[tokenize.TokenInfo]: """Return the complete set of tokens for a file.""" - if self._file_tokens is None: - line_iter = iter(self.lines) - self._file_tokens = list( - tokenize.generate_tokens(lambda: next(line_iter)) - ) + line_iter = iter(self.lines) + return list(tokenize.generate_tokens(lambda: next(line_iter))) - return self._file_tokens - - def fstring_start(self, lineno: int) -> None: + def fstring_start(self, lineno: int) -> None: # pragma: >=3.12 cover """Signal the beginning of an fstring.""" self._fstring_start = lineno @@ -138,7 +131,7 @@ class FileProcessor: self, token: tokenize.TokenInfo ) -> Generator[str, None, None]: """Iterate through the lines of a multiline string.""" - if token.type == FSTRING_END: + if token.type == FSTRING_END: # pragma: >=3.12 cover start = self._fstring_start else: start = token.start[0] @@ -209,7 +202,7 @@ class FileProcessor: continue if token_type == tokenize.STRING: text = mutate_string(text) - elif token_type == FSTRING_MIDDLE: + elif token_type == FSTRING_MIDDLE: # pragma: >=3.12 cover text = "x" * len(text) if previous_row: (start_row, start_column) = start @@ -277,41 +270,37 @@ class FileProcessor: joined = "".join(self.lines[min_line - 1 : max_line]) return dict.fromkeys(line_range, joined) - def noqa_line_for(self, line_number: int) -> str | None: - """Retrieve the line which will be used to determine noqa.""" - if self._noqa_line_mapping is None: - try: - file_tokens = self.file_tokens - except (tokenize.TokenError, SyntaxError): - # if we failed to parse the file tokens, we'll always fail in - # the future, so set this so the code does not try again - self._noqa_line_mapping = {} - else: - ret = {} + @functools.cached_property + def _noqa_line_mapping(self) -> dict[int, str]: + """Map from line number to the line we'll search for `noqa` in.""" + try: + file_tokens = self.file_tokens + except (tokenize.TokenError, SyntaxError): + # if we failed to parse the file tokens, we'll always fail in + # the future, so set this so the code does not try again + return {} + else: + ret = {} - min_line = len(self.lines) + 2 - max_line = -1 - for tp, _, (s_line, _), (e_line, _), _ in file_tokens: - if tp == tokenize.ENDMARKER: - break + min_line = len(self.lines) + 2 + max_line = -1 + for tp, _, (s_line, _), (e_line, _), _ in file_tokens: + if tp == tokenize.ENDMARKER or tp == tokenize.DEDENT: + continue - min_line = min(min_line, s_line) - max_line = max(max_line, e_line) + min_line = min(min_line, s_line) + max_line = max(max_line, e_line) - if tp in (tokenize.NL, tokenize.NEWLINE): - ret.update(self._noqa_line_range(min_line, max_line)) - - min_line = len(self.lines) + 2 - max_line = -1 - - # in newer versions of python, a `NEWLINE` token is inserted - # at the end of the file even if it doesn't have one. - # on old pythons, they will not have hit a `NEWLINE` - if max_line != -1: + if tp in (tokenize.NL, tokenize.NEWLINE): ret.update(self._noqa_line_range(min_line, max_line)) - self._noqa_line_mapping = ret + min_line = len(self.lines) + 2 + max_line = -1 + return ret + + def noqa_line_for(self, line_number: int) -> str | None: + """Retrieve the line which will be used to determine noqa.""" # NOTE(sigmavirus24): Some plugins choose to report errors for empty # files on Line 1. In those cases, we shouldn't bother trying to # retrieve a physical line (since none exist). @@ -377,12 +366,8 @@ class FileProcessor: # If we have nothing to analyze quit early return - first_byte = ord(self.lines[0][0]) - if first_byte not in (0xEF, 0xFEFF): - return - # If the first byte of the file is a UTF-8 BOM, strip it - if first_byte == 0xFEFF: + if self.lines[0][:1] == "\uFEFF": self.lines[0] = self.lines[0][1:] elif self.lines[0][:3] == "\xEF\xBB\xBF": self.lines[0] = self.lines[0][3:] diff --git a/tox.ini b/tox.ini index aae002d..539b5c4 100644 --- a/tox.ini +++ b/tox.ini @@ -6,6 +6,7 @@ envlist = py,flake8,linters,docs deps = pytest!=3.0.5,!=5.2.3 coverage>=6 + covdefaults commands = coverage run -m pytest {posargs} coverage report From b3e251512238ad39c87e4b8d1614903fe493f7ea Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Jul 2023 15:53:22 -0400 Subject: [PATCH 37/92] remove --include-in-doctest and --exclude-in-doctest --- docs/source/user/options.rst | 60 ------------------------ src/flake8/plugins/pyflakes.py | 85 ++-------------------------------- 2 files changed, 3 insertions(+), 142 deletions(-) diff --git a/docs/source/user/options.rst b/docs/source/user/options.rst index 8db2df8..d767748 100644 --- a/docs/source/user/options.rst +++ b/docs/source/user/options.rst @@ -98,10 +98,6 @@ Index of Options - :option:`flake8 --doctests` -- :option:`flake8 --include-in-doctest` - -- :option:`flake8 --exclude-from-doctest` - - :option:`flake8 --benchmark` - :option:`flake8 --bug-report` @@ -997,62 +993,6 @@ Options and their Descriptions doctests = True -.. option:: --include-in-doctest= - - :ref:`Go back to index ` - - Specify which files are checked by PyFlakes for doctest syntax. - - This is registered by the default PyFlakes plugin. - - Command-line example: - - .. prompt:: bash - - flake8 --include-in-doctest=dir/subdir/file.py,dir/other/file.py dir/ - - This **can** be specified in config files. - - Example config file usage: - - .. code-block:: ini - - include-in-doctest = - dir/subdir/file.py, - dir/other/file.py - include_in_doctest = - dir/subdir/file.py, - dir/other/file.py - - -.. option:: --exclude-from-doctest= - - :ref:`Go back to index ` - - Specify which files are not to be checked by PyFlakes for doctest syntax. - - This is registered by the default PyFlakes plugin. - - Command-line example: - - .. prompt:: bash - - flake8 --exclude-from-doctest=dir/subdir/file.py,dir/other/file.py dir/ - - This **can** be specified in config files. - - Example config file usage: - - .. code-block:: ini - - exclude-from-doctest = - dir/subdir/file.py, - dir/other/file.py - exclude_from_doctest = - dir/subdir/file.py, - dir/other/file.py - - .. option:: --benchmark :ref:`Go back to index ` diff --git a/src/flake8/plugins/pyflakes.py b/src/flake8/plugins/pyflakes.py index f62527e..6c57619 100644 --- a/src/flake8/plugins/pyflakes.py +++ b/src/flake8/plugins/pyflakes.py @@ -4,13 +4,11 @@ from __future__ import annotations import argparse import ast import logging -import os from typing import Any from typing import Generator import pyflakes.checker -from flake8 import utils from flake8.options.manager import OptionManager LOG = logging.getLogger(__name__) @@ -68,34 +66,12 @@ class FlakesChecker(pyflakes.checker.Checker): """Subclass the Pyflakes checker to conform with the flake8 API.""" with_doctest = False - include_in_doctest: list[str] = [] - exclude_from_doctest: list[str] = [] def __init__(self, tree: ast.AST, filename: str) -> None: """Initialize the PyFlakes plugin with an AST tree and filename.""" - filename = utils.normalize_path(filename) - with_doctest = self.with_doctest - included_by = [ - include - for include in self.include_in_doctest - if include != "" and filename.startswith(include) - ] - if included_by: - with_doctest = True - - for exclude in self.exclude_from_doctest: - if exclude != "" and filename.startswith(exclude): - with_doctest = False - overlapped_by = [ - include - for include in included_by - if include.startswith(exclude) - ] - - if overlapped_by: - with_doctest = True - - super().__init__(tree, filename=filename, withDoctest=with_doctest) + super().__init__( + tree, filename=filename, withDoctest=self.with_doctest + ) @classmethod def add_options(cls, parser: OptionManager) -> None: @@ -113,24 +89,6 @@ class FlakesChecker(pyflakes.checker.Checker): parse_from_config=True, help="also check syntax of the doctests", ) - parser.add_option( - "--include-in-doctest", - default="", - dest="include_in_doctest", - parse_from_config=True, - comma_separated_list=True, - normalize_paths=True, - help="Run doctests only on these files", - ) - parser.add_option( - "--exclude-from-doctest", - default="", - dest="exclude_from_doctest", - parse_from_config=True, - comma_separated_list=True, - normalize_paths=True, - help="Skip these files when running doctests", - ) @classmethod def parse_options(cls, options: argparse.Namespace) -> None: @@ -139,43 +97,6 @@ class FlakesChecker(pyflakes.checker.Checker): cls.builtIns = cls.builtIns.union(options.builtins) cls.with_doctest = options.doctests - if options.include_in_doctest or options.exclude_from_doctest: - LOG.warning( - "--include-in-doctest / --exclude-from-doctest will be " - "removed in a future version. see PyCQA/flake8#1747" - ) - - included_files = [] - for included_file in options.include_in_doctest: - if included_file == "": - continue - if not included_file.startswith((os.sep, "./", "~/")): - included_files.append(f"./{included_file}") - else: - included_files.append(included_file) - cls.include_in_doctest = utils.normalize_paths(included_files) - - excluded_files = [] - for excluded_file in options.exclude_from_doctest: - if excluded_file == "": - continue - if not excluded_file.startswith((os.sep, "./", "~/")): - excluded_files.append(f"./{excluded_file}") - else: - excluded_files.append(excluded_file) - cls.exclude_from_doctest = utils.normalize_paths(excluded_files) - - inc_exc = set(cls.include_in_doctest).intersection( - cls.exclude_from_doctest - ) - if inc_exc: - raise ValueError( - f"{inc_exc!r} was specified in both the " - f"include-in-doctest and exclude-from-doctest " - f"options. You are not allowed to specify it in " - f"both for doctesting." - ) - def run(self) -> Generator[tuple[int, int, str, type[Any]], None, None]: """Run the plugin.""" for message in self.messages: From d734e316890aad2cab1ad02e8ba8a277f23d7dfb Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 31 Jul 2023 19:27:59 -0400 Subject: [PATCH 38/92] add minimal rtd configuration --- .readthedocs.yaml | 10 ++++++++++ docs/source/requirements.txt | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..0425dc2 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,10 @@ +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.11" +python: + install: + - path: . + - requirements: docs/source/requirements.txt diff --git a/docs/source/requirements.txt b/docs/source/requirements.txt index da3b991..93f773e 100644 --- a/docs/source/requirements.txt +++ b/docs/source/requirements.txt @@ -1,4 +1,4 @@ sphinx>=2.1.0,!=3.1.0 -sphinx_rtd_theme -sphinx-prompt +sphinx-rtd-theme>=1.2.2 +sphinx-prompt>=1.5.0 docutils!=0.18 From 5cd0bcb45a22e490545d8741e57557bf4400f488 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 12:27:47 +0000 Subject: [PATCH 39/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.9.0 → v3.10.1](https://github.com/asottile/pyupgrade/compare/v3.9.0...v3.10.1) - [github.com/PyCQA/flake8: 6.0.0 → 6.1.0](https://github.com/PyCQA/flake8/compare/6.0.0...6.1.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6de9c1b..0c8544e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.9.0 + rev: v3.10.1 hooks: - id: pyupgrade args: [--py38-plus] @@ -31,7 +31,7 @@ repos: - id: black args: [--line-length=79] - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 + rev: 6.1.0 hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy From 5a5ebaf10a5996de1d759f7088ca9aaec2175f12 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 10:33:21 +0000 Subject: [PATCH 40/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.4.1 → v1.5.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.4.1...v1.5.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0c8544e..10c91d1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.4.1 + rev: v1.5.0 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From aceddfeabb6a59b8cef318ac29bab15a8bc78b6f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 11:03:53 +0000 Subject: [PATCH 41/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.5.0 → v1.5.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.5.0...v1.5.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 10c91d1..1bcfab6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.5.0 + rev: v1.5.1 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From a0f393ca71c7e19b7cf2a30e801f84ceb3c12106 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 13:10:16 +0000 Subject: [PATCH 42/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1bcfab6..1394545 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/psf/black - rev: 23.7.0 + rev: 23.9.1 hooks: - id: black args: [--line-length=79] From 7899a82c5de1489849e722905661f703d89ece7f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 19 Sep 2023 12:01:32 +0000 Subject: [PATCH 43/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.11.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.11.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.11.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.11.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1394545..5969610 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,7 +12,7 @@ repos: hooks: - id: setup-cfg-fmt - repo: https://github.com/asottile/reorder-python-imports - rev: v3.10.0 + rev: v3.11.0 hooks: - id: reorder-python-imports args: [ @@ -21,7 +21,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.10.1 + rev: v3.11.0 hooks: - id: pyupgrade args: [--py38-plus] From fb5759b37facaee1b8db4a7666ee6b82d2293ee0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 12:18:31 +0000 Subject: [PATCH 44/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.11.0 → v3.13.0](https://github.com/asottile/pyupgrade/compare/v3.11.0...v3.13.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5969610..4783496 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.11.0 + rev: v3.13.0 hooks: - id: pyupgrade args: [--py38-plus] From 0a67cbc61ff6fece30b3be1d6e089bbc04cc3e5f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 14:57:35 +0000 Subject: [PATCH 45/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/setup-cfg-fmt: v2.4.0 → v2.5.0](https://github.com/asottile/setup-cfg-fmt/compare/v2.4.0...v2.5.0) - [github.com/asottile/reorder-python-imports: v3.11.0 → v3.12.0](https://github.com/asottile/reorder-python-imports/compare/v3.11.0...v3.12.0) - [github.com/asottile/pyupgrade: v3.13.0 → v3.14.0](https://github.com/asottile/pyupgrade/compare/v3.13.0...v3.14.0) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4783496..b51f834 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,11 +8,11 @@ repos: - id: trailing-whitespace exclude: ^tests/fixtures/ - repo: https://github.com/asottile/setup-cfg-fmt - rev: v2.4.0 + rev: v2.5.0 hooks: - id: setup-cfg-fmt - repo: https://github.com/asottile/reorder-python-imports - rev: v3.11.0 + rev: v3.12.0 hooks: - id: reorder-python-imports args: [ @@ -21,7 +21,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.13.0 + rev: v3.14.0 hooks: - id: pyupgrade args: [--py38-plus] From 67c0ecc6df951cf3e37f41db935cb7390c1c1678 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 21:55:48 +0000 Subject: [PATCH 46/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.4.0 → v4.5.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.4.0...v4.5.0) - [github.com/asottile/pyupgrade: v3.14.0 → v3.15.0](https://github.com/asottile/pyupgrade/compare/v3.14.0...v3.15.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b51f834..595cae4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-yaml - id: debug-statements @@ -21,7 +21,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.14.0 + rev: v3.15.0 hooks: - id: pyupgrade args: [--py38-plus] From 8bdec0b54ef230e9d0fa5ca9554d4a3d6a764cf5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 21:14:00 +0000 Subject: [PATCH 47/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.5.1 → v1.6.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.5.1...v1.6.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 595cae4..372a9ec 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.5.1 + rev: v1.6.0 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From 61d6ca224df709be82fd370bf1a84d0ddd69965f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 21:45:49 +0000 Subject: [PATCH 48/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.9.1 → 23.10.1](https://github.com/psf/black/compare/23.9.1...23.10.1) - [github.com/pre-commit/mirrors-mypy: v1.6.0 → v1.6.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.6.0...v1.6.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 372a9ec..92467ac 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/psf/black - rev: 23.9.1 + rev: 23.10.1 hooks: - id: black args: [--line-length=79] @@ -35,7 +35,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.6.0 + rev: v1.6.1 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From d1b1ec73be7ecbf3cbc55a1a5d07d8e37c725ee1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 21:55:32 +0000 Subject: [PATCH 49/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.10.1 → 23.11.0](https://github.com/psf/black/compare/23.10.1...23.11.0) - [github.com/pre-commit/mirrors-mypy: v1.6.1 → v1.7.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.6.1...v1.7.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 92467ac..3dbc531 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/psf/black - rev: 23.10.1 + rev: 23.11.0 hooks: - id: black args: [--line-length=79] @@ -35,7 +35,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.6.1 + rev: v1.7.0 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From 7e1c87554df99a3c779747b30e6a52aace323d4f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 21:09:51 +0000 Subject: [PATCH 50/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.7.0 → v1.7.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.7.0...v1.7.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3dbc531..fa2ea66 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.0 + rev: v1.7.1 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From c8801c129ab3138c4f3db4841d76bb30ed8e3f8c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 21:54:28 +0000 Subject: [PATCH 51/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.11.0 → 23.12.0](https://github.com/psf/black/compare/23.11.0...23.12.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fa2ea66..44f785d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/psf/black - rev: 23.11.0 + rev: 23.12.0 hooks: - id: black args: [--line-length=79] From b67ce03a4a9c9902fea163021a844f34287ee6bc Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Wed, 20 Dec 2023 06:54:05 -0600 Subject: [PATCH 52/92] Fix bugbear lints --- src/flake8/checker.py | 3 ++- tests/unit/plugins/reporter_test.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/flake8/checker.py b/src/flake8/checker.py index 6c4caef..39c43e3 100644 --- a/src/flake8/checker.py +++ b/src/flake8/checker.py @@ -70,7 +70,8 @@ def _mp_init(argv: Sequence[str]) -> None: signal.signal(signal.SIGINT, signal.SIG_IGN) try: - _mp_plugins, _mp_options # for `fork` this'll already be set + # for `fork` this'll already be set + _mp_plugins, _mp_options # noqa: B018 except NameError: plugins, options = parse_args(argv) _mp_plugins, _mp_options = plugins.checkers, options diff --git a/tests/unit/plugins/reporter_test.py b/tests/unit/plugins/reporter_test.py index ff4d97f..842465a 100644 --- a/tests/unit/plugins/reporter_test.py +++ b/tests/unit/plugins/reporter_test.py @@ -11,7 +11,7 @@ from flake8.plugins import reporter def _opts(**kwargs): - kwargs.setdefault("quiet", 0), + kwargs.setdefault("quiet", 0) kwargs.setdefault("color", "never") kwargs.setdefault("output_file", None) return argparse.Namespace(**kwargs) From 06c1503842ee90a4cca5ed57908c0f27595a6f4d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 20 Dec 2023 12:54:27 +0000 Subject: [PATCH 53/92] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/flake8/checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flake8/checker.py b/src/flake8/checker.py index 39c43e3..329a2cc 100644 --- a/src/flake8/checker.py +++ b/src/flake8/checker.py @@ -71,7 +71,7 @@ def _mp_init(argv: Sequence[str]) -> None: try: # for `fork` this'll already be set - _mp_plugins, _mp_options # noqa: B018 + _mp_plugins, _mp_options # noqa: B018 except NameError: plugins, options = parse_args(argv) _mp_plugins, _mp_options = plugins.checkers, options From e27611f1eadc16a5bd02125aa8a054c632d3b0c7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 25 Dec 2023 21:35:51 +0000 Subject: [PATCH 54/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.12.0 → 23.12.1](https://github.com/psf/black/compare/23.12.0...23.12.1) - [github.com/pre-commit/mirrors-mypy: v1.7.1 → v1.8.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.7.1...v1.8.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 44f785d..bbb1833 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/psf/black - rev: 23.12.0 + rev: 23.12.1 hooks: - id: black args: [--line-length=79] @@ -35,7 +35,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.1 + rev: v1.8.0 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From cde8570df3bf4b647dfa65a97613fb325a9f1bbd Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 4 Jan 2024 19:36:48 -0500 Subject: [PATCH 55/92] upgrade pyflakes to 3.2.x --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 70c2b8d..2254902 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,7 +30,7 @@ packages = find: install_requires = mccabe>=0.7.0,<0.8.0 pycodestyle>=2.11.0,<2.12.0 - pyflakes>=3.1.0,<3.2.0 + pyflakes>=3.2.0,<3.3.0 python_requires = >=3.8.1 package_dir = =src From 88a4f9b2f48fc44b025a48fa6a8ac7cc89ef70e0 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 4 Jan 2024 19:41:07 -0500 Subject: [PATCH 56/92] Release 7.0.0 --- docs/source/internal/releases.rst | 2 +- docs/source/release-notes/7.0.0.rst | 19 +++++++++++++++++++ docs/source/release-notes/index.rst | 6 ++++++ src/flake8/__init__.py | 2 +- 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 docs/source/release-notes/7.0.0.rst diff --git a/docs/source/internal/releases.rst b/docs/source/internal/releases.rst index fc29bd3..0081509 100644 --- a/docs/source/internal/releases.rst +++ b/docs/source/internal/releases.rst @@ -30,7 +30,7 @@ Historically, |Flake8| has generated major releases for: - Large scale refactoring (2.0, 3.0, 5.0, 6.0) -- Subtly breaking CLI changes (3.0, 4.0, 5.0, 6.0) +- Subtly breaking CLI changes (3.0, 4.0, 5.0, 6.0, 7.0) - Breaking changes to its plugin interface (3.0) diff --git a/docs/source/release-notes/7.0.0.rst b/docs/source/release-notes/7.0.0.rst new file mode 100644 index 0000000..6cd852a --- /dev/null +++ b/docs/source/release-notes/7.0.0.rst @@ -0,0 +1,19 @@ +7.0.0 -- 2024-01-04 +------------------- + +You can view the `7.0.0 milestone`_ on GitHub for more details. + +Backwards Incompatible Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Remove ``--include-in-doctest`` and ``--exclude-from-doctest`` options. + (See also :issue:`1747`, :pull:`1854`) + +New Dependency Information +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Pyflakes has been updated to >= 3.2.0, < 3.3.0 (See also :pull:`1906`). + +.. all links +.. _7.0.0 milestone: + https://github.com/PyCQA/flake8/milestone/49 diff --git a/docs/source/release-notes/index.rst b/docs/source/release-notes/index.rst index 8cd7573..58c6845 100644 --- a/docs/source/release-notes/index.rst +++ b/docs/source/release-notes/index.rst @@ -5,6 +5,12 @@ All of the release notes that have been recorded for Flake8 are organized here with the newest releases first. +7.x Release Series +================== + +.. toctree:: + 7.0.0 + 6.x Release Series ================== diff --git a/src/flake8/__init__.py b/src/flake8/__init__.py index 171b1db..ea7a56d 100644 --- a/src/flake8/__init__.py +++ b/src/flake8/__init__.py @@ -17,7 +17,7 @@ import sys LOG = logging.getLogger(__name__) LOG.addHandler(logging.NullHandler()) -__version__ = "6.1.0" +__version__ = "7.0.0" __version_info__ = tuple(int(i) for i in __version__.split(".") if i.isdigit()) _VERBOSITY_TO_LOG_LEVEL = { From 26d3184ae2432eb382980590c77b47bb393ce4ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Fri, 5 Jan 2024 12:14:44 +0100 Subject: [PATCH 57/92] update plugins for sphinx-prompt-1.8.0 The sphinx-prompt plugin has renamed its package in 1.8.0 from erraneous `sphinx-prompt` name to `sphinx_prompt`. Adjust the conf accordingly. --- docs/source/conf.py | 2 +- docs/source/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index a2b4af3..9b7aa5a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -34,7 +34,7 @@ extensions = [ "sphinx.ext.todo", "sphinx.ext.coverage", "sphinx.ext.viewcode", - "sphinx-prompt", + "sphinx_prompt", ] # Add any paths that contain templates here, relative to this directory. diff --git a/docs/source/requirements.txt b/docs/source/requirements.txt index 93f773e..765fb13 100644 --- a/docs/source/requirements.txt +++ b/docs/source/requirements.txt @@ -1,4 +1,4 @@ sphinx>=2.1.0,!=3.1.0 sphinx-rtd-theme>=1.2.2 -sphinx-prompt>=1.5.0 +sphinx-prompt>=1.8.0 docutils!=0.18 From a2b68c84e760a4906ad47eac84d277c85aaf8322 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 21:35:25 +0000 Subject: [PATCH 58/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/PyCQA/flake8: 6.1.0 → 7.0.0](https://github.com/PyCQA/flake8/compare/6.1.0...7.0.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bbb1833..ad60be1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: - id: black args: [--line-length=79] - repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy From 49f52a8598d8a934b07f367a1b3ad87dbe51be5b Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Thu, 14 Mar 2024 21:06:23 +0100 Subject: [PATCH 59/92] Update documentation regarding entry points Refer to the PyPA packaging guide Replace references to the deprecated `pkg_resources` docs --- docs/source/conf.py | 6 +++++- docs/source/plugin-development/index.rst | 7 ++----- .../registering-plugins.rst | 21 ++++++++++--------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 9b7aa5a..48f8a52 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -296,7 +296,11 @@ texinfo_documents = [ # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {"python": ("https://docs.python.org/3/", None)} +intersphinx_mapping = { + "python": ("https://docs.python.org/3/", None), + "packaging": ("https://packaging.python.org/en/latest/", None), + "setuptools": ("https://setuptools.pypa.io/en/latest/", None), +} extlinks = { "issue": ("https://github.com/pycqa/flake8/issues/%s", "#%s"), diff --git a/docs/source/plugin-development/index.rst b/docs/source/plugin-development/index.rst index c89e5f0..82f4a6b 100644 --- a/docs/source/plugin-development/index.rst +++ b/docs/source/plugin-development/index.rst @@ -30,7 +30,8 @@ To get started writing a |Flake8| :term:`plugin` you first need: Once you've gathered these things, you can get started. -All plugins for |Flake8| must be registered via `entry points`_. In this +All plugins for |Flake8| must be registered via +:external:doc:`entry points`. In this section we cover: - How to register your plugin so |Flake8| can find it @@ -62,7 +63,3 @@ Here's a tutorial which goes over building an ast checking plugin from scratch: registering-plugins plugin-parameters formatters - - -.. _entry points: - https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points diff --git a/docs/source/plugin-development/registering-plugins.rst b/docs/source/plugin-development/registering-plugins.rst index ca74008..e5568b8 100644 --- a/docs/source/plugin-development/registering-plugins.rst +++ b/docs/source/plugin-development/registering-plugins.rst @@ -12,16 +12,15 @@ To register any kind of plugin with |Flake8|, you need: #. A name for your plugin that will (ideally) be unique. -#. A somewhat recent version of setuptools (newer than 0.7.0 but preferably as - recent as you can attain). - -|Flake8| relies on functionality provided by setuptools called -`Entry Points`_. These allow any package to register a plugin with |Flake8| -via that package's ``setup.py`` file. +|Flake8| relies on functionality provided by build tools called +:external:doc:`entry points`. These allow +any package to register a plugin with |Flake8| via that package's metadata. Let's presume that we already have our plugin written and it's in a module -called ``flake8_example``. We might have a ``setup.py`` that looks something -like: +called ``flake8_example``. We will also assume ``setuptools`` is used as a +:term:`Build Backend`, but be aware that most backends support entry points. + +We might have a ``setup.py`` that looks something like: .. code-block:: python @@ -150,5 +149,7 @@ If your plugin is intended to be opt-in, it can set the attribute :ref:`enable-extensions` with your plugin's entry point. -.. _Entry Points: - https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points +.. seealso:: + + The :external:doc:`setuptools user guide ` about + entry points. From 350f2545fd3ec75640a1605e4995a2f921e8b38b Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Sun, 17 Mar 2024 08:56:07 +0100 Subject: [PATCH 60/92] Use explicit external references --- docs/source/plugin-development/index.rst | 2 +- .../plugin-development/registering-plugins.rst | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/source/plugin-development/index.rst b/docs/source/plugin-development/index.rst index 82f4a6b..9b38fe2 100644 --- a/docs/source/plugin-development/index.rst +++ b/docs/source/plugin-development/index.rst @@ -31,7 +31,7 @@ To get started writing a |Flake8| :term:`plugin` you first need: Once you've gathered these things, you can get started. All plugins for |Flake8| must be registered via -:external:doc:`entry points`. In this +:external+packaging:doc:`entry points`. In this section we cover: - How to register your plugin so |Flake8| can find it diff --git a/docs/source/plugin-development/registering-plugins.rst b/docs/source/plugin-development/registering-plugins.rst index e5568b8..41c34e0 100644 --- a/docs/source/plugin-development/registering-plugins.rst +++ b/docs/source/plugin-development/registering-plugins.rst @@ -13,12 +13,14 @@ To register any kind of plugin with |Flake8|, you need: #. A name for your plugin that will (ideally) be unique. |Flake8| relies on functionality provided by build tools called -:external:doc:`entry points`. These allow -any package to register a plugin with |Flake8| via that package's metadata. +:external+packaging:doc:`entry points`. These +allow any package to register a plugin with |Flake8| via that package's +metadata. Let's presume that we already have our plugin written and it's in a module +:external+packaging:term:`Build Backend`, but be aware that most backends called ``flake8_example``. We will also assume ``setuptools`` is used as a -:term:`Build Backend`, but be aware that most backends support entry points. +support entry points. We might have a ``setup.py`` that looks something like: @@ -151,5 +153,5 @@ point. .. seealso:: - The :external:doc:`setuptools user guide ` about - entry points. + The :external+setuptools:doc:`setuptools user guide ` + about entry points. From ba0f56610adbd4d8733772ce1c63efcab1b70079 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Sun, 17 Mar 2024 08:56:07 +0100 Subject: [PATCH 61/92] Use explicit external references --- docs/source/plugin-development/registering-plugins.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/plugin-development/registering-plugins.rst b/docs/source/plugin-development/registering-plugins.rst index 41c34e0..aac87e8 100644 --- a/docs/source/plugin-development/registering-plugins.rst +++ b/docs/source/plugin-development/registering-plugins.rst @@ -20,6 +20,7 @@ metadata. Let's presume that we already have our plugin written and it's in a module :external+packaging:term:`Build Backend`, but be aware that most backends called ``flake8_example``. We will also assume ``setuptools`` is used as a +:external+packaging:term:`Build Backend`, but be aware that most backends support entry points. We might have a ``setup.py`` that looks something like: From 6659b213c9aa8fa49235e13a365fcd34f58cbc6b Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Mon, 18 Mar 2024 10:43:13 -0500 Subject: [PATCH 62/92] Fix toctree ordering in index Also fix line-length issue in PR --- docs/source/plugin-development/index.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/plugin-development/index.rst b/docs/source/plugin-development/index.rst index 9b38fe2..9088942 100644 --- a/docs/source/plugin-development/index.rst +++ b/docs/source/plugin-development/index.rst @@ -55,6 +55,8 @@ Here's a tutorial which goes over building an ast checking plugin from scratch: +Detailed Plugin Development Documentation +========================================= .. toctree:: :caption: Plugin Developer Documentation From 866ad729c64eea359960a8ac4e3f1201104ee55c Mon Sep 17 00:00:00 2001 From: mzagol Date: Mon, 15 Apr 2024 15:52:25 -0500 Subject: [PATCH 63/92] Add --extend-exclude to the TOC --- docs/source/user/options.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/user/options.rst b/docs/source/user/options.rst index d767748..bd80c87 100644 --- a/docs/source/user/options.rst +++ b/docs/source/user/options.rst @@ -46,6 +46,8 @@ Index of Options - :option:`flake8 --exclude` +- :option:`flake8 --extend-exclude` + - :option:`flake8 --filename` - :option:`flake8 --stdin-display-name` From defd315175b7b77472affb61a410e5720dabdc1a Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 15 Jun 2024 17:30:39 -0400 Subject: [PATCH 64/92] latest pycodestyle --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 2254902..28e6f93 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,7 +29,7 @@ classifiers = packages = find: install_requires = mccabe>=0.7.0,<0.8.0 - pycodestyle>=2.11.0,<2.12.0 + pycodestyle>=2.12.0,<2.13.0 pyflakes>=3.2.0,<3.3.0 python_requires = >=3.8.1 package_dir = From 65a38c42a7f1a05ff8d99b313160754fc9b7a0d8 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 15 Jun 2024 17:36:14 -0400 Subject: [PATCH 65/92] Release 7.1.0 --- docs/source/release-notes/7.1.0.rst | 13 +++++++++++++ docs/source/release-notes/index.rst | 1 + src/flake8/__init__.py | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 docs/source/release-notes/7.1.0.rst diff --git a/docs/source/release-notes/7.1.0.rst b/docs/source/release-notes/7.1.0.rst new file mode 100644 index 0000000..2229baa --- /dev/null +++ b/docs/source/release-notes/7.1.0.rst @@ -0,0 +1,13 @@ +7.1.0 -- 2024-06-15 +------------------- + +You can view the `7.1.0 milestone`_ on GitHub for more details. + +New Dependency Information +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- pycodestyle has been updated to >= 2.12.0, < 2.13.0 (See also :pull:`1939`). + +.. all links +.. _7.1.0 milestone: + https://github.com/PyCQA/flake8/milestone/50 diff --git a/docs/source/release-notes/index.rst b/docs/source/release-notes/index.rst index 58c6845..4ae650a 100644 --- a/docs/source/release-notes/index.rst +++ b/docs/source/release-notes/index.rst @@ -10,6 +10,7 @@ with the newest releases first. .. toctree:: 7.0.0 + 7.1.0 6.x Release Series ================== diff --git a/src/flake8/__init__.py b/src/flake8/__init__.py index ea7a56d..19df059 100644 --- a/src/flake8/__init__.py +++ b/src/flake8/__init__.py @@ -17,7 +17,7 @@ import sys LOG = logging.getLogger(__name__) LOG.addHandler(logging.NullHandler()) -__version__ = "7.0.0" +__version__ = "7.1.0" __version_info__ = tuple(int(i) for i in __version__.split(".") if i.isdigit()) _VERBOSITY_TO_LOG_LEVEL = { From 10314ad9e5236f1ddf70cb25c2854c93c0840b66 Mon Sep 17 00:00:00 2001 From: Victorien <65306057+Viicos@users.noreply.github.com> Date: Tue, 23 Jul 2024 13:39:49 +0200 Subject: [PATCH 66/92] Fix wording of plugins documentation --- docs/source/plugin-development/registering-plugins.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/plugin-development/registering-plugins.rst b/docs/source/plugin-development/registering-plugins.rst index aac87e8..964ff99 100644 --- a/docs/source/plugin-development/registering-plugins.rst +++ b/docs/source/plugin-development/registering-plugins.rst @@ -18,7 +18,6 @@ allow any package to register a plugin with |Flake8| via that package's metadata. Let's presume that we already have our plugin written and it's in a module -:external+packaging:term:`Build Backend`, but be aware that most backends called ``flake8_example``. We will also assume ``setuptools`` is used as a :external+packaging:term:`Build Backend`, but be aware that most backends support entry points. From bdcd5c2c0afadaf7c92a4b26d96055cecdd38cf3 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 1 Aug 2024 11:08:06 +0100 Subject: [PATCH 67/92] Handle escaped braces in f-strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To use a curly brace in an f-string, you must escape it. For example: >>> k = 1 >>> f'{{{k}' '{1' Saving this as a script and running the 'tokenize' module highlights something odd around the counting of tokens: ❯ python -m tokenize wow.py 0,0-0,0: ENCODING 'utf-8' 1,0-1,1: NAME 'k' 1,2-1,3: OP '=' 1,4-1,5: NUMBER '1' 1,5-1,6: NEWLINE '\n' 2,0-2,2: FSTRING_START "f'" 2,2-2,3: FSTRING_MIDDLE '{' # <-- here... 2,4-2,5: OP '{' # <-- and here 2,5-2,6: NAME 'k' 2,6-2,7: OP '}' 2,7-2,8: FSTRING_END "'" 2,8-2,9: NEWLINE '\n' 3,0-3,0: ENDMARKER '' The FSTRING_MIDDLE character we have is the escaped/post-parse single curly brace rather than the raw double curly brace, however, while our end index of this token accounts for the parsed form, the start index of the next token does not (put another way, it jumps from 3 -> 4). This triggers some existing, unrelated code that we need to bypass. Do just that. Signed-off-by: Stephen Finucane Closes: #1948 --- src/flake8/processor.py | 8 ++++++- tests/integration/test_plugins.py | 35 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/flake8/processor.py b/src/flake8/processor.py index 21a25e0..e44547b 100644 --- a/src/flake8/processor.py +++ b/src/flake8/processor.py @@ -203,7 +203,13 @@ class FileProcessor: if token_type == tokenize.STRING: text = mutate_string(text) elif token_type == FSTRING_MIDDLE: # pragma: >=3.12 cover - text = "x" * len(text) + # A curly brace in an FSTRING_MIDDLE token must be an escaped + # curly brace. Both 'text' and 'end' will account for the + # escaped version of the token (i.e. a single brace) rather + # than the raw double brace version, so we must counteract this + brace_offset = text.count("{") + text.count("}") + text = "x" * (len(text) + brace_offset) + end = (end[0], end[1] + brace_offset) if previous_row: (start_row, start_column) = start if previous_row != start_row: diff --git a/tests/integration/test_plugins.py b/tests/integration/test_plugins.py index d4c22b0..90ca555 100644 --- a/tests/integration/test_plugins.py +++ b/tests/integration/test_plugins.py @@ -1,6 +1,8 @@ """Integration tests for plugin loading.""" from __future__ import annotations +import sys + import pytest from flake8.main.cli import main @@ -261,3 +263,36 @@ t.py:1:1: T001 "f'xxxxxxxxxxx'" """ out, err = capsys.readouterr() assert out == expected + + +def test_escaping_of_fstrings_in_string_redacter(tmpdir, capsys): + cfg_s = f"""\ +[flake8] +extend-ignore = F +[flake8:local-plugins] +extension = + T = {yields_logical_line.__module__}:{yields_logical_line.__name__} +""" + + cfg = tmpdir.join("tox.ini") + cfg.write(cfg_s) + + src = """\ +f'{{"{hello}": "{world}"}}' +""" + t_py = tmpdir.join("t.py") + t_py.write_binary(src.encode()) + + with tmpdir.as_cwd(): + assert main(("t.py", "--config", str(cfg))) == 1 + + if sys.version_info >= (3, 12): # pragma: >=3.12 cover + expected = """\ +t.py:1:1: T001 "f'xxx{hello}xxxx{world}xxx'" +""" + else: # pragma: <3.12 cover + expected = """\ +t.py:1:1: T001 "f'xxxxxxxxxxxxxxxxxxxxxxxx'" +""" + out, err = capsys.readouterr() + assert out == expected From cf1542cefa3e766670b2066dd75c4571d682a649 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sun, 4 Aug 2024 16:31:56 -0400 Subject: [PATCH 68/92] Release 7.1.1 --- docs/source/release-notes/7.1.1.rst | 15 +++++++++++++++ docs/source/release-notes/index.rst | 1 + src/flake8/__init__.py | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 docs/source/release-notes/7.1.1.rst diff --git a/docs/source/release-notes/7.1.1.rst b/docs/source/release-notes/7.1.1.rst new file mode 100644 index 0000000..62f2d11 --- /dev/null +++ b/docs/source/release-notes/7.1.1.rst @@ -0,0 +1,15 @@ +7.1.1 -- 2024-08-04 +------------------- + +You can view the `7.1.1 milestone`_ on GitHub for more details. + +Bugs Fixed +~~~~~~~~~~ + +- Properly preserve escaped `{` and `}` in fstrings in logical lines in 3.12+. + (See also :issue:`1948`, :pull:`1949`). + + +.. all links +.. _7.1.1 milestone: + https://github.com/PyCQA/flake8/milestone/51 diff --git a/docs/source/release-notes/index.rst b/docs/source/release-notes/index.rst index 4ae650a..9bf8646 100644 --- a/docs/source/release-notes/index.rst +++ b/docs/source/release-notes/index.rst @@ -11,6 +11,7 @@ with the newest releases first. .. toctree:: 7.0.0 7.1.0 + 7.1.1 6.x Release Series ================== diff --git a/src/flake8/__init__.py b/src/flake8/__init__.py index 19df059..101eafe 100644 --- a/src/flake8/__init__.py +++ b/src/flake8/__init__.py @@ -17,7 +17,7 @@ import sys LOG = logging.getLogger(__name__) LOG.addHandler(logging.NullHandler()) -__version__ = "7.1.0" +__version__ = "7.1.1" __version_info__ = tuple(int(i) for i in __version__.split(".") if i.isdigit()) _VERBOSITY_TO_LOG_LEVEL = { From f35737a32d8283fd0d3456bd9919718ff2d1b077 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sun, 16 Feb 2025 13:29:05 -0500 Subject: [PATCH 69/92] avoid starting unnecessary processes when file count is limited --- src/flake8/checker.py | 1 + tests/unit/test_checker_manager.py | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/flake8/checker.py b/src/flake8/checker.py index 329a2cc..ff62679 100644 --- a/src/flake8/checker.py +++ b/src/flake8/checker.py @@ -256,6 +256,7 @@ class Manager: exclude=self.exclude, ) ) + self.jobs = min(len(self.filenames), self.jobs) def stop(self) -> None: """Stop checking files.""" diff --git a/tests/unit/test_checker_manager.py b/tests/unit/test_checker_manager.py index 68dd82a..8d6b3dc 100644 --- a/tests/unit/test_checker_manager.py +++ b/tests/unit/test_checker_manager.py @@ -61,6 +61,16 @@ def test_multiprocessing_cpu_count_not_implemented(): assert manager.jobs == 0 +def test_jobs_count_limited_to_file_count(): + style_guide = style_guide_mock() + style_guide.options.jobs = JobsArgument("4") + style_guide.options.filenames = ["file1", "file2"] + manager = checker.Manager(style_guide, finder.Checkers([], [], []), []) + assert manager.jobs == 4 + manager.start() + assert manager.jobs == 2 + + def test_make_checkers(): """Verify that we create a list of FileChecker instances.""" style_guide = style_guide_mock() From fffee8ba9dc5903484f99390e6c7f4bbef59bda7 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sun, 16 Feb 2025 13:48:15 -0500 Subject: [PATCH 70/92] Release 7.1.2 --- docs/source/release-notes/7.1.2.rst | 15 +++++++++++++++ docs/source/release-notes/index.rst | 1 + src/flake8/__init__.py | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 docs/source/release-notes/7.1.2.rst diff --git a/docs/source/release-notes/7.1.2.rst b/docs/source/release-notes/7.1.2.rst new file mode 100644 index 0000000..010656c --- /dev/null +++ b/docs/source/release-notes/7.1.2.rst @@ -0,0 +1,15 @@ +7.1.2 -- 2025-02-16 +------------------- + +You can view the `7.1.2 milestone`_ on GitHub for more details. + +Bugs Fixed +~~~~~~~~~~ + +- Avoid starting unnecessary processes when "# files" < "jobs". + (See also :pull:`1966`). + + +.. all links +.. _7.1.2 milestone: + https://github.com/PyCQA/flake8/milestone/52 diff --git a/docs/source/release-notes/index.rst b/docs/source/release-notes/index.rst index 9bf8646..2145179 100644 --- a/docs/source/release-notes/index.rst +++ b/docs/source/release-notes/index.rst @@ -12,6 +12,7 @@ with the newest releases first. 7.0.0 7.1.0 7.1.1 + 7.1.2 6.x Release Series ================== diff --git a/src/flake8/__init__.py b/src/flake8/__init__.py index 101eafe..0345499 100644 --- a/src/flake8/__init__.py +++ b/src/flake8/__init__.py @@ -17,7 +17,7 @@ import sys LOG = logging.getLogger(__name__) LOG.addHandler(logging.NullHandler()) -__version__ = "7.1.1" +__version__ = "7.1.2" __version_info__ = tuple(int(i) for i in __version__.split(".") if i.isdigit()) _VERBOSITY_TO_LOG_LEVEL = { From fa2ed7145cdf80fd983c2a436226a074f9a9d664 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sun, 16 Feb 2025 15:21:24 -0500 Subject: [PATCH 71/92] remove a few unnecessary mocks in test_checker_manager noticed while implementing the --jobs limiter --- tests/unit/test_checker_manager.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/unit/test_checker_manager.py b/tests/unit/test_checker_manager.py index 8d6b3dc..593822b 100644 --- a/tests/unit/test_checker_manager.py +++ b/tests/unit/test_checker_manager.py @@ -76,9 +76,5 @@ def test_make_checkers(): style_guide = style_guide_mock() style_guide.options.filenames = ["file1", "file2"] manager = checker.Manager(style_guide, finder.Checkers([], [], []), []) - - with mock.patch("flake8.utils.fnmatch", return_value=True): - with mock.patch("flake8.processor.FileProcessor"): - manager.start() - + manager.start() assert manager.filenames == ("file1", "file2") From 9d55ccdb729d1255b9cf09438b6073b05b9ce52c Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Mar 2025 15:39:58 -0400 Subject: [PATCH 72/92] py39+ --- .github/workflows/main.yml | 10 +++++----- .pre-commit-config.yaml | 10 +++++----- bin/gen-pycodestyle-plugin | 10 +++++----- docs/source/internal/releases.rst | 4 ++-- docs/source/user/invocation.rst | 10 +++++----- example-plugin/setup.py | 2 -- setup.cfg | 2 +- src/flake8/checker.py | 10 ++++------ src/flake8/discover_files.py | 8 ++++---- src/flake8/main/application.py | 2 +- src/flake8/main/cli.py | 2 +- src/flake8/options/aggregator.py | 2 +- src/flake8/options/manager.py | 2 +- src/flake8/options/parse_args.py | 2 +- src/flake8/plugins/finder.py | 12 ++++++------ src/flake8/plugins/pycodestyle.py | 6 +++--- src/flake8/plugins/pyflakes.py | 4 ++-- src/flake8/processor.py | 16 ++++++---------- src/flake8/statistics.py | 4 ++-- src/flake8/style_guide.py | 18 ++++++------------ src/flake8/utils.py | 4 ++-- src/flake8/violation.py | 2 +- 22 files changed, 64 insertions(+), 78 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e210204..08f54ea 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,9 +15,6 @@ jobs: - os: ubuntu-latest python: pypy-3.9 toxenv: py - - os: ubuntu-latest - python: 3.8 - toxenv: py - os: ubuntu-latest python: 3.9 toxenv: py @@ -28,11 +25,14 @@ jobs: python: '3.11' toxenv: py - os: ubuntu-latest - python: '3.12-dev' + python: '3.12' + toxenv: py + - os: ubuntu-latest + python: '3.13' toxenv: py # windows - os: windows-latest - python: 3.8 + python: 3.9 toxenv: py # misc - os: ubuntu-latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ad60be1..9df4a79 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,19 +12,19 @@ repos: hooks: - id: setup-cfg-fmt - repo: https://github.com/asottile/reorder-python-imports - rev: v3.12.0 + rev: v3.14.0 hooks: - id: reorder-python-imports args: [ --application-directories, '.:src', - --py38-plus, + --py39-plus, --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.15.0 + rev: v3.19.1 hooks: - id: pyupgrade - args: [--py38-plus] + args: [--py39-plus] - repo: https://github.com/psf/black rev: 23.12.1 hooks: @@ -35,7 +35,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.8.0 + rev: v1.15.0 hooks: - id: mypy exclude: ^(docs/|example-plugin/) diff --git a/bin/gen-pycodestyle-plugin b/bin/gen-pycodestyle-plugin index 8bc2efc..c93fbfe 100755 --- a/bin/gen-pycodestyle-plugin +++ b/bin/gen-pycodestyle-plugin @@ -3,9 +3,9 @@ from __future__ import annotations import inspect import os.path +from collections.abc import Generator from typing import Any from typing import Callable -from typing import Generator from typing import NamedTuple import pycodestyle @@ -42,7 +42,7 @@ class Call(NamedTuple): return cls(func.__name__, inspect.isgeneratorfunction(func), params) -def lines() -> Generator[str, None, None]: +def lines() -> Generator[str]: logical = [] physical = [] @@ -58,8 +58,8 @@ def lines() -> Generator[str, None, None]: yield "# fmt: off" yield "from __future__ import annotations" yield "" + yield "from collections.abc import Generator" yield "from typing import Any" - yield "from typing import Generator" yield "" imports = sorted(call.name for call in logical + physical) for name in imports: @@ -71,7 +71,7 @@ def lines() -> Generator[str, None, None]: logical_params = {param for call in logical for param in call.params} for param in sorted(logical_params): yield f" {param}: Any," - yield ") -> Generator[tuple[int, str], None, None]:" + yield ") -> Generator[tuple[int, str]]:" yield ' """Run pycodestyle logical checks."""' for call in sorted(logical): yield call.to_src() @@ -82,7 +82,7 @@ def lines() -> Generator[str, None, None]: physical_params = {param for call in physical for param in call.params} for param in sorted(physical_params): yield f" {param}: Any," - yield ") -> Generator[tuple[int, str], None, None]:" + yield ") -> Generator[tuple[int, str]]:" yield ' """Run pycodestyle physical checks."""' for call in sorted(physical): yield call.to_src() diff --git a/docs/source/internal/releases.rst b/docs/source/internal/releases.rst index 0081509..d71796d 100644 --- a/docs/source/internal/releases.rst +++ b/docs/source/internal/releases.rst @@ -81,9 +81,9 @@ for users. Before releasing, the following tox test environments must pass: -- Python 3.8 (a.k.a., ``tox -e py38``) +- Python 3.9 (a.k.a., ``tox -e py39``) -- Python 3.12 (a.k.a., ``tox -e py312``) +- Python 3.13 (a.k.a., ``tox -e py313``) - PyPy 3 (a.k.a., ``tox -e pypy3``) diff --git a/docs/source/user/invocation.rst b/docs/source/user/invocation.rst index 61cef97..10895dd 100644 --- a/docs/source/user/invocation.rst +++ b/docs/source/user/invocation.rst @@ -14,25 +14,25 @@ like so: Where you simply allow the shell running in your terminal to locate |Flake8|. In some cases, though, you may have installed |Flake8| for multiple versions -of Python (e.g., Python 3.8 and Python 3.9) and you need to call a specific +of Python (e.g., Python 3.13 and Python 3.14) and you need to call a specific version. In that case, you will have much better results using: .. prompt:: bash - python3.8 -m flake8 + python3.13 -m flake8 Or .. prompt:: bash - python3.9 -m flake8 + python3.14 -m flake8 Since that will tell the correct version of Python to run |Flake8|. .. note:: - Installing |Flake8| once will not install it on both Python 3.8 and - Python 3.9. It will only install it for the version of Python that + Installing |Flake8| once will not install it on both Python 3.13 and + Python 3.14. It will only install it for the version of Python that is running pip. It is also possible to specify command-line options directly to |Flake8|: diff --git a/example-plugin/setup.py b/example-plugin/setup.py index c0720bd..9e7c89f 100644 --- a/example-plugin/setup.py +++ b/example-plugin/setup.py @@ -23,8 +23,6 @@ setuptools.setup( "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Quality Assurance", ], diff --git a/setup.cfg b/setup.cfg index 28e6f93..688e349 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,7 +31,7 @@ install_requires = mccabe>=0.7.0,<0.8.0 pycodestyle>=2.12.0,<2.13.0 pyflakes>=3.2.0,<3.3.0 -python_requires = >=3.8.1 +python_requires = >=3.9 package_dir = =src diff --git a/src/flake8/checker.py b/src/flake8/checker.py index ff62679..d1659b7 100644 --- a/src/flake8/checker.py +++ b/src/flake8/checker.py @@ -9,12 +9,10 @@ import multiprocessing.pool import operator import signal import tokenize +from collections.abc import Generator +from collections.abc import Sequence from typing import Any -from typing import Generator -from typing import List from typing import Optional -from typing import Sequence -from typing import Tuple from flake8 import defaults from flake8 import exceptions @@ -27,7 +25,7 @@ from flake8.plugins.finder import Checkers from flake8.plugins.finder import LoadedPlugin from flake8.style_guide import StyleGuideManager -Results = List[Tuple[str, int, int, str, Optional[str]]] +Results = list[tuple[str, int, int, str, Optional[str]]] LOG = logging.getLogger(__name__) @@ -53,7 +51,7 @@ _mp_options: argparse.Namespace @contextlib.contextmanager def _mp_prefork( plugins: Checkers, options: argparse.Namespace -) -> Generator[None, None, None]: +) -> Generator[None]: # we can save significant startup work w/ `fork` multiprocessing global _mp_plugins, _mp_options _mp_plugins, _mp_options = plugins, options diff --git a/src/flake8/discover_files.py b/src/flake8/discover_files.py index 580d5fd..da28ba5 100644 --- a/src/flake8/discover_files.py +++ b/src/flake8/discover_files.py @@ -3,9 +3,9 @@ from __future__ import annotations import logging import os.path +from collections.abc import Generator +from collections.abc import Sequence from typing import Callable -from typing import Generator -from typing import Sequence from flake8 import utils @@ -16,7 +16,7 @@ def _filenames_from( arg: str, *, predicate: Callable[[str], bool], -) -> Generator[str, None, None]: +) -> Generator[str]: """Generate filenames from an argument. :param arg: @@ -55,7 +55,7 @@ def expand_paths( stdin_display_name: str, filename_patterns: Sequence[str], exclude: Sequence[str], -) -> Generator[str, None, None]: +) -> Generator[str]: """Expand out ``paths`` from commandline to the lintable files.""" if not paths: paths = ["."] diff --git a/src/flake8/main/application.py b/src/flake8/main/application.py index b6bfae3..4704cbd 100644 --- a/src/flake8/main/application.py +++ b/src/flake8/main/application.py @@ -5,7 +5,7 @@ import argparse import json import logging import time -from typing import Sequence +from collections.abc import Sequence import flake8 from flake8 import checker diff --git a/src/flake8/main/cli.py b/src/flake8/main/cli.py index 01a67ac..1a52f36 100644 --- a/src/flake8/main/cli.py +++ b/src/flake8/main/cli.py @@ -2,7 +2,7 @@ from __future__ import annotations import sys -from typing import Sequence +from collections.abc import Sequence from flake8.main import application diff --git a/src/flake8/options/aggregator.py b/src/flake8/options/aggregator.py index af8e744..999161a 100644 --- a/src/flake8/options/aggregator.py +++ b/src/flake8/options/aggregator.py @@ -8,7 +8,7 @@ from __future__ import annotations import argparse import configparser import logging -from typing import Sequence +from collections.abc import Sequence from flake8.options import config from flake8.options.manager import OptionManager diff --git a/src/flake8/options/manager.py b/src/flake8/options/manager.py index 4fd26b2..cb195fe 100644 --- a/src/flake8/options/manager.py +++ b/src/flake8/options/manager.py @@ -5,9 +5,9 @@ import argparse import enum import functools import logging +from collections.abc import Sequence from typing import Any from typing import Callable -from typing import Sequence from flake8 import utils from flake8.plugins.finder import Plugins diff --git a/src/flake8/options/parse_args.py b/src/flake8/options/parse_args.py index e3f8795..ff5e08f 100644 --- a/src/flake8/options/parse_args.py +++ b/src/flake8/options/parse_args.py @@ -2,7 +2,7 @@ from __future__ import annotations import argparse -from typing import Sequence +from collections.abc import Sequence import flake8 from flake8.main import options diff --git a/src/flake8/plugins/finder.py b/src/flake8/plugins/finder.py index 380ec3a..88b66a0 100644 --- a/src/flake8/plugins/finder.py +++ b/src/flake8/plugins/finder.py @@ -7,9 +7,9 @@ import inspect import itertools import logging import sys +from collections.abc import Generator +from collections.abc import Iterable from typing import Any -from typing import Generator -from typing import Iterable from typing import NamedTuple from flake8 import utils @@ -68,7 +68,7 @@ class Plugins(NamedTuple): reporters: dict[str, LoadedPlugin] disabled: list[LoadedPlugin] - def all_plugins(self) -> Generator[LoadedPlugin, None, None]: + def all_plugins(self) -> Generator[LoadedPlugin]: """Return an iterator over all :class:`LoadedPlugin`s.""" yield from self.checkers.tree yield from self.checkers.logical_line @@ -151,7 +151,7 @@ def _flake8_plugins( eps: Iterable[importlib.metadata.EntryPoint], name: str, version: str, -) -> Generator[Plugin, None, None]: +) -> Generator[Plugin]: pyflakes_meta = importlib.metadata.distribution("pyflakes").metadata pycodestyle_meta = importlib.metadata.distribution("pycodestyle").metadata @@ -173,7 +173,7 @@ def _flake8_plugins( yield Plugin(name, version, ep) -def _find_importlib_plugins() -> Generator[Plugin, None, None]: +def _find_importlib_plugins() -> Generator[Plugin]: # some misconfigured pythons (RHEL) have things on `sys.path` twice seen = set() for dist in importlib.metadata.distributions(): @@ -212,7 +212,7 @@ def _find_importlib_plugins() -> Generator[Plugin, None, None]: def _find_local_plugins( cfg: configparser.RawConfigParser, -) -> Generator[Plugin, None, None]: +) -> Generator[Plugin]: for plugin_type in ("extension", "report"): group = f"flake8.{plugin_type}" for plugin_s in utils.parse_comma_separated_list( diff --git a/src/flake8/plugins/pycodestyle.py b/src/flake8/plugins/pycodestyle.py index 9e1d2bb..cd760dc 100644 --- a/src/flake8/plugins/pycodestyle.py +++ b/src/flake8/plugins/pycodestyle.py @@ -2,8 +2,8 @@ # fmt: off from __future__ import annotations +from collections.abc import Generator from typing import Any -from typing import Generator from pycodestyle import ambiguous_identifier as _ambiguous_identifier from pycodestyle import bare_except as _bare_except @@ -55,7 +55,7 @@ def pycodestyle_logical( previous_unindented_logical_line: Any, tokens: Any, verbose: Any, -) -> Generator[tuple[int, str], None, None]: +) -> Generator[tuple[int, str]]: """Run pycodestyle logical checks.""" yield from _ambiguous_identifier(logical_line, tokens) yield from _bare_except(logical_line, noqa) @@ -93,7 +93,7 @@ def pycodestyle_physical( noqa: Any, physical_line: Any, total_lines: Any, -) -> Generator[tuple[int, str], None, None]: +) -> Generator[tuple[int, str]]: """Run pycodestyle physical checks.""" ret = _maximum_line_length(physical_line, max_line_length, multiline, line_number, noqa) # noqa: E501 if ret is not None: diff --git a/src/flake8/plugins/pyflakes.py b/src/flake8/plugins/pyflakes.py index 6c57619..2835e03 100644 --- a/src/flake8/plugins/pyflakes.py +++ b/src/flake8/plugins/pyflakes.py @@ -4,8 +4,8 @@ from __future__ import annotations import argparse import ast import logging +from collections.abc import Generator from typing import Any -from typing import Generator import pyflakes.checker @@ -97,7 +97,7 @@ class FlakesChecker(pyflakes.checker.Checker): cls.builtIns = cls.builtIns.union(options.builtins) cls.with_doctest = options.doctests - def run(self) -> Generator[tuple[int, int, str, type[Any]], None, None]: + def run(self) -> Generator[tuple[int, int, str, type[Any]]]: """Run the plugin.""" for message in self.messages: col = getattr(message, "col", 0) diff --git a/src/flake8/processor.py b/src/flake8/processor.py index e44547b..610964d 100644 --- a/src/flake8/processor.py +++ b/src/flake8/processor.py @@ -6,10 +6,8 @@ import ast import functools import logging import tokenize +from collections.abc import Generator from typing import Any -from typing import Generator -from typing import List -from typing import Tuple from flake8 import defaults from flake8 import utils @@ -24,8 +22,8 @@ SKIP_TOKENS = frozenset( [tokenize.NL, tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT] ) -_LogicalMapping = List[Tuple[int, Tuple[int, int]]] -_Logical = Tuple[List[str], List[str], _LogicalMapping] +_LogicalMapping = list[tuple[int, tuple[int, int]]] +_Logical = tuple[list[str], list[str], _LogicalMapping] class FileProcessor: @@ -127,9 +125,7 @@ class FileProcessor: """Signal the beginning of an fstring.""" self._fstring_start = lineno - def multiline_string( - self, token: tokenize.TokenInfo - ) -> Generator[str, None, None]: + def multiline_string(self, token: tokenize.TokenInfo) -> Generator[str]: """Iterate through the lines of a multiline string.""" if token.type == FSTRING_END: # pragma: >=3.12 cover start = self._fstring_start @@ -210,7 +206,7 @@ class FileProcessor: brace_offset = text.count("{") + text.count("}") text = "x" * (len(text) + brace_offset) end = (end[0], end[1] + brace_offset) - if previous_row: + if previous_row is not None and previous_column is not None: (start_row, start_column) = start if previous_row != start_row: row_index = previous_row - 1 @@ -263,7 +259,7 @@ class FileProcessor: ) return ret - def generate_tokens(self) -> Generator[tokenize.TokenInfo, None, None]: + def generate_tokens(self) -> Generator[tokenize.TokenInfo]: """Tokenize the file and yield the tokens.""" for token in tokenize.generate_tokens(self.next_line): if token[2][0] > self.total_lines: diff --git a/src/flake8/statistics.py b/src/flake8/statistics.py index a33e6a6..5a22254 100644 --- a/src/flake8/statistics.py +++ b/src/flake8/statistics.py @@ -1,7 +1,7 @@ """Statistic collection logic for Flake8.""" from __future__ import annotations -from typing import Generator +from collections.abc import Generator from typing import NamedTuple from flake8.violation import Violation @@ -36,7 +36,7 @@ class Statistics: def statistics_for( self, prefix: str, filename: str | None = None - ) -> Generator[Statistic, None, None]: + ) -> Generator[Statistic]: """Generate statistics for the prefix and filename. If you have a :class:`Statistics` object that has recorded errors, diff --git a/src/flake8/style_guide.py b/src/flake8/style_guide.py index a409484..f72e6d8 100644 --- a/src/flake8/style_guide.py +++ b/src/flake8/style_guide.py @@ -7,8 +7,8 @@ import copy import enum import functools import logging -from typing import Generator -from typing import Sequence +from collections.abc import Generator +from collections.abc import Sequence from flake8 import defaults from flake8 import statistics @@ -225,13 +225,11 @@ class StyleGuideManager: *self.populate_style_guides_with(options), ] - self.style_guide_for = functools.lru_cache(maxsize=None)( - self._style_guide_for - ) + self.style_guide_for = functools.cache(self._style_guide_for) def populate_style_guides_with( self, options: argparse.Namespace - ) -> Generator[StyleGuide, None, None]: + ) -> Generator[StyleGuide]: """Generate style guides from the per-file-ignores option. :param options: @@ -253,9 +251,7 @@ class StyleGuideManager: ) @contextlib.contextmanager - def processing_file( - self, filename: str - ) -> Generator[StyleGuide, None, None]: + def processing_file(self, filename: str) -> Generator[StyleGuide]: """Record the fact that we're processing the file's results.""" guide = self.style_guide_for(filename) with guide.processing_file(filename): @@ -338,9 +334,7 @@ class StyleGuide: ) @contextlib.contextmanager - def processing_file( - self, filename: str - ) -> Generator[StyleGuide, None, None]: + def processing_file(self, filename: str) -> Generator[StyleGuide]: """Record the fact that we're processing the file's results.""" self.formatter.beginning(filename) yield self diff --git a/src/flake8/utils.py b/src/flake8/utils.py index afc3896..67db33f 100644 --- a/src/flake8/utils.py +++ b/src/flake8/utils.py @@ -11,9 +11,9 @@ import re import sys import textwrap import tokenize +from collections.abc import Sequence +from re import Pattern from typing import NamedTuple -from typing import Pattern -from typing import Sequence from flake8 import exceptions diff --git a/src/flake8/violation.py b/src/flake8/violation.py index 96161d4..ae1631a 100644 --- a/src/flake8/violation.py +++ b/src/flake8/violation.py @@ -4,7 +4,7 @@ from __future__ import annotations import functools import linecache import logging -from typing import Match +from re import Match from typing import NamedTuple from flake8 import defaults From d56d569ce40a623a17c212ea7f2b306714f27f31 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Mar 2025 15:53:41 -0400 Subject: [PATCH 73/92] update versions of pycodestyle / pyflakes --- setup.cfg | 4 ++-- src/flake8/plugins/pyflakes.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 688e349..6f63f5a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,8 +29,8 @@ classifiers = packages = find: install_requires = mccabe>=0.7.0,<0.8.0 - pycodestyle>=2.12.0,<2.13.0 - pyflakes>=3.2.0,<3.3.0 + pycodestyle>=2.13.0,<2.14.0 + pyflakes>=3.3.0,<3.4.0 python_requires = >=3.9 package_dir = =src diff --git a/src/flake8/plugins/pyflakes.py b/src/flake8/plugins/pyflakes.py index 2835e03..3620a27 100644 --- a/src/flake8/plugins/pyflakes.py +++ b/src/flake8/plugins/pyflakes.py @@ -55,6 +55,7 @@ FLAKE8_PYFLAKES_CODES = { "UndefinedName": "F821", "UndefinedExport": "F822", "UndefinedLocal": "F823", + "UnusedIndirectAssignment": "F824", "DuplicateArgument": "F831", "UnusedVariable": "F841", "UnusedAnnotation": "F842", From 16f5f28a384f0781bebb37a08aa45e65b9526c50 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 29 Mar 2025 16:17:35 -0400 Subject: [PATCH 74/92] Release 7.2.0 --- docs/source/release-notes/7.2.0.rst | 19 +++++++++++++++++++ docs/source/release-notes/index.rst | 1 + src/flake8/__init__.py | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 docs/source/release-notes/7.2.0.rst diff --git a/docs/source/release-notes/7.2.0.rst b/docs/source/release-notes/7.2.0.rst new file mode 100644 index 0000000..fe124d7 --- /dev/null +++ b/docs/source/release-notes/7.2.0.rst @@ -0,0 +1,19 @@ +7.2.0 -- 2025-03-29 +------------------- + +You can view the `7.2.0 milestone`_ on GitHub for more details. + +New Dependency Information +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- pycodestyle has been updated to >= 2.13.0, < 2.14.0 (See also :pull:`1974`). +- pyflakes has been updated to >= 3.3.0, < 3.4.0 (See also :pull:`1974`). + +Features +~~~~~~~~ + +- Require python >= 3.9 (See also :pull:`1973`). + +.. all links +.. _7.2.0 milestone: + https://github.com/PyCQA/flake8/milestone/53 diff --git a/docs/source/release-notes/index.rst b/docs/source/release-notes/index.rst index 2145179..a4d8bfc 100644 --- a/docs/source/release-notes/index.rst +++ b/docs/source/release-notes/index.rst @@ -13,6 +13,7 @@ with the newest releases first. 7.1.0 7.1.1 7.1.2 + 7.2.0 6.x Release Series ================== diff --git a/src/flake8/__init__.py b/src/flake8/__init__.py index 0345499..cf91f8b 100644 --- a/src/flake8/__init__.py +++ b/src/flake8/__init__.py @@ -17,7 +17,7 @@ import sys LOG = logging.getLogger(__name__) LOG.addHandler(logging.NullHandler()) -__version__ = "7.1.2" +__version__ = "7.2.0" __version_info__ = tuple(int(i) for i in __version__.split(".") if i.isdigit()) _VERBOSITY_TO_LOG_LEVEL = { From 3613896bd9051147ffa7fd04ac1a98cbc9e35cf2 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 31 Mar 2025 10:05:31 -0400 Subject: [PATCH 75/92] document F824 --- docs/source/user/error-codes.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/user/error-codes.rst b/docs/source/user/error-codes.rst index 2a91413..3090d47 100644 --- a/docs/source/user/error-codes.rst +++ b/docs/source/user/error-codes.rst @@ -102,6 +102,9 @@ generates its own :term:`error code`\ s for ``pyflakes``: +------+---------------------------------------------------------------------+ | F823 | local variable ``name`` ... referenced before assignment | +------+---------------------------------------------------------------------+ +| F824 | ``global name`` / ``nonlocal name`` is unused: name is never | +| | assigned in scope | ++------+---------------------------------------------------------------------+ | F831 | duplicate argument ``name`` in function definition | +------+---------------------------------------------------------------------+ | F841 | local variable ``name`` is assigned to but never used | From 8dfa6695b4fb1e1401b357367a0a71037d29f6aa Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Fri, 11 Apr 2025 17:39:39 -0400 Subject: [PATCH 76/92] add rtd sphinx config --- .readthedocs.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 0425dc2..dfa8b9d 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -8,3 +8,5 @@ python: install: - path: . - requirements: docs/source/requirements.txt +sphinx: + configuration: docs/source/conf.py From 019424b80d3d7d5d8a2a1638f5877080546e3f46 Mon Sep 17 00:00:00 2001 From: anthony sottile Date: Fri, 23 May 2025 16:25:06 -0400 Subject: [PATCH 77/92] add support for t-strings --- src/flake8/_compat.py | 7 +++++++ src/flake8/checker.py | 3 +++ src/flake8/processor.py | 17 +++++++++++++--- tests/integration/test_plugins.py | 33 +++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/flake8/_compat.py b/src/flake8/_compat.py index e8a3ccd..22bb84e 100644 --- a/src/flake8/_compat.py +++ b/src/flake8/_compat.py @@ -9,3 +9,10 @@ if sys.version_info >= (3, 12): # pragma: >=3.12 cover FSTRING_END = tokenize.FSTRING_END else: # pragma: <3.12 cover FSTRING_START = FSTRING_MIDDLE = FSTRING_END = -1 + +if sys.version_info >= (3, 14): # pragma: >=3.14 cover + TSTRING_START = tokenize.TSTRING_START + TSTRING_MIDDLE = tokenize.TSTRING_MIDDLE + TSTRING_END = tokenize.TSTRING_END +else: # pragma: <3.14 cover + TSTRING_START = TSTRING_MIDDLE = TSTRING_END = -1 diff --git a/src/flake8/checker.py b/src/flake8/checker.py index d1659b7..84d45aa 100644 --- a/src/flake8/checker.py +++ b/src/flake8/checker.py @@ -19,6 +19,7 @@ from flake8 import exceptions from flake8 import processor from flake8 import utils from flake8._compat import FSTRING_START +from flake8._compat import TSTRING_START from flake8.discover_files import expand_paths from flake8.options.parse_args import parse_args from flake8.plugins.finder import Checkers @@ -554,6 +555,8 @@ class FileChecker: assert self.processor is not None if token.type == FSTRING_START: # pragma: >=3.12 cover self.processor.fstring_start(token.start[0]) + elif token.type == TSTRING_START: # pragma: >=3.14 cover + self.processor.tstring_start(token.start[0]) # a newline token ends a single physical line. elif processor.is_eol_token(token): # if the file does not end with a newline, the NEWLINE diff --git a/src/flake8/processor.py b/src/flake8/processor.py index 610964d..ccb4c57 100644 --- a/src/flake8/processor.py +++ b/src/flake8/processor.py @@ -13,6 +13,8 @@ from flake8 import defaults from flake8 import utils from flake8._compat import FSTRING_END from flake8._compat import FSTRING_MIDDLE +from flake8._compat import TSTRING_END +from flake8._compat import TSTRING_MIDDLE from flake8.plugins.finder import LoadedPlugin LOG = logging.getLogger(__name__) @@ -113,7 +115,7 @@ class FileProcessor: self.verbose = options.verbose #: Statistics dictionary self.statistics = {"logical lines": 0} - self._fstring_start = -1 + self._fstring_start = self._tstring_start = -1 @functools.cached_property def file_tokens(self) -> list[tokenize.TokenInfo]: @@ -125,10 +127,16 @@ class FileProcessor: """Signal the beginning of an fstring.""" self._fstring_start = lineno + def tstring_start(self, lineno: int) -> None: # pragma: >=3.14 cover + """Signal the beginning of an tstring.""" + self._tstring_start = lineno + def multiline_string(self, token: tokenize.TokenInfo) -> Generator[str]: """Iterate through the lines of a multiline string.""" if token.type == FSTRING_END: # pragma: >=3.12 cover start = self._fstring_start + elif token.type == TSTRING_END: # pragma: >=3.14 cover + start = self._tstring_start else: start = token.start[0] @@ -198,7 +206,10 @@ class FileProcessor: continue if token_type == tokenize.STRING: text = mutate_string(text) - elif token_type == FSTRING_MIDDLE: # pragma: >=3.12 cover + elif token_type in { + FSTRING_MIDDLE, + TSTRING_MIDDLE, + }: # pragma: >=3.12 cover # noqa: E501 # A curly brace in an FSTRING_MIDDLE token must be an escaped # curly brace. Both 'text' and 'end' will account for the # escaped version of the token (i.e. a single brace) rather @@ -382,7 +393,7 @@ def is_eol_token(token: tokenize.TokenInfo) -> bool: def is_multiline_string(token: tokenize.TokenInfo) -> bool: """Check if this is a multiline string.""" - return token.type == FSTRING_END or ( + return token.type in {FSTRING_END, TSTRING_END} or ( token.type == tokenize.STRING and "\n" in token.string ) diff --git a/tests/integration/test_plugins.py b/tests/integration/test_plugins.py index 90ca555..471cab8 100644 --- a/tests/integration/test_plugins.py +++ b/tests/integration/test_plugins.py @@ -296,3 +296,36 @@ t.py:1:1: T001 "f'xxxxxxxxxxxxxxxxxxxxxxxx'" """ out, err = capsys.readouterr() assert out == expected + + +@pytest.mark.xfail(sys.version_info < (3, 14), reason="3.14+") +def test_tstring_logical_line(tmpdir, capsys): # pragma: >=3.14 cover + cfg_s = f"""\ +[flake8] +extend-ignore = F +[flake8:local-plugins] +extension = + T = {yields_logical_line.__module__}:{yields_logical_line.__name__} +""" + + cfg = tmpdir.join("tox.ini") + cfg.write(cfg_s) + + src = """\ +t''' +hello {world} +''' +t'{{"{hello}": "{world}"}}' +""" + t_py = tmpdir.join("t.py") + t_py.write_binary(src.encode()) + + with tmpdir.as_cwd(): + assert main(("t.py", "--config", str(cfg))) == 1 + + expected = """\ +t.py:1:1: T001 "t'''xxxxxxx{world}x'''" +t.py:4:1: T001 "t'xxx{hello}xxxx{world}xxx'" +""" + out, err = capsys.readouterr() + assert out == expected From 4941a3e32e54488698ecbc23993bfeb2a60c0fc5 Mon Sep 17 00:00:00 2001 From: anthony sottile Date: Fri, 20 Jun 2025 15:15:53 -0400 Subject: [PATCH 78/92] upgrade pyflakes / pycodestyle --- setup.cfg | 4 ++-- src/flake8/plugins/pyflakes.py | 1 + tests/unit/test_checker_manager.py | 8 +++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/setup.cfg b/setup.cfg index 6f63f5a..a6b5a5e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,8 +29,8 @@ classifiers = packages = find: install_requires = mccabe>=0.7.0,<0.8.0 - pycodestyle>=2.13.0,<2.14.0 - pyflakes>=3.3.0,<3.4.0 + pycodestyle>=2.14.0,<2.15.0 + pyflakes>=3.4.0,<3.5.0 python_requires = >=3.9 package_dir = =src diff --git a/src/flake8/plugins/pyflakes.py b/src/flake8/plugins/pyflakes.py index 3620a27..66d8c1c 100644 --- a/src/flake8/plugins/pyflakes.py +++ b/src/flake8/plugins/pyflakes.py @@ -36,6 +36,7 @@ FLAKE8_PYFLAKES_CODES = { "StringDotFormatMissingArgument": "F524", "StringDotFormatMixingAutomatic": "F525", "FStringMissingPlaceholders": "F541", + "TStringMissingPlaceholders": "F542", "MultiValueRepeatedKeyLiteral": "F601", "MultiValueRepeatedKeyVariable": "F602", "TooManyExpressionsInStarredAssignment": "F621", diff --git a/tests/unit/test_checker_manager.py b/tests/unit/test_checker_manager.py index 593822b..eecba3b 100644 --- a/tests/unit/test_checker_manager.py +++ b/tests/unit/test_checker_manager.py @@ -41,9 +41,11 @@ def test_oserrors_are_reraised(): err = OSError(errno.EAGAIN, "Ominous message") with mock.patch("_multiprocessing.SemLock", side_effect=err): manager = _parallel_checker_manager() - with mock.patch.object(manager, "run_serial") as serial: - with pytest.raises(OSError): - manager.run() + with ( + mock.patch.object(manager, "run_serial") as serial, + pytest.raises(OSError), + ): + manager.run() assert serial.call_count == 0 From 6bcdb628597fa2d03494965089ff87a492ffc1e9 Mon Sep 17 00:00:00 2001 From: anthony sottile Date: Fri, 20 Jun 2025 15:21:27 -0400 Subject: [PATCH 79/92] document F542 --- docs/source/user/error-codes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/user/error-codes.rst b/docs/source/user/error-codes.rst index 3090d47..c8b46c1 100644 --- a/docs/source/user/error-codes.rst +++ b/docs/source/user/error-codes.rst @@ -59,6 +59,8 @@ generates its own :term:`error code`\ s for ``pyflakes``: +------+---------------------------------------------------------------------+ | F541 | f-string without any placeholders | +------+---------------------------------------------------------------------+ +| F542 | t-string without any placeholders | ++------+---------------------------------------------------------------------+ +------+---------------------------------------------------------------------+ | F601 | dictionary key ``name`` repeated with different values | +------+---------------------------------------------------------------------+ From c48217e1fc006c2dddd14df54e83b67da15de5cd Mon Sep 17 00:00:00 2001 From: anthony sottile Date: Fri, 20 Jun 2025 15:30:19 -0400 Subject: [PATCH 80/92] Release 7.3.0 --- docs/source/release-notes/7.3.0.rst | 15 +++++++++++++++ docs/source/release-notes/index.rst | 11 ++++++----- src/flake8/__init__.py | 2 +- 3 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 docs/source/release-notes/7.3.0.rst diff --git a/docs/source/release-notes/7.3.0.rst b/docs/source/release-notes/7.3.0.rst new file mode 100644 index 0000000..dedc918 --- /dev/null +++ b/docs/source/release-notes/7.3.0.rst @@ -0,0 +1,15 @@ +7.3.0 -- 2025-06-20 +------------------- + +You can view the `7.3.0 milestone`_ on GitHub for more details. + +New Dependency Information +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Added support for python 3.14 (See also :pull:`1983`). +- pycodestyle has been updated to >= 2.14.0, < 2.15.0 (See also :pull:`1985`). +- Pyflakes has been updated to >= 3.4.0, < 3.5.0 (See also :pull:`1985`). + +.. all links +.. _7.3.0 milestone: + https://github.com/PyCQA/flake8/milestone/54 diff --git a/docs/source/release-notes/index.rst b/docs/source/release-notes/index.rst index a4d8bfc..10697df 100644 --- a/docs/source/release-notes/index.rst +++ b/docs/source/release-notes/index.rst @@ -9,18 +9,19 @@ with the newest releases first. ================== .. toctree:: - 7.0.0 - 7.1.0 - 7.1.1 - 7.1.2 + 7.3.0 7.2.0 + 7.1.2 + 7.1.1 + 7.1.0 + 7.0.0 6.x Release Series ================== .. toctree:: - 6.0.0 6.1.0 + 6.0.0 5.x Release Series ================== diff --git a/src/flake8/__init__.py b/src/flake8/__init__.py index cf91f8b..db29166 100644 --- a/src/flake8/__init__.py +++ b/src/flake8/__init__.py @@ -17,7 +17,7 @@ import sys LOG = logging.getLogger(__name__) LOG.addHandler(logging.NullHandler()) -__version__ = "7.2.0" +__version__ = "7.3.0" __version_info__ = tuple(int(i) for i in __version__.split(".") if i.isdigit()) _VERBOSITY_TO_LOG_LEVEL = { From 628aece714c9265e8def265f5fcc574605aca524 Mon Sep 17 00:00:00 2001 From: anthony sottile Date: Fri, 20 Jun 2025 15:40:43 -0400 Subject: [PATCH 81/92] adjust global variable definition for new pyflakes the original code was only passing pyflakes by accident due to __future__.annotations --- src/flake8/checker.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/flake8/checker.py b/src/flake8/checker.py index 84d45aa..c52955d 100644 --- a/src/flake8/checker.py +++ b/src/flake8/checker.py @@ -45,8 +45,7 @@ SERIAL_RETRY_ERRNOS = { # noise in diffs. } -_mp_plugins: Checkers -_mp_options: argparse.Namespace +_mp: tuple[Checkers, argparse.Namespace] | None = None @contextlib.contextmanager @@ -54,31 +53,31 @@ def _mp_prefork( plugins: Checkers, options: argparse.Namespace ) -> Generator[None]: # we can save significant startup work w/ `fork` multiprocessing - global _mp_plugins, _mp_options - _mp_plugins, _mp_options = plugins, options + global _mp + _mp = plugins, options try: yield finally: - del _mp_plugins, _mp_options + _mp = None def _mp_init(argv: Sequence[str]) -> None: - global _mp_plugins, _mp_options + global _mp # Ensure correct signaling of ^C using multiprocessing.Pool. signal.signal(signal.SIGINT, signal.SIG_IGN) - try: - # for `fork` this'll already be set - _mp_plugins, _mp_options # noqa: B018 - except NameError: + # for `fork` this'll already be set + if _mp is None: plugins, options = parse_args(argv) - _mp_plugins, _mp_options = plugins.checkers, options + _mp = plugins.checkers, options def _mp_run(filename: str) -> tuple[str, Results, dict[str, int]]: + assert _mp is not None, _mp + plugins, options = _mp return FileChecker( - filename=filename, plugins=_mp_plugins, options=_mp_options + filename=filename, plugins=plugins, options=options ).run_checks() From 5fab0d18870b861ffbcb2757adb44154aff126c2 Mon Sep 17 00:00:00 2001 From: Max R Date: Sun, 20 Jul 2025 19:12:27 -0400 Subject: [PATCH 82/92] Update hooks and use `autopep8` + `add-trailing-comma` instead of `black` --- .pre-commit-config.yaml | 23 ++++++++++++--------- setup.cfg | 1 - src/flake8/__init__.py | 2 +- src/flake8/api/legacy.py | 4 ++-- src/flake8/checker.py | 16 +++++++-------- src/flake8/formatting/base.py | 2 +- src/flake8/main/application.py | 2 +- src/flake8/main/debug.py | 2 +- src/flake8/main/options.py | 2 +- src/flake8/options/config.py | 6 +++--- src/flake8/options/manager.py | 2 +- src/flake8/plugins/finder.py | 10 ++++----- src/flake8/plugins/pyflakes.py | 2 +- src/flake8/processor.py | 10 ++++----- src/flake8/statistics.py | 4 ++-- src/flake8/style_guide.py | 10 ++++----- src/flake8/utils.py | 6 +++--- src/flake8/violation.py | 2 +- tests/integration/test_checker.py | 6 +++--- tests/integration/test_main.py | 6 +++--- tests/integration/test_plugins.py | 2 +- tests/unit/plugins/finder_test.py | 32 +++++++++++++++++------------ tests/unit/plugins/reporter_test.py | 4 ++-- tests/unit/test_application.py | 2 +- tests/unit/test_base_formatter.py | 6 +++--- tests/unit/test_debug.py | 2 +- tests/unit/test_decision_engine.py | 10 ++++----- tests/unit/test_discover_files.py | 6 +++--- tests/unit/test_file_processor.py | 12 +++++------ tests/unit/test_main_options.py | 2 +- tests/unit/test_option_manager.py | 8 ++++---- tests/unit/test_options_config.py | 4 ++-- tests/unit/test_style_guide.py | 4 ++-- 33 files changed, 110 insertions(+), 102 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9df4a79..837e6e5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,10 @@ repos: +- repo: https://github.com/asottile/add-trailing-comma + rev: v3.2.0 + hooks: + - id: add-trailing-comma - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v5.0.0 hooks: - id: check-yaml - id: debug-statements @@ -8,11 +12,11 @@ repos: - id: trailing-whitespace exclude: ^tests/fixtures/ - repo: https://github.com/asottile/setup-cfg-fmt - rev: v2.5.0 + rev: v2.8.0 hooks: - id: setup-cfg-fmt - repo: https://github.com/asottile/reorder-python-imports - rev: v3.14.0 + rev: v3.15.0 hooks: - id: reorder-python-imports args: [ @@ -21,21 +25,20 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.19.1 + rev: v3.20.0 hooks: - id: pyupgrade args: [--py39-plus] -- repo: https://github.com/psf/black - rev: 23.12.1 +- repo: https://github.com/hhatto/autopep8 + rev: v2.3.2 hooks: - - id: black - args: [--line-length=79] + - id: autopep8 - repo: https://github.com/PyCQA/flake8 - rev: 7.0.0 + rev: 7.3.0 hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.15.0 + rev: v1.17.0 hooks: - id: mypy exclude: ^(docs/|example-plugin/) diff --git a/setup.cfg b/setup.cfg index a6b5a5e..dc967d3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,7 +16,6 @@ classifiers = Environment :: Console Framework :: Flake8 Intended Audience :: Developers - License :: OSI Approved :: MIT License Programming Language :: Python Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only diff --git a/src/flake8/__init__.py b/src/flake8/__init__.py index db29166..0dea638 100644 --- a/src/flake8/__init__.py +++ b/src/flake8/__init__.py @@ -66,5 +66,5 @@ def configure_logging( LOG.addHandler(handler) LOG.setLevel(log_level) LOG.debug( - "Added a %s logging handler to logger root at %s", filename, __name__ + "Added a %s logging handler to logger root at %s", filename, __name__, ) diff --git a/src/flake8/api/legacy.py b/src/flake8/api/legacy.py index 446df29..4d5c91d 100644 --- a/src/flake8/api/legacy.py +++ b/src/flake8/api/legacy.py @@ -135,7 +135,7 @@ class StyleGuide: stdin_display_name=self.options.stdin_display_name, filename_patterns=self.options.filename, exclude=self.options.exclude, - ) + ), ) return not paths @@ -153,7 +153,7 @@ class StyleGuide: if not issubclass(reporter, formatter.BaseFormatter): raise ValueError( "Report should be subclass of " - "flake8.formatter.BaseFormatter." + "flake8.formatter.BaseFormatter.", ) self._application.formatter = reporter(self.options) self._application.guide = None diff --git a/src/flake8/checker.py b/src/flake8/checker.py index c52955d..d957915 100644 --- a/src/flake8/checker.py +++ b/src/flake8/checker.py @@ -50,7 +50,7 @@ _mp: tuple[Checkers, argparse.Namespace] | None = None @contextlib.contextmanager def _mp_prefork( - plugins: Checkers, options: argparse.Namespace + plugins: Checkers, options: argparse.Namespace, ) -> Generator[None]: # we can save significant startup work w/ `fork` multiprocessing global _mp @@ -77,7 +77,7 @@ def _mp_run(filename: str) -> tuple[str, Results, dict[str, int]]: assert _mp is not None, _mp plugins, options = _mp return FileChecker( - filename=filename, plugins=plugins, options=options + filename=filename, plugins=plugins, options=options, ).run_checks() @@ -137,7 +137,7 @@ class Manager: if utils.is_using_stdin(self.options.filenames): LOG.warning( "The --jobs option is not compatible with supplying " - "input using - . Ignoring --jobs arguments." + "input using - . Ignoring --jobs arguments.", ) return 0 @@ -252,7 +252,7 @@ class Manager: stdin_display_name=self.options.stdin_display_name, filename_patterns=self.options.filename, exclude=self.exclude, - ) + ), ) self.jobs = min(len(self.filenames), self.jobs) @@ -332,11 +332,11 @@ class FileChecker: assert self.processor is not None, self.filename try: params = self.processor.keyword_arguments_for( - plugin.parameters, arguments + plugin.parameters, arguments, ) except AttributeError as ae: raise exceptions.PluginRequestedUnknownParameters( - plugin_name=plugin.display_name, exception=ae + plugin_name=plugin.display_name, exception=ae, ) try: return plugin.obj(**arguments, **params) @@ -548,7 +548,7 @@ class FileChecker: self.run_logical_checks() def check_physical_eol( - self, token: tokenize.TokenInfo, prev_physical: str + self, token: tokenize.TokenInfo, prev_physical: str, ) -> None: """Run physical checks if and only if it is at the end of the line.""" assert self.processor is not None @@ -598,7 +598,7 @@ def _try_initialize_processpool( def find_offset( - offset: int, mapping: processor._LogicalMapping + offset: int, mapping: processor._LogicalMapping, ) -> tuple[int, int]: """Find the offset tuple for a single offset.""" if isinstance(offset, tuple): diff --git a/src/flake8/formatting/base.py b/src/flake8/formatting/base.py index d986d65..bbbfdff 100644 --- a/src/flake8/formatting/base.py +++ b/src/flake8/formatting/base.py @@ -110,7 +110,7 @@ class BaseFormatter: The formatted error string. """ raise NotImplementedError( - "Subclass of BaseFormatter did not implement" " format." + "Subclass of BaseFormatter did not implement" " format.", ) def show_statistics(self, statistics: Statistics) -> None: diff --git a/src/flake8/main/application.py b/src/flake8/main/application.py index 4704cbd..165a6ef 100644 --- a/src/flake8/main/application.py +++ b/src/flake8/main/application.py @@ -76,7 +76,7 @@ class Application: assert self.formatter is not None assert self.options is not None self.guide = style_guide.StyleGuideManager( - self.options, self.formatter + self.options, self.formatter, ) def make_file_checker_manager(self, argv: Sequence[str]) -> None: diff --git a/src/flake8/main/debug.py b/src/flake8/main/debug.py index c3a8b0b..73ca74b 100644 --- a/src/flake8/main/debug.py +++ b/src/flake8/main/debug.py @@ -14,7 +14,7 @@ def information(version: str, plugins: Plugins) -> dict[str, Any]: (loaded.plugin.package, loaded.plugin.version) for loaded in plugins.all_plugins() if loaded.plugin.package not in {"flake8", "local"} - } + }, ) return { "version": version, diff --git a/src/flake8/main/options.py b/src/flake8/main/options.py index 9d57321..e8cbe09 100644 --- a/src/flake8/main/options.py +++ b/src/flake8/main/options.py @@ -32,7 +32,7 @@ def stage1_arg_parser() -> argparse.ArgumentParser: ) parser.add_argument( - "--output-file", default=None, help="Redirect report to a file." + "--output-file", default=None, help="Redirect report to a file.", ) # Config file options diff --git a/src/flake8/options/config.py b/src/flake8/options/config.py index b51949c..fddee55 100644 --- a/src/flake8/options/config.py +++ b/src/flake8/options/config.py @@ -78,7 +78,7 @@ def load_config( if config is not None: if not cfg.read(config, encoding="UTF-8"): raise exceptions.ExecutionError( - f"The specified config file does not exist: {config}" + f"The specified config file does not exist: {config}", ) cfg_dir = os.path.dirname(config) else: @@ -89,7 +89,7 @@ def load_config( for filename in extra: if not cfg.read(filename, encoding="UTF-8"): raise exceptions.ExecutionError( - f"The specified config file does not exist: {filename}" + f"The specified config file does not exist: {filename}", ) return cfg, cfg_dir @@ -131,7 +131,7 @@ def parse_config( raise ValueError( f"Error code {error_code!r} " f"supplied to {option_name!r} option " - f"does not match {VALID_CODE_PREFIX.pattern!r}" + f"does not match {VALID_CODE_PREFIX.pattern!r}", ) assert option.config_name is not None diff --git a/src/flake8/options/manager.py b/src/flake8/options/manager.py index cb195fe..addd3ec 100644 --- a/src/flake8/options/manager.py +++ b/src/flake8/options/manager.py @@ -165,7 +165,7 @@ class Option: if long_option_name is _ARG.NO: raise ValueError( "When specifying parse_from_config=True, " - "a long_option_name must also be specified." + "a long_option_name must also be specified.", ) self.config_name = long_option_name[2:].replace("-", "_") diff --git a/src/flake8/plugins/finder.py b/src/flake8/plugins/finder.py index 88b66a0..4da3402 100644 --- a/src/flake8/plugins/finder.py +++ b/src/flake8/plugins/finder.py @@ -83,8 +83,8 @@ class Plugins(NamedTuple): f"{loaded.plugin.package}: {loaded.plugin.version}" for loaded in self.all_plugins() if loaded.plugin.package not in {"flake8", "local"} - } - ) + }, + ), ) @@ -167,7 +167,7 @@ def _flake8_plugins( # ideally pycodestyle's plugin entrypoints would exactly represent # the codes they produce... yield Plugin( - pycodestyle_meta["name"], pycodestyle_meta["version"], ep + pycodestyle_meta["name"], pycodestyle_meta["version"], ep, ) else: yield Plugin(name, version, ep) @@ -240,7 +240,7 @@ def _check_required_plugins( f"required plugins were not installed!\n" f"- installed: {', '.join(sorted(plugin_names))}\n" f"- expected: {', '.join(sorted(expected_names))}\n" - f"- missing: {', '.join(sorted(missing_plugins))}" + f"- missing: {', '.join(sorted(missing_plugins))}", ) @@ -338,7 +338,7 @@ def _classify_plugins( if not VALID_CODE_PREFIX.match(loaded.entry_name): raise ExecutionError( f"plugin code for `{loaded.display_name}` does not match " - f"{VALID_CODE_PREFIX.pattern}" + f"{VALID_CODE_PREFIX.pattern}", ) return Plugins( diff --git a/src/flake8/plugins/pyflakes.py b/src/flake8/plugins/pyflakes.py index 66d8c1c..9844025 100644 --- a/src/flake8/plugins/pyflakes.py +++ b/src/flake8/plugins/pyflakes.py @@ -72,7 +72,7 @@ class FlakesChecker(pyflakes.checker.Checker): def __init__(self, tree: ast.AST, filename: str) -> None: """Initialize the PyFlakes plugin with an AST tree and filename.""" super().__init__( - tree, filename=filename, withDoctest=self.with_doctest + tree, filename=filename, withDoctest=self.with_doctest, ) @classmethod diff --git a/src/flake8/processor.py b/src/flake8/processor.py index ccb4c57..b1742ca 100644 --- a/src/flake8/processor.py +++ b/src/flake8/processor.py @@ -21,7 +21,7 @@ LOG = logging.getLogger(__name__) NEWLINE = frozenset([tokenize.NL, tokenize.NEWLINE]) SKIP_TOKENS = frozenset( - [tokenize.NL, tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT] + [tokenize.NL, tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT], ) _LogicalMapping = list[tuple[int, tuple[int, int]]] @@ -173,7 +173,7 @@ class FileProcessor: """Update the checker_state attribute for the plugin.""" if "checker_state" in plugin.parameters: self.checker_state = self._checker_states.setdefault( - plugin.entry_name, {} + plugin.entry_name, {}, ) def next_logical_line(self) -> None: @@ -280,7 +280,7 @@ class FileProcessor: def _noqa_line_range(self, min_line: int, max_line: int) -> dict[int, str]: line_range = range(min_line, max_line + 1) - joined = "".join(self.lines[min_line - 1 : max_line]) + joined = "".join(self.lines[min_line - 1: max_line]) return dict.fromkeys(line_range, joined) @functools.cached_property @@ -367,7 +367,7 @@ class FileProcessor: elif any(defaults.NOQA_FILE.search(line) for line in self.lines): LOG.warning( "Detected `flake8: noqa` on line with code. To ignore an " - "error on a line use `noqa` instead." + "error on a line use `noqa` instead.", ) return False else: @@ -388,7 +388,7 @@ class FileProcessor: def is_eol_token(token: tokenize.TokenInfo) -> bool: """Check if the token is an end-of-line token.""" - return token[0] in NEWLINE or token[4][token[3][1] :].lstrip() == "\\\n" + return token[0] in NEWLINE or token[4][token[3][1]:].lstrip() == "\\\n" def is_multiline_string(token: tokenize.TokenInfo) -> bool: diff --git a/src/flake8/statistics.py b/src/flake8/statistics.py index 5a22254..b30e4c7 100644 --- a/src/flake8/statistics.py +++ b/src/flake8/statistics.py @@ -35,7 +35,7 @@ class Statistics: self._store[key].increment() def statistics_for( - self, prefix: str, filename: str | None = None + self, prefix: str, filename: str | None = None, ) -> Generator[Statistic]: """Generate statistics for the prefix and filename. @@ -108,7 +108,7 @@ class Statistic: """ def __init__( - self, error_code: str, filename: str, message: str, count: int + self, error_code: str, filename: str, message: str, count: int, ) -> None: """Initialize our Statistic.""" self.error_code = error_code diff --git a/src/flake8/style_guide.py b/src/flake8/style_guide.py index f72e6d8..d675df7 100644 --- a/src/flake8/style_guide.py +++ b/src/flake8/style_guide.py @@ -218,7 +218,7 @@ class StyleGuideManager: self.decider = decider or DecisionEngine(options) self.style_guides: list[StyleGuide] = [] self.default_style_guide = StyleGuide( - options, formatter, self.stats, decider=decider + options, formatter, self.stats, decider=decider, ) self.style_guides = [ self.default_style_guide, @@ -228,7 +228,7 @@ class StyleGuideManager: self.style_guide_for = functools.cache(self._style_guide_for) def populate_style_guides_with( - self, options: argparse.Namespace + self, options: argparse.Namespace, ) -> Generator[StyleGuide]: """Generate style guides from the per-file-ignores option. @@ -240,7 +240,7 @@ class StyleGuideManager: per_file = utils.parse_files_to_codes_mapping(options.per_file_ignores) for filename, violations in per_file: yield self.default_style_guide.copy( - filename=filename, extend_ignore_with=violations + filename=filename, extend_ignore_with=violations, ) def _style_guide_for(self, filename: str) -> StyleGuide: @@ -288,7 +288,7 @@ class StyleGuideManager: """ guide = self.style_guide_for(filename) return guide.handle_error( - code, filename, line_number, column_number, text, physical_line + code, filename, line_number, column_number, text, physical_line, ) @@ -330,7 +330,7 @@ class StyleGuide: options.extend_ignore = options.extend_ignore or [] options.extend_ignore.extend(extend_ignore_with or []) return StyleGuide( - options, self.formatter, self.stats, filename=filename + options, self.formatter, self.stats, filename=filename, ) @contextlib.contextmanager diff --git a/src/flake8/utils.py b/src/flake8/utils.py index 67db33f..e5c086e 100644 --- a/src/flake8/utils.py +++ b/src/flake8/utils.py @@ -23,7 +23,7 @@ NORMALIZE_PACKAGE_NAME_RE = re.compile(r"[-_.]+") def parse_comma_separated_list( - value: str, regexp: Pattern[str] = COMMA_SEPARATED_LIST_RE + value: str, regexp: Pattern[str] = COMMA_SEPARATED_LIST_RE, ) -> list[str]: """Parse a comma-separated list. @@ -115,7 +115,7 @@ def parse_files_to_codes_mapping( # noqa: C901 f"Expected `per-file-ignores` to be a mapping from file exclude " f"patterns to ignore codes.\n\n" f"Configured `per-file-ignores` setting:\n\n" - f"{textwrap.indent(value.strip(), ' ')}" + f"{textwrap.indent(value.strip(), ' ')}", ) for token in _tokenize_files_to_codes_mapping(value): @@ -150,7 +150,7 @@ def parse_files_to_codes_mapping( # noqa: C901 def normalize_paths( - paths: Sequence[str], parent: str = os.curdir + paths: Sequence[str], parent: str = os.curdir, ) -> list[str]: """Normalize a list of paths relative to a parent directory. diff --git a/src/flake8/violation.py b/src/flake8/violation.py index ae1631a..8535178 100644 --- a/src/flake8/violation.py +++ b/src/flake8/violation.py @@ -64,6 +64,6 @@ class Violation(NamedTuple): return True LOG.debug( - "%r is not ignored inline with ``# noqa: %s``", self, codes_str + "%r is not ignored inline with ``# noqa: %s``", self, codes_str, ) return False diff --git a/tests/integration/test_checker.py b/tests/integration/test_checker.py index a585f5a..60d0132 100644 --- a/tests/integration/test_checker.py +++ b/tests/integration/test_checker.py @@ -97,7 +97,7 @@ def mock_file_checker_with_plugin(plugin_target): # Prevent it from reading lines from stdin or somewhere else with mock.patch( - "flake8.processor.FileProcessor.read_lines", return_value=["Line 1"] + "flake8.processor.FileProcessor.read_lines", return_value=["Line 1"], ): file_checker = checker.FileChecker( filename="-", @@ -325,12 +325,12 @@ def test_handling_syntaxerrors_across_pythons(): if sys.version_info < (3, 10): # pragma: no cover (<3.10) # Python 3.9 or older err = SyntaxError( - "invalid syntax", ("", 2, 5, "bad python:\n") + "invalid syntax", ("", 2, 5, "bad python:\n"), ) expected = (2, 4) else: # pragma: no cover (3.10+) err = SyntaxError( - "invalid syntax", ("", 2, 1, "bad python:\n", 2, 11) + "invalid syntax", ("", 2, 1, "bad python:\n", 2, 11), ) expected = (2, 1) file_checker = checker.FileChecker( diff --git a/tests/integration/test_main.py b/tests/integration/test_main.py index 68b93cb..5091573 100644 --- a/tests/integration/test_main.py +++ b/tests/integration/test_main.py @@ -314,7 +314,7 @@ def test_cli_config_option_respected(tmp_path): """\ [flake8] ignore = F401 -""" +""", ) py_file = tmp_path / "t.py" @@ -330,7 +330,7 @@ def test_cli_isolated_overrides_config_option(tmp_path): """\ [flake8] ignore = F401 -""" +""", ) py_file = tmp_path / "t.py" @@ -364,7 +364,7 @@ def test_output_file(tmpdir, capsys): def test_early_keyboard_interrupt_does_not_crash(capsys): with mock.patch.object( - config, "load_config", side_effect=KeyboardInterrupt + config, "load_config", side_effect=KeyboardInterrupt, ): assert cli.main(["does-not-exist"]) == 1 out, err = capsys.readouterr() diff --git a/tests/integration/test_plugins.py b/tests/integration/test_plugins.py index 471cab8..9f9c1a0 100644 --- a/tests/integration/test_plugins.py +++ b/tests/integration/test_plugins.py @@ -86,7 +86,7 @@ def test_local_plugin_can_add_option(local_config): stage1_args, rest = stage1_parser.parse_known_args(argv) cfg, cfg_dir = config.load_config( - config=stage1_args.config, extra=[], isolated=False + config=stage1_args.config, extra=[], isolated=False, ) opts = finder.parse_plugin_options( diff --git a/tests/unit/plugins/finder_test.py b/tests/unit/plugins/finder_test.py index b289bef..a155ef1 100644 --- a/tests/unit/plugins/finder_test.py +++ b/tests/unit/plugins/finder_test.py @@ -42,7 +42,7 @@ def test_plugins_all_plugins(): logical_line_plugin = _loaded(parameters={"logical_line": True}) physical_line_plugin = _loaded(parameters={"physical_line": True}) report_plugin = _loaded( - plugin=_plugin(ep=_ep(name="R", group="flake8.report")) + plugin=_plugin(ep=_ep(name="R", group="flake8.report")), ) plugins = finder.Plugins( @@ -200,14 +200,16 @@ def test_flake8_plugins(flake8_dist, mock_distribution): "flake8", "9001", importlib.metadata.EntryPoint( - "default", "flake8.formatting.default:Default", "flake8.report" + "default", + "flake8.formatting.default:Default", + "flake8.report", ), ), finder.Plugin( "flake8", "9001", importlib.metadata.EntryPoint( - "pylint", "flake8.formatting.default:Pylint", "flake8.report" + "pylint", "flake8.formatting.default:Pylint", "flake8.report", ), ), } @@ -270,7 +272,7 @@ unrelated = unrelated:main "flake8-foo", "1.2.3", importlib.metadata.EntryPoint( - "Q", "flake8_foo:Plugin", "flake8.extension" + "Q", "flake8_foo:Plugin", "flake8.extension", ), ), finder.Plugin( @@ -304,21 +306,23 @@ unrelated = unrelated:main "flake8", "9001", importlib.metadata.EntryPoint( - "default", "flake8.formatting.default:Default", "flake8.report" + "default", + "flake8.formatting.default:Default", + "flake8.report", ), ), finder.Plugin( "flake8", "9001", importlib.metadata.EntryPoint( - "pylint", "flake8.formatting.default:Pylint", "flake8.report" + "pylint", "flake8.formatting.default:Pylint", "flake8.report", ), ), finder.Plugin( "flake8-foo", "1.2.3", importlib.metadata.EntryPoint( - "foo", "flake8_foo:Formatter", "flake8.report" + "foo", "flake8_foo:Formatter", "flake8.report", ), ), } @@ -485,28 +489,30 @@ def test_find_plugins( "flake8", "9001", importlib.metadata.EntryPoint( - "default", "flake8.formatting.default:Default", "flake8.report" + "default", + "flake8.formatting.default:Default", + "flake8.report", ), ), finder.Plugin( "flake8", "9001", importlib.metadata.EntryPoint( - "pylint", "flake8.formatting.default:Pylint", "flake8.report" + "pylint", "flake8.formatting.default:Pylint", "flake8.report", ), ), finder.Plugin( "flake8-foo", "1.2.3", importlib.metadata.EntryPoint( - "Q", "flake8_foo:Plugin", "flake8.extension" + "Q", "flake8_foo:Plugin", "flake8.extension", ), ), finder.Plugin( "flake8-foo", "1.2.3", importlib.metadata.EntryPoint( - "foo", "flake8_foo:Formatter", "flake8.report" + "foo", "flake8_foo:Formatter", "flake8.report", ), ), finder.Plugin( @@ -518,7 +524,7 @@ def test_find_plugins( "local", "local", importlib.metadata.EntryPoint( - "Y", "mod2:attr", "flake8.extension" + "Y", "mod2:attr", "flake8.extension", ), ), finder.Plugin( @@ -723,7 +729,7 @@ def test_import_plugins_extends_sys_path(): def test_classify_plugins(): report_plugin = _loaded( - plugin=_plugin(ep=_ep(name="R", group="flake8.report")) + plugin=_plugin(ep=_ep(name="R", group="flake8.report")), ) tree_plugin = _loaded(parameters={"tree": True}) logical_line_plugin = _loaded(parameters={"logical_line": True}) diff --git a/tests/unit/plugins/reporter_test.py b/tests/unit/plugins/reporter_test.py index 842465a..48b2873 100644 --- a/tests/unit/plugins/reporter_test.py +++ b/tests/unit/plugins/reporter_test.py @@ -25,7 +25,7 @@ def reporters(): "flake8", "123", importlib.metadata.EntryPoint( - name, f"{cls.__module__}:{cls.__name__}", "flake8.report" + name, f"{cls.__module__}:{cls.__name__}", "flake8.report", ), ), cls, @@ -72,5 +72,5 @@ def test_make_formatter_format_string(reporters, caplog): "flake8.plugins.reporter", 30, "'hi %(code)s' is an unknown formatter. Falling back to default.", - ) + ), ] diff --git a/tests/unit/test_application.py b/tests/unit/test_application.py index 04147ec..3c93085 100644 --- a/tests/unit/test_application.py +++ b/tests/unit/test_application.py @@ -36,7 +36,7 @@ def application(): ], ) def test_application_exit_code( - result_count, catastrophic, exit_zero, value, application + result_count, catastrophic, exit_zero, value, application, ): """Verify Application.exit_code returns the correct value.""" application.result_count = result_count diff --git a/tests/unit/test_base_formatter.py b/tests/unit/test_base_formatter.py index 5b57335..0d81c81 100644 --- a/tests/unit/test_base_formatter.py +++ b/tests/unit/test_base_formatter.py @@ -50,7 +50,7 @@ def test_format_needs_to_be_implemented(): formatter = base.BaseFormatter(options()) with pytest.raises(NotImplementedError): formatter.format( - Violation("A000", "file.py", 1, 1, "error text", None) + Violation("A000", "file.py", 1, 1, "error text", None), ) @@ -59,7 +59,7 @@ def test_show_source_returns_nothing_when_not_showing_source(): formatter = base.BaseFormatter(options(show_source=False)) assert ( formatter.show_source( - Violation("A000", "file.py", 1, 1, "error text", "line") + Violation("A000", "file.py", 1, 1, "error text", "line"), ) == "" ) @@ -70,7 +70,7 @@ def test_show_source_returns_nothing_when_there_is_source(): formatter = base.BaseFormatter(options(show_source=True)) assert ( formatter.show_source( - Violation("A000", "file.py", 1, 1, "error text", None) + Violation("A000", "file.py", 1, 1, "error text", None), ) == "" ) diff --git a/tests/unit/test_debug.py b/tests/unit/test_debug.py index 4ba604f..298b598 100644 --- a/tests/unit/test_debug.py +++ b/tests/unit/test_debug.py @@ -14,7 +14,7 @@ def test_debug_information(): pkg, version, importlib.metadata.EntryPoint( - ep_name, "dne:dne", "flake8.extension" + ep_name, "dne:dne", "flake8.extension", ), ), None, diff --git a/tests/unit/test_decision_engine.py b/tests/unit/test_decision_engine.py index d543d5e..cd8f80d 100644 --- a/tests/unit/test_decision_engine.py +++ b/tests/unit/test_decision_engine.py @@ -35,7 +35,7 @@ def create_options(**kwargs): def test_was_ignored_ignores_errors(ignore_list, extend_ignore, error_code): """Verify we detect users explicitly ignoring an error.""" decider = style_guide.DecisionEngine( - create_options(ignore=ignore_list, extend_ignore=extend_ignore) + create_options(ignore=ignore_list, extend_ignore=extend_ignore), ) assert decider.was_ignored(error_code) is style_guide.Ignored.Explicitly @@ -53,11 +53,11 @@ def test_was_ignored_ignores_errors(ignore_list, extend_ignore, error_code): ], ) def test_was_ignored_implicitly_selects_errors( - ignore_list, extend_ignore, error_code + ignore_list, extend_ignore, error_code, ): """Verify we detect users does not explicitly ignore an error.""" decider = style_guide.DecisionEngine( - create_options(ignore=ignore_list, extend_ignore=extend_ignore) + create_options(ignore=ignore_list, extend_ignore=extend_ignore), ) assert decider.was_ignored(error_code) is style_guide.Selected.Implicitly @@ -179,7 +179,7 @@ def test_was_selected_excludes_errors(select_list, error_code): ], ) def test_decision_for( - select_list, ignore_list, extend_ignore, error_code, expected + select_list, ignore_list, extend_ignore, error_code, expected, ): """Verify we decide when to report an error.""" decider = style_guide.DecisionEngine( @@ -187,7 +187,7 @@ def test_decision_for( select=select_list, ignore=ignore_list, extend_ignore=extend_ignore, - ) + ), ) assert decider.decision_for(error_code) is expected diff --git a/tests/unit/test_discover_files.py b/tests/unit/test_discover_files.py index ca945c2..ea55ccc 100644 --- a/tests/unit/test_discover_files.py +++ b/tests/unit/test_discover_files.py @@ -47,7 +47,7 @@ def test_filenames_from_a_directory_with_a_predicate(): _filenames_from( arg=_normpath("a/b/"), predicate=lambda path: path.endswith(_normpath("b/c.py")), - ) + ), ) # should not include c.py expected = _normpaths(("a/b/d.py", "a/b/e/f.py")) @@ -61,7 +61,7 @@ def test_filenames_from_a_directory_with_a_predicate_from_the_current_dir(): _filenames_from( arg=_normpath("./a/b"), predicate=lambda path: path == "c.py", - ) + ), ) # none should have matched the predicate so all returned expected = _normpaths(("./a/b/c.py", "./a/b/d.py", "./a/b/e/f.py")) @@ -132,7 +132,7 @@ def _expand_paths( stdin_display_name=stdin_display_name, filename_patterns=filename_patterns, exclude=exclude, - ) + ), ) diff --git a/tests/unit/test_file_processor.py b/tests/unit/test_file_processor.py index a90c628..22c5bcf 100644 --- a/tests/unit/test_file_processor.py +++ b/tests/unit/test_file_processor.py @@ -28,7 +28,7 @@ def _lines_from_file(tmpdir, contents, options): def test_read_lines_universal_newlines(tmpdir, default_options): r"""Verify that line endings are translated to \n.""" lines = _lines_from_file( - tmpdir, b"# coding: utf-8\r\nx = 1\r\n", default_options + tmpdir, b"# coding: utf-8\r\nx = 1\r\n", default_options, ) assert lines == ["# coding: utf-8\n", "x = 1\n"] @@ -36,7 +36,7 @@ def test_read_lines_universal_newlines(tmpdir, default_options): def test_read_lines_incorrect_utf_16(tmpdir, default_options): """Verify that an incorrectly encoded file is read as latin-1.""" lines = _lines_from_file( - tmpdir, b"# coding: utf16\nx = 1\n", default_options + tmpdir, b"# coding: utf16\nx = 1\n", default_options, ) assert lines == ["# coding: utf16\n", "x = 1\n"] @@ -44,7 +44,7 @@ def test_read_lines_incorrect_utf_16(tmpdir, default_options): def test_read_lines_unknown_encoding(tmpdir, default_options): """Verify that an unknown encoding is still read as latin-1.""" lines = _lines_from_file( - tmpdir, b"# coding: fake-encoding\nx = 1\n", default_options + tmpdir, b"# coding: fake-encoding\nx = 1\n", default_options, ) assert lines == ["# coding: fake-encoding\n", "x = 1\n"] @@ -289,7 +289,7 @@ def test_processor_split_line(default_options): def test_build_ast(default_options): """Verify the logic for how we build an AST for plugins.""" file_processor = processor.FileProcessor( - "-", default_options, lines=["a = 1\n"] + "-", default_options, lines=["a = 1\n"], ) module = file_processor.build_ast() @@ -299,7 +299,7 @@ def test_build_ast(default_options): def test_next_logical_line_updates_the_previous_logical_line(default_options): """Verify that we update our tracking of the previous logical line.""" file_processor = processor.FileProcessor( - "-", default_options, lines=["a = 1\n"] + "-", default_options, lines=["a = 1\n"], ) file_processor.indent_level = 1 @@ -315,7 +315,7 @@ def test_next_logical_line_updates_the_previous_logical_line(default_options): def test_visited_new_blank_line(default_options): """Verify we update the number of blank lines seen.""" file_processor = processor.FileProcessor( - "-", default_options, lines=["a = 1\n"] + "-", default_options, lines=["a = 1\n"], ) assert file_processor.blank_lines == 0 diff --git a/tests/unit/test_main_options.py b/tests/unit/test_main_options.py index 7c1feba..0b1fb69 100644 --- a/tests/unit/test_main_options.py +++ b/tests/unit/test_main_options.py @@ -6,7 +6,7 @@ from flake8.main import options def test_stage1_arg_parser(): stage1_parser = options.stage1_arg_parser() opts, args = stage1_parser.parse_known_args( - ["--foo", "--verbose", "src", "setup.py", "--statistics", "--version"] + ["--foo", "--verbose", "src", "setup.py", "--statistics", "--version"], ) assert opts.verbose diff --git a/tests/unit/test_option_manager.py b/tests/unit/test_option_manager.py index 92266f3..9904a2e 100644 --- a/tests/unit/test_option_manager.py +++ b/tests/unit/test_option_manager.py @@ -122,7 +122,7 @@ def test_parse_args_handles_comma_separated_defaults(optmanager): assert optmanager.config_options_dict == {} optmanager.add_option( - "--exclude", default="E123,W234", comma_separated_list=True + "--exclude", default="E123,W234", comma_separated_list=True, ) options = optmanager.parse_args([]) @@ -135,7 +135,7 @@ def test_parse_args_handles_comma_separated_lists(optmanager): assert optmanager.config_options_dict == {} optmanager.add_option( - "--exclude", default="E123,W234", comma_separated_list=True + "--exclude", default="E123,W234", comma_separated_list=True, ) options = optmanager.parse_args(["--exclude", "E201,W111,F280"]) @@ -148,11 +148,11 @@ def test_parse_args_normalize_paths(optmanager): assert optmanager.config_options_dict == {} optmanager.add_option( - "--extra-config", normalize_paths=True, comma_separated_list=True + "--extra-config", normalize_paths=True, comma_separated_list=True, ) options = optmanager.parse_args( - ["--extra-config", "../config.ini,tox.ini,flake8/some-other.cfg"] + ["--extra-config", "../config.ini,tox.ini,flake8/some-other.cfg"], ) assert options.extra_config == [ os.path.abspath("../config.ini"), diff --git a/tests/unit/test_options_config.py b/tests/unit/test_options_config.py index 7de58f0..d73f471 100644 --- a/tests/unit/test_options_config.py +++ b/tests/unit/test_options_config.py @@ -169,7 +169,7 @@ def test_load_extra_config_utf8(tmpdir): @pytest.fixture def opt_manager(): ret = OptionManager( - version="123", plugin_versions="", parents=[], formatter_names=[] + version="123", plugin_versions="", parents=[], formatter_names=[], ) register_default_options(ret) return ret @@ -213,7 +213,7 @@ def test_parse_config_ignores_unknowns(tmp_path, opt_manager, caplog): "flake8.options.config", 10, 'Option "wat" is not registered. Ignoring.', - ) + ), ] diff --git a/tests/unit/test_style_guide.py b/tests/unit/test_style_guide.py index 94fcb26..c66cfd2 100644 --- a/tests/unit/test_style_guide.py +++ b/tests/unit/test_style_guide.py @@ -36,7 +36,7 @@ def test_handle_error_does_not_raise_type_errors(): ) assert 1 == guide.handle_error( - "T111", "file.py", 1, 1, "error found", "a = 1" + "T111", "file.py", 1, 1, "error found", "a = 1", ) @@ -110,7 +110,7 @@ def test_style_guide_manager_pre_file_ignores_parsing(): ], ) def test_style_guide_manager_pre_file_ignores( - ignores, violation, filename, handle_error_return + ignores, violation, filename, handle_error_return, ): """Verify how the StyleGuideManager creates a default style guide.""" formatter = mock.create_autospec(base.BaseFormatter, instance=True) From 0f1af5010897439534e95dd4ec38d2738a136bc5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 21:56:25 +0000 Subject: [PATCH 83/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.17.0 → v1.17.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.17.0...v1.17.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 837e6e5..d3fd0cc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.17.0 + rev: v1.17.1 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From 3a2eff0868553e6cec0930bb996ed7a05acd8d52 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 11 Aug 2025 22:22:04 +0000 Subject: [PATCH 84/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v5.0.0 → v6.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v5.0.0...v6.0.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d3fd0cc..30581db 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: hooks: - id: add-trailing-comma - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-yaml - id: debug-statements From 4b13c2cc19ef9436a1048a2dfcf0ee934d17dbf4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 21:47:50 +0000 Subject: [PATCH 85/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.17.1 → v1.18.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.17.1...v1.18.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 30581db..14ac934 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.17.1 + rev: v1.18.1 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From e9f1cf3f484498c98c41f16c61c676b633b6c49d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 22:17:05 +0000 Subject: [PATCH 86/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.18.1 → v1.18.2](https://github.com/pre-commit/mirrors-mypy/compare/v1.18.1...v1.18.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 14ac934..20e006f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.18.1 + rev: v1.18.2 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From 567cafc15a0b20ad814579c17b306c058029334c Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 16 Oct 2025 10:01:02 -0400 Subject: [PATCH 87/92] py310+ --- .github/workflows/main.yml | 14 ++++++------ .pre-commit-config.yaml | 12 +++++----- bin/gen-pycodestyle-plugin | 2 +- setup.cfg | 2 +- src/flake8/checker.py | 37 ------------------------------- src/flake8/discover_files.py | 2 +- src/flake8/options/manager.py | 2 +- tests/integration/test_checker.py | 16 ++++--------- tests/integration/test_main.py | 12 ++++------ 9 files changed, 25 insertions(+), 74 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 08f54ea..486b0cb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,10 +13,7 @@ jobs: include: # linux - os: ubuntu-latest - python: pypy-3.9 - toxenv: py - - os: ubuntu-latest - python: 3.9 + python: pypy-3.11 toxenv: py - os: ubuntu-latest python: '3.10' @@ -30,9 +27,12 @@ jobs: - os: ubuntu-latest python: '3.13' toxenv: py + - os: ubuntu-latest + python: '3.14' + toxenv: py # windows - os: windows-latest - python: 3.9 + python: '3.10' toxenv: py # misc - os: ubuntu-latest @@ -46,8 +46,8 @@ jobs: toxenv: dogfood runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - run: python -mpip install --upgrade setuptools pip tox virtualenv diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 20e006f..2fac6b3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/asottile/add-trailing-comma - rev: v3.2.0 + rev: v4.0.0 hooks: - id: add-trailing-comma - repo: https://github.com/pre-commit/pre-commit-hooks @@ -12,23 +12,23 @@ repos: - id: trailing-whitespace exclude: ^tests/fixtures/ - repo: https://github.com/asottile/setup-cfg-fmt - rev: v2.8.0 + rev: v3.1.0 hooks: - id: setup-cfg-fmt - repo: https://github.com/asottile/reorder-python-imports - rev: v3.15.0 + rev: v3.16.0 hooks: - id: reorder-python-imports args: [ --application-directories, '.:src', - --py39-plus, + --py310-plus, --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.20.0 + rev: v3.21.0 hooks: - id: pyupgrade - args: [--py39-plus] + args: [--py310-plus] - repo: https://github.com/hhatto/autopep8 rev: v2.3.2 hooks: diff --git a/bin/gen-pycodestyle-plugin b/bin/gen-pycodestyle-plugin index c93fbfe..7fc504a 100755 --- a/bin/gen-pycodestyle-plugin +++ b/bin/gen-pycodestyle-plugin @@ -3,9 +3,9 @@ from __future__ import annotations import inspect import os.path +from collections.abc import Callable from collections.abc import Generator from typing import Any -from typing import Callable from typing import NamedTuple import pycodestyle diff --git a/setup.cfg b/setup.cfg index dc967d3..c0b8137 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,7 +30,7 @@ install_requires = mccabe>=0.7.0,<0.8.0 pycodestyle>=2.14.0,<2.15.0 pyflakes>=3.4.0,<3.5.0 -python_requires = >=3.9 +python_requires = >=3.10 package_dir = =src diff --git a/src/flake8/checker.py b/src/flake8/checker.py index d957915..c6a24eb 100644 --- a/src/flake8/checker.py +++ b/src/flake8/checker.py @@ -372,43 +372,6 @@ class FileChecker: token = () row, column = (1, 0) - if ( - column > 0 - and token - and isinstance(exception, SyntaxError) - and len(token) == 4 # Python 3.9 or earlier - ): - # NOTE(sigmavirus24): SyntaxErrors report 1-indexed column - # numbers. We need to decrement the column number by 1 at - # least. - column_offset = 1 - row_offset = 0 - # See also: https://github.com/pycqa/flake8/issues/169, - # https://github.com/PyCQA/flake8/issues/1372 - # On Python 3.9 and earlier, token will be a 4-item tuple with the - # last item being the string. Starting with 3.10, they added to - # the tuple so now instead of it ending with the code that failed - # to parse, it ends with the end of the section of code that - # failed to parse. Luckily the absolute position in the tuple is - # stable across versions so we can use that here - physical_line = token[3] - - # NOTE(sigmavirus24): Not all "tokens" have a string as the last - # argument. In this event, let's skip trying to find the correct - # column and row values. - if physical_line is not None: - # NOTE(sigmavirus24): SyntaxErrors also don't exactly have a - # "physical" line so much as what was accumulated by the point - # tokenizing failed. - # See also: https://github.com/pycqa/flake8/issues/169 - lines = physical_line.rstrip("\n").split("\n") - row_offset = len(lines) - 1 - logical_line = lines[0] - logical_line_length = len(logical_line) - if column > logical_line_length: - column = logical_line_length - row -= row_offset - column -= column_offset return row, column def run_ast_checks(self) -> None: diff --git a/src/flake8/discover_files.py b/src/flake8/discover_files.py index da28ba5..40b6e5c 100644 --- a/src/flake8/discover_files.py +++ b/src/flake8/discover_files.py @@ -3,9 +3,9 @@ from __future__ import annotations import logging import os.path +from collections.abc import Callable from collections.abc import Generator from collections.abc import Sequence -from typing import Callable from flake8 import utils diff --git a/src/flake8/options/manager.py b/src/flake8/options/manager.py index addd3ec..ae40794 100644 --- a/src/flake8/options/manager.py +++ b/src/flake8/options/manager.py @@ -5,9 +5,9 @@ import argparse import enum import functools import logging +from collections.abc import Callable from collections.abc import Sequence from typing import Any -from typing import Callable from flake8 import utils from flake8.plugins.finder import Plugins diff --git a/tests/integration/test_checker.py b/tests/integration/test_checker.py index 60d0132..f7f07af 100644 --- a/tests/integration/test_checker.py +++ b/tests/integration/test_checker.py @@ -2,7 +2,6 @@ from __future__ import annotations import importlib.metadata -import sys from unittest import mock import pytest @@ -322,17 +321,10 @@ def test_handling_syntaxerrors_across_pythons(): We need to handle that correctly to avoid crashing. https://github.com/PyCQA/flake8/issues/1372 """ - if sys.version_info < (3, 10): # pragma: no cover (<3.10) - # Python 3.9 or older - err = SyntaxError( - "invalid syntax", ("", 2, 5, "bad python:\n"), - ) - expected = (2, 4) - else: # pragma: no cover (3.10+) - err = SyntaxError( - "invalid syntax", ("", 2, 1, "bad python:\n", 2, 11), - ) - expected = (2, 1) + err = SyntaxError( + "invalid syntax", ("", 2, 1, "bad python:\n", 2, 11), + ) + expected = (2, 1) file_checker = checker.FileChecker( filename="-", plugins=finder.Checkers([], [], []), diff --git a/tests/integration/test_main.py b/tests/integration/test_main.py index 5091573..0ca5b63 100644 --- a/tests/integration/test_main.py +++ b/tests/integration/test_main.py @@ -168,10 +168,8 @@ def test_tokenization_error_but_not_syntax_error(tmpdir, capsys): tmpdir.join("t.py").write("b'foo' \\\n") assert cli.main(["t.py"]) == 1 - if hasattr(sys, "pypy_version_info"): # pragma: no cover (pypy) - expected = "t.py:2:1: E999 SyntaxError: end of file (EOF) in multi-line statement\n" # noqa: E501 - elif sys.version_info < (3, 10): # pragma: no cover (cp38+) - expected = "t.py:1:8: E999 SyntaxError: unexpected EOF while parsing\n" + if sys.implementation.name == "pypy": # pragma: no cover (pypy) + expected = "t.py:1:9: E999 SyntaxError: unexpected end of file (EOF) in multi-line statement\n" # noqa: E501 else: # pragma: no cover (cp310+) expected = "t.py:1:10: E999 SyntaxError: unexpected EOF while parsing\n" # noqa: E501 @@ -186,10 +184,8 @@ def test_tokenization_error_is_a_syntax_error(tmpdir, capsys): tmpdir.join("t.py").write("if True:\n pass\n pass\n") assert cli.main(["t.py"]) == 1 - if hasattr(sys, "pypy_version_info"): # pragma: no cover (pypy) - expected = "t.py:3:2: E999 IndentationError: unindent does not match any outer indentation level\n" # noqa: E501 - elif sys.version_info < (3, 10): # pragma: no cover ( Date: Mon, 10 Nov 2025 22:38:48 +0000 Subject: [PATCH 88/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.21.0 → v3.21.1](https://github.com/asottile/pyupgrade/compare/v3.21.0...v3.21.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2fac6b3..c35ff64 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.21.0 + rev: v3.21.1 hooks: - id: pyupgrade args: [--py310-plus] From 01af84d980b9d467e89cbb27e619eb1346c1c673 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 22:27:23 +0000 Subject: [PATCH 89/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.21.1 → v3.21.2](https://github.com/asottile/pyupgrade/compare/v3.21.1...v3.21.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c35ff64..02808bf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: --add-import, 'from __future__ import annotations', ] - repo: https://github.com/asottile/pyupgrade - rev: v3.21.1 + rev: v3.21.2 hooks: - id: pyupgrade args: [--py310-plus] From 72c267d2e5eef80b59ff05dbe31a000b22ed4615 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 22:40:09 +0000 Subject: [PATCH 90/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.18.2 → v1.19.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.18.2...v1.19.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 02808bf..8108d1e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.18.2 + rev: v1.19.0 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From 45c1af5e2426ff5a3638b6c771f3d27ebed92fbd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:21:22 +0000 Subject: [PATCH 91/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.19.0 → v1.19.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.19.0...v1.19.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8108d1e..7d6a6ca 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.19.0 + rev: v1.19.1 hooks: - id: mypy exclude: ^(docs/|example-plugin/) From 941f908d6c0fa0aff9993ed1c1bb4e0aa11e9847 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 21:52:21 +0000 Subject: [PATCH 92/92] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/setup-cfg-fmt: v3.1.0 → v3.2.0](https://github.com/asottile/setup-cfg-fmt/compare/v3.1.0...v3.2.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7d6a6ca..f75e5ee 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,7 +12,7 @@ repos: - id: trailing-whitespace exclude: ^tests/fixtures/ - repo: https://github.com/asottile/setup-cfg-fmt - rev: v3.1.0 + rev: v3.2.0 hooks: - id: setup-cfg-fmt - repo: https://github.com/asottile/reorder-python-imports