chore: merge cli output fixes

This commit is contained in:
Abdessamad Derraz committed 2026-11-06 15:57:13 +01:00
commit 5a1c157ded
270 files changed
+2107 -70

No files matched your search

+16
View File
@@ -32,6 +32,9 @@ on:
- "retired.json"
- "measurements/**"
- "website/**"
# The type check's configuration and baseline.
- "pyproject.toml"
- "mypy-baseline.txt"
# Spelled out twice because the workflow parser reads no YAML anchor. A test
# holds the two lists equal.
push:
@@ -58,6 +61,8 @@ on:
- "retired.json"
- "measurements/**"
- "website/**"
- "pyproject.toml"
- "mypy-baseline.txt"
permissions:
contents: read
@@ -163,6 +168,17 @@ jobs:
- name: Validate platform configs and emulator profiles
run: python scripts/validate_schemas.py --source-only
# The annotations are checked against mypy-baseline.txt, the errors the
# code carried when the check started: a new error fails, and so does
# an entry that no longer occurs until the baseline is synced. mypy
# reads no installed package (no_site_packages in pyproject.toml), so
# what this job has installed does not change the result.
- name: Type-check the scripts and the installer
run: |
pip install "mypy==1.18.2" "mypy-baseline==0.7.4"
mypy > "$RUNNER_TEMP/mypy.txt" || true
mypy-baseline filter --no-colors < "$RUNNER_TEMP/mypy.txt"
# A profile written from a clone can cite lines that do not hold the value
# it declares, and schemas and tests pass it. Each profile a change adds is
# confronted with its upstream, both roads into main. An edited profile is
+974
View File
@@ -0,0 +1,974 @@
install.py:0: error: "Invocation" has no attribute "__iter__" (not iterable) [attr-defined]
install.py:0: error: "None" object is not iterable [misc]
install.py:0: error: "OSError" has no attribute "attempts" [attr-defined]
install.py:0: error: "_Unclosed" has no attribute "name" [attr-defined]
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]
install.py:0: error: Argument 1 to "_folder_writable" has incompatible type "Optional[Path]"; expected "Path" [arg-type]
install.py:0: error: Argument 1 to "_listed_names" has incompatible type "bool"; expected "Path" [arg-type]
install.py:0: error: Argument 1 to "_nearest_folder" has incompatible type "Optional[Path]"; expected "Path" [arg-type]
install.py:0: error: Argument 1 to "_replace_released" has incompatible type "Optional[Path]"; expected "Path" [arg-type]
install.py:0: error: Argument 1 to "append" of "list" has incompatible type "Optional[CardApp]"; expected "CardApp" [arg-type]
install.py:0: error: Argument 1 to "append" of "list" has incompatible type "Union[TuiKey, TuiMouse]"; expected "TuiKey" [arg-type]
install.py:0: error: Argument 1 to "cannot_write_words" has incompatible type "Optional[Path]"; expected "Path" [arg-type]
install.py:0: error: Argument 1 to "chmod" has incompatible type "Optional[Path]"; expected "Union[int, Union[str, bytes, PathLike[str], PathLike[bytes]]]" [arg-type]
install.py:0: error: Argument 1 to "copy_source_refusal" has incompatible type "object"; expected "Optional[Path]" [arg-type]
install.py:0: error: Argument 1 to "first_holding" of "FolderIndex" has incompatible type "set[Optional[Any]]"; expected "set[int]" [arg-type]
install.py:0: error: Argument 1 to "len" has incompatible type "Optional[Any]"; expected "Sized" [arg-type]
install.py:0: error: Argument 1 to "len" has incompatible type "Optional[Any]"; expected "Sized" [arg-type]
install.py:0: error: Argument 1 to "len" has incompatible type "Optional[Any]"; expected "Sized" [arg-type]
install.py:0: error: Argument 1 to "len" has incompatible type "Optional[list[dict[Any, Any]]]"; expected "Sized" [arg-type]
install.py:0: error: Argument 1 to "remove" of "list" has incompatible type "int"; expected "FolderIndex" [arg-type]
install.py:0: error: Argument 1 to "replace" has incompatible type "Optional[Path]"; expected "Union[str, bytes, PathLike[str], PathLike[bytes]]" [arg-type]
install.py:0: error: Argument 1 to "setdefault" of "MutableMapping" has incompatible type "Optional[Any]"; expected "str" [arg-type]
install.py:0: error: Argument 1 to "settimeout" of "socket" has incompatible type "object"; expected "Optional[float]" [arg-type]
install.py:0: error: Argument 1 to "shown_path" has incompatible type "Optional[Path]"; expected "Union[Path, str]" [arg-type]
install.py:0: error: Argument 1 to "shown_path" has incompatible type "Optional[Path]"; expected "Union[Path, str]" [arg-type]
install.py:0: error: Argument 1 to "shown_path" has incompatible type "Optional[Path]"; expected "Union[Path, str]" [arg-type]
install.py:0: error: Argument 1 to "shown_path" has incompatible type "Optional[Path]"; expected "Union[Path, str]" [arg-type]
install.py:0: error: Argument 2 to "_browse_to" has incompatible type "object"; expected "Optional[Path]" [arg-type]
install.py:0: error: Argument 2 to "_browse_to" has incompatible type "object"; expected "Optional[Path]" [arg-type]
install.py:0: error: Argument 2 to "_choose_card" has incompatible type "Optional[Path]"; expected "Path" [arg-type]
install.py:0: error: Argument 2 to "_choose_card" has incompatible type "object"; expected "Path" [arg-type]
install.py:0: error: Argument 2 to "_found_elsewhere" has incompatible type "Optional[FolderIndex]"; expected "FolderIndex" [arg-type]
install.py:0: error: Argument 2 to "_setup_label" has incompatible type "Optional[Path]"; expected "Path" [arg-type]
install.py:0: error: Argument 2 to "_toggle_region" has incompatible type "object"; expected "str" [arg-type]
install.py:0: error: Argument 2 to "core_dirs" has incompatible type "Optional[Path]"; expected "Path" [arg-type]
install.py:0: error: Argument 2 to "detected_os" has incompatible type "Optional[Path]"; expected "Path" [arg-type]
install.py:0: error: Argument 2 to "first_holding" of "FolderIndex" has incompatible type "set[Optional[Any]]"; expected "set[str]" [arg-type]
install.py:0: error: Argument 2 to "from_bytes" of "int" has incompatible type "str"; expected "Literal['little', 'big']" [arg-type]
install.py:0: error: Argument 2 to "insert" of "list" has incompatible type "str"; expected "TuiLine" [arg-type]
install.py:0: error: Argument 2 to "insert" of "list" has incompatible type "str"; expected "TuiLine" [arg-type]
install.py:0: error: Argument 2 to "insert" of "list" has incompatible type "str"; expected "TuiLine" [arg-type]
install.py:0: error: Argument 2 to "insert" of "list" has incompatible type "str"; expected "TuiLine" [arg-type]
install.py:0: error: Argument 2 to "insert" of "list" has incompatible type "str"; expected "TuiLine" [arg-type]
install.py:0: error: Argument 3 to "CardSetup" has incompatible type "Optional[str]"; expected "str" [arg-type]
install.py:0: error: Argument 3 to "_choose" has incompatible type "Optional[Path]"; expected "Path" [arg-type]
install.py:0: error: Argument 3 to "_choose" has incompatible type "object"; expected "Path" [arg-type]
install.py:0: error: Argument 3 to "_misplaced" has incompatible type "Optional[FolderIndex]"; expected "FolderIndex" [arg-type]
install.py:0: error: Argument 3 to "_wrong_contents" has incompatible type "Optional[FolderIndex]"; expected "FolderIndex" [arg-type]
install.py:0: error: Argument 3 to "create_connection" has incompatible type "object"; expected "Optional[Union[tuple[Any, ...], str, Buffer]]" [arg-type]
install.py:0: error: Argument 3 to "keep_regions" has incompatible type "list[str]"; expected "frozenset[Any]" [arg-type]
install.py:0: error: Argument 4 to "_write_verified" has incompatible type "Callable[[], IO[bytes]]"; expected "Callable[[], ContextManager[BinaryIO]]" [arg-type]
install.py:0: error: Argument 6 to "_compose" has incompatible type "tuple[()]"; expected "list[Any]" [arg-type]
install.py:0: error: Argument 6 to "_compose" has incompatible type "tuple[()]"; expected "list[Any]" [arg-type]
install.py:0: error: Argument 6 to "_compose" has incompatible type "tuple[()]"; expected "list[Any]" [arg-type]
install.py:0: error: Argument 7 to "_install_data_member" has incompatible type "object"; expected "list[tuple[str, str]]" [arg-type]
install.py:0: error: Cannot determine type of "cores" [has-type]
install.py:0: error: Cannot determine type of "mount" [has-type]
install.py:0: error: Cannot determine type of "mount" [has-type]
install.py:0: error: Cannot determine type of "plat" [has-type]
install.py:0: error: Cannot determine type of "plat" [has-type]
install.py:0: error: Cannot determine type of "plat" [has-type]
install.py:0: error: Cannot determine type of "regions" [has-type]
install.py:0: error: Cannot determine type of "system" [has-type]
install.py:0: error: Cannot determine type of "system" [has-type]
install.py:0: error: Cannot determine type of "system" [has-type]
install.py:0: error: Cannot determine type of "systems" [has-type]
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]
install.py:0: error: Incompatible default for argument "footer" (default has type "tuple[()]", argument has type "list[Any]") [assignment]
install.py:0: error: Incompatible default for argument "omitted" (default has type "tuple[()]", argument has type "list[dict[Any, Any]]") [assignment]
install.py:0: error: Incompatible default for argument "pinned" (default has type "tuple[()]", argument has type "list[Any]") [assignment]
install.py:0: error: Incompatible default for argument "regions" (default has type "tuple[()]", argument has type "list[str]") [assignment]
install.py:0: error: Incompatible default for argument "systems" (default has type "tuple[()]", argument has type "list[str]") [assignment]
install.py:0: error: Incompatible default for argument "trees" (default has type "tuple[()]", argument has type "list[tuple[dict[Any, Any], dict[str, dict[Any, Any]]]]") [assignment]
install.py:0: error: Incompatible return value type (got "IO[bytes]", expected "ContextManager[BinaryIO]") [return-value]
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]
install.py:0: error: Incompatible types in "yield" (actual type "tuple[str, int, Callable[[Any], IO[bytes]]]", expected type "tuple[str, int, Callable[[], BinaryIO]]") [misc]
install.py:0: error: Incompatible types in "yield" (actual type "tuple[str, int, Callable[[Any], Optional[IO[bytes]]]]", expected type "tuple[str, int, Callable[[], BinaryIO]]") [misc]
install.py:0: error: Incompatible types in assignment (expression has type "FolderIndex", base class "tuple" defined the type as "Callable[[Any, SupportsIndex, SupportsIndex], int]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "FolderIndex", base class "tuple" defined the type as "Callable[[Any, SupportsIndex, SupportsIndex], int]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "FolderIndex", variable has type "int") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "GamesChoice", variable has type "Optional[tuple[list[str], list[str], list[str]]]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "GamesChoice", variable has type "Optional[tuple[list[str], list[str], list[str]]]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "GamesChoice", variable has type "Optional[tuple[list[str], list[str], list[str]]]") [assignment]
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]
install.py:0: error: Incompatible types in assignment (expression has type "Union[Any, list[Any]]", variable has type "set[str]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "Union[tuple[list[str], list[str], list[str]], str, GamesChoice, None]", variable has type "Optional[tuple[list[str], list[str], list[str]]]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "_TemporaryFileWrapper[bytes]", variable has type "_Unclosed") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "Optional[int]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "int", base class "tuple" defined the type as "Callable[[Any, SupportsIndex, SupportsIndex], int]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "int", base class "tuple" defined the type as "Callable[[Any], int]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "int", variable has type "list[dict[Any, Any]]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "int", variable has type "str") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "list[dict[Any, Any]]", variable has type "int") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "list[str]", variable has type "Invocation") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "list[str]", variable has type "str") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "set[int]", variable has type "int") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "set[int]", variable has type "list[dict[Any, Any]]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "set[int]", variable has type "list[dict[Any, Any]]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "str", target has type "int") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "Optional[Path]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "Optional[tuple[list[str], list[str], list[str]]]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "bool") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "tuple[int, str]", variable has type "Optional[frozenset[Any]]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "tuple[tuple[str, Any], tuple[str, Any], tuple[str, Any], tuple[str, Any], tuple[str, Any], tuple[str, Any], tuple[str, Any]]", variable has type "tuple[tuple[str, Any], tuple[str, Any], tuple[str, Any], tuple[str, Any]]") [assignment]
install.py:0: error: Incompatible types in assignment (expression has type "tuple[tuple[str, Any], tuple[str, Any], tuple[str, Any], tuple[str, Any], tuple[str, Any]]", variable has type "tuple[tuple[str, Any], tuple[str, Any], tuple[str, Any], tuple[str, Any]]") [assignment]
install.py:0: error: Item "None" of "Optional[BinaryIO]" has no attribute "truncate" [union-attr]
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]
install.py:0: error: Item "None" of "Optional[Terminal]" has no attribute "stream" [union-attr]
install.py:0: error: Item "None" of "Optional[Terminal]" has no attribute "stream" [union-attr]
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]
install.py:0: error: List item 0 has incompatible type "tuple[Optional[str], str]"; expected "tuple[str, str]" [list-item]
install.py:0: error: List item 3 has incompatible type "tuple[Optional[str], str]"; expected "tuple[str, str]" [list-item]
install.py:0: error: Module has no attribute "HKEY_CURRENT_USER" [attr-defined]
install.py:0: error: Module has no attribute "HKEY_LOCAL_MACHINE" [attr-defined]
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]
install.py:0: error: No overload variant of "__getitem__" of "list" matches argument type "object" [call-overload]
install.py:0: error: No overload variant of "min" matches argument types "float", "object" [call-overload]
install.py:0: error: Unsupported left operand type for + ("None") [operator]
install.py:0: error: Unsupported left operand type for + ("None") [operator]
install.py:0: error: Unsupported left operand type for + ("None") [operator]
install.py:0: error: Unsupported left operand type for < ("object") [operator]
install.py:0: error: Unsupported operand types for + ("object" and "int") [operator]
install.py:0: error: Unsupported operand types for + ("object" and "int") [operator]
install.py:0: error: Unsupported operand types for / ("Path" and "None") [operator]
install.py:0: error: Unsupported operand types for / ("Path" and "None") [operator]
install.py:0: error: Unsupported operand types for > ("str" and "int") [operator]
install.py:0: error: Unsupported operand types for in ("object" and "str") [operator]
install.py:0: error: Unsupported right operand type for in ("int") [operator]
install.py:0: error: Value of type "Optional[Match[str]]" is not indexable [index]
install.py:0: error: Value of type "Optional[Match[str]]" is not indexable [index]
install.py:0: error: Value of type "Optional[dict[Any, Any]]" is not indexable [index]
install.py:0: error: Value of type "Optional[tuple[str, str]]" is not indexable [index]
install.py:0: error: Value of type "Optional[tuple[str, str]]" is not indexable [index]
install.py:0: error: Value of type "Optional[tuple[str, str]]" is not indexable [index]
install.py:0: error: Value of type "Optional[tuple[str, str]]" is not indexable [index]
install.py:0: error: Value of type "Optional[tuple[str, str]]" is not indexable [index]
install.py:0: error: Value of type "Optional[tuple[str, str]]" is not indexable [index]
install.py:0: error: Value of type "Optional[tuple[str, str]]" is not indexable [index]
install.py:0: error: Value of type "object" is not indexable [index]
install.py:0: error: Value of type "object" is not indexable [index]
install.py:0: error: Value of type variable "SupportsRichComparisonT" of "min" cannot be "object" [type-var]
install.py:0: error: Value of type variable "SupportsRichComparisonT" of "sorted" cannot be "Optional[Any]" [type-var]
scripts/campaign.py:0: error: "object" has no attribute "__enter__" [attr-defined]
scripts/campaign.py:0: error: "object" has no attribute "__enter__" [attr-defined]
scripts/campaign.py:0: error: "object" has no attribute "__enter__" [attr-defined]
scripts/campaign.py:0: error: "object" has no attribute "__exit__" [attr-defined]
scripts/campaign.py:0: error: "object" has no attribute "__exit__" [attr-defined]
scripts/campaign.py:0: error: "object" has no attribute "__exit__" [attr-defined]
scripts/campaign.py:0: error: "object" has no attribute "decode" [attr-defined]
scripts/campaign.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "bytes") [assignment]
scripts/campaign.py:0: error: Invalid index type "bytes" for "dict[str, str]"; expected type "str" [index]
scripts/campaign.py:0: error: Item "None" of "Optional[dict[Any, Any]]" has no attribute "get" [union-attr]
scripts/campaign.py:0: error: No overload variant of "Popen" matches argument types "list[str]", "bool", "dict[str, object]" [call-overload]
scripts/campaign.py:0: error: Unpacked dict entry 0 has incompatible type "object"; expected "SupportsKeysAndGetItem[Any, Any]" [dict-item]
scripts/campaign.py:0: error: Unsupported operand types for / ("Path" and "bytes") [operator]
scripts/campaign.py:0: error: Value of type "object" is not indexable [index]
scripts/campaign.py:0: error: Value of type "object" is not indexable [index]
scripts/campaign_profiles.py:0: error: Incompatible types in assignment (expression has type "int", variable has type "str") [assignment]
scripts/campaign_profiles.py:0: error: Incompatible types in assignment (expression has type "tuple[str, int]", target has type "tuple[int, int]") [assignment]
scripts/campaign_profiles.py:0: error: Unsupported operand types for + ("str" and "int") [operator]
scripts/campaign_rules.py:0: error: "object" not callable [operator]
scripts/campaign_rules.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Optional[str]"; expected "str" [arg-type]
scripts/campaign_rules.py:0: error: No overload variant of "set" matches argument type "object" [call-overload]
scripts/check_freshness.py:0: error: Argument 2 to "unresolved_target_cores" has incompatible type "dict[str, set[str]]"; expected "dict[str, str]" [arg-type]
scripts/check_freshness.py:0: error: Argument 2 to "unresolved_target_cores" has incompatible type "dict[str, set[str]]"; expected "dict[str, str]" [arg-type]
scripts/check_freshness.py:0: error: Argument 2 to "unresolved_target_cores" has incompatible type "dict[str, set[str]]"; expected "dict[str, str]" [arg-type]
scripts/check_freshness.py:0: error: Argument 2 to "unresolved_target_cores" has incompatible type "dict[str, set[str]]"; expected "dict[str, str]" [arg-type]
scripts/check_freshness.py:0: error: Item "None" of "Optional[Match[str]]" has no attribute "group" [union-attr]
scripts/check_freshness.py:0: error: Need type annotation for "overrides" (hint: "overrides: dict[<type>, <type>] = ...") [var-annotated]
scripts/check_platform_folder.py:0: error: Argument 1 to "exit" has incompatible type "Union[str, HTTPError]"; expected "Union[str, int, None]" [arg-type]
scripts/check_platform_folder.py:0: error: Argument 1 to "read" of "ZipFile" has incompatible type "Optional[str]"; expected "Union[str, ZipInfo]" [arg-type]
scripts/check_platform_folder.py:0: error: Incompatible types in assignment (expression has type "list[str]", variable has type "dict[str, str]") [assignment]
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]
scripts/core_probe.py:0: error: Item "None" of "Optional[Path]" has no attribute "name" [union-attr]
scripts/core_probe.py:0: error: Item "None" of "Optional[Path]" has no attribute "open" [union-attr]
scripts/core_probe.py:0: error: Need type annotation for "info" [var-annotated]
scripts/core_probe.py:0: error: Value of type "Optional[Any]" is not indexable [index]
scripts/cross_reference.py:0: error: Need type annotation for "declared" (hint: "declared: dict[<type>, <type>] = ...") [var-annotated]
scripts/cross_reference.py:0: error: Need type annotation for "platform_data_dirs" (hint: "platform_data_dirs: dict[<type>, <type>] = ...") [var-annotated]
scripts/cross_reference.py:0: error: Need type annotation for "report" (hint: "report: dict[<type>, <type>] = ...") [var-annotated]
scripts/dedup.py:0: error: "Sequence[str]" has no attribute "append" [attr-defined]
scripts/derivations.py:0: error: Argument 1 to "_gf2_times" has incompatible type "tuple[int, ...]"; expected "list[int]" [arg-type]
scripts/derivations.py:0: error: Argument 1 to "_gf2_times" has incompatible type "tuple[int, ...]"; expected "list[int]" [arg-type]
scripts/derivations.py:0: error: Argument 1 to "get" of "dict" has incompatible type "tuple[Optional[int], str]"; expected "tuple[int, str]" [arg-type]
scripts/derivations.py:0: error: Incompatible types in assignment (expression has type "Optional[ZipFile]", variable has type "ZipFile") [assignment]
scripts/dumpcatalog.py:0: error: Need type annotation for "snapshots" (hint: "snapshots: dict[<type>, <type>] = ...") [var-annotated]
scripts/export_native.py:0: error: "object" has no attribute "carries" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "clears" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "component_url" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "destination" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "fills" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "lands" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "name" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "names_anew" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "native_sources" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "native_system" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "platform" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "platform" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "platform_name" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "required_value" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "required_value" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "required_value" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "size" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "size" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "states" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "states" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "states" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "states" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "states" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "written" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "written_list" [attr-defined]
scripts/export_native.py:0: error: "object" has no attribute "written_list" [attr-defined]
scripts/export_native.py:0: error: Argument 1 to "_read_archive" has incompatible type "Optional[Any]"; expected "Callable[[bytes], dict[str, str]]" [arg-type]
scripts/export_native.py:0: error: Argument 1 to "_read_archive" has incompatible type "Optional[Any]"; expected "Callable[[bytes], dict[str, str]]" [arg-type]
scripts/exporter/baseline.py:0: error: Incompatible types in assignment (expression has type "Optional[int]", variable has type "int") [assignment]
scripts/exporter/baseline.py:0: error: No overload variant of "int" matches argument type "object" [call-overload]
scripts/exporter/batocera_exporter.py:0: error: Argument 1 to "append" of "list" has incompatible type "tuple[tuple[Any, ...], str]"; expected "tuple[tuple[Any, ...], dict[Any, Any]]" [arg-type]
scripts/exporter/batocera_exporter.py:0: error: Incompatible types in assignment (expression has type "Optional[tuple[str, Optional[str]]]", target has type "Optional[tuple[str, str]]") [assignment]
scripts/exporter/batocera_exporter.py:0: error: Incompatible types in assignment (expression has type "dict[Any, Any]", variable has type "str") [assignment]
scripts/exporter/batocera_exporter.py:0: error: Item "None" of "Optional[Match[str]]" has no attribute "group" [union-attr]
scripts/exporter/batocera_exporter.py:0: error: Item "None" of "Union[Any, dict[Any, Any], None]" has no attribute "get" [union-attr]
scripts/exporter/batocera_exporter.py:0: error: Signature of "writable" incompatible with supertype "scripts.exporter.base_exporter.BaseExporter" [override]
scripts/exporter/misterfpga_exporter.py:0: error: "object" has no attribute "size" [attr-defined]
scripts/exporter/misterfpga_exporter.py:0: error: Argument 1 to "written" of "Exporter" has incompatible type "object"; expected "NativeFile" [arg-type]
scripts/exporter/misterfpga_exporter.py:0: error: Argument 1 to "written" of "Exporter" has incompatible type "object"; expected "NativeFile" [arg-type]
scripts/exporter/misterfpga_exporter.py:0: error: Return type "dict[str, Union[str, bytes]]" of "render" incompatible with return type "dict[str, str]" in supertype "scripts.exporter.base_exporter.BaseExporter" [override]
scripts/exporter/retrodeck_exporter.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[str, str]"; expected "tuple[str, str, tuple[str, ...]]" [arg-type]
scripts/exporter/retrodeck_exporter.py:0: error: Incompatible types in assignment (expression has type "dict[Any, Any]", variable has type "OrderedDict[Any, Any]") [assignment]
scripts/exporter/retrodeck_exporter.py:0: error: Incompatible types in assignment (expression has type "dict[Any, Any]", variable has type "OrderedDict[Any, Any]") [assignment]
scripts/exporter/retrodeck_exporter.py:0: error: Incompatible types in assignment (expression has type "tuple[str, str, tuple[str, ...]]", variable has type "tuple[str, str]") [assignment]
scripts/exporter/retropie_exporter.py:0: error: "object" has no attribute "__iter__"; maybe "__dir__" or "__str__"? (not iterable) [attr-defined]
scripts/exporter/retropie_exporter.py:0: error: "object" has no attribute "__iter__"; maybe "__dir__" or "__str__"? (not iterable) [attr-defined]
scripts/exporter/retropie_exporter.py:0: error: Argument 2 to "_extended" of "Exporter" has incompatible type "Optional[tuple[int, int, list[str]]]"; expected "tuple[int, int, list[str]]" [arg-type]
scripts/exporter/retropie_exporter.py:0: error: Expected iterable as variadic argument [misc]
scripts/exporter/retropie_exporter.py:0: error: Value of type "Optional[tuple[int, int, list[str]]]" is not indexable [index]
scripts/exporter/retropie_exporter.py:0: error: Value of type "Optional[tuple[int, int, list[str]]]" is not indexable [index]
scripts/exporter/retropie_exporter.py:0: error: Value of type "Optional[tuple[int, int, list[str]]]" is not indexable [index]
scripts/exporter/romm_exporter.py:0: error: Signature of "writable" incompatible with supertype "scripts.exporter.base_exporter.BaseExporter" [override]
scripts/game_rules.py:0: error: Item "None" of "Optional[dict[str, dict[Any, Any]]]" has no attribute "get" [union-attr]
scripts/generate_db.py:0: error: Name "matched" already defined on line 0 [no-redef]
scripts/generate_db.py:0: error: Need type annotation for "aliases" (hint: "aliases: dict[<type>, <type>] = ...") [var-annotated]
scripts/generate_db.py:0: error: Need type annotation for "aliases" (hint: "aliases: dict[<type>, <type>] = ...") [var-annotated]
scripts/generate_db.py:0: error: Need type annotation for "by_name" (hint: "by_name: dict[<type>, <type>] = ...") [var-annotated]
scripts/generate_db.py:0: error: Need type annotation for "by_path_suffix" (hint: "by_path_suffix: dict[<type>, <type>] = ...") [var-annotated]
scripts/generate_db.py:0: error: Need type annotation for "files" (hint: "files: dict[<type>, <type>] = ...") [var-annotated]
scripts/generate_db.py:0: error: Unsupported left operand type for | ("None") [operator]
scripts/generate_event_schema.py:0: error: Argument 1 to "module_from_spec" has incompatible type "Optional[ModuleSpec]"; expected "ModuleSpec" [arg-type]
scripts/generate_event_schema.py:0: error: Item "None" of "Optional[ModuleSpec]" has no attribute "loader" [union-attr]
scripts/generate_event_schema.py:0: error: Item "None" of "Union[Loader, Any, None]" has no attribute "exec_module" [union-attr]
scripts/generate_games_index.py:0: error: Argument 1 to "fallback_set" has incompatible type "Optional[dict[Any, Any]]"; expected "dict[Any, Any]" [arg-type]
scripts/generate_installer_doc.py:0: error: "object" has no attribute "add" [attr-defined]
scripts/generate_installer_doc.py:0: error: Argument 1 to "__init__" of "SimpleHTTPRequestHandler" has incompatible type "*tuple[object, ...]"; expected "BaseServer" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 1 to "__init__" of "SimpleHTTPRequestHandler" has incompatible type "*tuple[object, ...]"; expected "Union[socket, tuple[bytes, socket]]" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 1 to "enter_context" of "_BaseExitStack" has incompatible type "object"; expected "AbstractContextManager[Never, Optional[bool]]" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 1 to "join" of "str" has incompatible type "Union[bool, list[str], str, None]"; expected "Iterable[str]" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 1 to "module_from_spec" has incompatible type "Optional[ModuleSpec]"; expected "ModuleSpec" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 1 to "sample_writers" has incompatible type "_LazySandbox"; expected "Sandbox" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 1 to "startswith" of "str" has incompatible type "Optional[str]"; expected "Union[str, tuple[str, ...]]" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 2 has incompatible type "*tuple[object, ...]"; expected "Optional[Union[tuple[Any, ...], str, Buffer]]" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 2 has incompatible type "*tuple[object, ...]"; expected "Optional[float]" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 3 has incompatible type "**dict[str, object]"; expected "Optional[Union[tuple[Any, ...], str, Buffer]]" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 3 has incompatible type "**dict[str, object]"; expected "Optional[float]" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 3 to "__init__" of "SimpleHTTPRequestHandler" has incompatible type "**dict[str, object]"; expected "BaseServer" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 3 to "__init__" of "SimpleHTTPRequestHandler" has incompatible type "**dict[str, object]"; expected "Union[socket, tuple[bytes, socket]]" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 3 to "run" of "Sandbox" has incompatible type "**dict[str, bool]"; expected "Optional[Path]" [arg-type]
scripts/generate_installer_doc.py:0: error: Argument 3 to "run" of "Sandbox" has incompatible type "**dict[str, bool]"; expected "tuple[Any, ...]" [arg-type]
scripts/generate_installer_doc.py:0: error: Incompatible return value type (got "tuple[int, ...]", expected "tuple[int, int]") [return-value]
scripts/generate_installer_doc.py:0: error: Incompatible types in assignment (expression has type "Union[str, bytes, bytearray]", variable has type "str") [assignment]
scripts/generate_installer_doc.py:0: error: Item "None" of "Optional[ModuleSpec]" has no attribute "loader" [union-attr]
scripts/generate_installer_doc.py:0: error: Item "None" of "Union[Loader, Any, None]" has no attribute "exec_module" [union-attr]
scripts/generate_installer_doc.py:0: error: Name "_install._OsRule" is not defined [name-defined]
scripts/generate_launcher_index.py:0: error: Argument 1 to "module_from_spec" has incompatible type "Optional[ModuleSpec]"; expected "ModuleSpec" [arg-type]
scripts/generate_launcher_index.py:0: error: Item "None" of "Optional[ModuleSpec]" has no attribute "loader" [union-attr]
scripts/generate_launcher_index.py:0: error: Item "None" of "Union[Loader, Any, None]" has no attribute "exec_module" [union-attr]
scripts/generate_pack.py:0: error: Argument 1 to "_narrowings" has incompatible type "Union[str, bool]"; expected "str" [arg-type]
scripts/generate_pack.py:0: error: Argument 1 to "_release_asset_name" has incompatible type "Optional[str]"; expected "str" [arg-type]
scripts/generate_pack.py:0: error: Argument 10 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[bool]" [arg-type]
scripts/generate_pack.py:0: error: Argument 10 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[dict[Any, Any]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 10 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[list[dict[Any, Any]]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 10 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[list[str]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 10 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[set[str]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 10 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[str]" [arg-type]
scripts/generate_pack.py:0: error: Argument 10 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "bool" [arg-type]
scripts/generate_pack.py:0: error: Argument 10 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "str" [arg-type]
scripts/generate_pack.py:0: error: Argument 4 to "_manifest_core_index" has incompatible type "dict_values[str, dict[Any, Any]]"; expected "list[dict[Any, Any]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 4 to "_narrowings" has incompatible type "Union[str, bool]"; expected "bool" [arg-type]
scripts/generate_pack.py:0: error: Argument 5 to "_narrowings" has incompatible type "Union[str, bool]"; expected "bool" [arg-type]
scripts/generate_pack.py:0: error: Argument 7 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[bool]" [arg-type]
scripts/generate_pack.py:0: error: Argument 7 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[dict[Any, Any]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 7 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[dict[str, str]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 7 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[list[dict[Any, Any]]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 7 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[list[str]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 7 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[set[str]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 7 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "Optional[str]" [arg-type]
scripts/generate_pack.py:0: error: Argument 7 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "bool" [arg-type]
scripts/generate_pack.py:0: error: Argument 7 to "generate_pack" has incompatible type "**dict[str, Union[dict[Any, Any], Any, set[str], list[str], str, bool, None]]"; expected "str" [arg-type]
scripts/generate_pack.py:0: error: Argument 9 to "generate_pack" has incompatible type "**dict[str, object]"; expected "Optional[bool]" [arg-type]
scripts/generate_pack.py:0: error: Argument 9 to "generate_pack" has incompatible type "**dict[str, object]"; expected "Optional[dict[Any, Any]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 9 to "generate_pack" has incompatible type "**dict[str, object]"; expected "Optional[list[dict[Any, Any]]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 9 to "generate_pack" has incompatible type "**dict[str, object]"; expected "Optional[list[str]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 9 to "generate_pack" has incompatible type "**dict[str, object]"; expected "Optional[set[str]]" [arg-type]
scripts/generate_pack.py:0: error: Argument 9 to "generate_pack" has incompatible type "**dict[str, object]"; expected "Optional[str]" [arg-type]
scripts/generate_pack.py:0: error: Argument 9 to "generate_pack" has incompatible type "**dict[str, object]"; expected "bool" [arg-type]
scripts/generate_pack.py:0: error: Argument 9 to "generate_pack" has incompatible type "**dict[str, object]"; expected "str" [arg-type]
scripts/generate_pack.py:0: error: Need type annotation for "missing_files" (hint: "missing_files: list[<type>] = ...") [var-annotated]
scripts/generate_pack.py:0: error: Unsupported target for indexed assignment ("Optional[dict[str, PackRecord]]") [index]
scripts/generate_readme.py:0: error: "object" has no attribute "TUI_SYSTEMS_ROW" [attr-defined]
scripts/generate_readme.py:0: error: Argument 1 to "module_from_spec" has incompatible type "Optional[ModuleSpec]"; expected "ModuleSpec" [arg-type]
scripts/generate_readme.py:0: error: Item "None" of "Optional[ModuleSpec]" has no attribute "loader" [union-attr]
scripts/generate_readme.py:0: error: Item "None" of "Union[Loader, Any, None]" has no attribute "exec_module" [union-attr]
scripts/generate_site.py:0: error: "object" has no attribute "EVERYTHING_IN_PLACE" [attr-defined]
scripts/generate_site.py:0: error: "object" has no attribute "TUI_CHOOSE_TITLE" [attr-defined]
scripts/generate_site.py:0: error: "object" has no attribute "TUI_FOLDER_TITLE" [attr-defined]
scripts/generate_site.py:0: error: "object" has no attribute "TUI_FOUND_TITLE" [attr-defined]
scripts/generate_site.py:0: error: "object" has no attribute "TUI_INSTALL_ROW" [attr-defined]
scripts/generate_site.py:0: error: "object" has no attribute "TUI_SYSTEMS_ROW" [attr-defined]
scripts/generate_site.py:0: error: "object" has no attribute "TUI_SYSTEMS_ROW" [attr-defined]
scripts/generate_site.py:0: error: "object" has no attribute "__iter__"; maybe "__dir__" or "__str__"? (not iterable) [attr-defined]
scripts/generate_site.py:0: error: "object" has no attribute "emulator_names" [attr-defined]
scripts/generate_site.py:0: error: "object" has no attribute "values" [attr-defined]
scripts/generate_site.py:0: error: "set[str]" has no attribute "get" [attr-defined]
scripts/generate_site.py:0: error: Argument 1 to "module_from_spec" has incompatible type "Optional[ModuleSpec]"; expected "ModuleSpec" [arg-type]
scripts/generate_site.py:0: error: Argument 1 to "setdefault" of "MutableMapping" has incompatible type "tuple[str, str, str]"; expected "tuple[str, str]" [arg-type]
scripts/generate_site.py:0: error: Argument 2 to "_version_said" has incompatible type "Union[Any, dict[Any, Any], None]"; expected "dict[Any, Any]" [arg-type]
scripts/generate_site.py:0: error: Argument 3 to "_blocks_in_runs" has incompatible type "Callable[[list[str]], float]"; expected "Callable[[list[str]], int]" [arg-type]
scripts/generate_site.py:0: error: Argument 3 to "_render_platform_systems" has incompatible type "Optional[dict[Any, Any]]"; expected "dict[Any, Any]" [arg-type]
scripts/generate_site.py:0: error: Argument 4 to "_emulator_part_page" has incompatible type "list[str]"; expected "list[tuple[str, range]]" [arg-type]
scripts/generate_site.py:0: error: Argument 5 to "_card_index" has incompatible type "list[str]"; expected "list[tuple[str, range]]" [arg-type]
scripts/generate_site.py:0: error: Cannot determine type of "entries" [has-type]
scripts/generate_site.py:0: error: Cannot determine type of "entries" [has-type]
scripts/generate_site.py:0: error: Cannot determine type of "entries" [has-type]
scripts/generate_site.py:0: error: Cannot determine type of "stem" [has-type]
scripts/generate_site.py:0: error: Expected iterable as variadic argument [misc]
scripts/generate_site.py:0: error: Generator has incompatible item type "int"; expected "bool" [misc]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "Optional[Any]", target has type "str") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "str") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "str") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "Union[dict[Any, Any], str, None]", variable has type "str") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "dict[Any, Any]", variable has type "int") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "dict[str, set[str]]", variable has type "set[str]") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "dict[str, str]", variable has type "dict[str, tuple[str, dict[str, list[Any]]]]") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "list[dict[str, Sequence[str]]]", target has type "str") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "list[str]", target has type "str") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "list[str]", variable has type "str") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "list[str]", variable has type "str") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "list[str]", variable has type "str") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "list[tuple[str, Any]]", variable has type "Optional[dict[Any, Any]]") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "list[tuple[str, list[int]]]", variable has type "list[str]") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "tuple[Any, Union[Any, str]]", variable has type "str") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "tuple[str, dict[str, list[Any]]]", variable has type "str") [assignment]
scripts/generate_site.py:0: error: Incompatible types in assignment (expression has type "tuple[str, str]", variable has type "tuple[str, str, str]") [assignment]
scripts/generate_site.py:0: error: Invalid index type "str" for "dict[tuple[str, str], dict[Any, Any]]"; expected type "tuple[str, str]" [index]
scripts/generate_site.py:0: error: Item "None" of "Optional[ModuleSpec]" has no attribute "loader" [union-attr]
scripts/generate_site.py:0: error: Item "None" of "Optional[dict[Any, Any]]" has no attribute "__iter__" (not iterable) [union-attr]
scripts/generate_site.py:0: error: Item "None" of "Optional[str]" has no attribute "startswith" [union-attr]
scripts/generate_site.py:0: error: Item "None" of "Union[Any, dict[Any, Any], None]" has no attribute "get" [union-attr]
scripts/generate_site.py:0: error: Item "None" of "Union[Loader, Any, None]" has no attribute "exec_module" [union-attr]
scripts/generate_site.py:0: error: Need type annotation for "arcade" (hint: "arcade: list[<type>] = ...") [var-annotated]
scripts/generate_site.py:0: error: Need type annotation for "links" (hint: "links: list[<type>] = ...") [var-annotated]
scripts/generate_site.py:0: error: Need type annotation for "machines" (hint: "machines: list[<type>] = ...") [var-annotated]
scripts/generate_site.py:0: error: Need type annotation for "record" [var-annotated]
scripts/generate_site.py:0: error: Need type annotation for "sample" [var-annotated]
scripts/generate_site.py:0: error: No overload variant of "get" of "dict" matches argument type "str" [call-overload]
scripts/generate_site.py:0: error: Unpacking a string is disallowed [misc]
scripts/generate_site.py:0: error: Value of type "Optional[Match[str]]" is not indexable [index]
scripts/generate_site.py:0: error: Value of type "int" is not indexable [index]
scripts/generate_site.py:0: error: Value of type "int" is not indexable [index]
scripts/generate_site.py:0: error: Value of type "int" is not indexable [index]
scripts/generate_site.py:0: error: Value of type "int" is not indexable [index]
scripts/generate_site.py:0: error: Value of type "int" is not indexable [index]
scripts/generate_site.py:0: error: Value of type "int" is not indexable [index]
scripts/generate_site.py:0: error: Value of type "int" is not indexable [index]
scripts/generate_site.py:0: error: Value of type "int" is not indexable [index]
scripts/generate_site.py:0: error: Value of type "int" is not indexable [index]
scripts/generate_site.py:0: error: Value of type "object" is not indexable [index]
scripts/hashing.py:0: error: No overload variant of "open" matches argument types "object", "str" [call-overload]
scripts/launchers.py:0: error: Argument 1 to "len" has incompatible type "Optional[list[str]]"; expected "Sized" [arg-type]
scripts/launchers.py:0: error: Incompatible types in assignment (expression has type "Optional[dict[Any, Any]]", variable has type "dict[Any, Any]") [assignment]
scripts/launchers.py:0: error: Item "None" of "Optional[list[str]]" has no attribute "__iter__" (not iterable) [union-attr]
scripts/measurement_records.py:0: error: Argument 1 to "add" of "set" has incompatible type "Optional[Any]"; expected "str" [arg-type]
scripts/migrate.py:0: error: Incompatible return value type (got "None", expected "tuple[Any, ...]") [return-value]
scripts/migrate.py:0: error: Incompatible return value type (got "None", expected "tuple[Any, ...]") [return-value]
scripts/migrate.py:0: error: Incompatible return value type (got "None", expected "tuple[Any, ...]") [return-value]
scripts/migrate.py:0: error: Incompatible return value type (got "None", expected "tuple[Any, ...]") [return-value]
scripts/migrate.py:0: error: Incompatible return value type (got "None", expected "tuple[Any, ...]") [return-value]
scripts/migrate.py:0: error: Incompatible return value type (got "None", expected "tuple[Any, ...]") [return-value]
scripts/migrate.py:0: error: Incompatible return value type (got "None", expected "tuple[Any, ...]") [return-value]
scripts/pack_probe.py:0: error: Need type annotation for "out" (hint: "out: list[<type>] = ...") [var-annotated]
scripts/pack_probe.py:0: error: Need type annotation for "units" (hint: "units: list[<type>] = ...") [var-annotated]
scripts/packextras.py:0: error: Argument 4 to "_emulator_ships" has incompatible type "Optional[dict[Any, Any]]"; expected "dict[Any, Any]" [arg-type]
scripts/packextras.py:0: error: Item "None" of "Optional[list[dict[Any, Any]]]" has no attribute "append" [union-attr]
scripts/packextras.py:0: error: Need type annotation for "profile" [var-annotated]
scripts/packresolve.py:0: error: Incompatible types in assignment (expression has type "Optional[Any]", variable has type "str") [assignment]
scripts/packresolve.py:0: error: Incompatible types in assignment (expression has type "Optional[Any]", variable has type "str") [assignment]
scripts/packverify.py:0: error: Incompatible types in assignment (expression has type "Union[Any, str, None]", variable has type "str") [assignment]
scripts/packverify.py:0: error: Incompatible types in assignment (expression has type "dict[str, str]", variable has type "str") [assignment]
scripts/packverify.py:0: error: Invalid index type "str" for "str"; expected type "Union[SupportsIndex, slice[Any, Any, Any]]" [index]
scripts/packverify.py:0: error: Need type annotation for "errors" (hint: "errors: list[<type>] = ...") [var-annotated]
scripts/packverify.py:0: error: Unsupported target for indexed assignment ("str") [index]
scripts/pipeline.py:0: error: "object" has no attribute "members" [attr-defined]
scripts/pipeline.py:0: error: "object" has no attribute "members" [attr-defined]
scripts/pipeline.py:0: error: "object" has no attribute "sources" [attr-defined]
scripts/pipeline.py:0: error: "object" has no attribute "sources" [attr-defined]
scripts/pipeline.py:0: error: Item "None" of "Optional[IO[str]]" has no attribute "__iter__" (not iterable) [union-attr]
scripts/profile_sync.py:0: error: "list[tuple[int, int, str]]" has no attribute "items" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "host" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "host" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "host" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "host" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "host" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "host" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "host" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "host" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "name" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "name" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" has no attribute "slug" [attr-defined]
scripts/profile_sync.py:0: error: "object" object is not iterable [misc]
scripts/profile_sync.py:0: error: Argument "entry" to "Citation" has incompatible type "Union[dict[Any, Any], list[Any]]"; expected "Optional[dict[Any, Any]]" [arg-type]
scripts/profile_sync.py:0: error: Argument 1 to "_anchor_tokens" has incompatible type "Optional[dict[Any, Any]]"; expected "dict[Any, Any]" [arg-type]
scripts/profile_sync.py:0: error: Argument 1 to "append" of "list" has incompatible type "object"; expected "str" [arg-type]
scripts/profile_sync.py:0: error: Argument 1 to "entry_hashes" has incompatible type "Optional[dict[Any, Any]]"; expected "dict[Any, Any]" [arg-type]
scripts/profile_sync.py:0: error: Argument 1 to "setdefault" of "MutableMapping" has incompatible type "Optional[int]"; expected "int" [arg-type]
scripts/profile_sync.py:0: error: Argument 1 to "version_tag_candidates" has incompatible type "Optional[Any]"; expected "str" [arg-type]
scripts/profile_sync.py:0: error: Argument 4 to "RepoView" has incompatible type "Optional[str]"; expected "str" [arg-type]
scripts/profile_sync.py:0: error: Argument 4 to "_set_pin" has incompatible type "Optional[str]"; expected "str" [arg-type]
scripts/profile_sync.py:0: error: Argument 4 to "_set_pin" has incompatible type "Optional[str]"; expected "str" [arg-type]
scripts/profile_sync.py:0: error: Cannot determine type of "actual" [has-type]
scripts/profile_sync.py:0: error: Cannot determine type of "old_lines" [has-type]
scripts/profile_sync.py:0: error: Cannot infer type of lambda [misc]
scripts/profile_sync.py:0: error: Cannot infer type of lambda [misc]
scripts/profile_sync.py:0: error: Incompatible return value type (got "object", expected "tuple[Any, list[str]]") [return-value]
scripts/profile_sync.py:0: error: Incompatible types in assignment (expression has type "dict[int, list[Any]]", variable has type "list[tuple[int, int, str]]") [assignment]
scripts/profile_sync.py:0: error: Invalid index type "Optional[int]" for "list[str]"; expected type "SupportsIndex" [index]
scripts/profile_sync.py:0: error: Invalid index type "tuple[str, Optional[int], tuple[Any, ...], str]" for "dict[tuple[str, Optional[int]], tuple[RepoView, str]]"; expected type "tuple[str, Optional[int]]" [index]
scripts/profile_sync.py:0: error: Invalid index type "tuple[str, Optional[int], tuple[Any, ...], str]" for "dict[tuple[str, Optional[int]], tuple[RepoView, str]]"; expected type "tuple[str, Optional[int]]" [index]
scripts/profile_sync.py:0: error: Invalid index type "tuple[str, str, Optional[int], tuple[str, ...], Union[RepoView, Any, None], str]" for "dict[tuple[str, str, Optional[int]], Optional[list[str]]]"; expected type "tuple[str, str, Optional[int]]" [index]
scripts/profile_sync.py:0: error: Invalid index type "tuple[str, str, Optional[int], tuple[str, ...], Union[RepoView, Any, None], str]" for "dict[tuple[str, str, Optional[int]], Optional[list[str]]]"; expected type "tuple[str, str, Optional[int]]" [index]
scripts/profile_sync.py:0: error: Item "None" of "Optional[Match[str]]" has no attribute "start" [union-attr]
scripts/profile_sync.py:0: error: Item "None" of "Optional[VersionReport]" has no attribute "declared" [union-attr]
scripts/profile_sync.py:0: error: Item "None" of "Optional[VersionReport]" has no attribute "latest_release" [union-attr]
scripts/profile_sync.py:0: error: Item "None" of "Optional[dict[Any, Any]]" has no attribute "get" [union-attr]
scripts/profile_sync.py:0: error: Item "None" of "Optional[dict[Any, Any]]" has no attribute "get" [union-attr]
scripts/profile_sync.py:0: error: Item "None" of "Optional[str]" has no attribute "startswith" [union-attr]
scripts/profile_sync.py:0: error: List item 0 has incompatible type "Optional[int]"; expected "int" [list-item]
scripts/profile_sync.py:0: error: Unsupported operand types for + ("None" and "int") [operator]
scripts/profile_sync.py:0: error: Unsupported target for indexed assignment ("object") [index]
scripts/profile_sync.py:0: error: Value of type "Optional[tuple[int, int]]" is not indexable [index]
scripts/profile_sync.py:0: error: Value of type "object" is not indexable [index]
scripts/profile_sync.py:0: error: Value of type "object" is not indexable [index]
scripts/provenance_report.py:0: error: Incompatible types in assignment (expression has type "int", variable has type "set[Any]") [assignment]
scripts/provenance_report.py:0: error: List comprehension has incompatible type List[tuple[str, str, Any]]; expected List[tuple[str, str]] [misc]
scripts/refresh_data_dirs.py:0: error: Item "None" of "Optional[IO[bytes]]" has no attribute "__enter__" [union-attr]
scripts/refresh_data_dirs.py:0: error: Item "None" of "Optional[IO[bytes]]" has no attribute "__exit__" [union-attr]
scripts/refresh_stale.py:0: error: Argument "area" to "Job" has incompatible type "Optional[Any]"; expected "str" [arg-type]
scripts/refresh_stale.py:0: error: Argument 1 to "_command_for" has incompatible type "Optional[Any]"; expected "str" [arg-type]
scripts/refresh_stale.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[Optional[Any], str]"; expected "tuple[str, str]" [arg-type]
scripts/region.py:0: error: Value of type variable "SupportsRichComparisonT" of "min" cannot be "Optional[int]" [type-var]
scripts/region_check.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, Optional[Path]]"; expected "str": "dict[str, Path]" [dict-item]
scripts/region_check.py:0: error: Dict entry 1 has incompatible type "str": "dict[str, Optional[Path]]"; expected "str": "dict[str, Path]" [dict-item]
scripts/region_check.py:0: error: Dict entry 2 has incompatible type "str": "dict[str, Optional[Path]]"; expected "str": "dict[str, Path]" [dict-item]
scripts/safeparse.py:0: error: Invalid base class "base" [misc]
scripts/safeparse.py:0: error: Variable "base" is not valid as a type [valid-type]
scripts/scraper/_hash_merge.py:0: error: Unsupported operand types for + ("None" and "int") [operator]
scripts/scraper/_hash_merge.py:0: error: Unsupported operand types for - ("None" and "int") [operator]
scripts/scraper/arcade_parent_importer.py:0: error: "IO[bytes]" has no attribute "close_archive" [attr-defined]
scripts/scraper/arcade_parent_importer.py:0: error: Argument 1 to "fbneo_sets" has incompatible type "list[Callable[[Any], Any]]"; expected "list[Callable[[], BufferedIOBase]]" [arg-type]
scripts/scraper/arcade_parent_importer.py:0: error: Argument 1 to "read_sets" has incompatible type "list[Callable[[Any], Any]]"; expected "list[Callable[[], BufferedIOBase]]" [arg-type]
scripts/scraper/arcade_parent_importer.py:0: error: Dict entry 2 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item]
scripts/scraper/arcade_parent_importer.py:0: error: Dict entry 2 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item]
scripts/scraper/arcade_parent_importer.py:0: error: Dict entry 2 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item]
scripts/scraper/arcade_parent_importer.py:0: error: Incompatible return value type (got "IO[bytes]", expected "BufferedIOBase") [return-value]
scripts/scraper/arcade_parent_importer.py:0: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "str") [assignment]
scripts/scraper/arcade_parent_importer.py:0: error: List comprehension has incompatible type List[Callable[[], BufferedIOBase]]; expected List[Callable[[Any], Any]] [misc]
scripts/scraper/base_scraper.py:0: error: "object" has no attribute "read" [attr-defined]
scripts/scraper/batocera_launchers.py:0: error: "expr" has no attribute "left" [attr-defined]
scripts/scraper/batocera_launchers.py:0: error: "expr" has no attribute "value" [attr-defined]
scripts/scraper/batocera_launchers.py:0: error: "expr" has no attribute "value" [attr-defined]
scripts/scraper/batocera_launchers.py:0: error: "expr" has no attribute "value" [attr-defined]
scripts/scraper/batocera_launchers.py:0: error: "stmt" has no attribute "body" [attr-defined]
scripts/scraper/batocera_launchers.py:0: error: "stmt" has no attribute "body" [attr-defined]
scripts/scraper/batocera_launchers.py:0: error: "stmt" has no attribute "value" [attr-defined]
scripts/scraper/batocera_launchers.py:0: error: Argument "depends_on_option" to "Launcher" has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "Optional[str]" [arg-type]
scripts/scraper/batocera_launchers.py:0: error: Argument "names" to "Launcher" has incompatible type "list[Union[str, bytes, int, float, complex, ellipsis, None]]"; expected "list[str]" [arg-type]
scripts/scraper/batocera_launchers.py:0: error: Argument "passes_to" to "Launcher" has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "Optional[str]" [arg-type]
scripts/scraper/batocera_launchers.py:0: error: Argument 1 to "append" of "list" has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "str" [arg-type]
scripts/scraper/batocera_launchers.py:0: error: Argument 1 to "join" of "str" has incompatible type "list[Union[str, bytes, int, float, complex, ellipsis, None]]"; expected "Iterable[str]" [arg-type]
scripts/scraper/batocera_launchers.py:0: error: Argument 1 to "ref" of "Source" has incompatible type "list[Union[tuple[int, Optional[int]], tuple[int, int]]]"; expected "list[tuple[int, int]]" [arg-type]
scripts/scraper/batocera_launchers.py:0: error: Argument 1 to <set> has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "str" [arg-type]
scripts/scraper/batocera_launchers.py:0: error: Argument 2 to "_string_lists" has incompatible type "Optional[expr]"; expected "AST" [arg-type]
scripts/scraper/batocera_launchers.py:0: error: Argument 2 to "_string_lists" has incompatible type "Optional[expr]"; expected "AST" [arg-type]
scripts/scraper/batocera_launchers.py:0: error: Argument 3 to "_mentions" has incompatible type "set[Optional[str]]"; expected "set[str]" [arg-type]
scripts/scraper/batocera_launchers.py:0: error: Argument 3 to "_raise_message" has incompatible type "Optional[str]"; expected "str" [arg-type]
scripts/scraper/batocera_launchers.py:0: error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes [str-bytes-safe]
scripts/scraper/batocera_launchers.py:0: error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes [str-bytes-safe]
scripts/scraper/batocera_launchers.py:0: error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes [str-bytes-safe]
scripts/scraper/batocera_launchers.py:0: error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes [str-bytes-safe]
scripts/scraper/batocera_launchers.py:0: error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes [str-bytes-safe]
scripts/scraper/batocera_launchers.py:0: error: Incompatible return value type (got "tuple[Union[str, bytes, int, float, complex, ellipsis, None], Union[str, bytes, int, float, complex, ellipsis, None]]", expected "Optional[tuple[str, Any]]") [return-value]
scripts/scraper/batocera_launchers.py:0: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "str") [assignment]
scripts/scraper/batocera_launchers.py:0: error: Item "None" of "Optional[expr]" has no attribute "lineno" [union-attr]
scripts/scraper/batocera_launchers.py:0: error: List comprehension has incompatible type List[Optional[str]]; expected List[str] [misc]
scripts/scraper/batocera_launchers.py:0: error: List comprehension has incompatible type List[tuple[int, Optional[int]]]; expected List[tuple[int, int]] [misc]
scripts/scraper/batocera_launchers.py:0: error: List item 0 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/batocera_launchers.py:0: error: List item 0 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/batocera_launchers.py:0: error: List item 0 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/batocera_launchers.py:0: error: List item 0 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/batocera_launchers.py:0: error: List item 1 has incompatible type "tuple[Union[int, Any], Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/batocera_launchers.py:0: error: List item 1 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/batocera_launchers.py:0: error: Need type annotation for "launchers" (hint: "launchers: list[<type>] = ...") [var-annotated]
scripts/scraper/batocera_launchers.py:0: error: Unsupported left operand type for + ("ellipsis") [operator]
scripts/scraper/batocera_launchers.py:0: error: Unsupported operand types for + ("bytes" and "str") [operator]
scripts/scraper/batocera_launchers.py:0: error: Unsupported operand types for + ("complex" and "str") [operator]
scripts/scraper/batocera_launchers.py:0: error: Unsupported operand types for + ("float" and "str") [operator]
scripts/scraper/batocera_launchers.py:0: error: Unsupported operand types for + ("int" and "str") [operator]
scripts/scraper/batocera_launchers.py:0: error: Unsupported operand types for in ("Union[str, bytes, int, float, complex, ellipsis]" and "str") [operator]
scripts/scraper/bizhawk_scraper.py:0: error: Name "BaseScraper" already defined (possibly by an import) [no-redef]
scripts/scraper/bizhawk_scraper.py:0: error: Name "BiosRequirement" already defined (possibly by an import) [no-redef]
scripts/scraper/bizhawk_scraper.py:0: error: Name "fetch_github_latest_version" already defined (possibly by an import) [no-redef]
scripts/scraper/bizhawk_scraper.py:0: error: Name "requirement_entry" already defined (possibly by an import) [no-redef]
scripts/scraper/bizhawk_scraper.py:0: error: Name "scraper_cli" already defined (possibly by an import) [no-redef]
scripts/scraper/configgen_launchers.py:0: error: Incompatible return value type (got "AST", expected "Union[Assign, AnnAssign]") [return-value]
scripts/scraper/coreinfo_scraper.py:0: error: Name "BaseScraper" already defined (possibly by an import) [no-redef]
scripts/scraper/coreinfo_scraper.py:0: error: Name "BiosRequirement" already defined (possibly by an import) [no-redef]
scripts/scraper/coreinfo_scraper.py:0: error: Name "fetch_github_latest_version" already defined (possibly by an import) [no-redef]
scripts/scraper/coreinfo_scraper.py:0: error: Name "github_headers" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_launchers.py:0: error: Item "None" of "Optional[str]" has no attribute "split" [union-attr]
scripts/scraper/emudeck_launchers.py:0: error: Name "Launcher" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_launchers.py:0: error: Name "LauncherPatternMissing" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_launchers.py:0: error: Name "RepoTree" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_launchers.py:0: error: Name "Script" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_launchers.py:0: error: Name "describe_keys" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_launchers.py:0: error: Name "settings" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_launchers.py:0: error: Name "source_ref" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_launchers.py:0: error: Name "words" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_launchers.py:0: error: Need type annotation for "records" (hint: "records: list[<type>] = ...") [var-annotated]
scripts/scraper/emudeck_scraper.py:0: error: Name "BaseScraper" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_scraper.py:0: error: Name "BiosRequirement" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_scraper.py:0: error: Name "RepoTree" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_scraper.py:0: error: Name "emulator_of_script" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_scraper.py:0: error: Name "extract_launchers" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_scraper.py:0: error: Name "fetch_branch_head" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_scraper.py:0: error: Name "fetch_github_latest_version" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_scraper.py:0: error: Name "github_headers" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_scraper.py:0: error: Name "requirement_entry" already defined (possibly by an import) [no-redef]
scripts/scraper/emudeck_scraper.py:0: error: Need type annotation for "entries" (hint: "entries: list[<type>] = ...") [var-annotated]
scripts/scraper/libretro_scraper.py:0: error: Unpacked dict entry 0 has incompatible type "Collection[str]"; expected "SupportsKeysAndGetItem[Any, Any]" [dict-item]
scripts/scraper/mame_devices.py:0: error: Incompatible types in "yield" (actual type "IO[bytes]", expected type "BufferedIOBase") [misc]
scripts/scraper/mame_hash_scraper.py:0: error: Item "None" of "Optional[dict[str, Any]]" has no attribute "get" [union-attr]
scripts/scraper/minui_scraper.py:0: error: Cannot infer type of lambda [misc]
scripts/scraper/minui_scraper.py:0: error: Name "BaseScraper" already defined (possibly by an import) [no-redef]
scripts/scraper/minui_scraper.py:0: error: Name "BiosRequirement" already defined (possibly by an import) [no-redef]
scripts/scraper/minui_scraper.py:0: error: Name "fetch_branch_head" already defined (possibly by an import) [no-redef]
scripts/scraper/minui_scraper.py:0: error: Name "fetch_bytes" already defined (possibly by an import) [no-redef]
scripts/scraper/minui_scraper.py:0: error: Name "github_headers" already defined (possibly by an import) [no-redef]
scripts/scraper/minui_scraper.py:0: error: Name "scraper_cli" already defined (possibly by an import) [no-redef]
scripts/scraper/misterfpga_scraper.py:0: error: Name "BaseScraper" already defined (possibly by an import) [no-redef]
scripts/scraper/misterfpga_scraper.py:0: error: Name "BiosRequirement" already defined (possibly by an import) [no-redef]
scripts/scraper/misterfpga_scraper.py:0: error: Name "_read_limited" already defined (possibly by an import) [no-redef]
scripts/scraper/misterfpga_scraper.py:0: error: Name "fetch_branch_head" already defined (possibly by an import) [no-redef]
scripts/scraper/misterfpga_scraper.py:0: error: Name "requirement_entry" already defined (possibly by an import) [no-redef]
scripts/scraper/misterfpga_scraper.py:0: error: Name "scraper_cli" already defined (possibly by an import) [no-redef]
scripts/scraper/myminui_scraper.py:0: error: Name "minui_scraper" already defined (by an import) [no-redef]
scripts/scraper/myminui_scraper.py:0: error: Name "scraper_cli" already defined (possibly by an import) [no-redef]
scripts/scraper/nextui_scraper.py:0: error: Name "minui_scraper" already defined (by an import) [no-redef]
scripts/scraper/nextui_scraper.py:0: error: Name "scraper_cli" already defined (possibly by an import) [no-redef]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "lineno" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "lineno" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "lineno" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "AST" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "None" object is not iterable [misc]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "args" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "attr" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "comparators" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "elts" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "id" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "values" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "expr" has no attribute "values" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "stmt" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "stmt" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "stmt" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "stmt" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "stmt" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "stmt" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "stmt" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "stmt" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: "stmt" has no attribute "value" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: Argument "emulator" to "Launcher" has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument "emulator" to "Launcher" has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument "fails_when_missing" to "Launcher" has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "Union[bool, str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument "names" to "Launcher" has incompatible type "list[Optional[str]]"; expected "list[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument "names" to "Launcher" has incompatible type "list[Union[str, bytes, int, float, complex, ellipsis, None]]"; expected "list[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument "passes_to" to "Launcher" has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "Optional[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument "slot" to "Launcher" has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "Optional[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "append" of "list" has incompatible type "Optional[str]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "append" of "list" has incompatible type "Optional[str]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "append" of "list" has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "append" of "list" has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "index" of "list" has incompatible type "Optional[stmt]"; expected "stmt" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "join" has incompatible type "*list[Optional[str]]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "join" of "str" has incompatible type "list[Union[str, bytes, int, float, complex, ellipsis, None]]"; expected "Iterable[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "join" of "str" has incompatible type "list[Union[str, bytes, int, float, complex, ellipsis, None]]"; expected "Iterable[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "join" of "str" has incompatible type "list[Union[str, bytes, int, float, complex, ellipsis, None]]"; expected "Iterable[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "ref" of "Source" has incompatible type "list[tuple[int, Optional[int]]]"; expected "list[tuple[int, int]]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "ref" of "Source" has incompatible type "list[tuple[int, Optional[int]]]"; expected "list[tuple[int, int]]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 1 to "setdefault" of "MutableMapping" has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 4 to "record" has incompatible type "list[tuple[int, Optional[int]]]"; expected "list[tuple[int, int]]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[bool]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[bool]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[bool]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[bool]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[bool]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[dict[str, list[str]]]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[dict[str, list[str]]]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[dict[str, list[str]]]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[dict[str, list[str]]]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[dict[str, list[str]]]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Union[bool, str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Union[bool, str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "Union[bool, str]" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: Argument 5 to "Launcher" has incompatible type "**dict[str, object]"; expected "str" [arg-type]
scripts/scraper/recalbox_launchers.py:0: error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes [str-bytes-safe]
scripts/scraper/recalbox_launchers.py:0: error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes [str-bytes-safe]
scripts/scraper/recalbox_launchers.py:0: error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes [str-bytes-safe]
scripts/scraper/recalbox_launchers.py:0: error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes [str-bytes-safe]
scripts/scraper/recalbox_launchers.py:0: error: Incompatible return value type (got "Union[str, bytes, int, float, complex, ellipsis, None]", expected "Optional[str]") [return-value]
scripts/scraper/recalbox_launchers.py:0: error: Incompatible return value type (got "dict[str, tuple[list[Union[str, bytes, int, float, complex, ellipsis, None]], AST]]", expected "dict[str, tuple[list[str], stmt]]") [return-value]
scripts/scraper/recalbox_launchers.py:0: error: Incompatible return value type (got "tuple[list[Optional[str]], If]", expected "tuple[list[str], If]") [return-value]
scripts/scraper/recalbox_launchers.py:0: error: Incompatible types in assignment (expression has type "Optional[stmt]", variable has type "stmt") [assignment]
scripts/scraper/recalbox_launchers.py:0: error: Incompatible types in assignment (expression has type "Optional[str]", target has type "str") [assignment]
scripts/scraper/recalbox_launchers.py:0: error: Incompatible types in assignment (expression has type "tuple[Union[str, bytes, int, float, complex, ellipsis, None], Optional[str]]", variable has type "Optional[tuple[str, str]]") [assignment]
scripts/scraper/recalbox_launchers.py:0: error: Item "None" of "Optional[FunctionDef]" has no attribute "args" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "None" of "Optional[FunctionDef]" has no attribute "name" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "None" of "Optional[expr]" has no attribute "keys" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "None" of "Optional[expr]" has no attribute "values" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "None" of "Optional[list[str]]" has no attribute "__iter__" (not iterable) [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "None" of "Optional[stmt]" has no attribute "body" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "None" of "Optional[stmt]" has no attribute "lineno" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "None" of "Optional[stmt]" has no attribute "lineno" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "None" of "Optional[stmt]" has no attribute "orelse" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "expr" of "Optional[expr]" has no attribute "keys" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "expr" of "Optional[expr]" has no attribute "values" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "stmt" of "Optional[stmt]" has no attribute "body" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: Item "stmt" of "Optional[stmt]" has no attribute "orelse" [union-attr]
scripts/scraper/recalbox_launchers.py:0: error: List item 0 has incompatible type "Union[str, bytes, int, float, complex, ellipsis, None]"; expected "str" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 0 has incompatible type "tuple[Any, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 0 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 0 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 0 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 0 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 0 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 0 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 0 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 1 has incompatible type "list[Optional[str]]"; expected "str" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 1 has incompatible type "list[tuple[int, Optional[int]]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 1 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 1 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 2 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 2 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: List item 3 has incompatible type "tuple[int, Optional[int]]"; expected "tuple[int, int]" [list-item]
scripts/scraper/recalbox_launchers.py:0: error: Module has no attribute "Match" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: Module has no attribute "MatchAs" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: Module has no attribute "MatchOr" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: Module has no attribute "MatchValue" [attr-defined]
scripts/scraper/recalbox_launchers.py:0: error: Value of type variable "SupportsRichComparisonT" of "max" cannot be "Optional[int]" [type-var]
scripts/scraper/retrobat_launchers.py:0: error: Incompatible types in assignment (expression has type "Optional[tuple[str, list[tuple[int, int]]]]", variable has type "str") [assignment]
scripts/scraper/retrobat_launchers.py:0: error: Item "None" of "Optional[Match[str]]" has no attribute "group" [union-attr]
scripts/scraper/retrobat_scraper.py:0: error: Argument 1 to "urlopen" has incompatible type "BiosRequirement"; expected "Union[str, Request]" [arg-type]
scripts/scraper/retrobat_scraper.py:0: error: Incompatible types in assignment (expression has type "Request", variable has type "BiosRequirement") [assignment]
scripts/scraper/retrobat_scraper.py:0: error: Name "BATOCERA_SLUGS" already defined (possibly by an import) [no-redef]
scripts/scraper/retrobat_scraper.py:0: error: Name "BaseScraper" already defined (possibly by an import) [no-redef]
scripts/scraper/retrobat_scraper.py:0: error: Name "BiosRequirement" already defined (possibly by an import) [no-redef]
scripts/scraper/retrobat_scraper.py:0: error: Name "LAUNCHER_FILES" already defined (possibly by an import) [no-redef]
scripts/scraper/retrobat_scraper.py:0: error: Name "extract_launchers" already defined (possibly by an import) [no-redef]
scripts/scraper/retrobat_scraper.py:0: error: Name "fetch_branch_head" already defined (possibly by an import) [no-redef]
scripts/scraper/retrobat_scraper.py:0: error: Name "fetch_bytes" already defined (possibly by an import) [no-redef]
scripts/scraper/retrobat_scraper.py:0: error: Name "fetch_github_latest_version" already defined (possibly by an import) [no-redef]
scripts/scraper/retrobat_scraper.py:0: error: Name "requirement_entry" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_launchers.py:0: error: Incompatible types in assignment (expression has type "tuple[str, ...]", variable has type "tuple[str, str, str, str]") [assignment]
scripts/scraper/retrodeck_launchers.py:0: error: Name "Launcher" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_launchers.py:0: error: Name "LauncherPatternMissing" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_launchers.py:0: error: Name "merge_records" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_launchers.py:0: error: Name "source_ref" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_scraper.py:0: error: Name "BaseScraper" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_scraper.py:0: error: Name "BiosRequirement" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_scraper.py:0: error: Name "extract_launchers" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_scraper.py:0: error: Name "fetch_branch_head" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_scraper.py:0: error: Name "fetch_bytes" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_scraper.py:0: error: Name "fetch_github_latest_version" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_scraper.py:0: error: Name "github_headers" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_scraper.py:0: error: Name "requirement_entry" already defined (possibly by an import) [no-redef]
scripts/scraper/retrodeck_scraper.py:0: error: Name "scraper_cli" already defined (possibly by an import) [no-redef]
scripts/scraper/retropie_launchers.py:0: error: "int" has no attribute "rstrip" [attr-defined]
scripts/scraper/retropie_launchers.py:0: error: "int" has no attribute "strip" [attr-defined]
scripts/scraper/retropie_launchers.py:0: error: Argument 3 to "Event" has incompatible type "list[str]"; expected "list[list[str]]" [arg-type]
scripts/scraper/retropie_launchers.py:0: error: Argument 3 to "Event" has incompatible type "list[str]"; expected "list[list[str]]" [arg-type]
scripts/scraper/retropie_launchers.py:0: error: Argument 3 to "_walk" of "Scripts" has incompatible type "dict[str, str]"; expected "dict[str, list[str]]" [arg-type]
scripts/scraper/retropie_launchers.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment]
scripts/scraper/retropie_launchers.py:0: error: List comprehension has incompatible type List[list[str]]; expected List[str] [misc]
scripts/scraper/retropie_launchers.py:0: error: List comprehension has incompatible type List[list[str]]; expected List[str] [misc]
scripts/scraper/retropie_launchers.py:0: error: List comprehension has incompatible type List[tuple[str, ...]]; expected List[tuple[str, str]] [misc]
scripts/scraper/retropie_launchers.py:0: error: No overload variant of "match" of "Pattern" matches argument type "int" [call-overload]
scripts/scraper/retropie_launchers.py:0: error: No overload variant of "search" of "Pattern" matches argument type "int" [call-overload]
scripts/scraper/retropie_scraper.py:0: error: Name "BaseScraper" already defined (possibly by an import) [no-redef]
scripts/scraper/retropie_scraper.py:0: error: Name "BiosRequirement" already defined (possibly by an import) [no-redef]
scripts/scraper/retropie_scraper.py:0: error: Name "SCRIPTMODULES" already defined (possibly by an import) [no-redef]
scripts/scraper/retropie_scraper.py:0: error: Name "_SCRIPT_SECTIONS" already defined (possibly by an import) [no-redef]
scripts/scraper/retropie_scraper.py:0: error: Name "extract_launchers" already defined (possibly by an import) [no-redef]
scripts/scraper/retropie_scraper.py:0: error: Name "fetch_branch_head" already defined (possibly by an import) [no-redef]
scripts/scraper/retropie_scraper.py:0: error: Name "scraper_cli" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_launchers.py:0: error: Argument "search_dir" to "Launcher" has incompatible type "object"; expected "Optional[str]" [arg-type]
scripts/scraper/rocknix_launchers.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Union[str, Match[str]]"; expected "str" [arg-type]
scripts/scraper/rocknix_launchers.py:0: error: Argument 1 to <set> has incompatible type "Optional[int]"; expected "int" [arg-type]
scripts/scraper/rocknix_launchers.py:0: error: Argument 2 to "next" has incompatible type "None"; expected "Match[str]" [arg-type]
scripts/scraper/rocknix_launchers.py:0: error: Argument 9 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[bool]" [arg-type]
scripts/scraper/rocknix_launchers.py:0: error: Argument 9 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[bool]" [arg-type]
scripts/scraper/rocknix_launchers.py:0: error: Argument 9 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[dict[str, list[str]]]" [arg-type]
scripts/scraper/rocknix_launchers.py:0: error: Argument 9 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[str]" [arg-type]
scripts/scraper/rocknix_launchers.py:0: error: Argument 9 to "Launcher" has incompatible type "**dict[str, object]"; expected "Optional[str]" [arg-type]
scripts/scraper/rocknix_launchers.py:0: error: Argument 9 to "Launcher" has incompatible type "**dict[str, object]"; expected "Union[bool, str]" [arg-type]
scripts/scraper/rocknix_launchers.py:0: error: Argument 9 to "Launcher" has incompatible type "**dict[str, object]"; expected "Union[bool, str]" [arg-type]
scripts/scraper/rocknix_launchers.py:0: error: Generator has incompatible item type "str"; expected "Match[str]" [misc]
scripts/scraper/rocknix_launchers.py:0: error: Name "Launcher" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_launchers.py:0: error: Name "LauncherPatternMissing" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_launchers.py:0: error: Name "Link" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_launchers.py:0: error: Name "RepoTree" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_launchers.py:0: error: Name "Script" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_launchers.py:0: error: Name "Setting" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_launchers.py:0: error: Name "describe_keys" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_launchers.py:0: error: Name "settings" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_launchers.py:0: error: Name "source_ref" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_scraper.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Optional[str]"; expected "str" [arg-type]
scripts/scraper/rocknix_scraper.py:0: error: Name "BaseScraper" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_scraper.py:0: error: Name "BiosRequirement" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_scraper.py:0: error: Name "RepoTree" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_scraper.py:0: error: Name "extract_launchers" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_scraper.py:0: error: Name "fetch_github_latest_version" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_scraper.py:0: error: Name "md5_field" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_scraper.py:0: error: Name "requirement_entry" already defined (possibly by an import) [no-redef]
scripts/scraper/rocknix_scraper.py:0: error: Name "scraper_cli" already defined (possibly by an import) [no-redef]
scripts/scraper/romfolders/card.py:0: error: Incompatible types in assignment (expression has type "list[str]", variable has type "str") [assignment]
scripts/scraper/romfolders/card.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "Optional[Match[str]]") [assignment]
scripts/scraper/romfolders/card.py:0: error: No overload variant of "get" of "dict" matches argument types "Optional[Match[str]]", "Optional[Match[str]]" [call-overload]
scripts/scraper/romfolders/es.py:0: error: Argument 2 to "setdefault" of "MutableMapping" has incompatible type "tuple[str, Any, str]"; expected "tuple[str, str, int]" [arg-type]
scripts/scraper/romfolders/es.py:0: error: Incompatible types in assignment (expression has type "Optional[Any]", variable has type "str") [assignment]
scripts/scraper/romfolders/es.py:0: error: Incompatible types in assignment (expression has type "int", variable has type "str") [assignment]
scripts/scraper/romfolders/es.py:0: error: Incompatible types in assignment (expression has type "int", variable has type "str") [assignment]
scripts/scraper/romfolders/es.py:0: error: List item 0 has incompatible type "None"; expected "dict[Any, Any]" [list-item]
scripts/scraper/romfolders/es.py:0: error: Value of type "Optional[str]" is not indexable [index]
scripts/scraper/romm_scraper.py:0: error: Name "BaseScraper" already defined (possibly by an import) [no-redef]
scripts/scraper/romm_scraper.py:0: error: Name "BiosRequirement" already defined (possibly by an import) [no-redef]
scripts/scraper/romm_scraper.py:0: error: Name "fetch_bytes" already defined (possibly by an import) [no-redef]
scripts/scraper/romm_scraper.py:0: error: Name "fetch_github_latest_version" already defined (possibly by an import) [no-redef]
scripts/scraper/romm_scraper.py:0: error: Name "requirement_entry" already defined (possibly by an import) [no-redef]
scripts/scraper/romset_dat_importer.py:0: error: "IO[bytes]" has no attribute "close_archive" [attr-defined]
scripts/scraper/romset_dat_importer.py:0: error: "object" has no attribute "__iter__"; maybe "__dir__" or "__str__"? (not iterable) [attr-defined]
scripts/scraper/romset_dat_importer.py:0: error: Incompatible return value type (got "IO[bytes]", expected "ZipExtFile") [return-value]
scripts/scraper/shell_launchers.py:0: error: Name "LauncherShapeError" already defined (possibly by an import) [no-redef]
scripts/scraper/shell_launchers.py:0: error: Name "fetch_bytes" already defined (possibly by an import) [no-redef]
scripts/scraper/shell_launchers.py:0: error: Name "github_headers" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/amberelec_targets_scraper.py:0: error: Name "BUILDS_OF" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/amberelec_targets_scraper.py:0: error: Name "ES_SYSTEMS_TEMPLATE" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/amberelec_targets_scraper.py:0: error: Name "RUNNERS" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/amberelec_targets_scraper.py:0: error: Name "_not_cores" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/amberelec_targets_scraper.py:0: error: Name "es_cores" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/amberelec_targets_scraper.py:0: error: Name "fetch_bytes" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/amberelec_targets_scraper.py:0: error: Name "xml_systems" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/batocera_targets_scraper.py:0: error: Name "github_headers" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/emuelec_targets_scraper.py:0: error: Name "BUILDS_OF" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/emuelec_targets_scraper.py:0: error: Name "ES_SYSTEMS_TEMPLATE" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/emuelec_targets_scraper.py:0: error: Name "PORTS_TEMPLATE" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/emuelec_targets_scraper.py:0: error: Name "RUNNERS" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/emuelec_targets_scraper.py:0: error: Name "SystemEmulators" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/emuelec_targets_scraper.py:0: error: Name "_not_cores" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/emuelec_targets_scraper.py:0: error: Name "es_cores" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/emuelec_targets_scraper.py:0: error: Name "fetch_bytes" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/emuelec_targets_scraper.py:0: error: Name "github_headers" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/emuelec_targets_scraper.py:0: error: Name "port_engines" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/emuelec_targets_scraper.py:0: error: Name "with_ports" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/lakka_targets_scraper.py:0: error: Name "fetch_bytes" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/lakka_targets_scraper.py:0: error: Name "github_headers" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/recalbox_targets_scraper.py:0: error: Name "PlatformScraper" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/recalbox_targets_scraper.py:0: error: Name "SYSTEMS_TREE_URL" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/recalbox_targets_scraper.py:0: error: Name "board_cores" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/recalbox_targets_scraper.py:0: error: Name "fetch_bytes" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/rocknix_targets_scraper.py:0: error: Name "fetch_bytes" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/rocknix_targets_scraper.py:0: error: Name "github_headers" already defined (possibly by an import) [no-redef]
scripts/scraper/targets/rocknix_targets_scraper.py:0: error: Name "standalone_emulators" already defined (possibly by an import) [no-redef]
scripts/sect233r1.py:0: error: Incompatible types in assignment (expression has type "Optional[tuple[int, int]]", variable has type "tuple[int, int]") [assignment]
scripts/site_insights.py:0: error: Item "list[Any]" of "Union[dict[Any, Any], list[Any]]" has no attribute "get" [union-attr]
scripts/site_insights.py:0: error: Item "list[Any]" of "Union[dict[Any, Any], list[Any]]" has no attribute "get" [union-attr]
scripts/site_insights.py:0: error: Item "list[Any]" of "Union[dict[Any, Any], list[Any]]" has no attribute "get" [union-attr]
scripts/site_insights.py:0: error: Item "list[Any]" of "Union[dict[Any, Any], list[Any]]" has no attribute "get" [union-attr]
scripts/sitediagrams.py:0: error: "AST" has no attribute "value" [attr-defined]
scripts/sitediagrams.py:0: error: Argument 1 to "lstrip" of "bytes" has incompatible type "str"; expected "Optional[Buffer]" [arg-type]
scripts/sitediagrams.py:0: error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes [str-bytes-safe]
scripts/sitediagrams.py:0: error: Incompatible types in assignment (expression has type "Union[str, bytes, int, float, complex, ellipsis, Any, None]", variable has type "str") [assignment]
scripts/sitediagrams.py:0: error: Item "None" of "Union[str, bytes, int, float, complex, ellipsis, None]" has no attribute "lstrip" [union-attr]
scripts/sitediagrams.py:0: error: Item "complex" of "Union[str, bytes, int, float, complex, ellipsis, None]" has no attribute "lstrip" [union-attr]
scripts/sitediagrams.py:0: error: Item "ellipsis" of "Union[str, bytes, int, float, complex, ellipsis, None]" has no attribute "lstrip" [union-attr]
scripts/sitediagrams.py:0: error: Item "float" of "Union[str, bytes, int, float, complex, ellipsis, None]" has no attribute "lstrip" [union-attr]
scripts/sitediagrams.py:0: error: Item "int" of "Union[str, bytes, int, float, complex, ellipsis, None]" has no attribute "lstrip" [union-attr]
scripts/siteguides.py:0: error: Argument 1 to "tuple" has incompatible type "list[tuple[str, ...]]"; expected "Iterable[tuple[str, str, str, str, str]]" [arg-type]
scripts/siteguides.py:0: error: Incompatible types in assignment (expression has type "tuple[str, ...]", target has type "tuple[str, str, str]") [assignment]
scripts/sitemeasurements.py:0: error: Argument 1 to "permalink" has incompatible type "Optional[Any]"; expected "str" [arg-type]
scripts/sitemeasurements.py:0: error: Argument 2 to "permalink" has incompatible type "Optional[Any]"; expected "str" [arg-type]
scripts/sitemeasurements.py:0: error: Value of type "Optional[Match[str]]" is not indexable [index]
scripts/siterender.py:0: error: "None" object is not iterable [misc]
scripts/siterender.py:0: error: Argument 1 to "add" of "set" has incompatible type "Optional[tuple[str, str]]"; expected "tuple[str, str]" [arg-type]
scripts/sitestarlight.py:0: error: "object" has no attribute "items" [attr-defined]
scripts/sitestarlight.py:0: error: Argument "key" to "max" has incompatible type overloaded function; expected "Callable[[str], Union[SupportsDunderLT[Any], SupportsDunderGT[Any]]]" [arg-type]
scripts/sitestarlight.py:0: error: Incompatible types in assignment (expression has type "Optional[dict[str, int]]", variable has type "dict[str, int]") [assignment]
scripts/slot.py:0: error: Value of type variable "SupportsRichComparisonT" of "min" cannot be "Optional[int]" [type-var]
scripts/sourceref.py:0: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "str") [assignment]
scripts/upstream.py:0: error: "object" has no attribute "get" [attr-defined]
scripts/upstream.py:0: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "str") [assignment]
scripts/upstream.py:0: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "str") [assignment]
scripts/upstream.py:0: error: Value of type "object" is not indexable [index]
scripts/validate_pr.py:0: error: "Collection[Any]" has no attribute "add" [attr-defined]
scripts/validate_pr.py:0: error: "Collection[Any]" has no attribute "setdefault" [attr-defined]
scripts/validate_pr.py:0: error: "Collection[Any]" has no attribute "setdefault" [attr-defined]
scripts/validate_pr.py:0: error: "Collection[Any]" has no attribute "update" [attr-defined]
scripts/validate_pr.py:0: error: "Collection[Any]" has no attribute "update" [attr-defined]
scripts/validate_pr.py:0: error: "Collection[Any]" has no attribute "update" [attr-defined]
scripts/validate_pr.py:0: error: "Collection[Any]" has no attribute "update" [attr-defined]
scripts/validate_pr.py:0: error: "_MutuallyExclusiveGroup" has no attribute "append" [attr-defined]
scripts/validate_pr.py:0: error: "add" of "set" does not return a value (it only ever returns None) [func-returns-value]
scripts/validate_pr.py:0: error: Argument 1 to "_note_sizes" has incompatible type "Collection[Any]"; expected "dict[str, list[Any]]" [arg-type]
scripts/validate_pr.py:0: error: Incompatible types in assignment (expression has type "list[Never]", variable has type "_MutuallyExclusiveGroup") [assignment]
scripts/validate_pr.py:0: error: Incompatible types in assignment (expression has type "set[Any]", variable has type "list[Any]") [assignment]
scripts/validate_pr.py:0: error: List item 0 has incompatible type "None"; expected "int" [list-item]
scripts/validate_pr.py:0: error: Need type annotation for "checks" (hint: "checks: list[<type>] = ...") [var-annotated]
scripts/validate_pr.py:0: error: Need type annotation for "expected" [var-annotated]
scripts/validate_pr.py:0: error: Need type annotation for "known" [var-annotated]
scripts/validate_schemas.py:0: error: "object" has no attribute "get" [attr-defined]
scripts/validate_schemas.py:0: error: "object" has no attribute "get" [attr-defined]
scripts/validate_schemas.py:0: error: "object" has no attribute "get" [attr-defined]
scripts/validate_schemas.py:0: error: "object" has no attribute "get" [attr-defined]
scripts/validate_schemas.py:0: error: "object" has no attribute "get" [attr-defined]
scripts/validate_schemas.py:0: error: "object" has no attribute "get" [attr-defined]
scripts/validate_schemas.py:0: error: "object" has no attribute "get" [attr-defined]
scripts/validate_schemas.py:0: error: "object" has no attribute "get" [attr-defined]
scripts/validate_schemas.py:0: error: "object" has no attribute "get" [attr-defined]
scripts/validate_schemas.py:0: error: "object" has no attribute "get" [attr-defined]
scripts/validate_schemas.py:0: error: Argument 1 to "_semantic_database_checks" has incompatible type "object"; expected "dict[Any, Any]" [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: 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]
scripts/validation.py:0: error: Argument 2 to "frontend_digest_matches" has incompatible type "Optional[str]"; expected "str" [arg-type]
scripts/validation.py:0: error: Argument 3 to "_entry_rule" has incompatible type "list[str]"; expected "set[str]" [arg-type]
scripts/validation.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "dict[str, str]") [assignment]
scripts/validation.py:0: error: Item "None" of "Optional[Match[str]]" has no attribute "group" [union-attr]
scripts/validation.py:0: error: Item "None" of "Optional[Match[str]]" has no attribute "group" [union-attr]
scripts/validation.py:0: error: Item "None" of "Optional[Match[str]]" has no attribute "group" [union-attr]
scripts/validation.py:0: error: Item "None" of "Optional[str]" has no attribute "lower" [union-attr]
scripts/verify.py:0: error: Item "None" of "Optional[dict[Any, Any]]" has no attribute "setdefault" [union-attr]
scripts/version_basis.py:0: error: Too many arguments for "describe_form" [call-arg]
+27 -1
View File
@@ -16,7 +16,8 @@ description = "BIOS collection manager for retrogaming platforms"
# install.py is the only entry point a user runs before cloning, and both
# bootstraps accept 3.8, so the floor stays where the bootstraps put it. That
# floor covers install.py alone: the build scripts under scripts/ need 3.9
# (pipeline.py checks it), and CI runs the test suite on 3.12.
# (common.py, which every build script imports, checks it), and CI runs the
# test suite on 3.12.
requires-python = ">=3.8"
dependencies = [
"pyyaml",
@@ -37,9 +38,34 @@ dev = [
# installs only in its isolated build environment and 3.12 no longer
# bundles: without it the guard skipped on every CI run.
"setuptools>=61",
# The type check CI runs, pinned: another mypy reports other errors
# than the ones mypy-baseline.txt holds.
"mypy==1.18.2",
"mypy-baseline==0.7.4",
]
# The site is built by Astro Starlight from website/package.json and its
# lockfile (npm ci --prefix website): no Python package builds it.
[project.urls]
Repository = "https://github.com/Abdess/retrobios"
# The annotations are checked, not only written. Third-party packages are left
# out (no_site_packages) so the result does not depend on what the machine
# has installed: yaml, jsonschema and the rest read as Any everywhere. The
# errors the code carried when the check started sit in mypy-baseline.txt.
# CI fails on an error that is not there and on an entry that no longer
# occurs: `mypy > out.txt`, then `mypy-baseline filter < out.txt`, and
# `mypy-baseline sync < out.txt` once the fix is in.
[tool.mypy]
files = ["install.py", "scripts"]
python_version = "3.9"
explicit_package_bases = true
ignore_missing_imports = true
no_site_packages = true
disable_error_code = ["import-untyped"]
cache_dir = "tmp/mypy_cache"
[tool.mypy-baseline]
baseline_path = "mypy-baseline.txt"
ignore_categories = ["note"]
sort_baseline = true
+3
View File
@@ -116,6 +116,9 @@ def main() -> int:
parser.add_argument("--json", action="store_true", help="print the list as JSON")
parser.add_argument("--strict", action="store_true", help="exit 1 while a file is listed")
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["db", "emulators_dir", "platforms_dir", "install_dir"])
rows = bundled_only(
load_database(args.db), load_emulator_profiles(args.emulators_dir),
+6 -3
View File
@@ -83,14 +83,17 @@ from collections.abc import Callable, Iterator, Sequence
from dataclasses import dataclass, field
from pathlib import Path
import yaml
sys.path.insert(0, str(Path(__file__).resolve().parent))
# First: core_probe stops an interpreter older than 3.9 before anything else
# fails on it.
import core_probe
import yaml
import autorun
import campaign_profiles
import campaign_rules as rules
import core_probe
import measurement_records as mr
ROOT = Path(__file__).resolve().parent.parent
+101 -15
View File
@@ -9,6 +9,7 @@ from __future__ import annotations
from collections.abc import Callable, Iterable
from collections import Counter
import argparse
import filecmp
import hashlib
import functools
@@ -19,6 +20,16 @@ import signal
import sys
import zipfile
from pathlib import Path
from typing import Any, TextIO
# Every build script imports this module. verify.py, slots.py, validate_pr.py
# and cross_reference.py started under 3.8 and stopped halfway on a
# str.removeprefix AttributeError, which named no version.
if sys.version_info < (3, 9):
sys.exit(
f"{Path(sys.argv[0]).name} needs Python 3.9 or newer, "
f"this is {sys.version.split()[0]}"
)
try:
@@ -53,6 +64,33 @@ class DatabaseUnreadable(InputMissing):
"""The database a command was pointed at does not exist or is not JSON."""
class SourceUnreadable(ValueError):
"""A profile or platform file that is not valid YAML. Not an InputMissing:
the callers that skip a platform whose file is absent must not skip one
whose file is damaged. run_cli prints the message on one line."""
def source_yaml(stream: TextIO) -> Any:
"""Parse one of our YAML sources, naming the file a syntax error is in.
Every profile is loaded whatever the command, so one misindented key in
an unrelated profile stopped `verify.py --emulator handy` on a 37-line
traceback, the faulty file named only near its end.
"""
if yaml is None:
return yaml_load(stream)
try:
return yaml_load(stream)
except yaml.YAMLError as exc:
mark = getattr(exc, "problem_mark", None)
where = f"{stream.name}:{mark.line + 1}" if mark else stream.name
problem = getattr(exc, "problem", None) or str(exc).splitlines()[0]
raise SourceUnreadable(
f"{where}: {problem}. Check it with: "
"python scripts/validate_schemas.py --source-only"
) from None
def load_database(db_path: str) -> dict:
"""Load database.json and return parsed dict.
@@ -64,6 +102,18 @@ def load_database(db_path: str) -> dict:
with open(db_path) as f:
return json.load(f)
except FileNotFoundError:
# A mistyped --db beside the real database was told to rescan the
# whole collection into a second file under the typo.
import difflib # noqa: PLC0415
typed = Path(db_path)
close = difflib.get_close_matches(
typed.name, [p.name for p in typed.parent.glob("*.json")], n=1, cutoff=0.8
)
if close:
raise DatabaseUnreadable(
f"{db_path} not found. Did you mean {typed.with_name(close[0])}?"
) from None
raise DatabaseUnreadable(
f"{db_path} not found. Build it with: python scripts/generate_db.py "
f"--force --bios-dir bios --output {db_path}"
@@ -302,7 +352,7 @@ def _inherited_yaml(platform_name: str, platforms_dir: str) -> tuple[dict, list[
raise FileNotFoundError(f"Platform config not found: {config_file}")
with open(config_file) as f:
config = yaml_load(f) or {}
config = source_yaml(f) or {}
if "inherits" not in config:
return config, [platform_name]
@@ -348,7 +398,7 @@ def load_platform_config(platform_name: str, platforms_dir: str = "platforms") -
reg_real = os.path.realpath(registry_path)
if reg_real not in _shared_yml_cache:
with open(registry_path) as f:
_shared_yml_cache[reg_real] = yaml_load(f) or {}
_shared_yml_cache[reg_real] = source_yaml(f) or {}
reg = _shared_yml_cache[reg_real]
# The platform's own entry first, then its parents' for what it does
# not say: RetroPie's status, scraper and install are its own, its
@@ -387,7 +437,7 @@ def load_platform_config(platform_name: str, platforms_dir: str = "platforms") -
shared_real = os.path.realpath(shared_path)
if shared_real not in _shared_yml_cache:
with open(shared_path) as f:
_shared_yml_cache[shared_real] = yaml_load(f) or {}
_shared_yml_cache[shared_real] = source_yaml(f) or {}
shared = _shared_yml_cache[shared_real]
shared_groups = shared.get("shared_groups", {})
for system in config.get("systems", {}).values():
@@ -494,7 +544,7 @@ def load_data_dir_registry(platforms_dir: str = "platforms") -> dict:
if not os.path.exists(registry_path):
return {}
with open(registry_path) as f:
data = yaml_load(f) or {}
data = source_yaml(f) or {}
return data.get("data_directories", {})
@@ -504,7 +554,7 @@ def load_platform_registry(platforms_dir: str = "platforms") -> dict:
if not os.path.exists(registry_path):
return {}
with open(registry_path) as f:
return (yaml_load(f) or {}).get("platforms", {})
return (source_yaml(f) or {}).get("platforms", {})
def list_registered_platforms(platforms_dir: str = "platforms") -> list[str]:
@@ -521,7 +571,7 @@ def list_registered_platforms(platforms_dir: str = "platforms") -> list[str]:
if not os.path.exists(registry_path):
raise InputMissing(f"no platform registry at {registry_path}")
with open(registry_path) as f:
registry = yaml_load(f) or {}
registry = source_yaml(f) or {}
platforms = []
for name, meta in sorted(registry.get("platforms", {}).items()):
config_path = os.path.join(platforms_dir, meta.get("config", f"{name}.yml"))
@@ -621,6 +671,31 @@ def suggest_names(
return f"{listing_flag} lists all {total}."
def work_from_repo_root(
args: argparse.Namespace, parser: argparse.ArgumentParser, path_flags: list[str]
) -> None:
"""Run from the repository root, whichever directory the command started in.
database.json records every file from the root and the data registry
names its caches the same way, so a run from scripts/ ended on a
FileNotFoundError traceback. A path the caller typed is read from where
they typed it, a default from the root.
"""
root = Path(__file__).resolve().parent.parent
if Path.cwd().resolve() == root:
return
for flag in path_flags:
value = getattr(args, flag, None)
if value and value != parser.get_default(flag):
# A Path stays a Path for the code that joins onto it.
setattr(args, flag, type(value)(os.path.abspath(value)))
os.chdir(root)
if getattr(args, "platform", None):
# Read before the move, the registry was not there to map
# "RetroArch" to its slug.
args.platform = platform_arg(args.platform)
def platform_arg(value: str) -> str:
"""--platform as typed, mapped to the registry's slug when it names one.
@@ -669,7 +744,7 @@ def _target_overrides(platform_name: str, targets_dir: str) -> dict:
if not os.path.exists(overrides_file):
return {}
with open(overrides_file) as f:
all_overrides = yaml_load(f) or {}
all_overrides = source_yaml(f) or {}
return all_overrides.get(platform_name, {}).get("targets", {})
@@ -690,7 +765,7 @@ def platform_files_target(platform: str, target: str, platforms_dir: str = "plat
if not os.path.exists(target_file):
return False
with open(target_file) as f:
targets = (yaml_load(f) or {}).get("targets", {})
targets = (source_yaml(f) or {}).get("targets", {})
return target in _target_alias_index(targets, _target_overrides(platform, targets_dir))
@@ -710,7 +785,7 @@ def canonical_target_name(
if not os.path.exists(target_file):
continue
with open(target_file) as f:
targets = (yaml_load(f) or {}).get("targets", {})
targets = (source_yaml(f) or {}).get("targets", {})
canonical = _target_alias_index(
targets, _target_overrides(platform_name, targets_dir)
).get(target)
@@ -764,7 +839,7 @@ def load_target_config(
f"(platforms with targets: {', '.join(with_targets)})"
)
with open(target_file) as f:
data = yaml_load(f) or {}
data = source_yaml(f) or {}
targets = data.get("targets", {})
overrides = _target_overrides(platform_name, targets_dir)
@@ -822,7 +897,7 @@ def list_available_targets(
if not os.path.exists(target_file):
return []
with open(target_file) as f:
data = yaml_load(f) or {}
data = source_yaml(f) or {}
# The count --target filters on: overrides applied, as load_target_config
# applies them. The scraped list counted Batocera's machine variants and
@@ -2229,7 +2304,7 @@ def load_emulator_profiles(
raise InputMissing(f"no emulator profile directory at {emulators_dir}")
for f in source_yaml_paths(emu_path):
with open(f) as fh:
profile = yaml_load(fh) or {}
profile = source_yaml(fh) or {}
if "emulator" not in profile:
continue
_normalize_hash_fields(profile)
@@ -2359,7 +2434,7 @@ def group_identical_platforms(
try:
raw_path = os.path.join(platforms_dir, f"{platform}.yml")
with open(raw_path) as f:
raw = yaml_load(f) or {}
raw = source_yaml(f) or {}
inherits[platform] = "inherits" in raw
config = load_platform_config(platform, platforms_dir)
except FileNotFoundError:
@@ -3503,6 +3578,9 @@ def build_target_cores_cache(
raise
notes.append(f"INFO: Skipping {p}: no hardware targets")
skip.append(p)
except SourceUnreadable:
# A damaged targets file is not a platform without the target.
raise
except ValueError as e:
if is_all:
notes.append(f"INFO: Skipping {p}: {e}")
@@ -3530,7 +3608,7 @@ def _unknown_target_message(target: str, platforms: list[str], platforms_dir: st
if not os.path.exists(target_file):
continue
with open(target_file) as f:
targets = (yaml_load(f) or {}).get("targets", {})
targets = (source_yaml(f) or {}).get("targets", {})
overrides = _target_overrides(platform, targets_dir)
for name in _target_alias_index(targets, overrides):
owners.setdefault(name, []).append(platform)
@@ -3624,10 +3702,18 @@ def run_cli(main: Callable[[], int | None]) -> None:
for name in ("SIGTERM", "SIGHUP"):
if hasattr(signal, name):
signal.signal(getattr(signal, name), _exit_on_signal)
# Redirected, stdout is block-buffered and stderr is not: the --strict
# verdict landed on the first line of the log, before the report it
# closes. Line buffering keeps the two in the order they were written.
# A stream a caller swapped in (a test's StringIO) has nothing to set.
reconfigure = getattr(sys.stdout, "reconfigure", None)
if reconfigure is not None:
reconfigure(line_buffering=True)
try:
code = main()
sys.stdout.flush()
except (InputMissing, ArtifactLockBusy, ArtifactDirectoryMissing) as exc:
except (InputMissing, SourceUnreadable, ArtifactLockBusy,
ArtifactDirectoryMissing) as exc:
print(f"ERROR: {exc}", file=sys.stderr)
sys.exit(1)
except BrokenPipeError:
+8
View File
@@ -40,6 +40,14 @@ from collections.abc import Iterable, Iterator, Sequence
from dataclasses import dataclass, field
from pathlib import Path
# The probe tools do not import common.py, which states the 3.9 floor for the
# other scripts. Under 3.8 they stopped on a str.removesuffix AttributeError.
if sys.version_info < (3, 9):
sys.exit(
f"{Path(sys.argv[0]).name} needs Python 3.9 or newer, "
f"this is {sys.version.split()[0]}"
)
ROOT = Path(__file__).resolve().parent.parent
MIN_BENCH_REPETITIONS = 5
DEFAULT_WORK_DIR = ROOT / "tmp" / "core_probe"
+3
View File
@@ -1191,6 +1191,9 @@ def main() -> None:
"--list-emulators", action="store_true", help="List available emulators"
)
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["emulators_dir", "platforms_dir", "db"])
if args.list_emulators:
ignored = [flag for flag, on in (
("--emulator", args.emulator), ("--platform", args.platform),
+3
View File
@@ -247,6 +247,9 @@ def main() -> int:
help="profiles the rules are checked against (default emulators)")
parser.add_argument("--json", action="store_true", help="print the summary as JSON")
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["regions", "extras", "headers", "emulators_dir"])
regions = load_yaml(args.regions)
extras = load_yaml(args.extras)
+17 -7
View File
@@ -43,6 +43,7 @@ from common import (
require_directory,
target_listing_line,
suggest_names,
system_index,
require_platform,
load_target_config,
archive_entry,
@@ -164,7 +165,9 @@ class PackRecord:
self.sources: dict[str, str] = {}
def _add_pack_member(zf: zipfile.ZipFile, source_path: str, arcname: str) -> None:
def _add_pack_member(
zf: zipfile.ZipFile | PackRecord, source_path: str, arcname: str
) -> None:
"""Add a file to the pack with metadata that does not depend on the build.
ZipFile.write copies the source file's mtime into the member. For a file
@@ -197,7 +200,9 @@ def _add_pack_member(zf: zipfile.ZipFile, source_path: str, arcname: str) -> Non
shutil.copyfileobj(source, target, 1024 * 1024)
def _write_generated_member(zf: zipfile.ZipFile, arcname: str, text: str) -> None:
def _write_generated_member(
zf: zipfile.ZipFile | PackRecord, arcname: str, text: str
) -> None:
"""Write a pack member the builder composes rather than copies.
READMEs, instruction notes and the manifest are produced at build time,
@@ -581,7 +586,7 @@ def _data_directory_members(
def _pack_data_directories(
zf: zipfile.ZipFile,
zf: zipfile.ZipFile | PackRecord,
pack_systems: dict,
data_registry: dict | None,
platform_name: str,
@@ -1476,7 +1481,9 @@ def generate_pack(
def _extract_zip_to_archive(
source_zip: str, dest_prefix: str, target_zf: zipfile.ZipFile
source_zip: str,
dest_prefix: str,
target_zf: zipfile.ZipFile | PackRecord,
) -> None:
"""Extract contents of a source ZIP into target ZIP under dest_prefix."""
with zipfile.ZipFile(source_zip, "r") as src:
@@ -1507,7 +1514,7 @@ def _extract_zip_to_archive(
def _add_zip_to_pack(
source_zip: str,
dest_path: str,
target_zf: zipfile.ZipFile,
target_zf: zipfile.ZipFile | PackRecord,
file_entry: dict | None = None,
) -> None:
"""Write a source ZIP into the pack, byte for byte.
@@ -1555,7 +1562,7 @@ class DamagedArchiveError(OSError):
def _pack_data_tree(
zf: zipfile.ZipFile,
zf: zipfile.ZipFile | PackRecord,
local_cache: str,
dd_dest: str,
seen_destinations: set[str],
@@ -2053,7 +2060,10 @@ def generate_system_pack(
f"No emulators found for system(s): {', '.join(system_ids)}",
file=sys.stderr,
)
print(suggest_names(system_ids, sorted(all_systems), "--list-systems"),
# --list-systems merges spellings that differ in case or separator:
# the hint counted 579 spellings for the 532 lines it prints.
print(suggest_names(system_ids, sorted(all_systems), "--list-systems",
listed=len(system_index(profiles))),
file=sys.stderr)
return None
+1 -1
View File
@@ -14,7 +14,6 @@ Usage:
from __future__ import annotations
from siterender import SECTION_LABELS, WIKI_SRC_DIR
import argparse
import csv
import hashlib
@@ -64,6 +63,7 @@ from common import (
unique_emulator_profiles,
yaml_load,
)
from siterender import SECTION_LABELS, WIKI_SRC_DIR
from artifacts import ArtifactLockBusy, artifact_lock
from artifacts import json_text as _json_text
from cross_reference import FileConsumers, entry_target, held_copy
+3
View File
@@ -146,6 +146,9 @@ def main() -> int:
"--strict", action="store_true", help="exit non-zero when any is found"
)
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["bios_dir"])
from common import require_directory # noqa: PLC0415
require_directory(args.bios_dir)
+4 -1
View File
@@ -26,7 +26,10 @@ def list_platforms() -> list[str]:
def main() -> None:
parser = argparse.ArgumentParser(allow_abbrev=False, description="List available platforms")
parser.parse_args()
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, [])
platforms = list_platforms()
+3
View File
@@ -384,6 +384,9 @@ def main() -> int:
"(the pipeline writes derivable.json)",
)
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["db", "provenance_dir", "emulators_dir", "write_derivable"])
if args.write_derivable and not args.derive:
parser.error("--write-derivable records what --derive finds: pass both")
+3
View File
@@ -201,6 +201,9 @@ def main() -> int:
)
parser.add_argument("--json", action="store_true", help="Machine-readable output")
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["db", "emulators_dir"])
db = load_database(args.db)
profiles = load_emulator_profiles(args.emulators_dir)
+8
View File
@@ -36,6 +36,14 @@ import urllib.request
from collections.abc import Callable, Iterable
from pathlib import Path
# The probe tools do not import common.py, which states the 3.9 floor for the
# other scripts. Under 3.8 they stopped on a str.removesuffix AttributeError.
if sys.version_info < (3, 9):
sys.exit(
f"{Path(sys.argv[0]).name} needs Python 3.9 or newer, "
f"this is {sys.version.split()[0]}"
)
sys.path.insert(0, str(Path(__file__).resolve().parent))
import yaml # noqa: E402
+3
View File
@@ -1009,6 +1009,9 @@ def main() -> int:
"without it the run reports them and exits 0",
)
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["db", "platforms_dir", "emulators_dir"])
import contextlib
+41 -38
View File
@@ -41,8 +41,10 @@ from common import (
_foreign_tree,
_owner_tokens,
platform_arg,
work_from_repo_root,
target_listing_line,
suggest_names,
system_index,
require_platform,
archive_entry,
archive_is_optional,
@@ -129,29 +131,6 @@ DEFAULT_EMULATORS_DIR = "emulators"
REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def work_from_repo_root(
args: argparse.Namespace, parser: argparse.ArgumentParser, path_flags: list[str]
) -> None:
"""Run from the repository root, whichever directory the command started in.
database.json records every file from the root and the data registry
names its caches the same way, so a run from scripts/ ended on a
FileNotFoundError traceback. A path the caller typed is read from where
they typed it, a default from the root.
"""
if os.path.realpath(os.getcwd()) == os.path.realpath(REPO_ROOT):
return
for flag in path_flags:
value = getattr(args, flag, None)
if value and value != parser.get_default(flag):
setattr(args, flag, os.path.abspath(value))
os.chdir(REPO_ROOT)
if getattr(args, "platform", None):
# Read before the move, the registry was not there to map
# "RetroArch" to its slug.
args.platform = platform_arg(args.platform)
# Status model: aligned with Batocera BiosStatus (batocera-systems:967-969)
@@ -1808,7 +1787,8 @@ def _print_undeclared_entry(
ref_part = f" [{u['source_ref']}]" if u.get("source_ref") else ""
print(f" validates {checks_label}{ref_part}")
else:
print(f" [{'+'.join(checks)}]")
# A bare "[size]" under the entry said nothing to a reader.
print(f" validates {'+'.join(checks)}")
def _split_undeclared(undeclared: list[dict]) -> tuple[list[dict], list[dict], list[dict]]:
@@ -1920,10 +1900,15 @@ def _print_undeclared_section(result: dict, verbose: bool) -> None:
u for u in bundled
if u["required"] and u.get("category", "bios") != "game_data"
]
names = ", ".join(sorted({u["name"] for u in shown}))
named = sorted({u["name"] for u in shown})
# The required firmware alone read as the whole count: 14 names
# for 154 entries, nothing saying the rest existed.
hidden = len({u["name"] for u in bundled}) - len(named)
more = f"{hidden} more, " if named else ""
items = named + ([f"{more}--verbose lists them"] if hidden else [])
print(
f" Bundled with their emulator, not collected: {len(bundled)}"
+ (f" ({names})" if names else "")
+ (f" ({', '.join(items)})" if items else "")
)
if unplaced:
print(f" Core files held but not packed: {len(unplaced)} "
@@ -2611,7 +2596,10 @@ def verify_system(
f"No emulators found for system(s): {', '.join(system_ids)}",
file=sys.stderr,
)
print(suggest_names(system_ids, sorted(all_systems), "--list-systems"),
# --list-systems merges spellings that differ in case or separator:
# the hint counted 579 spellings for the 532 lines it prints.
print(suggest_names(system_ids, sorted(all_systems), "--list-systems",
listed=len(system_index(profiles))),
file=sys.stderr)
sys.exit(1)
@@ -2821,7 +2809,7 @@ def _main(held: contextlib.ExitStack) -> None:
parser = argparse.ArgumentParser(allow_abbrev=False, description="Platform-native BIOS verification")
parser.add_argument("--platform", "-p", type=platform_arg, help="Platform name")
parser.add_argument(
"--all", action="store_true", help="Verify all active platforms"
"--all", action="store_true", help="Verify every registered platform"
)
parser.add_argument(
"--emulator", "-e", help="Emulator profile name(s), comma-separated"
@@ -3121,6 +3109,13 @@ def _overall_summary(group_results: list[tuple[dict, list[str]]]) -> str:
named = [f"{name} {count}" for name, count in counts.items() if count]
return f" ({', '.join(named)})" if named else ""
def on(groups: tuple[str, ...]) -> str:
"""The platforms a file is missing on, by the shorter side."""
if len(group_results) < 2 or len(groups) * 2 <= len(group_results):
return ", ".join(groups)
others = [" / ".join(g) for _, g in group_results if " / ".join(g) not in groups]
return "every platform" + (f" but {', '.join(others)}" if others else "")
parts = []
for severity, label in ((Severity.CRITICAL, "critical"), (Severity.WARNING, "warning"),
(Severity.INFO, "info")):
@@ -3139,18 +3134,26 @@ def _overall_summary(group_results: list[tuple[dict, list[str]]]) -> str:
parts.append(f"{total} {'discrepancy' if total == 1 else 'discrepancies'}{where(counts)}")
lines = [f"{platforms} platforms: {', '.join(parts)}"]
missing = {
" / ".join(group): sorted({
# Grouped by file, not by platform: sfiii2a.zip missing everywhere was
# counted and printed once per platform, 24 files for 10 distinct ones.
holders: dict[str, list[str]] = {}
for r, group in group_results:
for name in sorted({
u["name"] for u in _core_required_missing(_split_undeclared(
r.get("undeclared_files", []))[1])
})
for r, group in group_results
}
total = sum(len(names) for names in missing.values())
if total:
detail = "; ".join(f"{group}: {', '.join(names)}"
for group, names in missing.items() if names)
lines.append(f"{total} core file(s) a core cannot run without are missing ({detail})")
}):
holders.setdefault(name, []).append(" / ".join(group))
if holders:
by_platforms: dict[tuple[str, ...], list[str]] = {}
for name, groups in sorted(holders.items()):
by_platforms.setdefault(tuple(groups), []).append(name)
detail = "; ".join(
f"{', '.join(names)} ({on(groups)})"
for groups, names in sorted(by_platforms.items(),
key=lambda item: (-len(item[0]), item[1]))
)
lines.append(f"{len(holders)} core file(s) a core cannot run without are "
f"missing: {detail}")
for category, label in _NOT_FIRMWARE.items():
counts = {
" / ".join(group): len((r.get("missing_not_firmware") or {}).get(category, []))
+2
View File
@@ -9,6 +9,8 @@ corrected it later, every other reader of the resolution did not.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import json
import shutil
+2
View File
@@ -12,6 +12,8 @@ BIOS root of platforms that do not run that emulator.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import sys
import tempfile
+2
View File
@@ -8,6 +8,8 @@ libretro core, while verify set the entry aside. Reads the repository.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import os
import sys
import unittest
+2
View File
@@ -9,6 +9,8 @@ was not where it looks.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import os
import sys
+2
View File
@@ -7,6 +7,8 @@ the slot missing and the manifest omitted it.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import re
import sys
import tempfile
+2
View File
@@ -8,6 +8,8 @@ the firmware of cores its image never had.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import io
import json
import tempfile
+2
View File
@@ -7,6 +7,8 @@ seven of the eight members Batocera checks were missing.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import os
import shutil
+2
View File
@@ -9,6 +9,8 @@ those members were never read there, and the archive matched no recipe.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import sys
import unittest
+2
View File
@@ -7,6 +7,8 @@ ZIPs, which surfaces as BadZipFile far from its cause.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import os
import subprocess
import sys
+2
View File
@@ -8,6 +8,8 @@ path in bios/: a scan running beside the copy hashed the truncated file.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import os
import sys
import tempfile
+161 -1
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import ast
import contextlib
import hashlib
@@ -136,6 +138,41 @@ class ReadmeRegressions(unittest.TestCase):
self.assertNotIn("SyntaxError", proc.stderr)
self.assertIn("generate_pack.py needs Python 3.9", proc.stderr)
def test_every_script_names_the_floor_under_an_older_interpreter(self):
"""Only generate_pack.py and pipeline.py checked the version. verify.py,
slots.py, validate_pr.py and cross_reference.py started under 3.8 and
stopped halfway on a str.removeprefix AttributeError."""
import shutil # noqa: PLC0415
python38 = shutil.which("python3.8")
if python38 is None:
if os.environ.get("CI"):
self.fail("CI must provide python3.8")
self.skipTest("no python3.8 on PATH")
commands = (
["verify.py", "--emulator", "handy"],
["verify.py", "--platform", "batocera"],
["validate_pr.py", "--json", "README.md"],
["cross_reference.py", "--emulator", "handy"],
["slots.py"],
["identity.py"],
["generate_site.py", "--help"],
["campaign.py", "--help"],
["region_check.py", "--help"],
)
for command in commands:
with self.subTest(command=" ".join(command)):
# -E -s rather than -I: -I drops the script's folder from
# sys.path, so the imports would fail before any check.
proc = subprocess.run(
[python38, "-E", "-s", f"scripts/{command[0]}", *command[1:]],
cwd=ROOT, capture_output=True, text=True, timeout=60,
check=False,
)
self.assertEqual(proc.returncode, 1, proc.stderr)
self.assertNotIn("Traceback", proc.stderr)
self.assertIn(f"{command[0]} needs Python 3.9", proc.stderr)
def test_the_floor_interpreter_imports_every_script(self):
"""Every module under scripts/ is loaded by a real interpreter of the
floor version, as the installer's 3.8 floor is proven by running it.
@@ -218,6 +255,46 @@ class AModuleRunAloneHasItsScratchDirectory(unittest.TestCase):
self.assertEqual(proc.stdout.split(), [scratch, scratch])
class EveryTestModuleImportsTheIsolation(unittest.TestCase):
"""tests/__init__.py keeps a run offline, its scratch under tmp/ and its
installer cache its own, but only `discover -s tests -t .` imported it:
`discover tests` ran with RETROBIOS_OFFLINE unset, scratch in /tmp and
the user's real cache. Each module now imports the package first."""
def test_the_package_import_comes_before_any_other(self):
missing = []
for path in sorted((ROOT / "tests").glob("test_*.py")):
body = ast.parse(path.read_text(encoding="utf-8")).body
imports = [
node for node in body
if isinstance(node, (ast.Import, ast.ImportFrom))
and getattr(node, "module", None) != "__future__"
]
first = imports[0] if imports else None
if not (isinstance(first, ast.Import)
and [alias.name for alias in first.names] == ["tests"]):
missing.append(path.name)
self.assertEqual(missing, [])
def test_discover_without_a_top_level_runs_isolated(self):
env = {k: v for k, v in os.environ.items()
if k not in ("RETROBIOS_OFFLINE", "TMPDIR", "RETROBIOS_CACHE")}
proc = subprocess.run(
[sys.executable, "-c",
"import os, sys, tempfile, unittest\n"
"unittest.TestLoader().discover('tests', pattern='test_artifact_lock.py')\n"
"print(os.environ.get('RETROBIOS_OFFLINE'), tempfile.gettempdir(),"
" os.environ.get('RETROBIOS_CACHE'))\n"],
cwd=ROOT, env=env, capture_output=True, text=True, timeout=120,
check=False,
)
self.assertEqual(proc.returncode, 0, proc.stderr)
offline, scratch, cache = proc.stdout.split()
self.assertEqual(offline, "1")
self.assertEqual(scratch, str(ROOT / "tmp" / "tests"))
self.assertEqual(cache, str(ROOT / "tmp" / "tests" / "cache"))
class ReleaseSigningRegressions(unittest.TestCase):
"""A checksum list published beside its own artifacts proves nothing.
@@ -2834,6 +2911,50 @@ class DeclaredDependenciesMatchTheDocumentedWorkflows(unittest.TestCase):
)
class TheAnnotationsAreChecked(unittest.TestCase):
"""Every signature carried type hints and nothing read them: six pack
helpers declared `zipfile.ZipFile` while every caller also passed a
PackRecord, and 990 such contradictions went through CI green. mypy now
runs in CI against mypy-baseline.txt, the errors the code carried when the
check started."""
BASELINE = ROOT / "mypy-baseline.txt"
ENTRY = re.compile(r"(?P<path>[^:]+\.py):0: error: .+ \[[a-z-]+\]")
def test_ci_holds_the_code_to_the_baseline(self):
body = (ROOT / ".github" / "workflows" / "validate.yml").read_text(
encoding="utf-8"
)
self.assertIn("mypy-baseline filter", body)
self.assertNotIn("--allow-unsynced", body)
def test_every_baseline_entry_names_a_file_that_exists(self):
stale = []
for line in self.BASELINE.read_text(encoding="utf-8").splitlines():
match = self.ENTRY.fullmatch(line)
self.assertIsNotNone(match, f"unreadable baseline entry: {line}")
if not (ROOT / match["path"]).is_file():
stale.append(match["path"])
self.assertEqual(stale, [], "baseline entries for files that are gone")
def test_the_code_reports_no_error_outside_the_baseline(self):
for module in ("mypy", "mypy_baseline"):
try:
__import__(module)
except ImportError:
self.skipTest(f"{module} is not installed (pip install -e '.[dev]')")
report = subprocess.run(
[sys.executable, "-m", "mypy"],
cwd=ROOT, capture_output=True, text=True, check=False,
)
result = subprocess.run(
[sys.executable, "-m", "mypy_baseline", "filter", "--no-colors"],
cwd=ROOT, input=report.stdout, capture_output=True, text=True,
check=False,
)
self.assertEqual(result.returncode, 0, result.stdout)
class TheProjectInstallsWithPip(unittest.TestCase):
"""pyproject declared a dev extra that pip could not install: without a
[build-system] and an explicit module list, setuptools' flat-layout
@@ -4991,9 +5112,34 @@ class VerifyAllSummaryNamesWhatIsWrong(unittest.TestCase):
[(clean, ["RetroArch"]), (warned, ["RetroDECK"]), (core_miss, ["ROCKNIX"])]
)
self.assertIn("1 warning (RetroDECK 1)", summary)
self.assertIn("ROCKNIX: n64.psh", summary)
self.assertIn("n64.psh (ROCKNIX)", summary)
self.assertIn("0 critical,", summary)
def test_a_file_missing_on_several_platforms_is_counted_once(self):
"""sfiii2a.zip missing on 15 platforms read '24 core file(s)' for 10
distinct files, the name printed 15 times on one line."""
sys.path.insert(0, str(ROOT / "scripts"))
import verify
def missing(*names: str) -> dict:
return {"severity_counts": {}, "undeclared_files": [
{"name": name, "required": True, "in_repo": False,
"category": "bios", "in_pack": True} for name in names
]}
summary = verify._overall_summary([
(missing("sfiii2a.zip"), ["Batocera"]),
(missing("sfiii2a.zip", "ROM"), ["RetroPie"]),
(missing("sfiii2a.zip"), ["RomM"]),
(missing(), ["MinUI"]),
])
self.assertIn(
"2 core file(s) a core cannot run without are missing: "
"sfiii2a.zip (every platform but MinUI); ROM (RetroPie)",
summary,
)
self.assertEqual(summary.count("sfiii2a.zip"), 1)
class OneOutputFormPerRun(unittest.TestCase):
@@ -5956,6 +6102,20 @@ class TheRepairCommandWritesTheFileNamed(unittest.TestCase):
load_database(target)
self.assertIn(f"--output {target}", str(caught.exception))
def test_a_typo_beside_the_database_names_the_database(self):
"""--db databse.json beside database.json was told to rescan the whole
collection into a second file named after the typo."""
from scripts.common import DatabaseUnreadable, load_database
with tempfile.TemporaryDirectory(dir=TMP_ROOT) as directory:
(Path(directory) / "database.json").write_text("{}")
typo = Path(directory) / "databse.json"
with self.assertRaises(DatabaseUnreadable) as caught:
load_database(str(typo))
message = str(caught.exception)
self.assertIn(f"Did you mean {typo.with_name('database.json')}?", message)
self.assertNotIn("generate_db.py", message)
class VerifyPacksRefusesWhatItCannotDo(unittest.TestCase):
"""The --verify-packs refusals lived in the --all-variants checks, which
+2
View File
@@ -7,6 +7,8 @@ a function returning canned CI runs.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import contextlib
import io
import json
+2
View File
@@ -9,6 +9,8 @@ under it: amiberry, fsuae and vice were never in a target list.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -9,6 +9,8 @@ a list, and verify accepts any listed md5.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import sys
import tempfile
+2
View File
@@ -9,6 +9,8 @@ the Batocera BIOS folder.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -7,6 +7,8 @@ Oric and Tangerine: one machine, two folders, two pages.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import subprocess
import unittest
from pathlib import Path
+2
View File
@@ -13,6 +13,8 @@ entry is written with the hash of the file the emulator ships.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import sys
import unittest
+2
View File
@@ -10,6 +10,8 @@ directory cache is not a collection.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import os
import sys
import unittest
+2
View File
@@ -10,6 +10,8 @@ resume and rerun on a changed core.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import contextlib
import hashlib
import io
+2
View File
@@ -7,6 +7,8 @@ went red. The flag lived in retrobat.yml and vanished at the next scrape.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import contextlib
import hashlib
import io
+2
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -8,6 +8,8 @@ report is folded, since each of those decides whether a row says STALE.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import json
import os
import sys
+2
View File
@@ -7,6 +7,8 @@ whose checksums every user's `sha256sum --check` rejected.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -6,6 +6,8 @@ one. validate_schemas now refuses it.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import subprocess
import sys
import unittest
+2
View File
@@ -7,6 +7,8 @@ does not hold the file.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import re
import sys
import unittest
+2
View File
@@ -6,6 +6,8 @@ the repository, five on the site, under two different titles.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import re
import sys
import unittest
+2
View File
@@ -10,6 +10,8 @@ reader now gets the tree, or the profile says its package installs it.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import os
import sys
import unittest
@@ -8,6 +8,8 @@ frontend sees a file at the path. verify kept it MISSING, so the pack said
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import contextlib
import io
+2
View File
@@ -7,6 +7,8 @@ probe on it: staging, the worker process, strace, the record and its schema.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import argparse
import contextlib
import hashlib
+2
View File
@@ -10,6 +10,8 @@ read one rule (validation.core_size_refusal).
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import os
import sys
+2
View File
@@ -9,6 +9,8 @@ tests change an input and expect a fresh computation.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import tempfile
import unittest
+2
View File
@@ -9,6 +9,8 @@ a directory called ROM).
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import tempfile
import unittest
+2
View File
@@ -7,6 +7,8 @@ contributor with none of them.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import ast
import sys
import unittest
+2
View File
@@ -18,6 +18,8 @@ Layouts, from Azahar src/core/hw/unique_data.cpp and src/core/file_sys/otp.cpp:
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import struct
import sys
+2
View File
@@ -14,6 +14,8 @@ constants rather than against itself. The AES vector is from NIST SP 800-38A.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import shutil
import sys
+2
View File
@@ -6,6 +6,8 @@ verify only said "not cached" and refresh_data_dirs had nothing to fetch.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -7,6 +7,8 @@ TypeError on the first loop.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import ast
import unittest
from pathlib import Path
+2
View File
@@ -8,6 +8,8 @@ disk ROM then served the CoCo one.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import os
import sys
import tempfile
+2
View File
@@ -8,6 +8,8 @@ set, enriched with every spelling the database knows.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -9,6 +9,8 @@ are both load-bearing.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import contextlib
import io
import os
+2
View File
@@ -7,6 +7,8 @@ is two held ROMs end to end. The gap report listed them as acquisition targets.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import os
import shutil
+2
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import os
import tempfile
+2
View File
@@ -9,6 +9,8 @@ reported missing while 3 584 collected files stayed out of every pack.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import json
import sys
+2
View File
@@ -7,6 +7,8 @@ code moves, and nothing else notices.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import ast
import hashlib
import inspect
+2
View File
@@ -9,6 +9,8 @@ tool prints, and a size is the one the release record holds.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import ast
import contextlib
import re
+2
View File
@@ -9,6 +9,8 @@ checksum of each layout and the staging location.
"""
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import contextlib
import functools
import hashlib
+2
View File
@@ -17,6 +17,8 @@ Covers:
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import contextlib
import hashlib
import io
+2
View File
@@ -9,6 +9,8 @@ upstream files.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -9,6 +9,8 @@ firmware of cores its image never had.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import json
import sys
import unittest
+2
View File
@@ -9,6 +9,8 @@ names and ten "missing".
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import re
import subprocess
import sys
+2
View File
@@ -6,6 +6,8 @@ from what the cores the platform runs open, never from the entry's name.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -9,6 +9,8 @@ from a file other than the one the hash describes.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import json
import sys
import unittest
+2
View File
@@ -9,6 +9,8 @@ libretro's System.dat (N88EXT0-3.ROM) as if libretro declared them.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import tempfile
import unittest
+2
View File
@@ -7,6 +7,8 @@ file from and no list to check the diff against.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import re
import sys
import tempfile
+2
View File
@@ -14,6 +14,8 @@ and skip when it has not been populated (python scripts/export_native.py
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import difflib
import io
import json
+2
View File
@@ -8,6 +8,8 @@ Galaksija ROM and a PS2 ROM2.BIN.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -9,6 +9,8 @@ have vanished with it.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import tempfile
import unittest
from pathlib import Path
+2
View File
@@ -8,6 +8,8 @@ homonym tests/test_game_data_homonyms.py forbids the resolver to serve.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import sys
import tempfile
+2
View File
@@ -8,6 +8,8 @@ directory, and only a manual reading found it.
"""
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import tempfile
import unittest
+2
View File
@@ -7,6 +7,8 @@ attached to misterfpga by substring and checked against the full list:
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import os
import sys
import tempfile
+2
View File
@@ -6,6 +6,8 @@ today's upstream no longer carries, but the bytes are in the project's history.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import sys
import unittest
+2
View File
@@ -9,6 +9,8 @@ and put every file one directory too deep.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import unittest
from pathlib import Path
+2
View File
@@ -9,6 +9,8 @@ to upstream PCSX2.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import os
import sys
+2
View File
@@ -9,6 +9,8 @@ served while data/bluemsx held the 8 KB one.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import os
import shutil
+2
View File
@@ -8,6 +8,8 @@ the pack and the manifest while verify, comparing md5, called it OK.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import os
import sys
+2
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import json
import subprocess
import sys
+2
View File
@@ -12,6 +12,8 @@ carries `unsourceable:` until its own bytes are held.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import os
import re
+2
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import json
import re
import sys
+2
View File
@@ -8,6 +8,8 @@ can lose its backing, then on the repository's own files.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import copy
import json
import sys
+2
View File
@@ -7,6 +7,8 @@ so a test pins the join and not the state of the data.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import json
import shutil
import sys
+2
View File
@@ -7,6 +7,8 @@ it. RetroArch names Galaksija's 4 KiB galaksija/rom1.bin, so DOSBox's
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import sys
import unittest
from pathlib import Path
+2
View File
@@ -10,6 +10,8 @@ the pad reaching the console, a compositor covering it) is not exercised.
"""
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import importlib.util
import json
+2
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import json
import tempfile
import unittest
+2
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import shutil
import sys
import tempfile
+2
View File
@@ -9,6 +9,8 @@ ROCKNIX's higan SGB1.sfc/program.rom under the file SGB1.sfc.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import os
import sys
import unittest
+2
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import shutil
import sys
import tempfile
+2
View File
@@ -1,6 +1,8 @@
"""Tests for install.py platform detection and config parsing."""
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import contextlib
import functools
import hashlib
+2
View File
@@ -8,6 +8,8 @@ menu) is not exercised.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import hashlib
import io
import json
+2
View File
@@ -8,6 +8,8 @@ which cores keep each system, the rule a pack built for a target follows.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import contextlib
import io
import json
+2
View File
@@ -7,6 +7,8 @@ honours Retry-After, and large files that resume where they stopped.
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import contextlib
import errno
import hashlib
Loaded 100 of 270 files, more files were not shown because too many files have changed in this diff. Show more