From 0a2846f29d4c2a0244f5d64f858644263dbed33c Mon Sep 17 00:00:00 2001 From: Kai Harder Date: Mon, 23 Feb 2026 10:42:58 +0000 Subject: [PATCH] Add FTP140 --- _flake8_tergeo/checks/ast_call.py | 22 ++++++++++++++++++++++ docs/checks.md | 5 +++++ news/+e471e45f.feature.md | 1 + tests/checks/test_ast_call.py | 21 +++++++++++++++++++++ tests/checks/test_ast_call/ftp140.txt | 8 ++++++++ 5 files changed, 57 insertions(+) create mode 100644 news/+e471e45f.feature.md create mode 100644 tests/checks/test_ast_call/ftp140.txt diff --git a/_flake8_tergeo/checks/ast_call.py b/_flake8_tergeo/checks/ast_call.py index 04dca78..14158f2 100644 --- a/_flake8_tergeo/checks/ast_call.py +++ b/_flake8_tergeo/checks/ast_call.py @@ -108,6 +108,7 @@ def check_call(node: ast.Call) -> IssueGenerator: yield from _check_type_none_in_isinstance(node) yield from _check_mock_builtins_open(node) yield from _check_sys_trace_functions(node) + yield from _check_utf_8_encoding(node) def _check_os_walk(node: ast.Call) -> IssueGenerator: @@ -867,3 +868,24 @@ def _check_sys_trace_functions(node: ast.Call) -> IssueGenerator: issue_number="138", message=f"Trace function {name} should not be called.", ) + + +def _check_utf_8_encoding(node: ast.Call) -> IssueGenerator: + if get_python_version() < (3, 15): + return + for keyword in node.keywords: + if ( + keyword.arg == "encoding" + and is_constant_node(keyword.value, str) + and cast(str, keyword.value.value).lower() == "utf-8" + ): + yield Issue( + line=node.lineno, + column=node.col_offset, + issue_number="140", + message=( + "UTF-8 encoding is the default in Python 3.15 and does not need to be " + "specified. Remove the encoding argument or specify a different encoding if " + "needed." + ), + ) diff --git a/docs/checks.md b/docs/checks.md index d174408..163a521 100644 --- a/docs/checks.md +++ b/docs/checks.md @@ -619,6 +619,11 @@ Finds calls of `sys` trace functions like `sys.settrace`. Checks if `profile` or `cProfile` are imported as with python 3.15 `profiling.tracing` should be used. The check is only active for python 3.15 and onwards. +## FTP140 +Checks if `encoding="UTF-8"` is used in any function call as UTF-8 is the default encoding +starting with python 3.15. +The check is only active for python 3.15 and onwards. + ## FTP200 Find calls of `flask.abort` and `werkzeug.exceptions.abort`. Instead of calling this helper function raise the appropriate exception directly diff --git a/news/+e471e45f.feature.md b/news/+e471e45f.feature.md new file mode 100644 index 0000000..1be7eaf --- /dev/null +++ b/news/+e471e45f.feature.md @@ -0,0 +1 @@ +FTP140 which can find unnecessary UTF-8 encodings diff --git a/tests/checks/test_ast_call.py b/tests/checks/test_ast_call.py index 9675d0f..fa623ec 100644 --- a/tests/checks/test_ast_call.py +++ b/tests/checks/test_ast_call.py @@ -250,6 +250,14 @@ issue_number="FTP138", message="Trace function {func} should not be called.", ) +FTP140 = partial( + Issue, + issue_number="FTP140", + message=( + "UTF-8 encoding is the default in Python 3.15 and does not need to be specified. " + "Remove the encoding argument or specify a different encoding if needed." + ), +) def FTP073( # pylint:disable=invalid-name @@ -1104,3 +1112,16 @@ def test(self, runner: Flake8RunnerFixture, imp: str, func: str) -> None: filename="ftp138.txt", issue_number="FTP138", imp=imp, func=func ) assert results == [FTP138(line=9, column=1, func=func)] + + +@pytest.mark.parametrize( + "python_version,find_by_version", [("3.10.0", False), ("3.15.1", True)] +) +def test_ftp140( + runner: Flake8RunnerFixture, python_version: str, find_by_version: bool +) -> None: + assert runner( + filename="ftp140.txt", + issue_number="FTP140", + args=("--ftp-python-version", python_version), + ) == ([FTP140(line=8, column=1)] if find_by_version else []) diff --git a/tests/checks/test_ast_call/ftp140.txt b/tests/checks/test_ast_call/ftp140.txt new file mode 100644 index 0000000..8685f65 --- /dev/null +++ b/tests/checks/test_ast_call/ftp140.txt @@ -0,0 +1,8 @@ +# code without issues +x() +x = 1 +x(env="utf-8") +foo(encoding="utf-16") + +# code with issues +foo(encoding="utf-8")