mirror of
https://github.com/malmeloo/FindMy.py.git
synced 2026-04-21 00:05:35 +02:00
Merge pull request #73 from malmeloo/fix/pre-commit
fix: Pre-commit hooks
This commit is contained in:
2
.github/workflows/pre-commit.yml
vendored
2
.github/workflows/pre-commit.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
run: |
|
||||
python -m pip install poetry
|
||||
poetry config virtualenvs.in-project true
|
||||
poetry install --with dev
|
||||
poetry install --with dev,test
|
||||
|
||||
- uses: pre-commit/action@v3.0.1
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.1.9
|
||||
rev: v0.6.3
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: ["--fix"]
|
||||
- id: ruff-format
|
||||
- repo: https://github.com/RobertCraigie/pyright-python
|
||||
rev: v1.1.350
|
||||
rev: v1.1.378
|
||||
hooks:
|
||||
- id: pyright
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# ruff: noqa: ASYNC230
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Example showing how to fetch locations of an AirTag, or any other FindMy accessory.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""A package providing everything you need to work with Apple's FindMy network."""
|
||||
|
||||
from . import errors, keys, reports, scanner
|
||||
from .accessory import FindMyAccessory
|
||||
from .keys import KeyPair
|
||||
|
||||
@@ -3,6 +3,7 @@ Module to interact with accessories that implement Find My.
|
||||
|
||||
Accessories could be anything ranging from AirTags to iPhones.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
@@ -64,7 +65,7 @@ class RollingKeyPairSource(ABC):
|
||||
class FindMyAccessory(RollingKeyPairSource):
|
||||
"""A findable Find My-accessory using official key rollover."""
|
||||
|
||||
def __init__( # noqa: PLR0913
|
||||
def __init__(
|
||||
self,
|
||||
master_key: bytes,
|
||||
skn: bytes,
|
||||
@@ -235,12 +236,10 @@ class AccessoryKeyGenerator(KeyGenerator[KeyPair]):
|
||||
return self._get_keypair(self._iter_ind)
|
||||
|
||||
@overload
|
||||
def __getitem__(self, val: int) -> KeyPair:
|
||||
...
|
||||
def __getitem__(self, val: int) -> KeyPair: ...
|
||||
|
||||
@overload
|
||||
def __getitem__(self, val: slice) -> Generator[KeyPair, None, None]:
|
||||
...
|
||||
def __getitem__(self, val: slice) -> Generator[KeyPair, None, None]: ...
|
||||
|
||||
@override
|
||||
def __getitem__(self, val: int | slice) -> KeyPair | Generator[KeyPair, None, None]:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Module to work with private and public keys as used in FindMy accessories."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
@@ -156,13 +157,11 @@ class KeyGenerator(ABC, Generic[K]):
|
||||
|
||||
@overload
|
||||
@abstractmethod
|
||||
def __getitem__(self, val: int) -> K:
|
||||
...
|
||||
def __getitem__(self, val: int) -> K: ...
|
||||
|
||||
@overload
|
||||
@abstractmethod
|
||||
def __getitem__(self, val: slice) -> Generator[K, None, None]:
|
||||
...
|
||||
def __getitem__(self, val: slice) -> Generator[K, None, None]: ...
|
||||
|
||||
@abstractmethod
|
||||
def __getitem__(self, val: int | slice) -> K | Generator[K, None, None]:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Code related to fetching location reports."""
|
||||
|
||||
from .account import AppleAccount, AsyncAppleAccount
|
||||
from .anisette import BaseAnisetteProvider, RemoteAnisetteProvider
|
||||
from .state import LoginState
|
||||
|
||||
@@ -228,8 +228,7 @@ class BaseAppleAccount(Closable, ABC):
|
||||
keys: HasHashedPublicKey,
|
||||
date_from: datetime,
|
||||
date_to: datetime | None,
|
||||
) -> MaybeCoro[list[LocationReport]]:
|
||||
...
|
||||
) -> MaybeCoro[list[LocationReport]]: ...
|
||||
|
||||
@overload
|
||||
@abstractmethod
|
||||
@@ -238,8 +237,7 @@ class BaseAppleAccount(Closable, ABC):
|
||||
keys: Sequence[HasHashedPublicKey],
|
||||
date_from: datetime,
|
||||
date_to: datetime | None,
|
||||
) -> MaybeCoro[dict[HasHashedPublicKey, list[LocationReport]]]:
|
||||
...
|
||||
) -> MaybeCoro[dict[HasHashedPublicKey, list[LocationReport]]]: ...
|
||||
|
||||
@overload
|
||||
@abstractmethod
|
||||
@@ -248,8 +246,7 @@ class BaseAppleAccount(Closable, ABC):
|
||||
keys: RollingKeyPairSource,
|
||||
date_from: datetime,
|
||||
date_to: datetime | None,
|
||||
) -> MaybeCoro[list[LocationReport]]:
|
||||
...
|
||||
) -> MaybeCoro[list[LocationReport]]: ...
|
||||
|
||||
@abstractmethod
|
||||
def fetch_reports(
|
||||
@@ -271,8 +268,7 @@ class BaseAppleAccount(Closable, ABC):
|
||||
self,
|
||||
keys: HasHashedPublicKey,
|
||||
hours: int = 7 * 24,
|
||||
) -> MaybeCoro[list[LocationReport]]:
|
||||
...
|
||||
) -> MaybeCoro[list[LocationReport]]: ...
|
||||
|
||||
@overload
|
||||
@abstractmethod
|
||||
@@ -280,8 +276,7 @@ class BaseAppleAccount(Closable, ABC):
|
||||
self,
|
||||
keys: Sequence[HasHashedPublicKey],
|
||||
hours: int = 7 * 24,
|
||||
) -> MaybeCoro[dict[HasHashedPublicKey, list[LocationReport]]]:
|
||||
...
|
||||
) -> MaybeCoro[dict[HasHashedPublicKey, list[LocationReport]]]: ...
|
||||
|
||||
@overload
|
||||
@abstractmethod
|
||||
@@ -289,8 +284,7 @@ class BaseAppleAccount(Closable, ABC):
|
||||
self,
|
||||
keys: RollingKeyPairSource,
|
||||
hours: int = 7 * 24,
|
||||
) -> MaybeCoro[list[LocationReport]]:
|
||||
...
|
||||
) -> MaybeCoro[list[LocationReport]]: ...
|
||||
|
||||
@abstractmethod
|
||||
def fetch_last_reports(
|
||||
@@ -629,8 +623,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
keys: HasHashedPublicKey,
|
||||
date_from: datetime,
|
||||
date_to: datetime | None,
|
||||
) -> list[LocationReport]:
|
||||
...
|
||||
) -> list[LocationReport]: ...
|
||||
|
||||
@overload
|
||||
async def fetch_reports(
|
||||
@@ -638,8 +631,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
keys: Sequence[HasHashedPublicKey],
|
||||
date_from: datetime,
|
||||
date_to: datetime | None,
|
||||
) -> dict[HasHashedPublicKey, list[LocationReport]]:
|
||||
...
|
||||
) -> dict[HasHashedPublicKey, list[LocationReport]]: ...
|
||||
|
||||
@overload
|
||||
async def fetch_reports(
|
||||
@@ -647,8 +639,7 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
keys: RollingKeyPairSource,
|
||||
date_from: datetime,
|
||||
date_to: datetime | None,
|
||||
) -> list[LocationReport]:
|
||||
...
|
||||
) -> list[LocationReport]: ...
|
||||
|
||||
@require_login_state(LoginState.LOGGED_IN)
|
||||
@override
|
||||
@@ -672,24 +663,21 @@ class AsyncAppleAccount(BaseAppleAccount):
|
||||
self,
|
||||
keys: HasHashedPublicKey,
|
||||
hours: int = 7 * 24,
|
||||
) -> list[LocationReport]:
|
||||
...
|
||||
) -> list[LocationReport]: ...
|
||||
|
||||
@overload
|
||||
async def fetch_last_reports(
|
||||
self,
|
||||
keys: Sequence[HasHashedPublicKey],
|
||||
hours: int = 7 * 24,
|
||||
) -> dict[HasHashedPublicKey, list[LocationReport]]:
|
||||
...
|
||||
) -> dict[HasHashedPublicKey, list[LocationReport]]: ...
|
||||
|
||||
@overload
|
||||
async def fetch_last_reports(
|
||||
self,
|
||||
keys: RollingKeyPairSource,
|
||||
hours: int = 7 * 24,
|
||||
) -> list[LocationReport]:
|
||||
...
|
||||
) -> list[LocationReport]: ...
|
||||
|
||||
@require_login_state(LoginState.LOGGED_IN)
|
||||
@override
|
||||
@@ -1035,8 +1023,7 @@ class AppleAccount(BaseAppleAccount):
|
||||
keys: HasHashedPublicKey,
|
||||
date_from: datetime,
|
||||
date_to: datetime | None,
|
||||
) -> list[LocationReport]:
|
||||
...
|
||||
) -> list[LocationReport]: ...
|
||||
|
||||
@overload
|
||||
def fetch_reports(
|
||||
@@ -1044,8 +1031,7 @@ class AppleAccount(BaseAppleAccount):
|
||||
keys: Sequence[HasHashedPublicKey],
|
||||
date_from: datetime,
|
||||
date_to: datetime | None,
|
||||
) -> dict[HasHashedPublicKey, list[LocationReport]]:
|
||||
...
|
||||
) -> dict[HasHashedPublicKey, list[LocationReport]]: ...
|
||||
|
||||
@overload
|
||||
def fetch_reports(
|
||||
@@ -1053,8 +1039,7 @@ class AppleAccount(BaseAppleAccount):
|
||||
keys: RollingKeyPairSource,
|
||||
date_from: datetime,
|
||||
date_to: datetime | None,
|
||||
) -> list[LocationReport]:
|
||||
...
|
||||
) -> list[LocationReport]: ...
|
||||
|
||||
@override
|
||||
def fetch_reports(
|
||||
@@ -1072,24 +1057,21 @@ class AppleAccount(BaseAppleAccount):
|
||||
self,
|
||||
keys: HasHashedPublicKey,
|
||||
hours: int = 7 * 24,
|
||||
) -> list[LocationReport]:
|
||||
...
|
||||
) -> list[LocationReport]: ...
|
||||
|
||||
@overload
|
||||
def fetch_last_reports(
|
||||
self,
|
||||
keys: Sequence[HasHashedPublicKey],
|
||||
hours: int = 7 * 24,
|
||||
) -> dict[HasHashedPublicKey, list[LocationReport]]:
|
||||
...
|
||||
) -> dict[HasHashedPublicKey, list[LocationReport]]: ...
|
||||
|
||||
@overload
|
||||
def fetch_last_reports(
|
||||
self,
|
||||
keys: RollingKeyPairSource,
|
||||
hours: int = 7 * 24,
|
||||
) -> list[LocationReport]:
|
||||
...
|
||||
) -> list[LocationReport]: ...
|
||||
|
||||
@override
|
||||
def fetch_last_reports(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Module for Anisette header providers."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
|
||||
@@ -232,8 +232,7 @@ class LocationReportsFetcher:
|
||||
date_from: datetime,
|
||||
date_to: datetime,
|
||||
device: HasHashedPublicKey,
|
||||
) -> list[LocationReport]:
|
||||
...
|
||||
) -> list[LocationReport]: ...
|
||||
|
||||
@overload
|
||||
async def fetch_reports(
|
||||
@@ -241,8 +240,7 @@ class LocationReportsFetcher:
|
||||
date_from: datetime,
|
||||
date_to: datetime,
|
||||
device: Sequence[HasHashedPublicKey],
|
||||
) -> dict[HasHashedPublicKey, list[LocationReport]]:
|
||||
...
|
||||
) -> dict[HasHashedPublicKey, list[LocationReport]]: ...
|
||||
|
||||
@overload
|
||||
async def fetch_reports(
|
||||
@@ -250,8 +248,7 @@ class LocationReportsFetcher:
|
||||
date_from: datetime,
|
||||
date_to: datetime,
|
||||
device: RollingKeyPairSource,
|
||||
) -> list[LocationReport]:
|
||||
...
|
||||
) -> list[LocationReport]: ...
|
||||
|
||||
async def fetch_reports(
|
||||
self,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Account login state."""
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from typing_extensions import override
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Public classes related to handling two-factor authentication."""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import TYPE_CHECKING, Generic, TypeVar
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Utilities related to physically discoverable FindMy-devices."""
|
||||
|
||||
from .scanner import (
|
||||
NearbyOfflineFindingDevice,
|
||||
OfflineFindingScanner,
|
||||
|
||||
@@ -139,7 +139,7 @@ class NearbyOfflineFindingDevice(OfflineFindingDevice):
|
||||
"""Length of OfflineFinding data payload in bytes."""
|
||||
return 0x02 # 2
|
||||
|
||||
def __init__( # noqa: PLR0913
|
||||
def __init__(
|
||||
self,
|
||||
mac_bytes: bytes,
|
||||
status_byte: int,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Utility functions and classes. Intended for internal use."""
|
||||
|
||||
from .http import HttpResponse, HttpSession
|
||||
from .parsers import decode_plist
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""ABC for async classes that need to be cleaned up before exiting."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
"""Module to simplify asynchronous HTTP calls."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, TypedDict
|
||||
from typing import Any, TypedDict, cast
|
||||
|
||||
from aiohttp import BasicAuth, ClientSession, ClientTimeout
|
||||
from typing_extensions import Unpack, override
|
||||
@@ -14,13 +15,20 @@ from .parsers import decode_plist
|
||||
logging.getLogger(__name__)
|
||||
|
||||
|
||||
class _HttpRequestOptions(TypedDict, total=False):
|
||||
class _RequestOptions(TypedDict, total=False):
|
||||
json: dict[str, Any] | None
|
||||
headers: dict[str, str]
|
||||
auth: tuple[str, str] | BasicAuth
|
||||
data: bytes
|
||||
|
||||
|
||||
class _AiohttpRequestOptions(_RequestOptions):
|
||||
auth: BasicAuth
|
||||
|
||||
|
||||
class _HttpRequestOptions(_RequestOptions, total=False):
|
||||
auth: BasicAuth | tuple[str, str]
|
||||
|
||||
|
||||
class HttpResponse:
|
||||
"""Response of a request made by `HttpSession`."""
|
||||
|
||||
@@ -94,15 +102,19 @@ class HttpSession(Closable):
|
||||
"""
|
||||
session = await self._get_session()
|
||||
|
||||
# cast from http options to library supported options
|
||||
auth = kwargs.get("auth")
|
||||
if isinstance(auth, tuple):
|
||||
kwargs["auth"] = BasicAuth(auth[0], auth[1])
|
||||
else:
|
||||
kwargs.pop("auth")
|
||||
options = cast(_AiohttpRequestOptions, kwargs)
|
||||
|
||||
async with await session.request(
|
||||
method,
|
||||
url,
|
||||
ssl=False,
|
||||
**kwargs,
|
||||
**options,
|
||||
) as r:
|
||||
return HttpResponse(r.status, await r.content.read())
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Parsers for various forms of data formats."""
|
||||
|
||||
import plistlib
|
||||
from typing import Any
|
||||
|
||||
|
||||
@@ -40,12 +40,20 @@ venv = ".venv"
|
||||
typeCheckingMode = "standard"
|
||||
reportImplicitOverride = true
|
||||
|
||||
# examples should be run from their own directory
|
||||
executionEnvironments = [
|
||||
{ root = "examples/" }
|
||||
]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 100
|
||||
|
||||
exclude = [
|
||||
"docs/",
|
||||
"tests/"
|
||||
]
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = [
|
||||
"ALL",
|
||||
]
|
||||
@@ -65,8 +73,6 @@ ignore = [
|
||||
"FBT", # boolean "traps"
|
||||
]
|
||||
|
||||
line-length = 100
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"examples/*" = [
|
||||
"T201", # use of "print"
|
||||
|
||||
Reference in New Issue
Block a user