From 233a58fcb14ce7f45336cc9195dfc7c1bc2a5b85 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 9 Jun 2026 11:08:39 -0400 Subject: [PATCH] Fix ty errors for missing generic parameters (#7326) Mostly these errors were around `dict` missing arguments, and they are almost always `[str, Any]`. But a real thorn here was `xml.etree.ElementTree.Element`. `ty` insists that this is a generic type, and indeed it appears to be one, or becoming one, in some python version. But it is not generic in python 3.12. So we are stuck in an unsolvable land where: - `ty` gives an error unless you write `[str]` on the type, because it thinks it is generic. - python3.12 gives an error if you do write `[str]` on the type, because it thinks it is not generic. Forcing `ty` to target exactly python 3.12 does not help. So I have just used a linter-ignore comment on that line. --- github_tools/github_helpers.py | 12 ++++++------ github_tools/pr_comments.py | 14 +++++++------- scripts/bench_runner.py | 16 ++++++++-------- scripts/fix_cc_deps.py | 5 ++++- toolchain/runtimes/configure_cmake_file_impl.py | 2 +- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/github_tools/github_helpers.py b/github_tools/github_helpers.py index 23ca7816ffce..6f8a7d9872db 100644 --- a/github_tools/github_helpers.py +++ b/github_tools/github_helpers.py @@ -12,7 +12,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception import argparse import os from collections.abc import Generator -from typing import Optional, cast +from typing import Any, Optional, cast # https://pypi.org/project/gql/ import gql @@ -56,11 +56,11 @@ class Client: self._client = gql.Client(transport=transport) def execute( - self, query: str, variable_values: Optional[dict] = None - ) -> dict: + self, query: str, variable_values: Optional[dict[str, Any]] = None + ) -> dict[str, Any]: """Runs a query.""" return cast( - dict, + dict[str, Any], self._client.execute( gql.gql(query), variable_values=variable_values ), @@ -70,8 +70,8 @@ class Client: self, query: str, path: tuple[str, ...], - first_page: Optional[dict] = None, - ) -> Generator[dict, None, None]: + first_page: Optional[dict[str, Any]] = None, + ) -> Generator[dict[str, Any], None, None]: """Runs a query with pagination. Arguments: diff --git a/github_tools/pr_comments.py b/github_tools/pr_comments.py index 0c81150b52b0..52a204f822b0 100755 --- a/github_tools/pr_comments.py +++ b/github_tools/pr_comments.py @@ -129,7 +129,7 @@ class _Comment: self.body = body @staticmethod - def from_raw_comment(raw_comment: dict) -> "_Comment": + def from_raw_comment(raw_comment: dict[str, Any]) -> "_Comment": """Creates the comment from a raw comment dict.""" return _Comment( raw_comment["author"]["login"], @@ -176,7 +176,7 @@ class _Comment: class _PRComment(_Comment): """A comment on the top-level PR.""" - def __init__(self, raw_comment: dict): + def __init__(self, raw_comment: dict[str, Any]): super().__init__( raw_comment["author"]["login"], raw_comment["createdAt"], @@ -195,7 +195,7 @@ class _PRComment(_Comment): class _Thread: """A review thread on a line of code.""" - def __init__(self, parsed_args: argparse.Namespace, thread: dict): + def __init__(self, parsed_args: argparse.Namespace, thread: dict[str, Any]): self.is_resolved: bool = thread["isResolved"] comments = thread["comments"]["nodes"] @@ -347,7 +347,7 @@ def _query( def _accumulate_pr_comment( parsed_args: argparse.Namespace, comments: list[_PRComment], - raw_comment: dict, + raw_comment: dict[str, Any], ) -> None: """Collects top-level comments and reviews.""" # Elide reviews that have no top-level comment body. @@ -358,7 +358,7 @@ def _accumulate_pr_comment( def _accumulate_thread( parsed_args: argparse.Namespace, threads_by_path: dict[str, list[_Thread]], - raw_thread: dict, + raw_thread: dict[str, Any], ) -> None: """Adds threads to threads_by_path for later sorting.""" thread = _Thread(parsed_args, raw_thread) @@ -387,10 +387,10 @@ def _accumulate_thread( def _paginate( field_name: str, - accumulator: Callable[[argparse.Namespace, Any, dict], None], + accumulator: Callable[[argparse.Namespace, Any, dict[str, Any]], None], parsed_args: argparse.Namespace, client: github_helpers.Client, - main_result: dict, + main_result: dict[str, Any], output: Any, ) -> None: """Paginates through the given field_name, accumulating results.""" diff --git a/scripts/bench_runner.py b/scripts/bench_runner.py index 60141e791534..dd49af09cc85 100755 --- a/scripts/bench_runner.py +++ b/scripts/bench_runner.py @@ -73,7 +73,7 @@ from collections import defaultdict from dataclasses import dataclass, field from enum import Enum from pathlib import Path -from typing import Optional, override +from typing import Any, Optional, override import numpy as np # type: ignore import scipy as sp # type: ignore @@ -687,7 +687,7 @@ def run_benchmark_binary( specific_args: list[str], num_runs: int, console: Console, -) -> list[dict]: +) -> list[dict[str, Any]]: """Runs a benchmark binary multiple times and collects results. The results are parsed out of the JSON output from each run, and returned as @@ -741,7 +741,7 @@ def run_benchmark_binary( def print_run_context( console: Console, num_runs: int, - exp_runs: list[dict], + exp_runs: list[dict[str, Any]], has_baseline: bool, ) -> None: """Prints the context from the benchmark runs. @@ -778,8 +778,8 @@ def print_run_context( def get_benchmark_names_and_metrics( console: Console, parsed_args: argparse.Namespace, - exp_runs: list[dict], - base_runs: list[dict], + exp_runs: list[dict[str, Any]], + base_runs: list[dict[str, Any]], ) -> tuple[list[str], list[str]]: """Extracts benchmark names and metrics from benchmark run results. @@ -853,8 +853,8 @@ def get_benchmark_names_and_metrics( def collect_benchmark_metrics( benchmark_names: list[str], metrics: list[str], - exp_runs: list[dict], - base_runs: list[dict], + exp_runs: list[dict[str, Any]], + base_runs: list[dict[str, Any]], comp_mapping: ComparableBenchmarkMapping, ) -> dict[str, dict[str, BenchmarkRunMetrics]]: """Collects and organizes all benchmark metrics from raw run data. @@ -1071,7 +1071,7 @@ def main() -> None: # Run the benchmark(s) and collect the results into a data structure for # processing. num_runs = parsed_args.runs - base_runs: list[dict] = [] + base_runs: list[dict[str, Any]] = [] has_baseline = bool(parsed_args.base_benchmark) if has_baseline: base_runs = run_benchmark_binary( diff --git a/scripts/fix_cc_deps.py b/scripts/fix_cc_deps.py index 23aed858dea6..b97c8ab139b2 100755 --- a/scripts/fix_cc_deps.py +++ b/scripts/fix_cc_deps.py @@ -113,7 +113,10 @@ def remap_file(label: str) -> str: return EXTERNAL_REPOS[repo].remap(path) -def get_bazel_list(list_child: ElementTree.Element, is_file: bool) -> set[str]: +def get_bazel_list( + list_child: ElementTree.Element, # ty: ignore[missing-type-argument] + is_file: bool, +) -> set[str]: """Returns the contents of a bazel list. The return will normally be the full label, unless `is_file` is set, in diff --git a/toolchain/runtimes/configure_cmake_file_impl.py b/toolchain/runtimes/configure_cmake_file_impl.py index 80d362f59d5a..d9b058962b57 100644 --- a/toolchain/runtimes/configure_cmake_file_impl.py +++ b/toolchain/runtimes/configure_cmake_file_impl.py @@ -55,7 +55,7 @@ def _is_cmake_true(value: str) -> bool: def _substitute_variables(text: str, defines: Dict[str, str]) -> str: """Substitutes @VAR@ and ${VAR} style variables in a string.""" - def repl(m: re.Match) -> str: + def repl(m: re.Match[str]) -> str: return defines.get(str(m.group(1)), "") return re.sub(