From 1b4177540ed812a57d06ca316f45ec7e20246699 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Thu, 4 Jan 2024 04:11:30 +0000 Subject: [PATCH] Enable RUF017 --- .ruff.toml | 2 +- sphinx/domains/python.py | 4 +++- sphinx/ext/autodoc/__init__.py | 10 +++++++--- sphinx/ext/autosummary/__init__.py | 5 ++++- sphinx/ext/todo.py | 5 ++++- sphinx/pycode/parser.py | 7 ++++--- tests/test_ext_autodoc.py | 4 +++- 7 files changed, 26 insertions(+), 11 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index 21cf9c768..e175a0edf 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -243,7 +243,7 @@ select = [ "RUF013", # PEP 484 prohibits implicit `Optional` # "RUF015", # Prefer `next({iterable})` over single element slice "RUF016", # Slice in indexed access to type `{value_type}` uses type `{index_type}` instead of an integer -# "RUF017", # Avoid quadratic list summation + "RUF017", # Avoid quadratic list summation "RUF018", # Avoid assignment expressions in `assert` statements "RUF019", # Unnecessary key check before dictionary access "RUF020", # `{never_like} | T` is equivalent to `T` diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index 2558dafbc..fcd2a73ce 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -5,7 +5,9 @@ from __future__ import annotations import ast import builtins import contextlib +import functools import inspect +import operator import re import token import typing @@ -185,7 +187,7 @@ def _parse_annotation(annotation: str, env: BuildEnvironment) -> list[Node]: result.append(addnodes.desc_sig_punctuation('', ']')) return result if isinstance(node, ast.Module): - return sum((unparse(e) for e in node.body), []) + return functools.reduce(operator.iadd, (unparse(e) for e in node.body), []) if isinstance(node, ast.Name): return [nodes.Text(node.id)] if isinstance(node, ast.Subscript): diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 400807898..2b614e3c9 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -7,6 +7,8 @@ for those who like elaborate docstrings. from __future__ import annotations +import functools +import operator import re import sys import warnings @@ -923,7 +925,7 @@ class Documenter: except PycodeError: pass - docstrings: list[str] = sum(self.get_doc() or [], []) + docstrings: list[str] = functools.reduce(operator.iadd, self.get_doc() or [], []) if ismock(self.object) and not docstrings: logger.warning(__('A mocked object is detected: %r'), self.name, type='autodoc') @@ -2054,7 +2056,8 @@ class DataDocumenter(GenericAliasMixin, return True else: doc = self.get_doc() or [] - docstring, metadata = separate_metadata('\n'.join(sum(doc, []))) + docstring, metadata = separate_metadata( + '\n'.join(functools.reduce(operator.iadd, doc, []))) if 'hide-value' in metadata: return True @@ -2625,7 +2628,8 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc] else: doc = self.get_doc() if doc: - docstring, metadata = separate_metadata('\n'.join(sum(doc, []))) + docstring, metadata = separate_metadata( + '\n'.join(functools.reduce(operator.iadd, doc, []))) if 'hide-value' in metadata: return True diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index afc4d3b97..2da8fd828 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -48,7 +48,9 @@ This can be used as the default role to make links 'smart'. from __future__ import annotations +import functools import inspect +import operator import os import posixpath import re @@ -651,7 +653,8 @@ def import_by_name( tried.append(prefixed_name) errors.append(exc) - exceptions: list[BaseException] = sum((e.exceptions for e in errors), []) + exceptions: list[BaseException] = functools.reduce( + operator.iadd, (e.exceptions for e in errors), []) raise ImportExceptionGroup('no module named %s' % ' or '.join(tried), exceptions) diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py index e540e7ecf..035e70bdd 100644 --- a/sphinx/ext/todo.py +++ b/sphinx/ext/todo.py @@ -7,6 +7,8 @@ with a backlink to the original location. from __future__ import annotations +import functools +import operator from typing import TYPE_CHECKING, Any, cast from docutils import nodes @@ -129,7 +131,8 @@ class TodoListProcessor: self.process(doctree, docname) def process(self, doctree: nodes.document, docname: str) -> None: - todos: list[todo_node] = sum(self.domain.todos.values(), []) + todos: list[todo_node] = functools.reduce( + operator.iadd, self.domain.todos.values(), []) for node in list(doctree.findall(todolist)): if not self.config.todo_include_todos: node.parent.remove(node) diff --git a/sphinx/pycode/parser.py b/sphinx/pycode/parser.py index 177527ada..11fe812ed 100644 --- a/sphinx/pycode/parser.py +++ b/sphinx/pycode/parser.py @@ -4,8 +4,10 @@ from __future__ import annotations import ast import contextlib +import functools import inspect import itertools +import operator import re import tokenize from inspect import Signature @@ -350,9 +352,8 @@ class VariableCommentPicker(ast.NodeVisitor): """Handles Assign node and pick up a variable comment.""" try: targets = get_assign_targets(node) - varnames: list[str] = sum( - [get_lvar_names(t, self=self.get_self()) for t in targets], [], - ) + varnames: list[str] = functools.reduce( + operator.iadd, [get_lvar_names(t, self=self.get_self()) for t in targets], []) current_line = self.get_line(node.lineno) except TypeError: return # this assignment is not new definition! diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py index 5cea65e1c..9ffc272ff 100644 --- a/tests/test_ext_autodoc.py +++ b/tests/test_ext_autodoc.py @@ -4,6 +4,8 @@ This tests mainly the Documenters; the auto directives are tested in a test source file translated by test_build. """ +import functools +import operator import sys from types import SimpleNamespace from unittest.mock import Mock @@ -330,7 +332,7 @@ def test_get_doc(app): inst.format_signature() # handle docstring signatures! ds = inst.get_doc() # for testing purposes, concat them and strip the empty line at the end - res = sum(ds, [])[:-1] + res = functools.reduce(operator.iadd, ds, [])[:-1] print(res) return res