From d4c739cdd15463118fe5beeb5451c2abcaa4f44f Mon Sep 17 00:00:00 2001 From: danieleades <33452915+danieleades@users.noreply.github.com> Date: Thu, 14 Mar 2024 10:16:36 +0000 Subject: [PATCH] [lint] add PERF401 lint (#12070) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: daniel.eades Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- .ruff.toml | 2 +- sphinx/domains/c/_ast.py | 8 +--- sphinx/domains/c/_symbol.py | 5 +-- sphinx/domains/cpp/_ast.py | 57 +++++++++++--------------- sphinx/domains/cpp/_symbol.py | 8 ++-- sphinx/environment/adapters/toctree.py | 14 ++++--- sphinx/ext/inheritance_diagram.py | 21 +++++----- sphinx/ext/napoleon/docstring.py | 5 +-- sphinx/util/cfamily.py | 3 +- sphinx/util/math.py | 3 +- sphinx/writers/html5.py | 4 +- sphinx/writers/manpage.py | 4 +- sphinx/writers/texinfo.py | 5 +-- sphinx/writers/text.py | 4 +- 14 files changed, 60 insertions(+), 83 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index b88b45f9586..a9d74559ac2 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -186,7 +186,7 @@ select = [ "PERF101", # Do not cast an iterable to `list` before iterating over it "PERF102", # When using only the {subset} of a dict use the `{subset}()` method # "PERF203", # `try`-`except` within a loop incurs performance overhead -# "PERF401", # Use a list comprehension to create a transformed list + "PERF401", # Use a list comprehension to create a transformed list "PERF402", # Use `list` or `list.copy` to create a copy of a list "PERF403", # Use a dictionary comprehension instead of a for-loop # pygrep-hooks ('PGH') diff --git a/sphinx/domains/c/_ast.py b/sphinx/domains/c/_ast.py index bd17e980f8f..65397759231 100644 --- a/sphinx/domains/c/_ast.py +++ b/sphinx/domains/c/_ast.py @@ -349,10 +349,7 @@ def __init__(self, prefix: ASTExpression, postFixes: list[ASTPostfixOp]): self.postFixes = postFixes def _stringify(self, transform: StringifyTransform) -> str: - res = [transform(self.prefix)] - for p in self.postFixes: - res.append(transform(p)) - return ''.join(res) + return ''.join([transform(self.prefix), *(transform(p) for p in self.postFixes)]) def describe_signature(self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol) -> None: @@ -881,8 +878,7 @@ def _stringify(self, transform: StringifyTransform) -> str: res = [] if self.declId: res.append(transform(self.declId)) - for op in self.arrayOps: - res.append(transform(op)) + res.extend(transform(op) for op in self.arrayOps) if self.param: res.append(transform(self.param)) return ''.join(res) diff --git a/sphinx/domains/c/_symbol.py b/sphinx/domains/c/_symbol.py index f01b51267da..b214882dd0e 100644 --- a/sphinx/domains/c/_symbol.py +++ b/sphinx/domains/c/_symbol.py @@ -693,7 +693,4 @@ def to_string(self, indent: int) -> str: return ''.join(res) def dump(self, indent: int) -> str: - res = [self.to_string(indent)] - for c in self._children: - res.append(c.dump(indent + 1)) - return ''.join(res) + return ''.join([self.to_string(indent), *(c.dump(indent + 1) for c in self._children)]) diff --git a/sphinx/domains/cpp/_ast.py b/sphinx/domains/cpp/_ast.py index c8cab3e12a9..145db972f22 100644 --- a/sphinx/domains/cpp/_ast.py +++ b/sphinx/domains/cpp/_ast.py @@ -194,8 +194,7 @@ def get_id(self, version: int, modifiers: str = '') -> str: if len(self.names) > 1 or len(modifiers) > 0: res.append('N') res.append(modifiers) - for n in self.names: - res.append(n.get_id(version)) + res.extend(n.get_id(version) for n in self.names) if len(self.names) > 1 or len(modifiers) > 0: res.append('E') return ''.join(res) @@ -631,11 +630,12 @@ def _stringify(self, transform: StringifyTransform) -> str: return transform(self.lst) def get_id(self, idPrefix: str, version: int) -> str: - res = ['cl', idPrefix] - for e in self.lst.exprs: - res.append(e.get_id(version)) - res.append('E') - return ''.join(res) + return ''.join([ + 'cl', + idPrefix, + *(e.get_id(version) for e in self.lst.exprs), + 'E', + ]) def describe_signature(self, signode: TextElement, mode: str, env: BuildEnvironment, symbol: Symbol) -> None: @@ -648,10 +648,7 @@ def __init__(self, prefix: ASTType, postFixes: list[ASTPostfixOp]): self.postFixes = postFixes def _stringify(self, transform: StringifyTransform) -> str: - res = [transform(self.prefix)] - for p in self.postFixes: - res.append(transform(p)) - return ''.join(res) + return ''.join([transform(self.prefix), *(transform(p) for p in self.postFixes)]) def get_id(self, version: int) -> str: id = self.prefix.get_id(version) @@ -2019,8 +2016,7 @@ def _stringify(self, transform: StringifyTransform) -> str: res = [] if self.declId: res.append(transform(self.declId)) - for op in self.arrayOps: - res.append(transform(op)) + res.extend(transform(op) for op in self.arrayOps) if self.paramQual: res.append(transform(self.paramQual)) return ''.join(res) @@ -3229,13 +3225,10 @@ def get_id(self, version: int, excludeRequires: bool = False) -> str: assert version >= 2 res = [] res.append("I") - for param in self.params: - res.append(param.get_id(version)) + res.extend(param.get_id(version) for param in self.params) res.append("E") if not excludeRequires and self.requiresClause: - res.append('IQ') - res.append(self.requiresClause.expr.get_id(version)) - res.append('E') + res.extend(['IQ', self.requiresClause.expr.get_id(version), 'E']) return ''.join(res) def _stringify(self, transform: StringifyTransform) -> str: @@ -3360,21 +3353,19 @@ def __init__(self, concept: ASTNestedName, def get_id(self, version: int) -> str: assert version >= 2 - # first do the same as a normal template parameter list - res = [] - res.append("I") - for param in self.params: - res.append(param.get_id(version)) - res.append("E") - # let's use X expr E, which is otherwise for constant template args - res.append("X") - res.append(self.concept.get_id(version)) - res.append("I") - for param in self.params: - res.append(param.get_id_as_arg(version)) - res.append("E") - res.append("E") - return ''.join(res) + return ''.join([ + # first do the same as a normal template parameter list + "I", + *(param.get_id(version) for param in self.params), + "E", + # let's use X expr E, which is otherwise for constant template args + "X", + self.concept.get_id(version), + "I", + *(param.get_id_as_arg(version) for param in self.params), + "E", + "E", + ]) def _stringify(self, transform: StringifyTransform) -> str: res = [] diff --git a/sphinx/domains/cpp/_symbol.py b/sphinx/domains/cpp/_symbol.py index d016059f76a..d5dfbb89ae7 100644 --- a/sphinx/domains/cpp/_symbol.py +++ b/sphinx/domains/cpp/_symbol.py @@ -1086,7 +1086,7 @@ def to_string(self, indent: int) -> str: return ''.join(res) def dump(self, indent: int) -> str: - res = [self.to_string(indent)] - for c in self._children: - res.append(c.dump(indent + 1)) - return ''.join(res) + return ''.join([ + self.to_string(indent), + *(c.dump(indent + 1) for c in self._children), + ]) diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py index afdf4a18da4..90c7d3bc650 100644 --- a/sphinx/environment/adapters/toctree.py +++ b/sphinx/environment/adapters/toctree.py @@ -73,9 +73,8 @@ def global_toctree_for_doc( This gives the global ToC, with all ancestors and their siblings. """ - toctrees: list[Element] = [] - for toctree_node in env.master_doctree.findall(addnodes.toctree): - if toctree := _resolve_toctree( + resolved = ( + _resolve_toctree( env, docname, builder, @@ -85,8 +84,13 @@ def global_toctree_for_doc( titles_only=titles_only, collapse=collapse, includehidden=includehidden, - ): - toctrees.append(toctree) + ) + for toctree_node in env.master_doctree.findall(addnodes.toctree) + ) + toctrees = [ + toctree for toctree in resolved if toctree is not None + ] + if not toctrees: return None result = toctrees[0] diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index 664c4d4444a..8d09fdb418d 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -316,20 +316,19 @@ def generate_dot(self, name: str, urls: dict[str, str] | None = None, # Write the node this_node_attrs = n_attrs.copy() if fullname in urls: - this_node_attrs['URL'] = '"%s"' % urls[fullname] - this_node_attrs['target'] = '"_top"' + this_node_attrs["URL"] = '"%s"' % urls[fullname] + this_node_attrs["target"] = '"_top"' if tooltip: - this_node_attrs['tooltip'] = tooltip - res.append(' "%s" [%s];\n' % - (name, self._format_node_attrs(this_node_attrs))) + this_node_attrs["tooltip"] = tooltip + res.append(' "%s" [%s];\n' % (name, self._format_node_attrs(this_node_attrs))) # Write the edges - for base_name in bases: - res.append(' "%s" -> "%s" [%s];\n' % - (base_name, name, - self._format_node_attrs(e_attrs))) - res.append('}\n') - return ''.join(res) + res.extend( + ' "%s" -> "%s" [%s];\n' % (base_name, name, self._format_node_attrs(e_attrs)) + for base_name in bases + ) + res.append("}\n") + return "".join(res) class inheritance_diagram(graphviz): diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py index f86b9d2c1b7..5d531e5580c 100644 --- a/sphinx/ext/napoleon/docstring.py +++ b/sphinx/ext/napoleon/docstring.py @@ -313,12 +313,11 @@ def _consume_field(self, parse_type: bool = True, prefer_type: bool = False, def _consume_fields(self, parse_type: bool = True, prefer_type: bool = False, multiple: bool = False) -> list[tuple[str, str, list[str]]]: self._consume_empty() - fields = [] + fields: list[tuple[str, str, list[str]]] = [] while not self._is_section_break(): _name, _type, _desc = self._consume_field(parse_type, prefer_type) if multiple and _name: - for name in _name.split(","): - fields.append((name.strip(), _type, _desc)) + fields.extend((name.strip(), _type, _desc) for name in _name.split(",")) elif _name or _type or _desc: fields.append((_name, _type, _desc)) return fields diff --git a/sphinx/util/cfamily.py b/sphinx/util/cfamily.py index ae035dbf224..c8879839ef0 100644 --- a/sphinx/util/cfamily.py +++ b/sphinx/util/cfamily.py @@ -302,8 +302,7 @@ def fail(self, msg: str) -> None: 'Invalid %s declaration: %s [error at %d]\n %s\n %s' % (self.language, msg, self.pos, self.definition, indicator)) errors.append((exMain, "Main error")) - for err in self.otherErrors: - errors.append((err, "Potential other error")) + errors.extend((err, "Potential other error") for err in self.otherErrors) self.otherErrors = [] raise self._make_multi_error(errors, '') diff --git a/sphinx/util/math.py b/sphinx/util/math.py index ef0eb3901c8..97b8440b67e 100644 --- a/sphinx/util/math.py +++ b/sphinx/util/math.py @@ -54,8 +54,7 @@ def is_equation(part: str) -> str: else: begin = r'\begin{align*}%s\!\begin{aligned}' % labeldef end = r'\end{aligned}\end{align*}' - for part in parts: - equations.append('%s\\\\\n' % part.strip()) + equations.extend('%s\\\\\n' % part.strip() for part in parts) concatenated_equations = ''.join(equations) return f'{begin}\n{concatenated_equations}{end}' diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py index 9eac2ebfb0b..f43ea24e5f4 100644 --- a/sphinx/writers/html5.py +++ b/sphinx/writers/html5.py @@ -589,10 +589,8 @@ def depart_literal(self, node: Element) -> None: def visit_productionlist(self, node: Element) -> None: self.body.append(self.starttag(node, 'pre')) - names = [] productionlist = cast(Iterable[addnodes.production], node) - for production in productionlist: - names.append(production['tokenname']) + names = (production['tokenname'] for production in productionlist) maxlen = max(len(name) for name in names) lastname = None for production in productionlist: diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py index 3c7185a3720..902f29ca213 100644 --- a/sphinx/writers/manpage.py +++ b/sphinx/writers/manpage.py @@ -272,12 +272,10 @@ def depart_seealso(self, node: Element) -> None: def visit_productionlist(self, node: Element) -> None: self.ensure_eol() - names = [] self.in_productionlist += 1 self.body.append('.sp\n.nf\n') productionlist = cast(Iterable[addnodes.production], node) - for production in productionlist: - names.append(production['tokenname']) + names = (production['tokenname'] for production in productionlist) maxlen = max(len(name) for name in names) lastname = None for production in productionlist: diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index 64f0d122522..dd19d040c79 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -1291,11 +1291,10 @@ def unknown_departure(self, node: Node) -> None: def visit_productionlist(self, node: Element) -> None: self.visit_literal_block(None) - names = [] productionlist = cast(Iterable[addnodes.production], node) - for production in productionlist: - names.append(production['tokenname']) + names = (production['tokenname'] for production in productionlist) maxlen = max(len(name) for name in names) + for production in productionlist: if production['tokenname']: for id in production.get('ids'): diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py index 521c2191580..ce3e2c91548 100644 --- a/sphinx/writers/text.py +++ b/sphinx/writers/text.py @@ -749,10 +749,8 @@ def depart_caption(self, node: Element) -> None: def visit_productionlist(self, node: Element) -> None: self.new_state() - names = [] productionlist = cast(Iterable[addnodes.production], node) - for production in productionlist: - names.append(production['tokenname']) + names = (production['tokenname'] for production in productionlist) maxlen = max(len(name) for name in names) lastname = None for production in productionlist: