From dba63f7c9ed8dec8f381011db0b277b007b7856c Mon Sep 17 00:00:00 2001 From: xuxiongjian Date: Thu, 10 Sep 2026 10:26:00 +0800 Subject: [PATCH] Import Iterable in build.py, the annotations already use it build.py annotates chunks and ast_sources with Iterable but never imports it, so ruff reports four F821 on v8 and typing.get_type_hints() raises on _tier_replacement_sources, merge_raw_extraction and build_merge. Nothing breaks at import because `from __future__ import annotations` keeps the hints as strings. The added test walks build.py's own functions rather than the package: nx under if TYPE_CHECKING in cross_repo_calls.py, cross_repo_types.py and prs.py is unresolvable on purpose, while build.py imports every annotated name at module scope. (cherry picked from commit c315a15c24816265e2c9d7acbc64166be8d8e3ad) --- graphify/build.py | 1 + tests/test_build.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/graphify/build.py b/graphify/build.py index d247b2962..c5d5a4b19 100644 --- a/graphify/build.py +++ b/graphify/build.py @@ -27,6 +27,7 @@ import os import re import sys import unicodedata +from collections.abc import Iterable from pathlib import Path import networkx as nx from .ids import make_id, normalize_id as _normalize_id diff --git a/tests/test_build.py b/tests/test_build.py index a19ca48e9..c496873cb 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -1983,3 +1983,21 @@ def test_build_merge_explicit_ast_sources_argument(tmp_path): G1 = build_merge([sln_chunk], graph_path, dedup=False, root=root, ast_sources=["A.sln"]) assert "nuget_pkg" in G1, "ast_sources explicit arg must protect undispatched A.csproj" + + +def test_build_annotations_all_resolve(): + # build.py imports every annotated name at module scope -- no TYPE_CHECKING-only + # names -- so an unresolvable hint here means a missing import, not a lazy one. + import inspect + import typing + + from graphify import build as build_module + + unresolvable = [] + for name, obj in vars(build_module).items(): + if inspect.isfunction(obj) and obj.__module__ == build_module.__name__: + try: + typing.get_type_hints(obj) + except NameError as exc: + unresolvable.append(f"{name}: {exc}") + assert not unresolvable, "\n".join(unresolvable)