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.
This commit is contained in:
Abdessamad Derraz committed 2026-11-07 00:55:46 +01:00
1 parent 16f8c869a5
commit 6cc646acd6
7 files changed
+26 -36

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 = "25a88f9a078717afbe34419481d222d2f6f42c4bf24b4ec64bc3faa9561ea01c"
$defaultInstallSha256 = "ee24f4f154e68d7d503f12e4816e3f1ff38f80159432093e4c6ed86411783ed7"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
+1 -1
View File
@@ -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)")
+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="25a88f9a078717afbe34419481d222d2f6f42c4bf24b4ec64bc3faa9561ea01c"
DEFAULT_INSTALL_SHA256="ee24f4f154e68d7d503f12e4816e3f1ff38f80159432093e4c6ed86411783ed7"
MAX_INSTALLER_BYTES=2097152
cleanup() {
+8 -8
View File
@@ -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
},
{
-10
View File
@@ -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]
+11 -11
View File
@@ -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"
+4 -4
View File
@@ -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)