From 6f19719df22d5aa60cc41925e98f7cb0a223b665 Mon Sep 17 00:00:00 2001 From: sora <2075279110@qq.com> Date: Mon, 14 Sep 2026 06:24:10 +0000 Subject: [PATCH] Fix UnboundLocalError on the report-reuse path The progress-reporter setup lived inside the generation branch; reuse skipped it but the success path still advanced the overall bar -> 'cannot access local variable progress_reporter'. Setup now runs for every path (reuse included). Co-Authored-By: Claude --- evalharness/cli.py | 56 +++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/evalharness/cli.py b/evalharness/cli.py index 7d0ffa9..b8ea9b8 100644 --- a/evalharness/cli.py +++ b/evalharness/cli.py @@ -755,35 +755,39 @@ def _cmd_eval_run(args) -> int: except Exception: pass # unreadable/stale report: score normally + # progress reporter setup runs for EVERY path (report reuse + # included): the success path advances the overall bar even when + # nothing was generated -- previously this block lived inside the + # generation branch and reuse blew up with UnboundLocalError + progress_reporter = None + if args.progress and model_spec: + from evalharness.progress import PROGRESS_REGISTRY + + _pname = getattr(args, 'progress_plugin', 'rich') \ + if args.progress is True else args.progress + try: + _P = PROGRESS_REGISTRY.get(_pname) + except KeyError: + raise SystemExit(f'unknown progress plugin {_pname!r}; ' + f'available: {", ".join(PROGRESS_REGISTRY.names())}') + if _P is not None: + # share ONE console: phase lines printed by another + # writer during the live bar interleave incorrectly. + # One reporter for the WHOLE run: overall bar (which + # benchmark) + sample bar (which sample), reused per + # benchmark via reset_samples(). + if _shared_reporter is None and ( + _pname == 'plain' or console.is_terminal): + # live bars only on a real terminal: through pipes + # (| grep, > log) rich's refresh thread misbehaves + # and stalls the run -- plain phases instead + _shared_reporter = _P(console=console) + _shared_reporter.owned_externally = True + progress_reporter = _shared_reporter + if report is None and model_spec: # generate + score in one go from evalharness.model import run_eval - progress_reporter = None - if args.progress: - from evalharness.progress import PROGRESS_REGISTRY - - _pname = getattr(args, 'progress_plugin', 'rich') \ - if args.progress is True else args.progress - try: - _P = PROGRESS_REGISTRY.get(_pname) - except KeyError: - raise SystemExit(f'unknown progress plugin {_pname!r}; ' - f'available: {", ".join(PROGRESS_REGISTRY.names())}') - if _P is not None: - # share ONE console: phase lines printed by another - # writer during the live bar interleave incorrectly. - # One reporter for the WHOLE run: overall bar (which - # benchmark) + sample bar (which sample), reused per - # benchmark via reset_samples(). - if _shared_reporter is None and ( - _pname == 'plain' or console.is_terminal): - # live bars only on a real terminal: through pipes - # (| grep, > log) rich's refresh thread misbehaves - # and stalls the run -- plain phases instead - _shared_reporter = _P(console=console) - _shared_reporter.owned_externally = True - progress_reporter = _shared_reporter - def status_callback(msg, _idx=i + 1, _name=name, _reporter=progress_reporter,