fix: clear the raw error flag on each run

--verbose set it and no run cleared it, so a later run in the same process ended its clock message with the raw SSL text. Also: --target named again in its refusal, three names mypy read as another type, a semicolon and a tooling file named in test comments.
This commit is contained in:
Abdessamad Derraz committed 2026-11-10 08:43:20 +01:00
1 parent 8e15f94ed1
commit e8e2215a49
8 files changed
+45 -35

No files matched your search

+1 -1
View File
@@ -16,7 +16,7 @@
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
# the site's build rewrites this line there (scripts/sitebootstrap.py).
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
$defaultInstallSha256 = "7a9074e972e7247ab3fbe3486624a4eacf6b0d090aa6d754f95aef03a93f6faf"
$defaultInstallSha256 = "97cd447f646ffe259805b98bfbdc98b2d5c63acccd823480dadfe331005208f5"
# The pin above refuses any changed byte: this cap only stops a body that
# cannot be the installer (a sign-in portal's page) before it is hashed.
$maximumInstallerBytes = 8MB
+14 -10
View File
@@ -4742,7 +4742,7 @@ def fetch_targets(plat: str) -> "dict | None":
if LOCAL.offline:
source = (f"{LOCAL.pack.name} carries none" if LOCAL.pack is not None
else f"{offline_named()} makes no request")
print(f"Error: no {display_name(plat)} board list here ({source}). Put "
print(f"Error: --target needs the {display_name(plat)} board list ({source}). Put "
f"install/targets/{plat}.json beside the --manifest file, or go online.",
file=sys.stderr)
sys.exit(2)
@@ -7226,15 +7226,15 @@ def _report_outcome(
say(f"BIOS folder: {_locations(paths)}")
for line in kept:
say(line)
left = [entry for entry in omitted_entries or []
if entry.get("reason") != "no_save_directory"]
skipped = [entry for entry in omitted_entries or []
if entry.get("reason") != "no_save_directory"]
if omitted > len(unplaced) and OUTPUT.verbose:
for line in _omission_lines(omitted - len(unplaced), left,
for line in _omission_lines(omitted - len(unplaced), skipped,
Path(paths[0]) if len(paths) == 1 else None):
say(line)
elif omitted > len(unplaced) and any(entry.get("required") for entry in left):
elif omitted > len(unplaced) and any(entry.get("required") for entry in skipped):
# A file an emulator cannot start without is no detail: counted.
say(needed_absent_words(sum(1 for entry in left if entry.get("required")),
say(needed_absent_words(sum(1 for entry in skipped if entry.get("required")),
"--verbose"))
# RomM's scan is the step after the install: the other hints say how to
# install less, a detail.
@@ -11347,9 +11347,9 @@ def plan_games(plat: str, bios_path: Path, manifest: dict, folder: Path | None =
continue
setup = setup or candidate
if folder is None:
found = games_root(candidate, bios_path)
if found is not None:
setup, root = candidate, found
found_root = games_root(candidate, bios_path)
if found_root is not None:
setup, root = candidate, found_root
break
if root is None:
return None
@@ -14250,8 +14250,12 @@ def main() -> None:
_INVOCATION.os_type = detect_os()
parser = build_parser()
args = parser.parse_args()
# Each run says it from its own options: a run with --verbose before it
# in the same process left every later message with its raw cause.
if args.verbose:
_RAW_ERRORS.set()
else:
_RAW_ERRORS.clear()
if args.cores_dir:
args.installed_cores = True
if args.yes:
@@ -23783,7 +23787,7 @@ def tui_view(state: TuiState, cols: int, rows: int) -> list[str]:
if cols < TUI_MIN_COLS or rows < TUI_MIN_ROWS:
# How large, and how large it is now: "larger" alone left the
# reader resizing by guess.
lines = [_styled("")] * rows
lines: list[str] = [_styled("")] * rows
said = [fit(text, cols) for text in (
"Make the window larger:",
f"{TUI_MIN_COLS}x{TUI_MIN_ROWS} or more, now {cols}x{rows}")][:rows]
+1 -1
View File
@@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins
# curl or wget stop on a cut transfer before the hash is read: the site's
# build rewrites this line there (scripts/sitebootstrap.py).
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
DEFAULT_INSTALL_SHA256="7a9074e972e7247ab3fbe3486624a4eacf6b0d090aa6d754f95aef03a93f6faf"
DEFAULT_INSTALL_SHA256="97cd447f646ffe259805b98bfbdc98b2d5c63acccd823480dadfe331005208f5"
# The pin above refuses any changed byte: this cap only stops a body that
# cannot be the installer (a sign-in portal's page) before it is hashed.
MAX_INSTALLER_BYTES=8388608
+8 -8
View File
@@ -27,8 +27,8 @@
{
"dest": "roms/ports/retrobios/install.py",
"repo_path": "install.py",
"size": 1162136,
"sha256": "7a9074e972e7247ab3fbe3486624a4eacf6b0d090aa6d754f95aef03a93f6faf",
"size": 1162373,
"sha256": "97cd447f646ffe259805b98bfbdc98b2d5c63acccd823480dadfe331005208f5",
"executable": false
},
{
@@ -71,8 +71,8 @@
"muos": {
"archive": {
"dest": "ARCHIVE/RetroBIOS.muxapp",
"size": 1215761,
"sha256": "112292319b9b3181bfd124ec211512b0f8d507b46bf878e1f84552c4980bc260"
"size": 1215998,
"sha256": "996a6e24cc5e2d067d86f8f368313e8afd1ba17391b3c595cb8f72e73b208433"
},
"members": [
{
@@ -92,8 +92,8 @@
{
"name": "RetroBIOS/install.py",
"repo_path": "install.py",
"size": 1162136,
"sha256": "7a9074e972e7247ab3fbe3486624a4eacf6b0d090aa6d754f95aef03a93f6faf",
"size": 1162373,
"sha256": "97cd447f646ffe259805b98bfbdc98b2d5c63acccd823480dadfe331005208f5",
"executable": false
},
{
@@ -166,8 +166,8 @@
{
"dest": ".config/modules/retrobios/install.py",
"repo_path": "install.py",
"size": 1162136,
"sha256": "7a9074e972e7247ab3fbe3486624a4eacf6b0d090aa6d754f95aef03a93f6faf",
"size": 1162373,
"sha256": "97cd447f646ffe259805b98bfbdc98b2d5c63acccd823480dadfe331005208f5",
"executable": false
},
{
-10
View File
@@ -78,7 +78,6 @@ install.py:0: error: Cannot infer type of lambda [misc]
install.py:0: error: Cannot infer type of lambda [misc]
install.py:0: error: Cannot infer type of lambda [misc]
install.py:0: error: Cannot infer type of lambda [misc]
install.py:0: error: Generator has incompatible item type "int"; expected "bool" [misc]
install.py:0: error: Incompatible default for argument "after" (default has type "tuple[()]", argument has type "list[Any]") [assignment]
install.py:0: error: Incompatible default for argument "copied" (default has type "tuple[()]", argument has type "list[str]") [assignment]
install.py:0: error: Incompatible default for argument "cores" (default has type "tuple[()]", argument has type "list[str]") [assignment]
@@ -92,7 +91,6 @@ install.py:0: error: Incompatible return value type (got "IO[bytes]", expected "
install.py:0: error: Incompatible return value type (got "Optional[Path]", expected "Path") [return-value]
install.py:0: error: Incompatible return value type (got "Union[Any, object]", expected "str") [return-value]
install.py:0: error: Incompatible return value type (got "list[TuiLine]", expected "list[str]") [return-value]
install.py:0: error: Incompatible return value type (got "list[TuiLine]", expected "list[str]") [return-value]
install.py:0: error: Incompatible return value type (got "list[tuple[Optional[str], str]]", expected "list[tuple[str, str]]") [return-value]
install.py:0: error: Incompatible return value type (got "object", expected "dict[Any, Any]") [return-value]
install.py:0: error: Incompatible types in "yield" (actual type "IO[bytes]", expected type "BinaryIO") [misc]
@@ -107,7 +105,6 @@ install.py:0: error: Incompatible types in assignment (expression has type "Game
install.py:0: error: Incompatible types in assignment (expression has type "Optional[Progress]", variable has type "Progress") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "Optional[frozenset[Any]]", variable has type "Optional[tuple[int, str]]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "Optional[frozenset[Any]]", variable has type "list[str]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "Optional[int]", variable has type "int") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "str") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "Path", variable has type "bool") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "Union[Any, bool]", variable has type "str") [assignment]
@@ -136,9 +133,6 @@ install.py:0: error: Item "None" of "Optional[BinaryIO]" has no attribute "trunc
install.py:0: error: Item "None" of "Optional[Element[str]]" has no attribute "iter" [union-attr]
install.py:0: error: Item "None" of "Optional[PackSource]" has no attribute "name" [union-attr]
install.py:0: error: Item "None" of "Optional[PackSource]" has no attribute "name" [union-attr]
install.py:0: error: Item "None" of "Optional[Path]" has no attribute "__iter__" (not iterable) [union-attr]
install.py:0: error: Item "None" of "Optional[Path]" has no attribute "__iter__" (not iterable) [union-attr]
install.py:0: error: Item "None" of "Optional[Path]" has no attribute "append" [union-attr]
install.py:0: error: Item "None" of "Optional[Path]" has no attribute "read_text" [union-attr]
install.py:0: error: Item "None" of "Optional[Path]" has no attribute "write_text" [union-attr]
install.py:0: error: Item "None" of "Optional[Terminal]" has no attribute "stream" [union-attr]
@@ -147,9 +141,6 @@ install.py:0: error: Item "None" of "Optional[Terminal]" has no attribute "strea
install.py:0: error: Item "None" of "Optional[Terminal]" has no attribute "stream" [union-attr]
install.py:0: error: Item "None" of "Optional[TuiHits]" has no attribute "frame" [union-attr]
install.py:0: error: Item "None" of "Optional[TuiHits]" has no attribute "shown" [union-attr]
install.py:0: error: Item "Path" of "Optional[Path]" has no attribute "__iter__" (not iterable) [union-attr]
install.py:0: error: Item "Path" of "Optional[Path]" has no attribute "__iter__" (not iterable) [union-attr]
install.py:0: error: Item "Path" of "Optional[Path]" has no attribute "append" [union-attr]
install.py:0: error: List comprehension has incompatible type List[object]; expected List[str] [misc]
install.py:0: error: List item 0 has incompatible type "int"; expected "FolderIndex" [list-item]
install.py:0: error: List item 0 has incompatible type "tuple[Optional[str], str]"; expected "tuple[str, str]" [list-item]
@@ -161,7 +152,6 @@ install.py:0: error: Module has no attribute "LK_NBLCK" [attr-defined]
install.py:0: error: Module has no attribute "OpenKey" [attr-defined]
install.py:0: error: Module has no attribute "QueryValueEx" [attr-defined]
install.py:0: error: Module has no attribute "locking" [attr-defined]
install.py:0: error: Name "found" already defined on line 0 [no-redef]
install.py:0: error: Name "top" already defined on line 0 [no-redef]
install.py:0: error: Need type annotation for "removed" (hint: "removed: list[<type>] = ...") [var-annotated]
install.py:0: error: Need type annotation for "words" (hint: "words: list[<type>] = ...") [var-annotated]
+18
View File
@@ -7834,5 +7834,23 @@ class TheNextStepFitsWhereTheInstallerRuns(unittest.TestCase):
install.NEXT_ON_CARD)
class EachRunSaysErrorsFromItsOwnOptions(unittest.TestCase):
"""--verbose set the raw-cause flag and nothing cleared it: a later run
in the same process ended its clock message with the raw SSL text."""
def test_a_run_without_verbose_clears_it(self):
install._RAW_ERRORS.set()
self.addCleanup(install._RAW_ERRORS.clear)
with unittest.mock.patch.object(sys, "argv",
["install.py", "--list-platforms", "--offline"]), \
contextlib.redirect_stdout(io.StringIO()), \
contextlib.redirect_stderr(io.StringIO()):
try:
install.main()
except SystemExit:
pass
self.assertFalse(install._RAW_ERRORS.is_set())
if __name__ == "__main__":
unittest.main()
+2 -4
View File
@@ -55,10 +55,8 @@ JOURNEY_KEYS = {
# Words each journey's screens show by default, summed over the screens it
# stops on, and the most one screen of the default path may show (owner,
# 2026-11-09: a beginner lost the important line in text). A path is no
# word: its length is the machine's. The counts from before the Details
# screen took the plan's and the result's notes are in claudedocs/
# user_research/installer_ux/phase1_measure.md. A change that adds words
# raises a number here and says why.
# word: its length is the machine's. A change that adds words raises a
# number here and says why.
JOURNEY_WORDS = {
"first_install": 63,
"card_with_games": 106,
+1 -1
View File
@@ -14934,7 +14934,7 @@ class GamesEndToEnd(unittest.TestCase):
# The most words each screen may show by default, one count per size of
# SIZES (owner, 2026-11-09: a beginner lost the important line in text). A
# path is no word. The plan, Confirm and the result say what happens, where
# and what next; their counts, notes and commands wait on Details. A list
# and what next, and their counts, notes and commands wait on Details. A list
# shows more rows on a taller window. A change that adds words to a screen
# raises its numbers here and says why: the result names its failed files
# (review of 2026-11-10), what the user acts on.