From 6cc646acd67f48fc5d3dd56982da37df34b16ca2 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sat, 7 Nov 2026 00:55:46 +0100 Subject: [PATCH] fix: type errors the merged batches brought The name step reused one variable for paths and for (path, md5, size) tuples, the standalone copies reused targets inside its own loop, and the WSL state read as object. Ten baseline entries no longer occur. --- install.ps1 | 2 +- install.py | 2 +- install.sh | 2 +- install/launchers/index.json | 16 ++++++++-------- mypy-baseline.txt | 10 ---------- scripts/common.py | 22 +++++++++++----------- scripts/generate_pack.py | 8 ++++---- 7 files changed, 26 insertions(+), 36 deletions(-) diff --git a/install.ps1 b/install.ps1 index b6ba50351..46ef83dfa 100644 --- a/install.ps1 +++ b/install.ps1 @@ -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 = "25a88f9a078717afbe34419481d222d2f6f42c4bf24b4ec64bc3faa9561ea01c" + $defaultInstallSha256 = "ee24f4f154e68d7d503f12e4816e3f1ff38f80159432093e4c6ed86411783ed7" $maximumInstallerBytes = 2MB $installerExit = 0 $installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null } diff --git a/install.py b/install.py index 05d0bc9d7..6613a0554 100644 --- a/install.py +++ b/install.py @@ -1202,7 +1202,7 @@ def _parse_os_release() -> dict[str, str]: # path and nothing Windows-side was ever found from WSL. # unasked: why Windows could not be asked for its folders, said once by # detection. -_WSL = {"active": False, "root": "/mnt", "unasked": ""} +_WSL: dict[str, Any] = {"active": False, "root": "/mnt", "unasked": ""} _WINDOWS_VARIABLES = ("USERPROFILE", "APPDATA", "LOCALAPPDATA", "ProgramFiles", "ProgramFiles(x86)") diff --git a/install.sh b/install.sh index 5bbfc4ecd..d5ee07167 100755 --- a/install.sh +++ b/install.sh @@ -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="25a88f9a078717afbe34419481d222d2f6f42c4bf24b4ec64bc3faa9561ea01c" +DEFAULT_INSTALL_SHA256="ee24f4f154e68d7d503f12e4816e3f1ff38f80159432093e4c6ed86411783ed7" MAX_INSTALLER_BYTES=2097152 cleanup() { diff --git a/install/launchers/index.json b/install/launchers/index.json index f40516460..44d04c39f 100644 --- a/install/launchers/index.json +++ b/install/launchers/index.json @@ -27,8 +27,8 @@ { "dest": "roms/ports/retrobios/install.py", "repo_path": "install.py", - "size": 1122406, - "sha256": "25a88f9a078717afbe34419481d222d2f6f42c4bf24b4ec64bc3faa9561ea01c", + "size": 1122422, + "sha256": "ee24f4f154e68d7d503f12e4816e3f1ff38f80159432093e4c6ed86411783ed7", "executable": false }, { @@ -71,8 +71,8 @@ "muos": { "archive": { "dest": "ARCHIVE/RetroBIOS.muxapp", - "size": 1176033, - "sha256": "05a543e24f2c996d79bea8c95d95789669b92574ad45ffe60df88eb4c80a553c" + "size": 1176049, + "sha256": "9ac4845d2a448ece2d421db3137c7aea6d636d0ecf6c92ed777630f47dd61021" }, "members": [ { @@ -92,8 +92,8 @@ { "name": "RetroBIOS/install.py", "repo_path": "install.py", - "size": 1122406, - "sha256": "25a88f9a078717afbe34419481d222d2f6f42c4bf24b4ec64bc3faa9561ea01c", + "size": 1122422, + "sha256": "ee24f4f154e68d7d503f12e4816e3f1ff38f80159432093e4c6ed86411783ed7", "executable": false }, { @@ -166,8 +166,8 @@ { "dest": ".config/modules/retrobios/install.py", "repo_path": "install.py", - "size": 1122406, - "sha256": "25a88f9a078717afbe34419481d222d2f6f42c4bf24b4ec64bc3faa9561ea01c", + "size": 1122422, + "sha256": "ee24f4f154e68d7d503f12e4816e3f1ff38f80159432093e4c6ed86411783ed7", "executable": false }, { diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 6399b243c..6031a5fe0 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -6,13 +6,10 @@ install.py:0: error: "bool" has no attribute "name" [attr-defined] install.py:0: error: "bool" has no attribute "parent" [attr-defined] install.py:0: error: "object" has no attribute "get" [attr-defined] install.py:0: error: "object" has no attribute "get" [attr-defined] -install.py:0: error: "object" has no attribute "rstrip" [attr-defined] install.py:0: error: "object" object is not iterable [misc] install.py:0: error: "object" object is not iterable [misc] install.py:0: error: "str" has no attribute "append" [attr-defined] install.py:0: error: "str" has no attribute "append" [attr-defined] -install.py:0: error: Argument 1 to "Path" has incompatible type "object"; expected "Union[str, PathLike[str]]" [arg-type] -install.py:0: error: Argument 1 to "Path" has incompatible type "object"; expected "Union[str, PathLike[str]]" [arg-type] install.py:0: error: Argument 1 to "_ZippedLookup" has incompatible type "Optional[FolderIndex]"; expected "FolderIndex" [arg-type] install.py:0: error: Argument 1 to "__iadd__" of "list" has incompatible type "Invocation"; expected "Iterable[str]" [arg-type] install.py:0: error: Argument 1 to "_digest_file" has incompatible type "Optional[Path]"; expected "Path" [arg-type] @@ -228,17 +225,11 @@ scripts/check_platform_folder.py:0: error: Incompatible types in assignment (exp scripts/check_release_assets.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Optional[str]"; expected "str" [arg-type] scripts/common.py:0: error: Argument "sha1_candidates" to "declared_hash_verdict" has incompatible type "list[str]"; expected "set[Any]" [arg-type] scripts/common.py:0: error: Argument "sha256_candidates" to "declared_hash_verdict" has incompatible type "list[str]"; expected "set[Any]" [arg-type] -scripts/common.py:0: error: Argument 1 to "append" of "list" has incompatible type "tuple[Any, Any, Any]"; expected "str" [arg-type] -scripts/common.py:0: error: Argument 2 to "name_match_size_ok" has incompatible type "str"; expected "Optional[int]" [arg-type] -scripts/common.py:0: error: Cannot determine type of "m" [has-type] -scripts/common.py:0: error: Cannot determine type of "size" [has-type] scripts/common.py:0: error: Incompatible return value type (got "str", expected "tuple[Optional[str], str]") [return-value] scripts/common.py:0: error: Incompatible return value type (got "str", expected "tuple[Optional[str], str]") [return-value] scripts/common.py:0: error: Incompatible types in assignment (expression has type "Optional[tuple[str, str]]", variable has type "Optional[str]") [assignment] scripts/common.py:0: error: Incompatible types in assignment (expression has type "Optional[tuple[str, str]]", variable has type "Optional[str]") [assignment] scripts/common.py:0: error: Name "folded" already defined on line 0 [no-redef] -scripts/common.py:0: error: Unpacking a string is disallowed [misc] -scripts/common.py:0: error: Unpacking a string is disallowed [misc] scripts/common.py:0: error: Unsupported left operand type for & ("None") [operator] scripts/core_probe.py:0: error: Incompatible types in assignment (expression has type "list[list[Any]]", target has type "Optional[str]") [assignment] scripts/core_probe.py:0: error: Incompatible types in assignment (expression has type "list[str]", target has type "Optional[str]") [assignment] @@ -956,7 +947,6 @@ scripts/validate_schemas.py:0: error: Argument 1 to "_semantic_database_checks" scripts/validate_schemas.py:0: error: Argument 3 to "_validate_json_files" has incompatible type "Callable[[Path, dict[Any, Any]], list[str]]"; expected "Optional[Callable[[Path, object], list[str]]]" [arg-type] scripts/validate_schemas.py:0: error: Argument 3 to "_validate_json_files" has incompatible type "Callable[[Path, dict[Any, Any]], list[str]]"; expected "Optional[Callable[[Path, object], list[str]]]" [arg-type] scripts/validate_schemas.py:0: error: Unpacked dict entry 0 has incompatible type "object"; expected "SupportsKeysAndGetItem[str, str]" [dict-item] -scripts/validation.py:0: error: "dict[str, str]" has no attribute "startswith" [attr-defined] scripts/validation.py:0: error: Argument 1 to "_merged_reason" has incompatible type "list[Optional[str]]"; expected "list[str]" [arg-type] scripts/validation.py:0: error: Argument 1 to "set" has incompatible type "Union[dict[Any, Any], list[str], Any, None]"; expected "Iterable[Any]" [arg-type] scripts/validation.py:0: error: Argument 1 to "setdefault" of "MutableMapping" has incompatible type "tuple[Optional[Any], Optional[Any]]"; expected "tuple[str, str]" [arg-type] diff --git a/scripts/common.py b/scripts/common.py index 777b6c745..b717ec9bb 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -1933,7 +1933,7 @@ def resolve_local_file( # 4. Name + alias fallback with md5_composite + direct MD5 per candidate md5_set = set(md5_list) - candidates = [] + named: list[tuple[str, str, int | None]] = [] seen_paths = set() for try_name in names_to_try: for match_sha1 in by_name.get(try_name, []): @@ -1942,28 +1942,28 @@ def resolve_local_file( path = entry["path"] if os.path.exists(path) and path not in seen_paths: seen_paths.add(path) - candidates.append( + named.append( (path, entry.get("md5", ""), entry.get("size")) ) if zipped_file: - candidates = [c for c in candidates if ".zip" in os.path.basename(c[0])] + named = [c for c in named if ".zip" in os.path.basename(c[0])] # Another maker's file is no mismatch of this one, it is another file. - candidates = [c for c in candidates if not other_maker(c[0], makers, db)] + named = [c for c in named if not other_maker(c[0], makers, db)] # A size the emulator itself verifies settles a name collision, so a # candidate that fits is preferred over one that does not: "ROM" answers # both an Apple IIgs image and a Macintosh one. It ranks rather than # excludes, because a present file of the wrong size is reported as # present and untested, and dropping it would report it as absent. - sized = [c for c in candidates if name_match_size_ok(file_entry, c[2])] + sized = [c for c in named if name_match_size_ok(file_entry, c[2])] if sized: - candidates = sized + named = sized - if candidates: + if named: if md5_set and not (sha1_candidates or sha256_candidates or crc_candidates): if composite_only: - candidates.sort(key=lambda c: "/.variants/" in c[0]) - for path, db_md5, _size in candidates: + named.sort(key=lambda c: "/.variants/" in c[0]) + for path, db_md5, _size in named: if ".zip" in os.path.basename(path): try: composite = md5_composite(path).lower() @@ -1982,7 +1982,7 @@ def resolve_local_file( # When zipped_file is set, only accept candidates that contain it if zipped_file: valid = [] - for path, m, size in candidates: + for path, m, size in named: try: with zipfile.ZipFile(path) as zf: inner_names = {n.casefold() for n in zf.namelist()} @@ -2001,7 +2001,7 @@ def resolve_local_file( return (primary[0] if primary else valid[0][0]), "hash_mismatch" # No candidate contains the zipped_file: fall through to step 5 elif not unsourceable: - ordered = _by_affinity([c[0] for c in candidates], file_entry, dest_hint) + ordered = _by_affinity([c[0] for c in named], file_entry, dest_hint) primary = [c for c in ordered if "/.variants/" not in c] return (primary[0] if primary else ordered[0]), "hash_mismatch" diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py index 5a4c34f16..4b4c4f726 100644 --- a/scripts/generate_pack.py +++ b/scripts/generate_pack.py @@ -4065,16 +4065,16 @@ def _profile_copies( continue source = held[0] where = PurePosixPath(standalone) - targets: dict[str, list[str]] = {} + placed: dict[str, list[str]] = {} for system, root in roots.items(): sep = "\\" if system == "windows" else "/" target = root if str(where.parent) == "." else ( root + sep + str(where.parent).replace("/", sep)) if not covered(system, target, where.name): - targets[system] = [target] - if not targets: + placed[system] = [target] + if not placed: continue - copy = {"file": source, "targets": targets} + copy = {"file": source, "targets": placed} if where.name != PurePosixPath(source).name: copy["as"] = where.name copies.append(copy)