diff --git a/findmy/accessory.py b/findmy/accessory.py index 544170a..18b0e58 100644 --- a/findmy/accessory.py +++ b/findmy/accessory.py @@ -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 diff --git a/findmy/errors.py b/findmy/errors.py index fbf88c7..b876ebc 100644 --- a/findmy/errors.py +++ b/findmy/errors.py @@ -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. """ diff --git a/findmy/keys.py b/findmy/keys.py index 76b849f..6a8188b 100644 --- a/findmy/keys.py +++ b/findmy/keys.py @@ -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") diff --git a/findmy/plist.py b/findmy/plist.py index 76872a2..046243e 100644 --- a/findmy/plist.py +++ b/findmy/plist.py @@ -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 diff --git a/findmy/reports/account.py b/findmy/reports/account.py index 6aef1d1..53f1ab1 100644 --- a/findmy/reports/account.py +++ b/findmy/reports/account.py @@ -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) diff --git a/findmy/reports/anisette.py b/findmy/reports/anisette.py index 240533c..a16eae1 100644 --- a/findmy/reports/anisette.py +++ b/findmy/reports/anisette.py @@ -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`.""" diff --git a/findmy/reports/reports.py b/findmy/reports/reports.py index 68c97f3..a8062b8 100644 --- a/findmy/reports/reports.py +++ b/findmy/reports/reports.py @@ -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] = {} diff --git a/findmy/reports/state.py b/findmy/reports/state.py index 165f5ae..852ace0 100644 --- a/findmy/reports/state.py +++ b/findmy/reports/state.py @@ -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): diff --git a/findmy/reports/twofactor.py b/findmy/reports/twofactor.py index 6a51e5b..c7bbb67 100644 --- a/findmy/reports/twofactor.py +++ b/findmy/reports/twofactor.py @@ -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) diff --git a/findmy/scanner/scanner.py b/findmy/scanner/scanner.py index af10f12..ad50589 100644 --- a/findmy/scanner/scanner.py +++ b/findmy/scanner/scanner.py @@ -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() diff --git a/findmy/util/abc.py b/findmy/util/abc.py index a88da3b..a660575 100644 --- a/findmy/util/abc.py +++ b/findmy/util/abc.py @@ -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 diff --git a/findmy/util/http.py b/findmy/util/http.py index 69190d5..780a23d 100644 --- a/findmy/util/http.py +++ b/findmy/util/http.py @@ -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()