mirror of
https://github.com/malmeloo/FindMy.py.git
synced 2026-04-26 18:55:46 +02:00
docs: somewhat fix references in source code
This commit is contained in:
@@ -41,7 +41,7 @@ class FindMyAccessoryMapping(TypedDict):
|
||||
|
||||
|
||||
class RollingKeyPairSource(ABC):
|
||||
"""A class that generates rolling `KeyPair`s."""
|
||||
"""A class that generates rolling :meth:`KeyPair`s."""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
|
||||
@@ -21,5 +21,5 @@ class InvalidStateError(RuntimeError):
|
||||
"""
|
||||
Raised when a method is used that is in conflict with the internal account state.
|
||||
|
||||
For example: calling `BaseAppleAccount.login` while already logged in.
|
||||
For example: calling :meth:`BaseAppleAccount.login` while already logged in.
|
||||
"""
|
||||
|
||||
@@ -91,7 +91,7 @@ class HasPublicKey(HasHashedPublicKey, ABC):
|
||||
@property
|
||||
@override
|
||||
def hashed_adv_key_bytes(self) -> bytes:
|
||||
"""See `HasHashedPublicKey.hashed_adv_key_bytes`."""
|
||||
"""See :meth:`HasHashedPublicKey.hashed_adv_key_bytes`."""
|
||||
return hashlib.sha256(self.adv_key_bytes).digest()
|
||||
|
||||
@property
|
||||
@@ -136,7 +136,7 @@ class KeyPair(HasPublicKey, Serializable[KeyPairMapping]):
|
||||
key_type: KeyType = KeyType.UNKNOWN,
|
||||
name: str | None = None,
|
||||
) -> None:
|
||||
"""Initialize the `KeyPair` with the private key bytes."""
|
||||
"""Initialize the :meth:`KeyPair` with the private key bytes."""
|
||||
priv_int = crypto.bytes_to_int(private_key)
|
||||
self._priv_key = ec.derive_private_key(
|
||||
priv_int,
|
||||
@@ -162,15 +162,15 @@ class KeyPair(HasPublicKey, Serializable[KeyPairMapping]):
|
||||
|
||||
@classmethod
|
||||
def new(cls) -> KeyPair:
|
||||
"""Generate a new random `KeyPair`."""
|
||||
"""Generate a new random :meth:`KeyPair`."""
|
||||
return cls(secrets.token_bytes(28))
|
||||
|
||||
@classmethod
|
||||
def from_b64(cls, key_b64: str) -> KeyPair:
|
||||
"""
|
||||
Import an existing `KeyPair` from its base64-encoded representation.
|
||||
Import an existing :meth:`KeyPair` from its base64-encoded representation.
|
||||
|
||||
Same format as returned by `KeyPair.private_key_b64`.
|
||||
Same format as returned by :meth:`KeyPair.private_key_b64`.
|
||||
"""
|
||||
return cls(base64.b64decode(key_b64))
|
||||
|
||||
@@ -185,7 +185,7 @@ class KeyPair(HasPublicKey, Serializable[KeyPairMapping]):
|
||||
"""
|
||||
Return the private key as a base64-encoded string.
|
||||
|
||||
Can be re-imported using `KeyPair.from_b64`.
|
||||
Can be re-imported using :meth:`KeyPair.from_b64`.
|
||||
"""
|
||||
return base64.b64encode(self.private_key_bytes).decode("ascii")
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ def get_key() -> bytes:
|
||||
|
||||
def decrypt_plist(encrypted: str | Path | bytes | IO[bytes], key: bytes) -> dict:
|
||||
"""
|
||||
Decrypts the encrypted plist file at `encrypted` using the provided `key`.
|
||||
Decrypts the encrypted plist file at :meth:`encrypted` using the provided :meth:`key`.
|
||||
|
||||
:param encrypted: If bytes or IO, the encrypted plist data.
|
||||
If str or Path, the path to the encrypted plist file, which is
|
||||
|
||||
@@ -200,7 +200,7 @@ class BaseAppleAccount(Closable, Serializable[AccountStateMapping], ABC):
|
||||
"""
|
||||
Request a 2FA code to be sent to a specific phone number ID.
|
||||
|
||||
Consider using `BaseSecondFactorMethod.request` instead.
|
||||
Consider using :meth:`BaseSecondFactorMethod.request` instead.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -209,7 +209,7 @@ class BaseAppleAccount(Closable, Serializable[AccountStateMapping], ABC):
|
||||
"""
|
||||
Submit a 2FA code that was sent to a specific phone number ID.
|
||||
|
||||
Consider using `BaseSecondFactorMethod.submit` instead.
|
||||
Consider using :meth:`BaseSecondFactorMethod.submit` instead.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -218,7 +218,7 @@ class BaseAppleAccount(Closable, Serializable[AccountStateMapping], ABC):
|
||||
"""
|
||||
Request a 2FA code to be sent to a trusted device.
|
||||
|
||||
Consider using `BaseSecondFactorMethod.request` instead.
|
||||
Consider using :meth:`BaseSecondFactorMethod.request` instead.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -227,7 +227,7 @@ class BaseAppleAccount(Closable, Serializable[AccountStateMapping], ABC):
|
||||
"""
|
||||
Submit a 2FA code that was sent to a trusted device.
|
||||
|
||||
Consider using `BaseSecondFactorMethod.submit` instead.
|
||||
Consider using :meth:`BaseSecondFactorMethod.submit` instead.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -270,9 +270,9 @@ class BaseAppleAccount(Closable, Serializable[AccountStateMapping], ABC):
|
||||
list[LocationReport] | dict[HasHashedPublicKey | RollingKeyPairSource, list[LocationReport]]
|
||||
]:
|
||||
"""
|
||||
Fetch location reports for `HasHashedPublicKey`s between `date_from` and `date_end`.
|
||||
Fetch location reports for :class:`HasHashedPublicKey`s between `date_from` and `date_end`.
|
||||
|
||||
Returns a dictionary mapping `HasHashedPublicKey`s to a list of their location reports.
|
||||
Returns a dictionary mapping :class:`HasHashedPublicKey`s to their location reports.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -311,9 +311,9 @@ class BaseAppleAccount(Closable, Serializable[AccountStateMapping], ABC):
|
||||
list[LocationReport] | dict[HasHashedPublicKey | RollingKeyPairSource, list[LocationReport]]
|
||||
]:
|
||||
"""
|
||||
Fetch location reports for a sequence of `HasHashedPublicKey`s for the last `hours` hours.
|
||||
Fetch location reports for :class:`HasHashedPublicKey`s for the last `hours` hours.
|
||||
|
||||
Utility method as an alternative to using `BaseAppleAccount.fetch_reports` directly.
|
||||
Utility method as an alternative to using :meth:`BaseAppleAccount.fetch_reports` directly.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -326,13 +326,13 @@ class BaseAppleAccount(Closable, Serializable[AccountStateMapping], ABC):
|
||||
"""
|
||||
Retrieve a complete dictionary of Anisette headers.
|
||||
|
||||
Utility method for `AnisetteProvider.get_headers` using this account's user and device ID.
|
||||
Utility method for :meth:`AnisetteProvider.get_headers` using this account's user/device ID.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class AsyncAppleAccount(BaseAppleAccount):
|
||||
"""An async implementation of `BaseAppleAccount`."""
|
||||
"""An async implementation of :meth:`BaseAppleAccount`."""
|
||||
|
||||
# auth endpoints
|
||||
_ENDPOINT_GSA = "https://gsa.apple.com/grandslam/GsService2"
|
||||
@@ -357,7 +357,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
"""
|
||||
Initialize the apple account.
|
||||
|
||||
:param anisette: An instance of `AsyncAnisetteProvider`.
|
||||
:param anisette: An instance of :meth:`AsyncAnisetteProvider`.
|
||||
"""
|
||||
super().__init__()
|
||||
|
||||
@@ -401,7 +401,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
@property
|
||||
@override
|
||||
def login_state(self) -> LoginState:
|
||||
"""See `BaseAppleAccount.login_state`."""
|
||||
"""See :meth:`BaseAppleAccount.login_state`."""
|
||||
return self._login_state
|
||||
|
||||
@property
|
||||
@@ -412,7 +412,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
)
|
||||
@override
|
||||
def account_name(self) -> str | None:
|
||||
"""See `BaseAppleAccount.account_name`."""
|
||||
"""See :meth:`BaseAppleAccount.account_name`."""
|
||||
return self._account_info["account_name"] if self._account_info else None
|
||||
|
||||
@property
|
||||
@@ -423,7 +423,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
)
|
||||
@override
|
||||
def first_name(self) -> str | None:
|
||||
"""See `BaseAppleAccount.first_name`."""
|
||||
"""See :meth:`BaseAppleAccount.first_name`."""
|
||||
return self._account_info["first_name"] if self._account_info else None
|
||||
|
||||
@property
|
||||
@@ -434,7 +434,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
)
|
||||
@override
|
||||
def last_name(self) -> str | None:
|
||||
"""See `BaseAppleAccount.last_name`."""
|
||||
"""See :meth:`BaseAppleAccount.last_name`."""
|
||||
return self._account_info["last_name"] if self._account_info else None
|
||||
|
||||
@override
|
||||
@@ -501,7 +501,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
@require_login_state(LoginState.LOGGED_OUT)
|
||||
@override
|
||||
async def login(self, username: str, password: str) -> LoginState:
|
||||
"""See `BaseAppleAccount.login`."""
|
||||
"""See :meth:`BaseAppleAccount.login`."""
|
||||
# LOGGED_OUT -> (REQUIRE_2FA or AUTHENTICATED)
|
||||
new_state = await self._gsa_authenticate(username, password)
|
||||
if new_state == LoginState.REQUIRE_2FA: # pass control back to handle 2FA
|
||||
@@ -513,7 +513,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
@require_login_state(LoginState.REQUIRE_2FA)
|
||||
@override
|
||||
async def get_2fa_methods(self) -> Sequence[AsyncSecondFactorMethod]:
|
||||
"""See `BaseAppleAccount.get_2fa_methods`."""
|
||||
"""See :meth:`BaseAppleAccount.get_2fa_methods`."""
|
||||
methods: list[AsyncSecondFactorMethod] = []
|
||||
|
||||
if self._account_info is None:
|
||||
@@ -542,7 +542,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
@require_login_state(LoginState.REQUIRE_2FA)
|
||||
@override
|
||||
async def sms_2fa_request(self, phone_number_id: int) -> None:
|
||||
"""See `BaseAppleAccount.sms_2fa_request`."""
|
||||
"""See :meth:`BaseAppleAccount.sms_2fa_request`."""
|
||||
data = {"phoneNumber": {"id": phone_number_id}, "mode": "sms"}
|
||||
|
||||
await self._sms_2fa_request(
|
||||
@@ -554,7 +554,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
@require_login_state(LoginState.REQUIRE_2FA)
|
||||
@override
|
||||
async def sms_2fa_submit(self, phone_number_id: int, code: str) -> LoginState:
|
||||
"""See `BaseAppleAccount.sms_2fa_submit`."""
|
||||
"""See :meth:`BaseAppleAccount.sms_2fa_submit`."""
|
||||
data = {
|
||||
"phoneNumber": {"id": phone_number_id},
|
||||
"securityCode": {"code": str(code)},
|
||||
@@ -579,7 +579,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
@require_login_state(LoginState.REQUIRE_2FA)
|
||||
@override
|
||||
async def td_2fa_request(self) -> None:
|
||||
"""See `BaseAppleAccount.td_2fa_request`."""
|
||||
"""See :meth:`BaseAppleAccount.td_2fa_request`."""
|
||||
headers = {
|
||||
"Content-Type": "text/x-xml-plist",
|
||||
"Accept": "text/x-xml-plist",
|
||||
@@ -593,7 +593,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
@require_login_state(LoginState.REQUIRE_2FA)
|
||||
@override
|
||||
async def td_2fa_submit(self, code: str) -> LoginState:
|
||||
"""See `BaseAppleAccount.td_2fa_submit`."""
|
||||
"""See :meth:`BaseAppleAccount.td_2fa_submit`."""
|
||||
headers = {
|
||||
"security-code": code,
|
||||
"Content-Type": "text/x-xml-plist",
|
||||
@@ -717,7 +717,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
) -> (
|
||||
list[LocationReport] | dict[HasHashedPublicKey | RollingKeyPairSource, list[LocationReport]]
|
||||
):
|
||||
"""See `BaseAppleAccount.fetch_reports`."""
|
||||
"""See :meth:`BaseAppleAccount.fetch_reports`."""
|
||||
date_to = date_to or datetime.now().astimezone()
|
||||
|
||||
return await self._reports.fetch_reports(
|
||||
@@ -758,7 +758,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
) -> (
|
||||
list[LocationReport] | dict[HasHashedPublicKey | RollingKeyPairSource, list[LocationReport]]
|
||||
):
|
||||
"""See `BaseAppleAccount.fetch_last_reports`."""
|
||||
"""See :meth:`BaseAppleAccount.fetch_last_reports`."""
|
||||
end = datetime.now(tz=timezone.utc)
|
||||
start = end - timedelta(hours=hours)
|
||||
|
||||
@@ -971,15 +971,15 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
with_client_info: bool = False,
|
||||
serial: str = "0",
|
||||
) -> dict[str, str]:
|
||||
"""See `BaseAppleAccount.get_anisette_headers`."""
|
||||
"""See :meth:`BaseAppleAccount.get_anisette_headers`."""
|
||||
return await self._anisette.get_headers(self._uid, self._devid, serial, with_client_info)
|
||||
|
||||
|
||||
class AppleAccount(BaseAppleAccount):
|
||||
"""
|
||||
A sync implementation of `BaseappleAccount`.
|
||||
A sync implementation of :meth:`BaseappleAccount`.
|
||||
|
||||
Uses `AsyncappleAccount` internally.
|
||||
Uses :meth:`AsyncappleAccount` internally.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@@ -988,7 +988,7 @@ class AppleAccount(BaseAppleAccount):
|
||||
*,
|
||||
state_info: AccountStateMapping | None = None,
|
||||
) -> None:
|
||||
"""See `AsyncAppleAccount.__init__`."""
|
||||
"""See :meth:`AsyncAppleAccount.__init__`."""
|
||||
self._asyncacc = AsyncAppleAccount(anisette=anisette, state_info=state_info)
|
||||
|
||||
try:
|
||||
@@ -1001,31 +1001,31 @@ class AppleAccount(BaseAppleAccount):
|
||||
|
||||
@override
|
||||
async def close(self) -> None:
|
||||
"""See `AsyncAppleAccount.close`."""
|
||||
"""See :meth:`AsyncAppleAccount.close`."""
|
||||
await self._asyncacc.close()
|
||||
|
||||
@property
|
||||
@override
|
||||
def login_state(self) -> LoginState:
|
||||
"""See `AsyncAppleAccount.login_state`."""
|
||||
"""See :meth:`AsyncAppleAccount.login_state`."""
|
||||
return self._asyncacc.login_state
|
||||
|
||||
@property
|
||||
@override
|
||||
def account_name(self) -> str | None:
|
||||
"""See `AsyncAppleAccount.login_state`."""
|
||||
"""See :meth:`AsyncAppleAccount.login_state`."""
|
||||
return self._asyncacc.account_name
|
||||
|
||||
@property
|
||||
@override
|
||||
def first_name(self) -> str | None:
|
||||
"""See `AsyncAppleAccount.first_name`."""
|
||||
"""See :meth:`AsyncAppleAccount.first_name`."""
|
||||
return self._asyncacc.first_name
|
||||
|
||||
@property
|
||||
@override
|
||||
def last_name(self) -> str | None:
|
||||
"""See `AsyncAppleAccount.last_name`."""
|
||||
"""See :meth:`AsyncAppleAccount.last_name`."""
|
||||
return self._asyncacc.last_name
|
||||
|
||||
@override
|
||||
@@ -1051,13 +1051,13 @@ class AppleAccount(BaseAppleAccount):
|
||||
|
||||
@override
|
||||
def login(self, username: str, password: str) -> LoginState:
|
||||
"""See `AsyncAppleAccount.login`."""
|
||||
"""See :meth:`AsyncAppleAccount.login`."""
|
||||
coro = self._asyncacc.login(username, password)
|
||||
return self._evt_loop.run_until_complete(coro)
|
||||
|
||||
@override
|
||||
def get_2fa_methods(self) -> Sequence[SyncSecondFactorMethod]:
|
||||
"""See `AsyncAppleAccount.get_2fa_methods`."""
|
||||
"""See :meth:`AsyncAppleAccount.get_2fa_methods`."""
|
||||
coro = self._asyncacc.get_2fa_methods()
|
||||
methods = self._evt_loop.run_until_complete(coro)
|
||||
|
||||
@@ -1078,25 +1078,25 @@ class AppleAccount(BaseAppleAccount):
|
||||
|
||||
@override
|
||||
def sms_2fa_request(self, phone_number_id: int) -> None:
|
||||
"""See `AsyncAppleAccount.sms_2fa_request`."""
|
||||
"""See :meth:`AsyncAppleAccount.sms_2fa_request`."""
|
||||
coro = self._asyncacc.sms_2fa_request(phone_number_id)
|
||||
return self._evt_loop.run_until_complete(coro)
|
||||
|
||||
@override
|
||||
def sms_2fa_submit(self, phone_number_id: int, code: str) -> LoginState:
|
||||
"""See `AsyncAppleAccount.sms_2fa_submit`."""
|
||||
"""See :meth:`AsyncAppleAccount.sms_2fa_submit`."""
|
||||
coro = self._asyncacc.sms_2fa_submit(phone_number_id, code)
|
||||
return self._evt_loop.run_until_complete(coro)
|
||||
|
||||
@override
|
||||
def td_2fa_request(self) -> None:
|
||||
"""See `AsyncAppleAccount.td_2fa_request`."""
|
||||
"""See :meth:`AsyncAppleAccount.td_2fa_request`."""
|
||||
coro = self._asyncacc.td_2fa_request()
|
||||
return self._evt_loop.run_until_complete(coro)
|
||||
|
||||
@override
|
||||
def td_2fa_submit(self, code: str) -> LoginState:
|
||||
"""See `AsyncAppleAccount.td_2fa_submit`."""
|
||||
"""See :meth:`AsyncAppleAccount.td_2fa_submit`."""
|
||||
coro = self._asyncacc.td_2fa_submit(code)
|
||||
return self._evt_loop.run_until_complete(coro)
|
||||
|
||||
@@ -1135,7 +1135,7 @@ class AppleAccount(BaseAppleAccount):
|
||||
) -> (
|
||||
list[LocationReport] | dict[HasHashedPublicKey | RollingKeyPairSource, list[LocationReport]]
|
||||
):
|
||||
"""See `AsyncAppleAccount.fetch_reports`."""
|
||||
"""See :meth:`AsyncAppleAccount.fetch_reports`."""
|
||||
coro = self._asyncacc.fetch_reports(keys, date_from, date_to)
|
||||
return self._evt_loop.run_until_complete(coro)
|
||||
|
||||
@@ -1170,7 +1170,7 @@ class AppleAccount(BaseAppleAccount):
|
||||
) -> (
|
||||
list[LocationReport] | dict[HasHashedPublicKey | RollingKeyPairSource, list[LocationReport]]
|
||||
):
|
||||
"""See `AsyncAppleAccount.fetch_last_reports`."""
|
||||
"""See :meth:`AsyncAppleAccount.fetch_last_reports`."""
|
||||
coro = self._asyncacc.fetch_last_reports(keys, hours)
|
||||
return self._evt_loop.run_until_complete(coro)
|
||||
|
||||
@@ -1180,6 +1180,6 @@ class AppleAccount(BaseAppleAccount):
|
||||
with_client_info: bool = False,
|
||||
serial: str = "0",
|
||||
) -> dict[str, str]:
|
||||
"""See `AsyncAppleAccount.get_anisette_headers`."""
|
||||
"""See :meth:`AsyncAppleAccount.get_anisette_headers`."""
|
||||
coro = self._asyncacc.get_anisette_headers(with_client_info, serial)
|
||||
return self._evt_loop.run_until_complete(coro)
|
||||
|
||||
@@ -135,7 +135,7 @@ class BaseAnisetteProvider(Closable, Serializable, ABC):
|
||||
"""
|
||||
Generate a complete dictionary of Anisette headers.
|
||||
|
||||
Consider using `BaseAppleAccount.get_anisette_headers` instead.
|
||||
Consider using :meth:`BaseAppleAccount.get_anisette_headers` instead.
|
||||
"""
|
||||
headers = {
|
||||
# Current Time
|
||||
@@ -207,7 +207,7 @@ class RemoteAnisetteProvider(BaseAnisetteProvider, Serializable[RemoteAnisetteMa
|
||||
|
||||
@override
|
||||
def to_json(self, dst: str | Path | None = None, /) -> RemoteAnisetteMapping:
|
||||
"""See `BaseAnisetteProvider.serialize`."""
|
||||
"""See :meth:`BaseAnisetteProvider.serialize`."""
|
||||
return save_and_return_json(
|
||||
{
|
||||
"type": "aniRemote",
|
||||
@@ -219,7 +219,7 @@ class RemoteAnisetteProvider(BaseAnisetteProvider, Serializable[RemoteAnisetteMa
|
||||
@classmethod
|
||||
@override
|
||||
def from_json(cls, val: str | Path | RemoteAnisetteMapping) -> RemoteAnisetteProvider:
|
||||
"""See `BaseAnisetteProvider.deserialize`."""
|
||||
"""See :meth:`BaseAnisetteProvider.deserialize`."""
|
||||
val = read_data_json(val)
|
||||
|
||||
assert val["type"] == "aniRemote"
|
||||
@@ -231,7 +231,7 @@ class RemoteAnisetteProvider(BaseAnisetteProvider, Serializable[RemoteAnisetteMa
|
||||
@property
|
||||
@override
|
||||
def otp(self) -> str:
|
||||
"""See `BaseAnisetteProvider.otp`_."""
|
||||
"""See :meth:`BaseAnisetteProvider.otp`."""
|
||||
otp = (self._anisette_data or {}).get("X-Apple-I-MD")
|
||||
if otp is None:
|
||||
logger.warning("X-Apple-I-MD header not found! Returning fallback...")
|
||||
@@ -240,7 +240,7 @@ class RemoteAnisetteProvider(BaseAnisetteProvider, Serializable[RemoteAnisetteMa
|
||||
@property
|
||||
@override
|
||||
def machine(self) -> str:
|
||||
"""See `BaseAnisetteProvider.machine`_."""
|
||||
"""See :meth:`BaseAnisetteProvider.machine`."""
|
||||
machine = (self._anisette_data or {}).get("X-Apple-I-MD-M")
|
||||
if machine is None:
|
||||
logger.warning("X-Apple-I-MD-M header not found! Returning fallback...")
|
||||
@@ -254,7 +254,7 @@ class RemoteAnisetteProvider(BaseAnisetteProvider, Serializable[RemoteAnisetteMa
|
||||
serial: str = "0",
|
||||
with_client_info: bool = False,
|
||||
) -> dict[str, str]:
|
||||
"""See `BaseAnisetteProvider.get_headers`_."""
|
||||
"""See :meth::meth:`BaseAnisetteProvider.get_headers`."""
|
||||
if self._closed:
|
||||
msg = "RemoteAnisetteProvider has been closed and cannot be used"
|
||||
raise RuntimeError(msg)
|
||||
@@ -270,7 +270,7 @@ class RemoteAnisetteProvider(BaseAnisetteProvider, Serializable[RemoteAnisetteMa
|
||||
|
||||
@override
|
||||
async def close(self) -> None:
|
||||
"""See `AnisetteProvider.close`."""
|
||||
"""See :meth:`AnisetteProvider.close`."""
|
||||
if self._closed:
|
||||
return # Already closed, make it idempotent
|
||||
|
||||
@@ -283,7 +283,7 @@ class RemoteAnisetteProvider(BaseAnisetteProvider, Serializable[RemoteAnisetteMa
|
||||
|
||||
|
||||
class LocalAnisetteProvider(BaseAnisetteProvider, Serializable[LocalAnisetteMapping]):
|
||||
"""Anisette provider. Generates headers without a remote server using the `anisette` library."""
|
||||
"""Local anisette provider using the `anisette` library."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -328,7 +328,7 @@ class LocalAnisetteProvider(BaseAnisetteProvider, Serializable[LocalAnisetteMapp
|
||||
|
||||
@override
|
||||
def to_json(self, dst: str | Path | None = None, /) -> LocalAnisetteMapping:
|
||||
"""See `BaseAnisetteProvider.serialize`."""
|
||||
"""See :meth:`BaseAnisetteProvider.serialize`."""
|
||||
with BytesIO() as buf:
|
||||
self._ani.save_provisioning(buf)
|
||||
prov_data = base64.b64encode(buf.getvalue()).decode("utf-8")
|
||||
@@ -349,7 +349,7 @@ class LocalAnisetteProvider(BaseAnisetteProvider, Serializable[LocalAnisetteMapp
|
||||
*,
|
||||
libs_path: str | Path | None = None,
|
||||
) -> LocalAnisetteProvider:
|
||||
"""See `BaseAnisetteProvider.deserialize`."""
|
||||
"""See :meth:`BaseAnisetteProvider.deserialize`."""
|
||||
val = read_data_json(val)
|
||||
|
||||
assert val["type"] == "aniLocal"
|
||||
@@ -366,7 +366,7 @@ class LocalAnisetteProvider(BaseAnisetteProvider, Serializable[LocalAnisetteMapp
|
||||
serial: str = "0",
|
||||
with_client_info: bool = False,
|
||||
) -> dict[str, str]:
|
||||
"""See `BaseAnisetteProvider.get_headers`_."""
|
||||
"""See :meth:`BaseAnisetteProvider.get_headers`."""
|
||||
self._ani_data = self._ani.get_data()
|
||||
|
||||
return await super().get_headers(user_id, device_id, serial, with_client_info)
|
||||
@@ -374,7 +374,7 @@ class LocalAnisetteProvider(BaseAnisetteProvider, Serializable[LocalAnisetteMapp
|
||||
@property
|
||||
@override
|
||||
def otp(self) -> str:
|
||||
"""See `BaseAnisetteProvider.otp`_."""
|
||||
"""See :meth:`BaseAnisetteProvider.otp`."""
|
||||
machine = (self._ani_data or {}).get("X-Apple-I-MD")
|
||||
if machine is None:
|
||||
logger.warning("X-Apple-I-MD header not found! Returning fallback...")
|
||||
@@ -383,7 +383,7 @@ class LocalAnisetteProvider(BaseAnisetteProvider, Serializable[LocalAnisetteMapp
|
||||
@property
|
||||
@override
|
||||
def machine(self) -> str:
|
||||
"""See `BaseAnisetteProvider.machine`_."""
|
||||
"""See :meth:`BaseAnisetteProvider.machine`."""
|
||||
machine = (self._ani_data or {}).get("X-Apple-I-MD-M")
|
||||
if machine is None:
|
||||
logger.warning("X-Apple-I-MD-M header not found! Returning fallback...")
|
||||
@@ -391,4 +391,4 @@ class LocalAnisetteProvider(BaseAnisetteProvider, Serializable[LocalAnisetteMapp
|
||||
|
||||
@override
|
||||
async def close(self) -> None:
|
||||
"""See `BaseAnisetteProvider.close`_."""
|
||||
"""See :meth:`BaseAnisetteProvider.close`."""
|
||||
|
||||
@@ -52,14 +52,18 @@ LocationReportMapping = Union[LocationReportEncryptedMapping, LocationReportDecr
|
||||
|
||||
|
||||
class LocationReport(HasHashedPublicKey, Serializable[LocationReportMapping]):
|
||||
"""Location report corresponding to a certain `HasHashedPublicKey`."""
|
||||
"""Location report corresponding to a certain :meth:`HasHashedPublicKey`."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
payload: bytes,
|
||||
hashed_adv_key: bytes,
|
||||
) -> None:
|
||||
"""Initialize a `KeyReport`. You should probably use `KeyReport.from_payload` instead."""
|
||||
"""
|
||||
Initialize a :class:`LocationReport`.
|
||||
|
||||
You should probably use :meth:`LocationReport.from_payload` instead.
|
||||
"""
|
||||
self._payload: bytes = payload
|
||||
self._hashed_adv_key: bytes = hashed_adv_key
|
||||
|
||||
@@ -68,7 +72,7 @@ class LocationReport(HasHashedPublicKey, Serializable[LocationReportMapping]):
|
||||
@property
|
||||
@override
|
||||
def hashed_adv_key_bytes(self) -> bytes:
|
||||
"""See `HasHashedPublicKey.hashed_adv_key_bytes`."""
|
||||
"""See :meth:`HasHashedPublicKey.hashed_adv_key_bytes`."""
|
||||
return self._hashed_adv_key
|
||||
|
||||
@property
|
||||
@@ -96,7 +100,7 @@ class LocationReport(HasHashedPublicKey, Serializable[LocationReportMapping]):
|
||||
return key.hashed_adv_key_bytes == self._hashed_adv_key
|
||||
|
||||
def decrypt(self, key: KeyPair) -> None:
|
||||
"""Decrypt the report using its corresponding `KeyPair`."""
|
||||
"""Decrypt the report using its corresponding :meth:`KeyPair`."""
|
||||
if not self.can_decrypt(key):
|
||||
msg = "Cannot decrypt with this key!"
|
||||
raise ValueError(msg)
|
||||
@@ -136,7 +140,7 @@ class LocationReport(HasHashedPublicKey, Serializable[LocationReportMapping]):
|
||||
|
||||
@property
|
||||
def timestamp(self) -> datetime:
|
||||
"""The `datetime` when this report was recorded by a device."""
|
||||
"""The :meth:`datetime` when this report was recorded by a device."""
|
||||
timestamp_int = int.from_bytes(self._payload[0:4], "big") + (60 * 60 * 24 * 11323)
|
||||
return datetime.fromtimestamp(timestamp_int, tz=timezone.utc).astimezone()
|
||||
|
||||
@@ -302,9 +306,9 @@ class LocationReport(HasHashedPublicKey, Serializable[LocationReportMapping]):
|
||||
|
||||
def __lt__(self, other: LocationReport) -> bool:
|
||||
"""
|
||||
Compare against another `KeyReport`.
|
||||
Compare against another :meth:`KeyReport`.
|
||||
|
||||
A `KeyReport` is said to be "less than" another `KeyReport` iff its recorded
|
||||
A :meth:`KeyReport` is said to be "less than" another :meth:`KeyReport` iff its recorded
|
||||
timestamp is strictly less than the other report.
|
||||
"""
|
||||
if isinstance(other, LocationReport):
|
||||
@@ -369,12 +373,12 @@ class LocationReportsFetcher:
|
||||
"""
|
||||
Fetch location reports for a certain device.
|
||||
|
||||
When ``device`` is a single :class:`.HasHashedPublicKey`, this method will return
|
||||
When `device` is a single :class:`HasHashedPublicKey`, this method will return
|
||||
a list of location reports corresponding to that key.
|
||||
When ``device`` is a :class:`.RollingKeyPairSource`, it will return a list of
|
||||
When `device` is a :class:`RollingKeyPairSource`, it will return a list of
|
||||
location reports corresponding to that source.
|
||||
When ``device`` is a sequence of :class:`.HasHashedPublicKey`s or RollingKeyPairSource's,
|
||||
it will return a dictionary with the :class:`.HasHashedPublicKey` or `.RollingKeyPairSource`
|
||||
When `device` is a sequence of :class:`HasHashedPublicKey`s or RollingKeyPairSource's,
|
||||
it will return a dictionary with the provided object
|
||||
as key, and a list of location reports as value.
|
||||
"""
|
||||
key_devs: dict[HasHashedPublicKey, HasHashedPublicKey | RollingKeyPairSource] = {}
|
||||
|
||||
@@ -6,7 +6,7 @@ from typing_extensions import override
|
||||
|
||||
|
||||
class LoginState(Enum):
|
||||
"""Enum of possible login states. Used for `AppleAccount`'s internal state machine."""
|
||||
"""Enum of possible login states. Used for :meth:`AppleAccount`'s internal state machine."""
|
||||
|
||||
LOGGED_OUT = 0
|
||||
REQUIRE_2FA = 1
|
||||
@@ -15,9 +15,9 @@ class LoginState(Enum):
|
||||
|
||||
def __lt__(self, other: "LoginState") -> bool:
|
||||
"""
|
||||
Compare against another `LoginState`.
|
||||
Compare against another :meth:`LoginState`.
|
||||
|
||||
A `LoginState` is said to be "less than" another `LoginState` iff it is in
|
||||
A :meth:`LoginState` is said to be "less than" another :meth:`LoginState` iff it is in
|
||||
an "earlier" stage of the login process, going from LOGGED_OUT to LOGGED_IN.
|
||||
"""
|
||||
if isinstance(other, LoginState):
|
||||
|
||||
@@ -63,13 +63,13 @@ class AsyncSecondFactorMethod(BaseSecondFactorMethod, ABC):
|
||||
@override
|
||||
@abstractmethod
|
||||
async def request(self) -> None:
|
||||
"""See `BaseSecondFactorMethod.request`."""
|
||||
"""See :meth:`BaseSecondFactorMethod.request`."""
|
||||
raise NotImplementedError
|
||||
|
||||
@override
|
||||
@abstractmethod
|
||||
async def submit(self, code: str) -> LoginState:
|
||||
"""See `BaseSecondFactorMethod.submit`."""
|
||||
"""See :meth:`BaseSecondFactorMethod.submit`."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@@ -93,13 +93,13 @@ class SyncSecondFactorMethod(BaseSecondFactorMethod, ABC):
|
||||
@override
|
||||
@abstractmethod
|
||||
def request(self) -> None:
|
||||
"""See `BaseSecondFactorMethod.request`."""
|
||||
"""See :meth:`BaseSecondFactorMethod.request`."""
|
||||
raise NotImplementedError
|
||||
|
||||
@override
|
||||
@abstractmethod
|
||||
def submit(self, code: str) -> LoginState:
|
||||
"""See `BaseSecondFactorMethod.submit`."""
|
||||
"""See :meth:`BaseSecondFactorMethod.submit`."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ class TrustedDeviceSecondFactorMethod(BaseSecondFactorMethod, ABC):
|
||||
|
||||
|
||||
class AsyncSmsSecondFactor(AsyncSecondFactorMethod, SmsSecondFactorMethod):
|
||||
"""An async implementation of `SmsSecondFactorMethod`."""
|
||||
"""An async implementation of :meth:`SmsSecondFactorMethod`."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -139,7 +139,7 @@ class AsyncSmsSecondFactor(AsyncSecondFactorMethod, SmsSecondFactorMethod):
|
||||
"""
|
||||
Initialize the second factor method.
|
||||
|
||||
Should not be done manually; use `AsyncAppleAccount.get_2fa_methods` instead.
|
||||
Should not be done manually; use :meth:`AsyncAppleAccount.get_2fa_methods` instead.
|
||||
"""
|
||||
super().__init__(account)
|
||||
|
||||
@@ -174,7 +174,7 @@ class AsyncSmsSecondFactor(AsyncSecondFactorMethod, SmsSecondFactorMethod):
|
||||
|
||||
|
||||
class SyncSmsSecondFactor(SyncSecondFactorMethod, SmsSecondFactorMethod):
|
||||
"""A sync implementation of `SmsSecondFactorMethod`."""
|
||||
"""A sync implementation of :meth:`SmsSecondFactorMethod`."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -182,7 +182,7 @@ class SyncSmsSecondFactor(SyncSecondFactorMethod, SmsSecondFactorMethod):
|
||||
number_id: int,
|
||||
phone_number: str,
|
||||
) -> None:
|
||||
"""See `AsyncSmsSecondFactor.__init__`."""
|
||||
"""See :meth:`AsyncSmsSecondFactor.__init__`."""
|
||||
super().__init__(account)
|
||||
|
||||
self._phone_number_id: int = number_id
|
||||
@@ -191,28 +191,28 @@ class SyncSmsSecondFactor(SyncSecondFactorMethod, SmsSecondFactorMethod):
|
||||
@property
|
||||
@override
|
||||
def phone_number_id(self) -> int:
|
||||
"""See `AsyncSmsSecondFactor.phone_number_id`."""
|
||||
"""See :meth:`AsyncSmsSecondFactor.phone_number_id`."""
|
||||
return self._phone_number_id
|
||||
|
||||
@property
|
||||
@override
|
||||
def phone_number(self) -> str:
|
||||
"""See `AsyncSmsSecondFactor.phone_number`."""
|
||||
"""See :meth:`AsyncSmsSecondFactor.phone_number`."""
|
||||
return self._phone_number
|
||||
|
||||
@override
|
||||
def request(self) -> None:
|
||||
"""See `AsyncSmsSecondFactor.request`."""
|
||||
"""See :meth:`AsyncSmsSecondFactor.request`."""
|
||||
return self.account.sms_2fa_request(self._phone_number_id)
|
||||
|
||||
@override
|
||||
def submit(self, code: str) -> LoginState:
|
||||
"""See `AsyncSmsSecondFactor.submit`."""
|
||||
"""See :meth:`AsyncSmsSecondFactor.submit`."""
|
||||
return self.account.sms_2fa_submit(self._phone_number_id, code)
|
||||
|
||||
|
||||
class AsyncTrustedDeviceSecondFactor(AsyncSecondFactorMethod, TrustedDeviceSecondFactorMethod):
|
||||
"""An async implementation of `TrustedDeviceSecondFactorMethod`."""
|
||||
"""An async implementation of :meth:`TrustedDeviceSecondFactorMethod`."""
|
||||
|
||||
@override
|
||||
async def request(self) -> None:
|
||||
@@ -224,14 +224,14 @@ class AsyncTrustedDeviceSecondFactor(AsyncSecondFactorMethod, TrustedDeviceSecon
|
||||
|
||||
|
||||
class SyncTrustedDeviceSecondFactor(SyncSecondFactorMethod, TrustedDeviceSecondFactorMethod):
|
||||
"""A sync implementation of `TrustedDeviceSecondFactorMethod`."""
|
||||
"""A sync implementation of :meth:`TrustedDeviceSecondFactorMethod`."""
|
||||
|
||||
@override
|
||||
def request(self) -> None:
|
||||
"""See `AsyncTrustedDeviceSecondFactor.request`."""
|
||||
"""See :meth:`AsyncTrustedDeviceSecondFactor.request`."""
|
||||
return self.account.td_2fa_request()
|
||||
|
||||
@override
|
||||
def submit(self, code: str) -> LoginState:
|
||||
"""See `AsyncTrustedDeviceSecondFactor.submit`."""
|
||||
"""See :meth:`AsyncTrustedDeviceSecondFactor.submit`."""
|
||||
return self.account.td_2fa_submit(code)
|
||||
|
||||
@@ -211,7 +211,7 @@ class SeparatedOfflineFindingDevice(OfflineFindingDevice, HasPublicKey):
|
||||
detected_at: datetime,
|
||||
additional_data: dict[Any, Any] | None = None,
|
||||
) -> None:
|
||||
"""Initialize a `SeparatedOfflineFindingDevice`."""
|
||||
"""Initialize a :meth:`SeparatedOfflineFindingDevice`."""
|
||||
super().__init__(mac_bytes, status, detected_at, additional_data)
|
||||
|
||||
self._public_key: bytes = public_key
|
||||
@@ -225,7 +225,7 @@ class SeparatedOfflineFindingDevice(OfflineFindingDevice, HasPublicKey):
|
||||
@property
|
||||
@override
|
||||
def adv_key_bytes(self) -> bytes:
|
||||
"""See `HasPublicKey.adv_key_bytes`."""
|
||||
"""See :meth:`HasPublicKey.adv_key_bytes`."""
|
||||
return self._public_key
|
||||
|
||||
@override
|
||||
@@ -300,7 +300,7 @@ _DEVICE_TYPES = {
|
||||
|
||||
|
||||
class OfflineFindingScanner:
|
||||
"""BLE scanner that searches for `OfflineFindingDevice`s."""
|
||||
"""BLE scanner that searches for :meth:`OfflineFindingDevice`s."""
|
||||
|
||||
_scan_ctrl_lock = asyncio.Lock()
|
||||
|
||||
@@ -311,7 +311,7 @@ class OfflineFindingScanner:
|
||||
Initialize an instance of the Scanner using an event loop.
|
||||
|
||||
You most likely do not want to use this yourself;
|
||||
check out `OfflineFindingScanner.create` instead.
|
||||
check out :meth:`OfflineFindingScanner.create` instead.
|
||||
"""
|
||||
self._scanner: BleakScanner = BleakScanner(self._scan_callback, cb={"use_bdaddr": True})
|
||||
|
||||
@@ -377,10 +377,10 @@ class OfflineFindingScanner:
|
||||
extend_timeout: bool = False,
|
||||
) -> AsyncGenerator[OfflineFindingDevice, None]:
|
||||
"""
|
||||
Scan for `OfflineFindingDevice`s for up to `timeout` seconds.
|
||||
Scan for :meth:`OfflineFindingDevice`s for up to :meth:`timeout` seconds.
|
||||
|
||||
If `extend_timeout` is set, the timer will be extended
|
||||
by `timeout` seconds every time a new device is discovered.
|
||||
If :meth:`extend_timeout` is set, the timer will be extended
|
||||
by :meth:`timeout` seconds every time a new device is discovered.
|
||||
"""
|
||||
await self._start_scan()
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ class Closable(ABC):
|
||||
|
||||
def __init__(self, loop: asyncio.AbstractEventLoop | None = None) -> None:
|
||||
"""
|
||||
Initialize the ``Closable``.
|
||||
Initialize the :class:`Closable`.
|
||||
|
||||
If an event loop is given, the ``Closable`` will attempt to close itself
|
||||
If an event loop is given, the :class:`Closable` will attempt to close itself
|
||||
using the loop when it is garbage collected.
|
||||
"""
|
||||
self._loop: asyncio.AbstractEventLoop | None = loop
|
||||
@@ -57,7 +57,7 @@ class Serializable(Generic[_T], ABC):
|
||||
If an argument is provided, the output will also be written to that file.
|
||||
|
||||
The output of this method is guaranteed to be JSON-serializable, and passing
|
||||
the return value of this function as an argument to `Serializable.from_json`
|
||||
the return value of this function as an argument to :meth:`Serializable.from_json`
|
||||
will always result in an exact copy of the internal state as it was when exported.
|
||||
|
||||
You are encouraged to save and load object states to and from disk whenever possible,
|
||||
@@ -69,11 +69,11 @@ class Serializable(Generic[_T], ABC):
|
||||
@abstractmethod
|
||||
def from_json(cls, val: str | Path | _T, /) -> Self:
|
||||
"""
|
||||
Restore state from a previous `Closable.to_json` export.
|
||||
Restore state from a previous :meth:`Closable.to_json` export.
|
||||
|
||||
If given a str or Path, it must point to a json file from `Serializable.to_json`.
|
||||
If given a str or Path, it must point to a json file from :meth:`Serializable.to_json`.
|
||||
Otherwise, it should be the Mapping itself.
|
||||
|
||||
See `Serializable.to_json` for more information.
|
||||
See :meth:`Serializable.to_json` for more information.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -33,7 +33,7 @@ class _HttpRequestOptions(_RequestOptions, total=False):
|
||||
|
||||
|
||||
class HttpResponse:
|
||||
"""Response of a request made by `HttpSession`."""
|
||||
"""Response of a request made by :meth:`HttpSession`."""
|
||||
|
||||
def __init__(self, status_code: int, content: bytes) -> None:
|
||||
"""Initialize the response."""
|
||||
@@ -115,7 +115,7 @@ class HttpSession(Closable):
|
||||
"""
|
||||
Make an HTTP request.
|
||||
|
||||
Keyword arguments will directly be passed to `aiohttp.ClientSession.request`.
|
||||
Keyword arguments will directly be passed to :meth:`aiohttp.ClientSession.request`.
|
||||
"""
|
||||
session = await self._get_session()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user