mirror of
https://github.com/malmeloo/FindMy.py.git
synced 2026-04-17 21:53:57 +02:00
refactor: specialize Serializable subclasses for stronger type safety
This commit is contained in:
@@ -82,7 +82,7 @@ class RollingKeyPairSource(ABC):
|
||||
return keys
|
||||
|
||||
|
||||
class FindMyAccessory(RollingKeyPairSource, Serializable):
|
||||
class FindMyAccessory(RollingKeyPairSource, Serializable[FindMyAccessoryMapping]):
|
||||
"""A findable Find My-accessory using official key rollover."""
|
||||
|
||||
def __init__( # noqa: PLR0913
|
||||
|
||||
@@ -127,7 +127,7 @@ class HasPublicKey(HasHashedPublicKey, ABC):
|
||||
)
|
||||
|
||||
|
||||
class KeyPair(HasPublicKey, Serializable):
|
||||
class KeyPair(HasPublicKey, Serializable[KeyPairMapping]):
|
||||
"""A private-public keypair for a trackable FindMy accessory."""
|
||||
|
||||
def __init__(
|
||||
|
||||
@@ -141,7 +141,7 @@ def _extract_phone_numbers(html: str) -> list[dict]:
|
||||
return data.get("direct", {}).get("phoneNumberVerification", {}).get("trustedPhoneNumbers", [])
|
||||
|
||||
|
||||
class BaseAppleAccount(Closable, Serializable, ABC):
|
||||
class BaseAppleAccount(Closable, Serializable[AccountStateMapping], ABC):
|
||||
"""Base class for an Apple account."""
|
||||
|
||||
@property
|
||||
|
||||
@@ -188,7 +188,7 @@ class BaseAnisetteProvider(Closable, Serializable, ABC):
|
||||
return cpd
|
||||
|
||||
|
||||
class RemoteAnisetteProvider(BaseAnisetteProvider):
|
||||
class RemoteAnisetteProvider(BaseAnisetteProvider, Serializable[RemoteAnisetteMapping]):
|
||||
"""Anisette provider. Fetches headers from a remote Anisette server."""
|
||||
|
||||
_ANISETTE_DATA_VALID_FOR = 30
|
||||
@@ -269,7 +269,7 @@ class RemoteAnisetteProvider(BaseAnisetteProvider):
|
||||
await self._http.close()
|
||||
|
||||
|
||||
class LocalAnisetteProvider(BaseAnisetteProvider):
|
||||
class LocalAnisetteProvider(BaseAnisetteProvider, Serializable[LocalAnisetteMapping]):
|
||||
"""Anisette provider. Generates headers without a remote server using the `anisette` library."""
|
||||
|
||||
def __init__(
|
||||
|
||||
@@ -51,7 +51,7 @@ class LocationReportDecryptedMapping(TypedDict):
|
||||
LocationReportMapping = Union[LocationReportEncryptedMapping, LocationReportDecryptedMapping]
|
||||
|
||||
|
||||
class LocationReport(HasHashedPublicKey, Serializable):
|
||||
class LocationReport(HasHashedPublicKey, Serializable[LocationReportMapping]):
|
||||
"""Location report corresponding to a certain `HasHashedPublicKey`."""
|
||||
|
||||
def __init__(
|
||||
|
||||
@@ -5,12 +5,13 @@ from __future__ import annotations
|
||||
import asyncio
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from collections.abc import Mapping
|
||||
from typing import TYPE_CHECKING, Generic, Self, TypeVar
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
logging.getLogger(__name__)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Closable(ABC):
|
||||
@@ -42,14 +43,14 @@ class Closable(ABC):
|
||||
pass
|
||||
|
||||
|
||||
T = TypeVar("T", bound=dict)
|
||||
_T = TypeVar("_T", bound=Mapping)
|
||||
|
||||
|
||||
class Serializable(Generic[T], ABC):
|
||||
class Serializable(Generic[_T], ABC):
|
||||
"""ABC for serializable classes."""
|
||||
|
||||
@abstractmethod
|
||||
def to_json(self, dst: str | Path | None = None, /) -> T:
|
||||
def to_json(self, dst: str | Path | None = None, /) -> _T:
|
||||
"""
|
||||
Export the current state of the object as a JSON-serializable dictionary.
|
||||
|
||||
@@ -66,7 +67,7 @@ class Serializable(Generic[T], ABC):
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def from_json(cls, val: str | Path | T, /) -> Self:
|
||||
def from_json(cls, val: str | Path | _T, /) -> Self:
|
||||
"""
|
||||
Restore state from a previous `Closable.to_json` export.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user