Files
FindMy.py/findmy/reports/state.py
2024-01-03 22:13:16 +01:00

61 lines
1.7 KiB
Python

"""Code related to internal account state handling."""
from enum import Enum
from functools import wraps
from typing import TYPE_CHECKING, Callable, Concatenate, ParamSpec, TypeVar
from findmy.util.errors import InvalidStateError
if TYPE_CHECKING:
# noinspection PyUnresolvedReferences
from .account import BaseAppleAccount
P = ParamSpec("P")
R = TypeVar("R")
A = TypeVar("A", bound="BaseAppleAccount")
F = Callable[Concatenate[A, P], R]
class LoginState(Enum):
"""Enum of possible login states. Used for `AppleAccount`'s internal state machine."""
LOGGED_OUT = 0
REQUIRE_2FA = 1
AUTHENTICATED = 2
LOGGED_IN = 3
def __lt__(self, other: "LoginState") -> bool:
"""
Compare against another `LoginState`.
A `LoginState` is said to be "less than" another `LoginState` iff it is in
an "earlier" stage of the login process, going from LOGGED_OUT to LOGGED_IN.
"""
if isinstance(other, LoginState):
return self.value < other.value
return NotImplemented
def __repr__(self) -> str:
"""Human-readable string representation of the state."""
return self.__str__()
def require_login_state(*states: LoginState) -> Callable[[F], F]:
"""Enforce a login state as precondition for a method."""
def decorator(func: F) -> F:
@wraps(func)
def wrapper(acc: A, *args: P.args, **kwargs: P.kwargs) -> R:
if acc.login_state not in states:
msg = (
f"Invalid login state! Currently: {acc.login_state}"
f" but should be one of: {states}"
)
raise InvalidStateError(msg)
return func(acc, *args, **kwargs)
return wrapper
return decorator