1515import json
1616import subprocess
1717from collections import Counter , defaultdict
18+ from collections .abc import Iterator
1819from datetime import UTC , datetime
1920from pathlib import Path
21+ from typing import Any
22+
23+ from app .validate import DATA_DIR
2024
2125from . import crossref , http_check , ledger , offline , promote
2226from .common import (
@@ -50,7 +54,6 @@ def _changed_data_slugs() -> set[str]:
5054 package lives in TechAPI (data alongside) or TechEngine (data in a separate
5155 TechAPI checkout pointed at by TECHAPI_DATA_DIR).
5256 """
53- from .common import DATA_DIR
5457 try :
5558 out = subprocess .run (
5659 ["git" , "diff" , "--name-only" , "origin/main" , "HEAD" , "--" , "data/" ],
@@ -73,7 +76,7 @@ def _iter_selected(
7376 unverified_only : bool ,
7477 changed : set [str ] | None ,
7578 limit : int | None ,
76- ):
79+ ) -> Iterator [ Record ] :
7780 count = 0
7881 for cat in categories :
7982 for rec in records [cat ]:
@@ -101,8 +104,8 @@ def cmd_score(args: argparse.Namespace) -> int:
101104 write_cache = full_scope and not args .no_cache
102105
103106 # category -> band -> count
104- hist : dict [str , Counter ] = defaultdict (Counter )
105- hard_flags : Counter = Counter ()
107+ hist : dict [str , Counter [ str ] ] = defaultdict (Counter )
108+ hard_flags : Counter [ str ] = Counter ()
106109 entries = []
107110 scored = 0
108111
@@ -133,7 +136,9 @@ def cmd_score(args: argparse.Namespace) -> int:
133136 return 0
134137
135138
136- def _print_histogram (hist , scored , hard_flags , wrote_cache ) -> None :
139+ def _print_histogram (
140+ hist : dict [str , Counter [str ]], scored : int , hard_flags : Counter [str ], wrote_cache : bool
141+ ) -> None :
137142 print (f"Tier 0 offline score — { scored } record(s)\n " )
138143 header = f"{ 'category' :<12} { 'green' :>8} { 'yellow' :>8} { 'red' :>8} { 'total' :>8} "
139144 print (header )
@@ -185,7 +190,7 @@ def _band_bar(green: int, yellow: int, red: int, width: int = 12) -> str:
185190 return "🟩" * counts ["🟩" ] + "🟨" * counts ["🟨" ] + "🟥" * counts ["🟥" ]
186191
187192
188- def _print_markdown (hist , scored , hard_flags ) -> None :
193+ def _print_markdown (hist : dict [ str , Counter [ str ]], scored : int , hard_flags : Counter [ str ] ) -> None :
189194 """Readable PR-comment report: a Mermaid pie of the overall band split (GitHub
190195 renders it natively) + a per-category table with a proportional colored bar."""
191196 if scored == 0 :
@@ -247,7 +252,7 @@ def cmd_status(args: argparse.Namespace) -> int:
247252 _ , _ , soc_release = foreign_key_sets (records )
248253 now_year = offline .now_year_today ()
249254
250- by_category : dict [str , dict ] = {}
255+ by_category : dict [str , dict [ str , Any ] ] = {}
251256 tot = ver = g = y = r = 0
252257 for cat in CATEGORIES :
253258 ct = cv = cg = cy = cr = 0
@@ -309,8 +314,8 @@ def cmd_report(args: argparse.Namespace) -> int:
309314 if not SCORES_PATH .exists ():
310315 print ("no scores cache — run `python -m app.verify score` first" )
311316 return 0
312- hist : dict [str , Counter ] = defaultdict (Counter )
313- hard_flags : Counter = Counter ()
317+ hist : dict [str , Counter [ str ] ] = defaultdict (Counter )
318+ hard_flags : Counter [ str ] = Counter ()
314319 for entry in ledger .iter_entries (SCORES_PATH ):
315320 cat = entry .get ("category" )
316321 t0 = entry .get ("tier0" , {})
@@ -324,7 +329,7 @@ def cmd_report(args: argparse.Namespace) -> int:
324329 _print_histogram (hist , scored , hard_flags , wrote_cache = False )
325330
326331 # Promotion decisions live in the git-tracked ledger.
327- promoted : Counter = Counter ()
332+ promoted : Counter [ str ] = Counter ()
328333 for (cat , _slug ), entry in ledger .latest_by_key ().items ():
329334 if entry .get ("decision" ) == "promote" :
330335 promoted [cat ] += 1
@@ -335,7 +340,10 @@ def cmd_report(args: argparse.Namespace) -> int:
335340 return 0
336341
337342
338- def _ranked_unverified (records , soc_release , now_year , categories ):
343+ def _ranked_unverified (
344+ records : dict [str , list [Record ]], soc_release : dict [str , str ], now_year : int ,
345+ categories : tuple [str , ...],
346+ ) -> list [Record ]:
339347 """Unverified records of the given categories, scored, highest-confidence first."""
340348 scored = []
341349 for cat in categories :
@@ -394,7 +402,7 @@ def cmd_check_urls(args: argparse.Namespace) -> int:
394402 return 0
395403
396404
397- def _summarize_cache (cache , targets ) -> None :
405+ def _summarize_cache (cache : dict [ str , dict [ str , Any ]], targets : list [ str ] ) -> None :
398406 from collections import Counter
399407 alive = sum (1 for u in targets if cache .get (u , {}).get ("alive" ))
400408 dead = sum (1 for u in targets if u in cache and not cache [u ].get ("alive" ))
@@ -438,7 +446,7 @@ def cmd_crossref(args: argparse.Namespace) -> int:
438446 "exact_heading" : res .exact_heading , "matched_url" : res .matched_url ,
439447 })
440448 if new_entries :
441- cache .update ({(e ["category" ], e ["slug" ]): e for e in new_entries })
449+ cache .update ({(str ( e ["category" ]), str ( e ["slug" ]) ): e for e in new_entries })
442450 ledger .replace_all (list (cache .values ()), promote .CROSSREF_CACHE_PATH )
443451
444452 print (f"crossref: examined { len (targets )} record(s)" )
@@ -556,7 +564,7 @@ def cmd_pr(args: argparse.Namespace) -> int:
556564 urls = sorted ({u for r , _ in scored
557565 for u in r .data .get ("source_urls" , []) if isinstance (u , str )})
558566 ts = _now_iso ()
559- url_cache : dict [str , dict ] = {}
567+ url_cache : dict [str , dict [ str , Any ] ] = {}
560568 try :
561569 for res in http_check .check_urls (urls , min_interval = 0.5 ):
562570 url_cache [res .url ] = http_check .result_to_entry (res , ts )
@@ -616,8 +624,8 @@ def cmd_pr(args: argparse.Namespace) -> int:
616624 print ()
617625
618626 # Full-dataset Tier 0 baseline (always).
619- hist : dict [str , Counter ] = defaultdict (Counter )
620- hard_flags : Counter = Counter ()
627+ hist : dict [str , Counter [ str ] ] = defaultdict (Counter )
628+ hard_flags : Counter [ str ] = Counter ()
621629 scored_n = 0
622630 for cat in CATEGORIES :
623631 for rec in records [cat ]:
@@ -696,4 +704,5 @@ def main(argv: list[str] | None = None) -> int:
696704 configure_stdout ()
697705 parser = build_parser ()
698706 args = parser .parse_args (argv )
699- return args .func (args )
707+ result : int = args .func (args )
708+ return result
0 commit comments