Code refactor
Right now ProfileData class has too many methods connected with working, known and watched accounts. We should make it more lightweight and create separated classes for holding and operating on this data. Upcoming class structure:
@dataclass
class Account:
name: str
@dataclass
class TrackedAccount(Account):
_alarms: AlarmsStorage
_data: NodeData
@dataclass
class KnownAccount(Account):
pass
@dataclass
class WatchedAccount(TrackedAccount):
pass
@dataclass
class WorkingAccount(TrackedAccount):
pass
AccountT = TypeVar("AccountT", KnownAccount, WatchedAccount)
class AccountContainer(Generic[AccountT]):
"""A container-like object that holds accounts."""
_accounts: set[AccountT]
def __iter__(self) -> Iterator[AccountT]:
"""Iterate over accounts copy, sorted by name."""
def __len__(self) -> int:
"""Return number of accounts"""
def __bool__(self) -> bool:
"""Return True if there are any accounts in the container, False otherwise"""
def get(self, to_get: str | Account) -> AccountT:
"""Get specific account by its name (accounts are distinguishable by name) or raise AccountNotFoundError."""
def add(self, to_add: str | Account) -> None:
"""
Add account to the container. When str or base Account is passed, it should be converted to a new instance of
proper account type. If account with the same name is already in the container, raise AccountAlreadyExistsError.
"""
def clear(self) -> None:
"""Remove all accounts from the container."""
def remove(self, to_remove: str | Account) -> None:
"""Remove account from the container by its name. Doesn't raise error if account is not found."""
class AccountManager:
_working_account: WorkingAccount | None
_watched_accounts: AccountContainer[WatchedAccount]
_known_accounts: AccountContainer[KnownAccount]
@property
def working(self) -> WorkingAccount:
"""Ensure working account is set and return it, otherwise raise an AccountNotFoundError"""
@property
def working_or_none(self) -> WorkingAccount | None:
"""Return working account or None if it's not set"""
@property
def watched(self) -> AccountContainer:
"""Container-like copy of watched accounts"""
@property
def known(self) -> AccountContainer:
"""Container-like copy of known accounts"""
@property
def tracked(self) -> set[TrackedAccount]:
"""Copy of tracked accounts (watched and working together), sorted by name with working account always first."""
@property
def has_working_account(self) -> bool: ...
@property
def has_watched_accounts(self) -> bool: ...
@property
def has_tracked_accounts(self) -> bool: ...
@property
def has_known_accounts(self) -> bool: ...
@property
def is_tracked_accounts_alarms_data_available(self) -> bool: ...
@property
def is_tracked_accounts_node_data_available(self) -> bool: ...
def is_account_working(self, account: str | Account) -> bool: ...
def is_account_tracked(self, account: str | Account) -> bool: ...
def set_working_account(self, value: str | Account) -> None: ...
def unset_working_account(self) -> None: ...
def switch_working_account(self, new_working_account: str | Account | None = None) -> None:
"""
Switch the working account to the one of watched accounts and move the old one to the watched accounts.
Working account can be unset and moved to watched accounts if `new_working_account` is None.
Raise AccountNotFoundError if new_working_account is not None and not found in watched accounts.
"""
def add_tracked_account(self, to_add: str | Account) -> None:
"""Same as self.watched.add"""
def remove_tracked_account(self, to_remove: str | Account) -> None:
"""Remove account from tracked accounts (either working or watched). Doesn't raise error if account is not found."""
def get_tracked_account(self, to_get: str | Account) -> TrackedAccount:
"""Get tracked account by name or raise AccountNotFoundError"""
class Profile:
accounts: AccountManager
Edited by Mateusz Kudela