diff --git a/3rdparty/python/flake8-requirements.txt b/3rdparty/python/flake8-requirements.txt index 08530824817..739a1d17f30 100644 --- a/3rdparty/python/flake8-requirements.txt +++ b/3rdparty/python/flake8-requirements.txt @@ -1,4 +1 @@ flake8>=5.0.4,<7 -flake8-2020>=1.7.0,<2 -flake8-no-implicit-concat -flake8-comprehensions>=3.10.0,<4.0 diff --git a/3rdparty/python/flake8.lock b/3rdparty/python/flake8.lock index d675e172af5..ce9e3506892 100644 --- a/3rdparty/python/flake8.lock +++ b/3rdparty/python/flake8.lock @@ -31,83 +31,6 @@ "requires_python": ">=3.8.1", "version": "6.1.0" }, - { - "artifacts": [ - { - "algorithm": "sha256", - "hash": "59b6b8ac01cde10ef11b31a2c9aa15b4509d828ae115ee5be34464b9e4de4ea6", - "url": "https://files.pythonhosted.org/packages/36/f0/14c6c25768ddc81999733e7bed89e9285b273920505180155e351ed92dc5/flake8_2020-1.8.1-py2.py3-none-any.whl" - }, - { - "algorithm": "sha256", - "hash": "094ea95e8b614c3bd123fd4f007be28ec117ca57a6169903d4baaabe78e3e590", - "url": "https://files.pythonhosted.org/packages/cf/0b/e71a0d9efd854a631e2d51707676886997c73bec70c3c221b84601b976d2/flake8_2020-1.8.1.tar.gz" - } - ], - "project_name": "flake8-2020", - "requires_dists": [ - "flake8>=5" - ], - "requires_python": ">=3.8", - "version": "1.8.1" - }, - { - "artifacts": [ - { - "algorithm": "sha256", - "hash": "3943a9c6f2593c3bc5cc64106c2f89d63c6ecd49c8343597f8257b8fcfc8b0a2", - "url": "https://files.pythonhosted.org/packages/39/bd/d6739d685fdd79349aa51c37bdedc0d8eab6ae9c6e6ed2ca935b3f88210d/flake8_comprehensions-3.17.0-py3-none-any.whl" - }, - { - "algorithm": "sha256", - "hash": "bf4fa102b2bf4d6c9e999e29e4b2724cbadffb70b937600fc782161be4dc0f4a", - "url": "https://files.pythonhosted.org/packages/91/93/da2d30987ce4c06404326e7c8e6636cae18c2b2f2d5542891a8ad64a34f4/flake8_comprehensions-3.17.0.tar.gz" - } - ], - "project_name": "flake8-comprehensions", - "requires_dists": [ - "flake8!=3.2,>=3" - ], - "requires_python": ">=3.9", - "version": "3.17.0" - }, - { - "artifacts": [ - { - "algorithm": "sha256", - "hash": "a173b4720fed1611b9b127e194aa7e46aa86fed3425df8d37267b78cbbae2e07", - "url": "https://files.pythonhosted.org/packages/11/43/4eb677c2e8d165dc89d05421b36850b1f06d69e6996622d6599ab85b309b/flake8_no_implicit_concat-0.3.7-py3-none-any.whl" - }, - { - "algorithm": "sha256", - "hash": "8472f2a6ddb11980e9bc35aa289d051e36d1e69c66ecd0fe5f5406ff8ab91e3a", - "url": "https://files.pythonhosted.org/packages/25/27/5057b10b1729f686af41edd45fc434d96faf25d925aec43bb9b3f27a559a/flake8_no_implicit_concat-0.3.7.tar.gz" - } - ], - "project_name": "flake8-no-implicit-concat", - "requires_dists": [ - "black; extra == \"dev\"", - "codecov; extra == \"dev\"", - "coverage; extra == \"dev\"", - "darglint; extra == \"dev\"", - "flake8", - "flake8-2020; extra == \"dev\"", - "flake8-black; extra == \"dev\"", - "flake8-broken-line; extra == \"dev\"", - "flake8-builtins; extra == \"dev\"", - "flake8-docstrings; extra == \"dev\"", - "flake8-isort; extra == \"dev\"", - "flake8-rst-docstrings; extra == \"dev\"", - "flake8; extra == \"dev\"", - "hacking>=4; extra == \"dev\"", - "isort; extra == \"dev\"", - "more-itertools; python_version < \"3.10\"", - "mypy; extra == \"dev\"", - "pep8-naming; extra == \"dev\"" - ], - "requires_python": ">=3.6", - "version": "0.3.7" - }, { "artifacts": [ { @@ -171,13 +94,10 @@ "only_wheels": [], "overridden": [], "path_mappings": {}, - "pex_version": "2.81.0", - "pip_version": "25.3", + "pex_version": "2.93.2", + "pip_version": "26.1", "prefer_older_binary": false, "requirements": [ - "flake8-2020<2,>=1.7.0", - "flake8-comprehensions<4.0,>=3.10.0", - "flake8-no-implicit-concat", "flake8<7,>=5.0.4" ], "requires_python": [ diff --git a/3rdparty/python/flake8.lock.metadata b/3rdparty/python/flake8.lock.metadata index cf72a02a6d1..47e704c1cbf 100644 --- a/3rdparty/python/flake8.lock.metadata +++ b/3rdparty/python/flake8.lock.metadata @@ -1,12 +1,9 @@ { - "version": 6, + "version": 8, "valid_for_interpreter_constraints": [ "CPython==3.14.*" ], "generated_with_requirements": [ - "flake8-2020<2,>=1.7.0", - "flake8-comprehensions<4.0,>=3.10.0", - "flake8-no-implicit-concat", "flake8<7,>=5.0.4" ], "manylinux": "manylinux2014", @@ -18,5 +15,8 @@ "sources": [], "lock_style": "universal", "complete_platforms": [], + "uploaded_prior_to": null, + "lockfile_format": "pex", + "resolve": "flake8", "description": "This lockfile was generated by Pants. To regenerate, run: pants generate-lockfiles --resolve=flake8" } \ No newline at end of file diff --git a/build-support/flake8/.flake8 b/build-support/flake8/.flake8 index 552ec41440f..4cbcc260873 100644 --- a/build-support/flake8/.flake8 +++ b/build-support/flake8/.flake8 @@ -1,25 +1,9 @@ [flake8] extend-ignore: - # whitespace before ':' (conflicts with Black) - E203, - # Bad trailing comma (conflicts with Black) - E231, - # line too long (> 79 characters) - E501, - # multiple statements on one line (colon) (conflicts with Black) - E701, - # Do not assign a lambda expression - E731, - # Ambiguous variable name (enable once fixed) - E741, - # line break before binary operator (conflicts with Black) - W503, - # Implicitly concatenated string literals over multiple lines - NIC002, - # Implicitly concatenated bytes literals over multiple lines - NIC102, - # Unnecessary dict call - rewrite as a literal - C408 + # Handled by ruff-check + F, + E, + W, [flake8:local-plugins] extension = diff --git a/pyproject.toml b/pyproject.toml index ae6d80e6721..b90c3cdee4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,17 +60,83 @@ line-length = 100 target-version = "py314" [tool.ruff.lint] -# I: isort (import sorting) -# UP: pyupgrade (update Python code to `target-version`) -select = ["I", "UP"] -# UP006/UP035: replaces DefaultDict with collections.defaultdict - lots of churn (which SJ wants to batch after 3.14) -# UP007: Many buried, non-auto-fixable unions -# UP018: Replaces `int(42)` in tests, breaking call-by-type and implicitly -# UP031: Two string replacements that are not auto-fixable -# UP036: Outdated version check (in rule_visitor for Python 3.8) -# UP040/UP046/UP047: Cost-benefit unclear, see https://github.com/python/cpython/issues/114159 -ignore = ["UP006", "UP007", "UP018", "UP031", "UP035", "UP036", "UP040", "UP046", "UP047"] +select = [ + "C4", # https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4 + "E", # https://docs.astral.sh/ruff/rules/#error-e + "F", # https://docs.astral.sh/ruff/rules/#pyflakes-f + "I", # https://docs.astral.sh/ruff/rules/#isort-i + "ISC", # https://docs.astral.sh/ruff/rules/#flake8-implicit-str-concat-isc + "RUF", # https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf + "UP", # https://docs.astral.sh/ruff/rules/#pyupgrade-up (update Python code to `target-version`) + "W", # https://docs.astral.sh/ruff/rules/#warning-w + "YTT", # https://docs.astral.sh/ruff/rules/#flake8-2020-ytt +] external = ["PNT20"] +ignore = [ + # unnecessary-collection-call: Unnecessary {kind}() call (rewrite as a literal). Note: Taken from existing Flake8 ignore. + "C408", + # unnecessary-dict-comprehension-for-iterable: Unnecessary dict comprehension for iterable; use dict.fromkeys instead. TODO: Revisit these errors. + "C420", + # line-too-long: Line too long ({width} > {limit}). Note: Handled by `ruff`. + "E501", + # type-comparison: Use is and is not for type comparisons, or isinstance() for isinstance checks. TODO: Revisit these errors. + "E721", + # lambda-assignment: Do not assign a lambda expression, use a def. TODO: Single instance, revisit. + "E731", + # ambiguous-variable-name: Ambiguous variable name: {name}. Note: Checks for certain single-letter variable names that look like numbers. + "E741", + # multi-value-repeated-key-literal: Dictionary key literal {name} repeated. TODO: Probably need to fix, these are likely real bugs. + "F601", + # explicit-string-concatenation: Explicitly concatenated string should be implicitly concatenated. TODO: Can be auto-fixed. + "ISC003", + # ambiguous-unicode-character-string: String contains ambiguous {}. Did you mean {}?. TODO: Revisit this. + "RUF001", + # ambiguous-unicode-character-comment: Comment contains ambiguous {}. Did you mean {}?. TODO: Revisit this. + "RUF003", + # collection-literal-concatenation: Consider {expression} instead of concatenation. TODO: Fix this. + "RUF005", + # function-call-in-dataclass-default-argument: Do not perform function call {name} in dataclass defaults + "RUF009", + # explicit-f-string-type-conversion: Use explicit conversion flag. TODO: Revisit and likely fix this. + "RUF010", + # mutable-class-default: Mutable default value for class attribute. TODO: Revisit this. + "RUF012", + # unnecessary-iterable-allocation-for-first-element: Prefer next({iterable}) over single element slice. TODO: Fix this. + "RUF015", + # unnecessary-key-check: Unnecessary key check before dictionary access. TODO: Fix this. + "RUF019", + # parenthesize-chained-operators: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear. TODO: Fix this. + "RUF021", + # unsorted-dunder-slots: {}.__slots__ is not sorted. TODO: Revisit this. + "RUF023", + # pytest-raises-ambiguous-pattern: Pattern passed to match= contains metacharacters but is neither escaped nor raw. TODO: Fix this. + "RUF043", + # unnecessary-cast-to-int: Value being cast to int is already an integer. TODO: Fix this. + "RUF046", + # unused-unpacked-variable: Unpacked variable {name} is never used. TODO: Fix this. + "RUF059", + # unused-noqa: Unused {}. TODO: Fix this. + "RUF100", + # non-pep585-annotation: Use {to} instead of {from} for type annotation. Note: (lots of churn) + "UP006", + # non-pep604-annotation-union: Use X | Y for type annotations. Note: Many buried, non-auto-fixable unions + "UP007", + # native-literals: Unnecessary {literal_type} call (rewrite as a literal). Note: Replaces `int(42)` in tests, breaking call-by-type and implicitly + "UP018", + # printf-string-formatting: Use format specifiers instead of percent format. Note: Two string replacements that are not auto-fixable + "UP031", + # deprecated-import: Import from {target} instead: {names}. Note: Replaces `DefaultDict` with `collections.defaultdict` (lots of churn). + "UP035", + # outdated-version-block: Version block is outdated for minimum Python version. Note: Outdated version check (in rule_visitor for Python 3.8) + "UP036", + # UP040/UP046/UP047: Cost-benefit unclear, see https://github.com/python/cpython/issues/114159 + # non-pep695-type-alias: Type alias {name} uses {type_alias_method} instead of the type keyword. Note: Cost-benefit unclear, see https://github.com/python/cpython/issues/114159 + "UP040", + # non-pep695-generic-class: Generic class {name} uses Generic subclass instead of type parameters. Note: Cost-benefit unclear, see https://github.com/python/cpython/issues/114159 + "UP046", + # non-pep695-generic-function: Generic function {name} should use type parameters. Note: Cost-benefit unclear, see https://github.com/python/cpython/issues/114159 + "UP047", +] [tool.ruff.lint.isort] known-first-party = ["internal_plugins", "pants", "pants_test", "python_constant"]