From 66f598decb380ec6600663d51e99452e8d42416f Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 23 Jul 2026 16:36:27 +0000 Subject: [PATCH 1/4] ruff rules --- .config/ruff.toml | 4 ++++ AGENTS.md | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.config/ruff.toml b/.config/ruff.toml index c74669ae..f037580c 100644 --- a/.config/ruff.toml +++ b/.config/ruff.toml @@ -62,8 +62,12 @@ ignore = [ "N999", # Ignoring this since we are using jinja templates in the directory path which will eventually turn into a valid module name. # TODO: make a task in downstream templates to remove this "S101", # We do not use the -o optimize flag, so it's fine to use `assert` in the main code. It's especially helpful for static typing "SIM102", # Nested if statements can be better analyzed by coverage detectors than compound statements + "SIM103", # Explicit if/else branches let the coverage checker track both paths, unlike evaluating an expression "SIM108", # Explicit if/else branches let the coverage checker track both paths, unlike a ternary + "SIM110", # Explicit if statements and loops let the coverage checker track both paths, unlike using `any` or `all` with a generator expression "SIM114", # Using `or` statements to simplify this would confuse the coverage checker + "SIM210", # Explicit if/else branches let the coverage checker track both paths, unlike evaluating an expression + "SIM401", # using dictionary getters to simplify this would inhibit the coverage checker from tracking both paths "TD002", # Adding author names to TODOs erodes shared ownership of codebase. Git history provides information about who originally created the TODO if that information is vitally needed "TD003", # Up to the author's judgement whether a TODO requires a link to an issue or not "TID252", # Sometimes it makes sense to use relative imports, that's a judgement call for us, not ruff diff --git a/AGENTS.md b/AGENTS.md index d7489b02..34347ed7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,12 +9,16 @@ This project is a Copier template used to generate other copier templates. It is - Comments should be used very rarely. Code should generally express its intent. - Never write a one-line docstring — either the name is sufficient or the behavior warrants a full explanation. - Don't sort or remove imports manually — pre-commit handles it. -- Always include type hints in Python -- Respect the pyrefly unused-call-result check; assign unneeded return values to `_` - Prefer keyword-only parameters (unless a very clear single-argument function): use `*` in Python signatures and destructured options objects in TypeScript. - When disabling a linting rule with an inline directive, provide a comment at the end of the line (or on the line above for tools that don't allow extra text after an inline directive) describing the reasoning for disabling the rule. - Avoid telling the type checker what a type is rather than letting it prove it. This includes type assertions (`as SomeType` in TypeScript, `cast()` in Python) and variable annotations that override inference. Prefer approaches that let the type checker verify the type itself: `isinstance`/`instanceof` narrowing, restructuring code so the correct type flows naturally, or using discriminated unions. When there is genuinely no alternative, add a comment explaining why the workaround is necessary and why it is safe. - Avoid `||` (TypeScript) or `or` (Python) in `if`/`elif` conditions, and avoid `x in ['a', 'b']`-style membership tests in implementation code — coverage tools treat these as a single branch, silently masking untested paths and producing false 100% branch coverage. Use separate `if`/`elif` branches instead so each condition is independently covered. + +### Python + +- Always include type hints. +- Respect the pyrefly unused-call-result check; assign unneeded return values to `_` +- Avoid `d.get(key, default)` — coverage tools see a function call, not a branch, so they can't tell whether both the found and fallback paths ran. Use `if key in d:` / `else` so each path is covered. - When filtering logic combines multiple `and`-joined guards (e.g. a null check alongside a value check), prefer a loop with explicit `if`/`continue` branches over a single-line comprehension. A compound boolean filter on one line hides individual branches from line coverage — each guard condition should be its own statement so missing test cases are surfaced. ## Testing From 47082d84da087cdffb75c45ec4e86c30e680d3ba Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 23 Jul 2026 16:48:23 +0000 Subject: [PATCH 2/4] phrasing --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 34347ed7..2d209e3e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,7 +18,7 @@ This project is a Copier template used to generate other copier templates. It is - Always include type hints. - Respect the pyrefly unused-call-result check; assign unneeded return values to `_` -- Avoid `d.get(key, default)` — coverage tools see a function call, not a branch, so they can't tell whether both the found and fallback paths ran. Use `if key in d:` / `else` so each path is covered. +- Prefer explicit `if`/`else` over one-line forms that collapse branches: a ternary, `d.get(key, default)`, returning a boolean expression `return b > 5`/`return bool(b)`. `coverage.py` tracks branches as line-to-line arcs, so a single-line expression hides the untaken path. - When filtering logic combines multiple `and`-joined guards (e.g. a null check alongside a value check), prefer a loop with explicit `if`/`continue` branches over a single-line comprehension. A compound boolean filter on one line hides individual branches from line coverage — each guard condition should be its own statement so missing test cases are surfaced. ## Testing From 2f688c5042e465b065315dc624c52a069e1ac33d Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 23 Jul 2026 16:51:53 +0000 Subject: [PATCH 3/4] loop --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 2d209e3e..bbcd203c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,7 +18,7 @@ This project is a Copier template used to generate other copier templates. It is - Always include type hints. - Respect the pyrefly unused-call-result check; assign unneeded return values to `_` -- Prefer explicit `if`/`else` over one-line forms that collapse branches: a ternary, `d.get(key, default)`, returning a boolean expression `return b > 5`/`return bool(b)`. `coverage.py` tracks branches as line-to-line arcs, so a single-line expression hides the untaken path. +- Prefer explicit `if`/`else` (or a `for` loop with `if`/`return`) over one-line forms that collapse branches: a ternary, `d.get(key, default)`, returning a boolean expression `return b > 5`/`return bool(b)`, or `any()`/`all()` over a generator in place of a loop. `coverage.py` tracks branches as line-to-line arcs, so a single-line expression hides the untaken path. - When filtering logic combines multiple `and`-joined guards (e.g. a null check alongside a value check), prefer a loop with explicit `if`/`continue` branches over a single-line comprehension. A compound boolean filter on one line hides individual branches from line coverage — each guard condition should be its own statement so missing test cases are surfaced. ## Testing From eaa8936481bc915e2927c51f83b5a89a22e1f106 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 23 Jul 2026 16:57:08 +0000 Subject: [PATCH 4/4] drop --- .config/ruff.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/.config/ruff.toml b/.config/ruff.toml index f037580c..61d486d4 100644 --- a/.config/ruff.toml +++ b/.config/ruff.toml @@ -66,7 +66,6 @@ ignore = [ "SIM108", # Explicit if/else branches let the coverage checker track both paths, unlike a ternary "SIM110", # Explicit if statements and loops let the coverage checker track both paths, unlike using `any` or `all` with a generator expression "SIM114", # Using `or` statements to simplify this would confuse the coverage checker - "SIM210", # Explicit if/else branches let the coverage checker track both paths, unlike evaluating an expression "SIM401", # using dictionary getters to simplify this would inhibit the coverage checker from tracking both paths "TD002", # Adding author names to TODOs erodes shared ownership of codebase. Git history provides information about who originally created the TODO if that information is vitally needed "TD003", # Up to the author's judgement whether a TODO requires a link to an issue or not