gnomeExtensions/update: Modernize type annotations

Since Python 3.9, standard collections can be used with generics in type annotations:
https://docs.python.org/3.9/whatsnew/3.9.html#type-hinting-generics-in-standard-collections

Since Python 3.10, `Optional` can be written using type union with `None`:
https://docs.python.org/3.10/whatsnew/3.10.html#pep-604-new-type-union-operator
This commit is contained in:
Honnip
2025-05-08 21:08:40 +02:00
committed by Jan Tojnar
parent 3f038d8334
commit 3a996268cd
@@ -10,7 +10,7 @@ import urllib.request
from contextlib import contextmanager
from operator import itemgetter
from pathlib import Path
from typing import List, Dict, Optional, Any, Tuple, Set
from typing import Any
# We don't want all those deprecated legacy extensions
# Group extensions by GNOME "major" version for compatibility reasons
@@ -35,15 +35,15 @@ ExtensionVersion = int
# Keep track of all names that have been used till now to detect collisions.
# This works because we deterministically process all extensions in historical order
# The outer dict level is the shell version, as we are tracking duplicates only per same Shell version.
# key: shell version, value: Dict with key: pname, value: list of UUIDs with that pname
package_name_registry: Dict[ShellVersion, Dict[PackageName, List[Uuid]]] = {}
# key: shell version, value: dict with key: pname, value: list of UUIDs with that pname
package_name_registry: dict[ShellVersion, dict[PackageName, list[Uuid]]] = {}
for shell_version in supported_versions.keys():
package_name_registry[shell_version] = {}
updater_dir_path = Path(__file__).resolve().parent
def fetch_extension_data(uuid: str, version: str) -> Tuple[str, str]:
def fetch_extension_data(uuid: str, version: str) -> tuple[str, str]:
"""
Download the extension and hash it. We use `nix-prefetch-url` for this for efficiency reasons.
Returns a tuple with the hash (Nix-compatible) of the zip file's content and the base64-encoded content of its metadata.json.
@@ -90,9 +90,9 @@ def fetch_extension_data(uuid: str, version: str) -> Tuple[str, str]:
def generate_extension_versions(
extension_version_map: Dict[ShellVersion, ExtensionVersion],
extension_version_map: dict[ShellVersion, ExtensionVersion],
uuid: str,
) -> Dict[ShellVersion, Dict[str, str]]:
) -> dict[ShellVersion, dict[str, str]]:
"""
Takes in a mapping from shell versions to extension versions and transforms it the way we need it:
- Only take one extension version per GNOME Shell major version (as per `supported_versions`)
@@ -101,10 +101,10 @@ def generate_extension_versions(
"""
# Determine extension version per shell version
extension_versions: Dict[ShellVersion, ExtensionVersion] = {}
extension_versions: dict[ShellVersion, ExtensionVersion] = {}
for shell_version, version_prefix in supported_versions.items():
# Newest compatible extension version
extension_version: Optional[int] = max(
extension_version: int | None = max(
(
int(ext_ver)
for shell_ver, ext_ver in extension_version_map.items()
@@ -119,7 +119,7 @@ def generate_extension_versions(
extension_versions[shell_version] = extension_version
# Download information once for all extension versions chosen above
extension_info_cache: Dict[ExtensionVersion, Tuple[str, str]] = {}
extension_info_cache: dict[ExtensionVersion, tuple[str, str]] = {}
for extension_version in sorted(set(extension_versions.values())):
logging.debug(f"[{uuid}] Downloading v{extension_version}")
extension_info_cache[extension_version] = fetch_extension_data(
@@ -128,7 +128,7 @@ def generate_extension_versions(
)
# Fill map
extension_versions_full: Dict[ShellVersion, Dict[str, str]] = {}
extension_versions_full: dict[ShellVersion, dict[str, str]] = {}
for shell_version, extension_version in extension_versions.items():
sha256, metadata = extension_info_cache[extension_version]
@@ -143,7 +143,7 @@ def generate_extension_versions(
return extension_versions_full
def pname_from_url(url: str) -> Tuple[str, str]:
def pname_from_url(url: str) -> tuple[str, str]:
"""
Parse something like "/extension/1475/battery-time/" and output ("battery-time", "1475")
"""
@@ -152,7 +152,7 @@ def pname_from_url(url: str) -> Tuple[str, str]:
return url[3], url[2]
def process_extension(extension: Dict[str, Any]) -> Optional[Dict[str, Any]]:
def process_extension(extension: dict[str, Any]) -> dict[str, Any] | None:
"""
Process an extension. It takes in raw scraped data and downloads all the necessary information that buildGnomeExtension.nix requires
@@ -203,11 +203,11 @@ def process_extension(extension: Dict[str, Any]) -> Optional[Dict[str, Any]]:
# Input is a mapping str -> { version: int, … }
# We want to map shell versions to extension versions
shell_version_map: Dict[ShellVersion, int] = {
shell_version_map: dict[ShellVersion, int] = {
k: v["version"] for k, v in extension["shell_version_map"].items()
}
# Transform shell_version_map to be more useful for us. Also throw away unwanted versions
shell_version_map: Dict[ShellVersion, Dict[str, str]] = generate_extension_versions(shell_version_map, uuid) # type: ignore
shell_version_map: dict[ShellVersion, dict[str, str]] = generate_extension_versions(shell_version_map, uuid) # type: ignore
# No compatible versions found
if not shell_version_map:
@@ -236,7 +236,7 @@ def process_extension(extension: Dict[str, Any]) -> Optional[Dict[str, Any]]:
@contextmanager
def request(url: str, retries: int = 5, retry_codes: List[int] = [500, 502, 503, 504]):
def request(url: str, retries: int = 5, retry_codes: list[int] = [500, 502, 503, 504]):
for attempt in range(retries + 1):
try:
with urllib.request.urlopen(url) as response:
@@ -249,7 +249,7 @@ def request(url: str, retries: int = 5, retry_codes: List[int] = [500, 502, 503,
raise e
def scrape_extensions_index() -> List[Dict[str, Any]]:
def scrape_extensions_index() -> list[dict[str, Any]]:
"""
Scrape the list of extensions by sending search queries to the API. We simply go over it
page by page until we hit a non-full page or a 404 error.
@@ -297,7 +297,7 @@ if __name__ == "__main__":
raw_extensions = scrape_extensions_index()
logging.info(f"Downloaded {len(raw_extensions)} extensions. Processing …")
processed_extensions: List[Dict[str, Any]] = []
processed_extensions: list[dict[str, Any]] = []
for num, raw_extension in enumerate(raw_extensions):
processed_extension = process_extension(raw_extension)
if processed_extension:
@@ -354,7 +354,7 @@ if __name__ == "__main__":
v for k, v in package_name_registry.items() if k in last_3_versions
]
# Merge all package names into a single dictionary
package_name_registry_filtered: Dict[PackageName, Set[Uuid]] = {}
package_name_registry_filtered: dict[PackageName, set[Uuid]] = {}
for pkgs in package_name_registry_for_versions:
for pname, uuids in pkgs.items():
if pname not in package_name_registry_filtered:
@@ -365,7 +365,7 @@ if __name__ == "__main__":
k: v for k, v in package_name_registry_filtered.items() if len(v) > 1
}
# Convert set to list
collisions: Dict[PackageName, List[Uuid]] = {
collisions: dict[PackageName, list[Uuid]] = {
k: list(v) for k, v in package_name_registry_filtered.items()
}
json.dump(collisions, out, indent=2, ensure_ascii=False)