ruff: Enable B023 Function definition does not bind loop variable.

Python’s loop scoping is misdesigned, resulting in a very common
gotcha for functions that close over loop variables [1].  The general
problem is so bad that even the Go developers plan to break
compatibility in order to fix the same design mistake in their
language [2].

Enable the Ruff rule function-uses-loop-variable (B023) [3], which
conservatively prohibits functions from binding loop variables at all.

[1] https://docs.python-guide.org/writing/gotchas/#late-binding-closures
[2] https://go.dev/s/loopvar-design
[3] https://beta.ruff.rs/docs/rules/function-uses-loop-variable/

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg
2023-04-12 17:05:54 -07:00
committed by Tim Abbott
parent cf4791264c
commit 6988622fe8
11 changed files with 143 additions and 92 deletions

View File

@@ -489,6 +489,20 @@ def validate(fn: Optional[str] = None, text: Optional[str] = None) -> List[Token
def ensure_matching_indentation(fn: str, tokens: List[Token], lines: List[str]) -> None:
def has_bad_indentation() -> bool:
is_inline_tag = start_tag in HTML_INLINE_TAGS and start_token.kind == "html_start"
if end_line > start_line + 1:
if is_inline_tag:
end_row_text = lines[end_line - 1]
if end_row_text.lstrip().startswith(end_token.s) and end_col != start_col:
return True
else:
if end_col != start_col:
return True
return False
for token in tokens:
if token.start_token is None:
continue
@@ -503,20 +517,6 @@ def ensure_matching_indentation(fn: str, tokens: List[Token], lines: List[str])
end_line = end_token.line
end_col = end_token.col
def has_bad_indentation() -> bool:
is_inline_tag = start_tag in HTML_INLINE_TAGS and start_token.kind == "html_start"
if end_line > start_line + 1:
if is_inline_tag:
end_row_text = lines[end_line - 1]
if end_row_text.lstrip().startswith(end_token.s) and end_col != start_col:
return True
else:
if end_col != start_col:
return True
return False
if has_bad_indentation():
raise TemplateParserError(
f"""