diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 269bd046ff449f082211f7012335fe03d4067d94..d08b19b2e61d53f2e5549cb007c5e60e281711a1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ workflow: include: - project: 'hive/hive' - ref: 888c7b858da0da4ca12a003c97b1387d070d247a + ref: 42e5901e47562ae80c9db03ff10fe2f4e72ce461 file: '/scripts/ci-helpers/prepare_data_image_job.yml' # Do not include common-ci-configuration here, it is already referenced by scripts/ci-helpers/prepare_data_image_job.yml included from Hive diff --git a/clive/__private/cli/commands/abc/world_based_command.py b/clive/__private/cli/commands/abc/world_based_command.py index 2e51f4df1ed822ce90a72cd094593ee8f6397aa7..d994ccd7b70d8ec094b822beeb9f85a1b02f07ba 100644 --- a/clive/__private/cli/commands/abc/world_based_command.py +++ b/clive/__private/cli/commands/abc/world_based_command.py @@ -4,6 +4,8 @@ from abc import ABC from dataclasses import dataclass from typing import TYPE_CHECKING +import beekeepy.communication as bkc + from clive.__private.cli.cli_world import CLIWorld from clive.__private.cli.commands.abc.contextual_cli_command import ContextualCLICommand from clive.__private.cli.exceptions import ( @@ -17,7 +19,6 @@ from clive.__private.cli.exceptions import ( from clive.__private.cli.print_cli import print_cli from clive.__private.core.accounts.exceptions import AccountNotFoundError from clive.__private.core.commands.get_wallet_names import GetWalletNames -from clive.__private.core.url_utils import is_url_reachable from clive.__private.core.world import World from clive.__private.settings import safe_settings @@ -77,7 +78,7 @@ class WorldBasedCommand(ContextualCLICommand[World], ABC): async def _validate_remote_beekeeper_running(self) -> None: beekeeper_remote_url = self.beekeeper_remote_url - if beekeeper_remote_url and not await is_url_reachable(beekeeper_remote_url): + if beekeeper_remote_url and not await bkc.async_is_url_reachable(beekeeper_remote_url): raise CLIBeekeeperRemoteAddressIsNotRespondingError(beekeeper_remote_url) async def _validate_session_is_locked(self) -> None: diff --git a/clive/__private/cli/commands/beekeeper/beekeeper_close.py b/clive/__private/cli/commands/beekeeper/beekeeper_close.py index 0552b41dcbea815a4afcf87d6ec14921ea2d7572..2d2c69a275120998525b0a7dba91bcccc2d57b8f 100644 --- a/clive/__private/cli/commands/beekeeper/beekeeper_close.py +++ b/clive/__private/cli/commands/beekeeper/beekeeper_close.py @@ -2,8 +2,8 @@ from __future__ import annotations from dataclasses import dataclass -from beekeepy import close_already_running_beekeeper -from beekeepy.exceptions import FailedToDetectRunningBeekeeperError +import beekeepy as bk +import beekeepy.exceptions as bke from clive.__private.cli.commands.abc.external_cli_command import ExternalCLICommand from clive.__private.cli.print_cli import print_cli @@ -16,8 +16,8 @@ class BeekeeperClose(ExternalCLICommand): print_cli("Closing beekeeper...") beekeeper_working_directory = safe_settings.beekeeper.working_directory try: - close_already_running_beekeeper(cwd=beekeeper_working_directory) - except FailedToDetectRunningBeekeeperError: + bk.close_already_running_beekeeper(cwd=beekeeper_working_directory) + except bke.FailedToDetectRunningBeekeeperError: print_cli("There was no running beekeeper.") else: print_cli("Beekeeper was closed.") diff --git a/clive/__private/cli/commands/beekeeper/beekeeper_spawn.py b/clive/__private/cli/commands/beekeeper/beekeeper_spawn.py index 6d1cf83379b3828369e435967398878124d2eb8d..975556430a5f86658be2aa40034539cb33d3af1b 100644 --- a/clive/__private/cli/commands/beekeeper/beekeeper_spawn.py +++ b/clive/__private/cli/commands/beekeeper/beekeeper_spawn.py @@ -3,7 +3,7 @@ from __future__ import annotations import time from dataclasses import dataclass -from beekeepy import AsyncBeekeeper +import beekeepy as bk from clive.__private.cli.commands.abc.external_cli_command import ExternalCLICommand from clive.__private.cli.exceptions import ( @@ -30,7 +30,9 @@ class BeekeeperSpawn(ExternalCLICommand): if not self.echo_address_only: print_cli("Launching beekeeper...") - async with await AsyncBeekeeper.factory(settings=safe_settings.beekeeper.settings_local_factory()) as beekeeper: + async with await bk.AsyncBeekeeper.factory( + settings=safe_settings.beekeeper.settings_local_factory() + ) as beekeeper: pid = beekeeper.detach() if self.echo_address_only: diff --git a/clive/__private/cli/commands/configure/node.py b/clive/__private/cli/commands/configure/node.py index 72c0dab220879687939335d72144e757d0925d2c..380726f2097c6a376225c166cea30d9d34e7527b 100644 --- a/clive/__private/cli/commands/configure/node.py +++ b/clive/__private/cli/commands/configure/node.py @@ -2,7 +2,7 @@ from __future__ import annotations from dataclasses import dataclass -from beekeepy.interfaces import HttpUrl +import beekeepy.interfaces as bki from clive.__private.cli.commands.abc.world_based_command import WorldBasedCommand @@ -12,5 +12,5 @@ class SetNode(WorldBasedCommand): node_address: str async def _run(self) -> None: - url = HttpUrl(self.node_address) + url = bki.HttpUrl(self.node_address) self.profile._set_node_address(url) diff --git a/clive/__private/cli/commands/configure/profile.py b/clive/__private/cli/commands/configure/profile.py index 841d1fa04275c89a419e0aae2209461a6c23804d..434efeb39375aee4f3cd54857fee38c9c886209b 100644 --- a/clive/__private/cli/commands/configure/profile.py +++ b/clive/__private/cli/commands/configure/profile.py @@ -3,7 +3,7 @@ from __future__ import annotations import errno from dataclasses import dataclass -from beekeepy.exceptions import CommunicationError +import beekeepy.exceptions as bke from clive.__private.cli.commands.abc.forceable_cli_command import ForceableCLICommand from clive.__private.cli.commands.abc.world_based_command import WorldBasedCommand @@ -58,7 +58,7 @@ class CreateProfile(WorldBasedCommand): result = ( await self.world.commands.create_profile_wallets(profile_name=profile.name, password=password) ).result_or_raise - except CommunicationError as error: + except bke.CommunicationError as error: if is_in_dev_mode(): raise raise CLICreatingProfileCommunicationError from error diff --git a/clive/__private/cli/error_handlers.py b/clive/__private/cli/error_handlers.py index 116d9c2ebe3acede354dc33e423d09e8add1ce67..471c592e1983c26dbff536360b2652dff126c1b6 100644 --- a/clive/__private/cli/error_handlers.py +++ b/clive/__private/cli/error_handlers.py @@ -3,7 +3,7 @@ from __future__ import annotations import errno from typing import TYPE_CHECKING -from beekeepy.exceptions import CommunicationError +import beekeepy.exceptions as bke from clive.__private.cli.exceptions import CLIPrettyError, CLIProfileAlreadyExistsError, CLIProfileDoesNotExistsError from clive.__private.core.error_handlers.abc.error_notificator import CannotNotifyError @@ -23,8 +23,8 @@ def register_error_handlers(cli: CliveTyper) -> None: message = f"Unhandled exception {type(error).__name__}{f': {error_message}' if error_message else ''}" raise CLIPrettyError(message, 1) - @cli.error_handler(CommunicationError) - def handle_communication_error(error: CommunicationError) -> None: + @cli.error_handler(bke.CommunicationError) + def handle_communication_error(error: bke.CommunicationError) -> None: raise CLIPrettyError(str(error), errno.ECOMM) from None @cli.error_handler(CannotNotifyError) diff --git a/clive/__private/core/beekeeper_manager.py b/clive/__private/core/beekeeper_manager.py index 6c1f3a05e6183c14e19f6fa4b2757f45064f0927..fc4c4b41d43230e8db64029845a59fe09bafc165 100644 --- a/clive/__private/core/beekeeper_manager.py +++ b/clive/__private/core/beekeeper_manager.py @@ -2,14 +2,14 @@ from __future__ import annotations from typing import TYPE_CHECKING, Final -from beekeepy import AsyncBeekeeper, AsyncSession -from beekeepy import Settings as BeekeepySettings +import beekeepy as bk from clive.__private.settings import safe_settings from clive.exceptions import CliveError if TYPE_CHECKING: - from beekeepy import AsyncSession, AsyncUnlockedWallet + from beekeepy import AsyncBeekeeper, AsyncSession, AsyncUnlockedWallet + from beekeepy.settings import InterfaceSettings from clive.__private.core.wallet_container import WalletContainer @@ -43,7 +43,7 @@ class BeekeeperManager: return bool(self._wallets) @property - def settings(self) -> BeekeepySettings: + def settings(self) -> InterfaceSettings: """Should be used only for modifying beekeeper settings before setup is done.""" use_instead_for_modify = "beekeeper_manager.beekeeper.update_settings" use_instead_for_read = "beekeeper_manager.beekeeper.settings" @@ -103,11 +103,11 @@ class BeekeeperManager: def clear_wallets(self) -> None: self._wallets = None - def _setup_beekeepy_settings(self) -> BeekeepySettings: + def _setup_beekeepy_settings(self) -> InterfaceSettings: return safe_settings.beekeeper.settings_factory() async def _setup(self) -> AsyncBeekeeper: if self.settings.http_endpoint is not None: - return await AsyncBeekeeper.remote_factory(url_or_settings=self.settings) + return await bk.AsyncBeekeeper.remote_factory(url_or_settings=self.settings) - return await AsyncBeekeeper.factory(settings=self.settings) + return await bk.AsyncBeekeeper.factory(settings=self.settings) diff --git a/clive/__private/core/commands/beekeeper.py b/clive/__private/core/commands/beekeeper.py index 4c0670528840e98390ebc7f004882640bf4d8193..08be226be686cb771e2e44194862fd32e0c69da0 100644 --- a/clive/__private/core/commands/beekeeper.py +++ b/clive/__private/core/commands/beekeeper.py @@ -2,7 +2,7 @@ from __future__ import annotations from dataclasses import dataclass -from beekeepy import find_running_beekeepers +import beekeepy as bk from clive.__private.core.commands.abc.command_with_result import CommandWithResult from clive.__private.settings import safe_settings @@ -23,7 +23,7 @@ class IsBeekeeperRunningResult: class IsBeekeeperRunning(CommandWithResult[IsBeekeeperRunningResult]): async def _execute(self) -> None: beekeeper_working_directory = safe_settings.beekeeper.working_directory - running_beekeepers = find_running_beekeepers(cwd=beekeeper_working_directory) + running_beekeepers = bk.find_running_beekeepers(cwd=beekeeper_working_directory) if running_beekeepers: assert len(running_beekeepers) == 1, "More beekeepers are running than expected." diff --git a/clive/__private/core/commands/create_encryption_wallet.py b/clive/__private/core/commands/create_encryption_wallet.py index 626300de6dd76d42dd292ea85307f2a0e4e14679..1bee7ae0084366ac133cdf46905ef76576be30b4 100644 --- a/clive/__private/core/commands/create_encryption_wallet.py +++ b/clive/__private/core/commands/create_encryption_wallet.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING -from beekeepy import AsyncUnlockedWallet +import beekeepy as bk from clive.__private.core.commands.abc.command_with_result import CommandWithResult from clive.__private.core.encryption import EncryptionService @@ -14,7 +14,7 @@ if TYPE_CHECKING: @dataclass(kw_only=True) -class CreateEncryptionWallet(CommandWithResult[AsyncUnlockedWallet]): +class CreateEncryptionWallet(CommandWithResult[bk.AsyncUnlockedWallet]): session: AsyncSession profile_name: str password: str diff --git a/clive/__private/core/commands/create_user_wallet.py b/clive/__private/core/commands/create_user_wallet.py index 0568b1626ee4ce66cdf9bdd6c8e21483227f71fe..416930772b0efcb2a73cfec21dc888479508080f 100644 --- a/clive/__private/core/commands/create_user_wallet.py +++ b/clive/__private/core/commands/create_user_wallet.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING -from beekeepy import AsyncUnlockedWallet +import beekeepy as bk from clive.__private.core.commands.abc.command_with_result import CommandWithResult @@ -12,7 +12,7 @@ if TYPE_CHECKING: @dataclass(kw_only=True) -class CreateUserWallet(CommandWithResult[AsyncUnlockedWallet]): +class CreateUserWallet(CommandWithResult[bk.AsyncUnlockedWallet]): session: AsyncSession profile_name: str password: str diff --git a/clive/__private/core/commands/data_retrieval/chain_data.py b/clive/__private/core/commands/data_retrieval/chain_data.py index e77c940bc43e1f33f52b87a03a0d174bab029ffe..9d1bd0d6fbfb2107fc544a6d4323f8171206ee72 100644 --- a/clive/__private/core/commands/data_retrieval/chain_data.py +++ b/clive/__private/core/commands/data_retrieval/chain_data.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING -from beekeepy.exceptions import UnknownDecisionPathError +import beekeepy.exceptions as bke from clive.__private.cli.styling import colorize_error, colorize_ok, colorize_warning from clive.__private.core.calculate_participation_count import calculate_participation_count_percent @@ -247,7 +247,7 @@ class ChainDataRetrieval(CommandDataRetrieval[HarvestedDataRaw, SanitizedData, C current_price_feed = await node.api.database_api.get_current_price_feed() feed = await node.api.database_api.get_feed_history() return HarvestedDataRaw(gdpo, witness_schedule, version, hardfork_properties, current_price_feed, feed) - raise UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") + raise bke.UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") async def _sanitize_data(self, data: HarvestedDataRaw) -> SanitizedData: witness_schedule = self.__assert_witnesses_schedule(data.witness_schedule) diff --git a/clive/__private/core/commands/data_retrieval/find_scheduled_transfers.py b/clive/__private/core/commands/data_retrieval/find_scheduled_transfers.py index 78c1ba501868a210f76e694be9cb1107630e0d19..df9dad6bba64ba6fc8e14c9f6417ff8a3f8474a8 100644 --- a/clive/__private/core/commands/data_retrieval/find_scheduled_transfers.py +++ b/clive/__private/core/commands/data_retrieval/find_scheduled_transfers.py @@ -4,7 +4,7 @@ from dataclasses import dataclass, fields from datetime import datetime, timedelta from typing import TYPE_CHECKING, Final, Literal, cast -from beekeepy.exceptions import UnknownDecisionPathError +import beekeepy.exceptions as bke from clive.__private.core.commands.abc.command import Command, CommandError from clive.__private.core.commands.abc.command_data_retrieval import CommandDataRetrieval @@ -236,7 +236,7 @@ class FindScheduledTransfers(CommandDataRetrieval[_HarvestedDataRaw, _SanitizedD recurrent_transfers=await node.api.database_api.find_recurrent_transfers(from_=self.account_name), account_data=await node.api.database_api.find_accounts(accounts=[self.account_name]), ) - raise UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") + raise bke.UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") async def _sanitize_data(self, data: _HarvestedDataRaw) -> _SanitizedData: return _SanitizedData( diff --git a/clive/__private/core/commands/data_retrieval/find_vesting_delegation_expirations.py b/clive/__private/core/commands/data_retrieval/find_vesting_delegation_expirations.py index 496ddb52aac752758c149dce0d239d55364cf495..241cd838bc6f3a63510c4748d4a270977c5c0f33 100644 --- a/clive/__private/core/commands/data_retrieval/find_vesting_delegation_expirations.py +++ b/clive/__private/core/commands/data_retrieval/find_vesting_delegation_expirations.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING -from beekeepy.exceptions import UnknownDecisionPathError +import beekeepy.exceptions as bke from clive.__private.core.commands.abc.command import CommandError from clive.__private.core.commands.abc.command_data_retrieval import CommandDataRetrieval @@ -70,7 +70,7 @@ class FindVestingDelegationExpirations( ) dgpo = await node.api.database_api.get_dynamic_global_properties() return HarvestedDataRaw(vesting_delegation_expirations, dgpo) - raise UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") + raise bke.UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") async def _sanitize_data(self, data: HarvestedDataRaw) -> SanitizedData: delegations = data.find_vesting_delegation_expirations.delegations diff --git a/clive/__private/core/commands/data_retrieval/get_node_basic_info.py b/clive/__private/core/commands/data_retrieval/get_node_basic_info.py index 903e10825f5489b1ba10d32dc50efd1e7e61c713..dea6c9ad4f74ac7c79d9af960cb0504199e7f199 100644 --- a/clive/__private/core/commands/data_retrieval/get_node_basic_info.py +++ b/clive/__private/core/commands/data_retrieval/get_node_basic_info.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING -from beekeepy.exceptions import UnknownDecisionPathError +import beekeepy.exceptions as bke from clive.__private.core.commands.abc.command_data_retrieval import CommandDataRetrieval @@ -39,4 +39,4 @@ class GetNodeBasicInfo(CommandDataRetrieval[NodeBasicInfoData, NodeBasicInfoData dynamic_global_properties=await node.api.database_api.get_dynamic_global_properties(), ) - raise UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") + raise bke.UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") diff --git a/clive/__private/core/commands/data_retrieval/hive_power_data.py b/clive/__private/core/commands/data_retrieval/hive_power_data.py index dfe55eaa855ecc79e918d88e4f52a9c877daa289..711f0fdd537c900bdc45572d875fd3d132cec776 100644 --- a/clive/__private/core/commands/data_retrieval/hive_power_data.py +++ b/clive/__private/core/commands/data_retrieval/hive_power_data.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING, Final -from beekeepy.exceptions import UnknownDecisionPathError +import beekeepy.exceptions as bke from clive.__private.core import iwax from clive.__private.core.commands.abc.command_data_retrieval import CommandDataRetrieval @@ -93,7 +93,7 @@ class HivePowerDataRetrieval(CommandDataRetrieval[HarvestedDataRaw, SanitizedDat ), await node.api.database_api.find_vesting_delegations(account=self.account_name), ) - raise UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") + raise bke.UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") async def _sanitize_data(self, data: HarvestedDataRaw) -> SanitizedData: return SanitizedData( diff --git a/clive/__private/core/commands/data_retrieval/proposals_data.py b/clive/__private/core/commands/data_retrieval/proposals_data.py index af74971ede3d75652af9333a3834eea1317307a6..e1d6ab606a5e05660de80526d0046a8313a197ed 100644 --- a/clive/__private/core/commands/data_retrieval/proposals_data.py +++ b/clive/__private/core/commands/data_retrieval/proposals_data.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING, ClassVar -from beekeepy.exceptions import UnknownDecisionPathError +import beekeepy.exceptions as bke from clive.__private.core.commands.abc.command_data_retrieval import CommandDataRetrieval from clive.__private.core.constants.data_retrieval import ( @@ -117,7 +117,7 @@ class ProposalsDataRetrieval(CommandDataRetrieval[HarvestedDataRaw, SanitizedDat status=self.status, ) return HarvestedDataRaw(gdpo, searched_proposals, proposal_votes) - raise UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") + raise bke.UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") async def _sanitize_data(self, data: HarvestedDataRaw) -> SanitizedData: return SanitizedData( diff --git a/clive/__private/core/commands/data_retrieval/savings_data.py b/clive/__private/core/commands/data_retrieval/savings_data.py index 5380b890c17d55ccbe7250855a4128c8b3a6b56a..cc8e16d0b2510186950b14b77a0660714faf3f3f 100644 --- a/clive/__private/core/commands/data_retrieval/savings_data.py +++ b/clive/__private/core/commands/data_retrieval/savings_data.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING, Final -from beekeepy.exceptions import UnknownDecisionPathError +import beekeepy.exceptions as bke from clive.__private.core.commands.abc.command_data_retrieval import CommandDataRetrieval from clive.__private.core.formatters.humanize import align_to_dot, humanize_asset @@ -97,7 +97,7 @@ class SavingsDataRetrieval(CommandDataRetrieval[HarvestedDataRaw, SanitizedData, await node.api.database_api.find_accounts(accounts=[self.account_name]), await node.api.database_api.find_savings_withdrawals(account=self.account_name), ) - raise UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") + raise bke.UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") async def _sanitize_data(self, data: HarvestedDataRaw) -> SanitizedData: return SanitizedData( diff --git a/clive/__private/core/commands/data_retrieval/update_node_data/command.py b/clive/__private/core/commands/data_retrieval/update_node_data/command.py index 0fcd6e632985ccd4fbef8b00bd070ae5c12ab867..f325a2c0c2bd3a7d908e9a38795af1334ec3525c 100644 --- a/clive/__private/core/commands/data_retrieval/update_node_data/command.py +++ b/clive/__private/core/commands/data_retrieval/update_node_data/command.py @@ -4,7 +4,7 @@ from dataclasses import dataclass, field from datetime import datetime, timedelta from typing import TYPE_CHECKING, Final -from beekeepy.interfaces import SuppressApiNotFound +import beekeepy.interfaces as bki from clive.__private.core import iwax from clive.__private.core.commands.abc.command_data_retrieval import CommandDataRetrieval @@ -209,7 +209,7 @@ class UpdateNodeData(CommandDataRetrieval[HarvestedDataRaw, SanitizedData, Dynam def __assert_rc_accounts(self, data: FindRcAccounts | None) -> list[RcAccount]: assert data is not None, "Rc account data is missing..." - with SuppressApiNotFound("rc_api"): + with bki.SuppressApiNotFound("rc_api"): assert len(data.rc_accounts) == len(self.accounts), "RC accounts are missing some accounts..." return data.rc_accounts return [] @@ -217,7 +217,7 @@ class UpdateNodeData(CommandDataRetrieval[HarvestedDataRaw, SanitizedData, Dynam def __assert_account_history_or_none(self, data: GetAccountHistory | None) -> GetAccountHistory | None: assert data is not None, "Account history info is missing..." - with SuppressApiNotFound("account_history_api"): + with bki.SuppressApiNotFound("account_history_api"): assert len(data.history) == 1, "Account history info malformed. Expected only one entry." return data return None diff --git a/clive/__private/core/commands/data_retrieval/witnesses_data.py b/clive/__private/core/commands/data_retrieval/witnesses_data.py index 98eb53f1f36715a22c7e521a0170b5198c2914bb..c69d332a06472ddb1cb516a0ab16bd0132730345 100644 --- a/clive/__private/core/commands/data_retrieval/witnesses_data.py +++ b/clive/__private/core/commands/data_retrieval/witnesses_data.py @@ -4,7 +4,7 @@ from collections import OrderedDict from dataclasses import dataclass, field from typing import TYPE_CHECKING, ClassVar -from beekeepy.exceptions import UnknownDecisionPathError +import beekeepy.exceptions as bke from clive.__private.core.commands.abc.command_data_retrieval import ( CommandDataRetrieval, @@ -132,7 +132,7 @@ class WitnessesDataRetrieval(CommandDataRetrieval[HarvestedDataRaw, SanitizedDat ) return HarvestedDataRaw(gdpo, witness_votes, top_witnesses, witnesses_by_name) - raise UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") + raise bke.UnknownDecisionPathError(f"{self.__class__.__name__}:_harvest_data_from_api") async def _sanitize_data(self, data: HarvestedDataRaw) -> SanitizedData: in_search_by_pattern_mode = self.mode == "search_by_pattern" diff --git a/clive/__private/core/commands/decrypt.py b/clive/__private/core/commands/decrypt.py index b4cb00d964ec00cb8e2b2dc8f226b23bee5b35bf..148e7a31102b3dafed7fe939342ef9fbe9129a0c 100644 --- a/clive/__private/core/commands/decrypt.py +++ b/clive/__private/core/commands/decrypt.py @@ -2,7 +2,7 @@ from __future__ import annotations from dataclasses import dataclass -from beekeepy.exceptions import CommunicationError +import beekeepy.exceptions as bke from clive.__private.core.commands.abc.command import Command, CommandError from clive.__private.core.commands.abc.command_encryption import CommandEncryption @@ -26,5 +26,5 @@ class Decrypt(CommandEncryption, CommandWithResult[str]): to_key=encryption_key, content=self.encrypted_content, ) - except CommunicationError as error: + except bke.CommunicationError as error: raise CommandDecryptError(self) from error diff --git a/clive/__private/core/commands/encrypt.py b/clive/__private/core/commands/encrypt.py index ead9879379e9c43a9dff07b9e0ec03b0dd82c890..3a0949e33ff1c26aadcefa084103f16d759bb0a5 100644 --- a/clive/__private/core/commands/encrypt.py +++ b/clive/__private/core/commands/encrypt.py @@ -2,7 +2,7 @@ from __future__ import annotations from dataclasses import dataclass -from beekeepy.exceptions import CommunicationError +import beekeepy.exceptions as bke from clive.__private.core.commands.abc.command import Command, CommandError from clive.__private.core.commands.abc.command_encryption import CommandEncryption @@ -26,5 +26,5 @@ class Encrypt(CommandEncryption, CommandWithResult[str]): to_key=encryption_key, content=self.content, ) - except CommunicationError as error: + except bke.CommunicationError as error: raise CommandEncryptError(self) from error diff --git a/clive/__private/core/commands/get_unlocked_encryption_wallet.py b/clive/__private/core/commands/get_unlocked_encryption_wallet.py index 0f2334003c1fb9f2dcbbaf185fc2b6a3b53f8d0f..2b8f76a0f23d77e10ef5ef5cd6ee05bc17060847 100644 --- a/clive/__private/core/commands/get_unlocked_encryption_wallet.py +++ b/clive/__private/core/commands/get_unlocked_encryption_wallet.py @@ -1,13 +1,17 @@ from __future__ import annotations from dataclasses import dataclass +from typing import TYPE_CHECKING -from beekeepy import AsyncSession, AsyncUnlockedWallet +import beekeepy as bk from clive.__private.core.commands.abc.command import Command, CommandError from clive.__private.core.commands.abc.command_with_result import CommandWithResult from clive.__private.core.encryption import EncryptionService +if TYPE_CHECKING: + from beekeepy import AsyncSession + class MultipleEncryptionWalletsUnlockedError(CommandError): def __init__(self, command: Command) -> None: @@ -22,7 +26,7 @@ class NoEncryptionWalletUnlockedError(CommandError): @dataclass(kw_only=True) -class GetUnlockedEncryptionWallet(CommandWithResult[AsyncUnlockedWallet]): +class GetUnlockedEncryptionWallet(CommandWithResult[bk.AsyncUnlockedWallet]): """ Get the unlocked encryption wallet - the one containing encryption key managed by clive. diff --git a/clive/__private/core/commands/get_unlocked_user_wallet.py b/clive/__private/core/commands/get_unlocked_user_wallet.py index 9c1fcb1c06ee6e7c0d4718e7619b94c1d0131648..bb0b08e4e121120f9fba9fa84fc80c894d5c0101 100644 --- a/clive/__private/core/commands/get_unlocked_user_wallet.py +++ b/clive/__private/core/commands/get_unlocked_user_wallet.py @@ -1,13 +1,17 @@ from __future__ import annotations from dataclasses import dataclass +from typing import TYPE_CHECKING -from beekeepy import AsyncSession, AsyncUnlockedWallet +import beekeepy as bk from clive.__private.core.commands.abc.command import Command, CommandError from clive.__private.core.commands.abc.command_with_result import CommandWithResult from clive.__private.core.encryption import EncryptionService +if TYPE_CHECKING: + from beekeepy import AsyncSession + class MultipleProfilesUnlockedError(CommandError): def __init__(self, command: Command) -> None: @@ -20,7 +24,7 @@ class NoProfileUnlockedError(CommandError): @dataclass(kw_only=True) -class GetUnlockedUserWallet(CommandWithResult[AsyncUnlockedWallet]): +class GetUnlockedUserWallet(CommandWithResult[bk.AsyncUnlockedWallet]): """ Get the unlocked user wallet - the one containing keys imported by user. diff --git a/clive/__private/core/commands/is_password_valid.py b/clive/__private/core/commands/is_password_valid.py index 7dad033f62d5801f44bcaee0ca43e88db33f0911..ab5cc260fded08f8062beed2dcb13c00a25179d5 100644 --- a/clive/__private/core/commands/is_password_valid.py +++ b/clive/__private/core/commands/is_password_valid.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING -from beekeepy.exceptions import InvalidPasswordError +import beekeepy.exceptions as bke from clive.__private.core.commands.abc.command_with_result import CommandWithResult @@ -36,6 +36,6 @@ class IsPasswordValid(CommandWithResult[bool]): async def _is_password_valid(self, wallet: AsyncWallet) -> bool: try: await wallet.unlock(password=self.password) - except InvalidPasswordError: + except bke.InvalidPasswordError: return False return True diff --git a/clive/__private/core/commands/save_profile.py b/clive/__private/core/commands/save_profile.py index c22cebf0a19cd0bbbd965e92ee7f150a83674f9a..db5d8abfac6a43d63f39c8e92f8625524674dac9 100644 --- a/clive/__private/core/commands/save_profile.py +++ b/clive/__private/core/commands/save_profile.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING, Final -from beekeepy.exceptions import CommunicationError +import beekeepy.exceptions as bke from clive.__private.core.beekeeper_manager import WalletsNotAvailableError from clive.__private.core.commands.abc.command import Command, CommandError @@ -34,5 +34,5 @@ class SaveProfile(CommandEncryption, Command): encryption_service = EncryptionService(WalletContainer(self.unlocked_wallet, self.unlocked_encryption_wallet)) try: await self.profile.save(encryption_service) - except (CommunicationError, WalletsNotAvailableError) as error: + except (bke.CommunicationError, WalletsNotAvailableError) as error: raise ProfileSavingFailedError(self) from error diff --git a/clive/__private/core/commands/unlock.py b/clive/__private/core/commands/unlock.py index ed25ff0d5c32f20d2e8b62753c577294386d3658..fd53d0d73965d95bfe397fa68bc273d39e5a7294 100644 --- a/clive/__private/core/commands/unlock.py +++ b/clive/__private/core/commands/unlock.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING -from beekeepy.exceptions import NoWalletWithSuchNameError +import beekeepy.exceptions as bke from clive.__private.core.commands.abc.command_secured import CommandPasswordSecured from clive.__private.core.commands.abc.command_with_result import CommandWithResult @@ -88,6 +88,6 @@ class Unlock(CommandPasswordSecured, CommandWithResult[UnlockWalletStatus]): async def _unlock_wallet(self, name: str) -> AsyncUnlockedWallet | None: try: wallet = await self.session.open_wallet(name=name) - except NoWalletWithSuchNameError: + except bke.NoWalletWithSuchNameError: return None return await wallet.unlock(password=self.password) diff --git a/clive/__private/core/error_handlers/communication_failure_notificator.py b/clive/__private/core/error_handlers/communication_failure_notificator.py index a66c01b25bbc7d3a5429b05cbcdade482e6e37c1..3ae59ef53f2761bc934b0496545f8606b38d102e 100644 --- a/clive/__private/core/error_handlers/communication_failure_notificator.py +++ b/clive/__private/core/error_handlers/communication_failure_notificator.py @@ -1,14 +1,17 @@ from __future__ import annotations -from typing import Final, TypeGuard +from typing import TYPE_CHECKING, Final, TypeGuard -from beekeepy.exceptions import CommunicationError, TimeoutExceededError +import beekeepy.exceptions as bke from clive.__private.core.clive_import import get_clive from clive.__private.core.error_handlers.abc.error_notificator import ErrorNotificator +if TYPE_CHECKING: + from beekeepy.exceptions import CommunicationError, TimeoutExceededError -class CommunicationFailureNotificator(ErrorNotificator[CommunicationError]): + +class CommunicationFailureNotificator(ErrorNotificator[bke.CommunicationError]): """ A context manager that notifies about errors of `CommunicatorError` type. @@ -24,11 +27,11 @@ class CommunicationFailureNotificator(ErrorNotificator[CommunicationError]): } def _is_exception_to_catch(self, error: Exception) -> TypeGuard[CommunicationError]: - return isinstance(error, CommunicationError) + return isinstance(error, bke.CommunicationError) @classmethod def _determine_message(cls, exception: CommunicationError) -> str: - if isinstance(exception, TimeoutExceededError): + if isinstance(exception, bke.TimeoutExceededError): return cls._get_communication_timeout_message(exception) error_messages = exception.get_response_error_messages() diff --git a/clive/__private/core/error_handlers/general_error_notificator.py b/clive/__private/core/error_handlers/general_error_notificator.py index 4f01cb9e2b50fcb23fe75329f10e581f85243ee6..be93dc8f6dcacb79f7f88d1b0cdcb75c886864e8 100644 --- a/clive/__private/core/error_handlers/general_error_notificator.py +++ b/clive/__private/core/error_handlers/general_error_notificator.py @@ -2,7 +2,7 @@ from __future__ import annotations from typing import Final, TypeGuard -from beekeepy.exceptions import InvalidPasswordError, NotExistingKeyError, NoWalletWithSuchNameError +import beekeepy.exceptions as bke from clive.__private.core.commands.recover_wallets import CannotRecoverWalletsError from clive.__private.core.commands.save_profile import ProfileSavingFailedError @@ -21,9 +21,9 @@ class GeneralErrorNotificator(ErrorNotificator[Exception]): """ SEARCHED_AND_PRINTED_MESSAGES: Final[dict[type[Exception], str]] = { - InvalidPasswordError: INVALID_PASSWORD_MESSAGE, - NoWalletWithSuchNameError: "Wallet with this name was not found on the beekeeper. Please try again.", - NotExistingKeyError: "Key does not exist in the wallet.", + bke.InvalidPasswordError: INVALID_PASSWORD_MESSAGE, + bke.NoWalletWithSuchNameError: "Wallet with this name was not found on the beekeeper. Please try again.", + bke.NotExistingKeyError: "Key does not exist in the wallet.", ProfileEncryptionError: "Profile encryption failed which means profile cannot be saved or loaded.", CannotRecoverWalletsError: CannotRecoverWalletsError.MESSAGE, ProfileSavingFailedError: ProfileSavingFailedError.MESSAGE, diff --git a/clive/__private/core/node.py b/clive/__private/core/node.py index 7e6b2fabfa4b35259e84e435c2a8d8ba0d306bc2..f55754b7f8e5f65ad56b1a44d7365872914ba3e2 100644 --- a/clive/__private/core/node.py +++ b/clive/__private/core/node.py @@ -6,7 +6,7 @@ from dataclasses import dataclass, field from datetime import timedelta from typing import TYPE_CHECKING -from beekeepy.exceptions import CommunicationError +import beekeepy.exceptions as bke from clive.__private.core.commands.data_retrieval.get_node_basic_info import GetNodeBasicInfo, NodeBasicInfoData from clive.__private.settings import safe_settings @@ -104,7 +104,7 @@ class Node(AsyncHived): async def online(self) -> bool: try: await self._fetch_basic_info() - except CommunicationError as error: + except bke.CommunicationError as error: if error.response is None: return False raise @@ -248,7 +248,7 @@ class Node(AsyncHived): async def _sync_node_basic_info(self) -> None: try: self.cached._basic_info = await GetNodeBasicInfo(self).execute_with_result() - except CommunicationError as error: + except bke.CommunicationError as error: if error.response is None: self.cached._set_offline() raise diff --git a/clive/__private/core/profile.py b/clive/__private/core/profile.py index a4b5ab1dcd65bab0b5f1bf7056cb7c0a285897de..b6750679a75c99e8cd7b304f2015ee6225628b20 100644 --- a/clive/__private/core/profile.py +++ b/clive/__private/core/profile.py @@ -3,7 +3,7 @@ from __future__ import annotations from copy import deepcopy from typing import TYPE_CHECKING, Final -from beekeepy.interfaces import HttpUrl +import beekeepy.interfaces as bki from clive.__private.core.accounts.account_manager import AccountManager from clive.__private.core.constants.tui.themes import DEFAULT_THEME @@ -23,6 +23,8 @@ if TYPE_CHECKING: from pathlib import Path from typing import Self + from beekeepy.interfaces import HttpUrl + from clive.__private.core.accounts.accounts import Account from clive.__private.core.encryption import EncryptionService @@ -342,8 +344,8 @@ class Profile: @staticmethod def _default_node_addresses() -> list[HttpUrl]: return [ - HttpUrl("api.hive.blog", protocol="https"), - HttpUrl("api.openhive.network", protocol="https"), + bki.HttpUrl("api.hive.blog", protocol="https"), + bki.HttpUrl("api.openhive.network", protocol="https"), ] @staticmethod @@ -362,7 +364,7 @@ class Profile: if secret_node_address: return secret_node_address if given_node_address: - return HttpUrl(given_node_address) + return bki.HttpUrl(given_node_address) return self._backup_node_addresses[0] def _set_node_address(self, value: HttpUrl) -> None: diff --git a/clive/__private/core/url_utils.py b/clive/__private/core/url_utils.py deleted file mode 100644 index 1cb8d7eb3638d837024e095272b2ae603273bf67..0000000000000000000000000000000000000000 --- a/clive/__private/core/url_utils.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from beekeepy.interfaces import HttpUrl - - -async def is_url_reachable(url: HttpUrl) -> bool: - """ - Check if the given url is reachable. - - Args: - url: The URL to check. - - Returns: - True if the URL is reachable, False otherwise. - """ - import aiohttp # noqa: PLC0415 - - try: - async with aiohttp.ClientSession() as session, session.get(str(url)): - return True - except aiohttp.ClientConnectorError: - return False diff --git a/clive/__private/models/schemas.py b/clive/__private/models/schemas.py index 221b4c6d32ea469367701018b1d85afa844b0bf1..424bc4591274617e271f973575d8f16e86355814 100644 --- a/clive/__private/models/schemas.py +++ b/clive/__private/models/schemas.py @@ -16,124 +16,9 @@ has unnecessary "Fundament" suffix, and is not specialized with HF26 assets. from __future__ import annotations -from schemas._preconfigured_base_model import PreconfiguredBaseModel -from schemas.apis.account_history_api import GetAccountHistory -from schemas.apis.database_api import ( - FindAccounts, - FindProposals, - FindRecurrentTransfers, - FindSavingsWithdrawals, - FindVestingDelegationExpirations, - FindVestingDelegations, - FindWitnesses, - GetConfig, - GetDynamicGlobalProperties, - GetFeedHistory, - GetHardforkProperties, - GetVersion, - GetWitnessSchedule, - ListChangeRecoveryAccountRequests, - ListDeclineVotingRightsRequests, - ListProposals, - ListProposalVotes, - ListWithdrawVestingRoutes, - ListWitnesses, - ListWitnessVotes, -) -from schemas.apis.database_api.fundaments_of_reponses import ( - AccountItemFundament, - FindRecurrentTransfersFundament, - ListChangeRecoveryAccountRequestsFundament, - ListDeclineVotingRightsRequestsFundament, - SavingsWithdrawalsFundament, - VestingDelegationExpirationsFundament, - VestingDelegationsFundament, - WithdrawVestingRoutesFundament, - WitnessesFundament, -) -from schemas.apis.rc_api import FindRcAccounts as SchemasFindRcAccounts -from schemas.apis.rc_api.fundaments_of_responses import RcAccount as SchemasRcAccount -from schemas.apis.transaction_status_api import FindTransaction -from schemas.base import field -from schemas.decoders import is_matching_model, validate_schema_field -from schemas.errors import DecodeError, ValidationError -from schemas.fields.assets import AssetHbd, AssetHive, AssetVests -from schemas.fields.basic import AccountName, PublicKey -from schemas.fields.compound import Authority, Manabar, Price -from schemas.fields.compound import HbdExchangeRate as SchemasHbdExchangeRate -from schemas.fields.compound import Proposal as SchemasProposal -from schemas.fields.hex import Sha256, Signature, TransactionId -from schemas.fields.hive_datetime import HiveDateTime -from schemas.fields.hive_int import HiveInt -from schemas.fields.integers import Uint16t, Uint32t -from schemas.fields.resolvables import JsonString -from schemas.operation import Operation -from schemas.operations import ( - AccountCreateOperation, - AccountCreateWithDelegationOperation, - AccountUpdate2Operation, - AccountUpdateOperation, - AccountWitnessProxyOperation, - AccountWitnessVoteOperation, - CancelTransferFromSavingsOperation, - ChangeRecoveryAccountOperation, - ClaimAccountOperation, - ClaimRewardBalanceOperation, - CollateralizedConvertOperation, - CommentOperation, - CommentOptionsOperation, - ConvertOperation, - CreateClaimedAccountOperation, - CreateProposalOperation, - CustomBinaryOperation, - CustomJsonOperation, - CustomOperation, - DeclineVotingRightsOperation, - DelegateVestingSharesOperation, - DeleteCommentOperation, - EscrowApproveOperation, - EscrowDisputeOperation, - EscrowReleaseOperation, - EscrowTransferOperation, - FeedPublishOperation, - Hf26OperationRepresentation, - Hf26Operations, - LimitOrderCancelOperation, - LimitOrderCreate2Operation, - LimitOrderCreateOperation, - Pow2Operation, - PowOperation, - RecoverAccountOperation, - RemoveProposalOperation, - RequestAccountRecoveryOperation, - ResetAccountOperation, - SetResetAccountOperation, - SetWithdrawVestingRouteOperation, - TransferFromSavingsOperation, - TransferOperation, - TransferToSavingsOperation, - TransferToVestingOperation, - UpdateProposalOperation, - UpdateProposalVotesOperation, - VoteOperation, - WithdrawVestingOperation, - WitnessBlockApproveOperation, - WitnessSetPropertiesOperation, - WitnessUpdateOperation, - convert_to_representation, -) -from schemas.operations.extensions.recurrent_transfer_extensions import RecurrentTransferPairId -from schemas.operations.extensions.representation_types import ( - HF26RepresentationRecurrentTransferPairIdOperationExtension, -) -from schemas.operations.recurrent_transfer_operation import RecurrentTransferOperation -from schemas.policies import ( - ExtraFieldsPolicy, - MissingFieldsInGetConfigPolicy, - TestnetAssetsPolicy, - set_policies, -) -from schemas.transaction import Transaction +from typing import TYPE_CHECKING + +from beekeepy._utilities.smart_lazy_import import aggregate_same_import, lazy_module_factory __all__ = [ # noqa: RUF022 # operation BASIC aliases @@ -269,47 +154,324 @@ __all__ = [ # noqa: RUF022 "field", ] -# operation BASIC aliases +if TYPE_CHECKING: + from schemas._preconfigured_base_model import PreconfiguredBaseModel + from schemas.apis.account_history_api import GetAccountHistory + from schemas.apis.database_api import ( + FindAccounts, + FindProposals, + FindRecurrentTransfers, + FindSavingsWithdrawals, + FindVestingDelegationExpirations, + FindVestingDelegations, + FindWitnesses, + GetConfig, + GetDynamicGlobalProperties, + GetFeedHistory, + GetHardforkProperties, + GetVersion, + GetWitnessSchedule, + ListChangeRecoveryAccountRequests, + ListDeclineVotingRightsRequests, + ListProposals, + ListProposalVotes, + ListWithdrawVestingRoutes, + ListWitnesses, + ListWitnessVotes, + ) + from schemas.apis.database_api.fundaments_of_reponses import ( + AccountItemFundament, + FindRecurrentTransfersFundament, + ListChangeRecoveryAccountRequestsFundament, + ListDeclineVotingRightsRequestsFundament, + SavingsWithdrawalsFundament, + VestingDelegationExpirationsFundament, + VestingDelegationsFundament, + WithdrawVestingRoutesFundament, + WitnessesFundament, + ) + from schemas.apis.rc_api import FindRcAccounts + from schemas.apis.rc_api.fundaments_of_responses import RcAccount + from schemas.apis.transaction_status_api import FindTransaction + from schemas.base import field + from schemas.decoders import is_matching_model, validate_schema_field + from schemas.errors import DecodeError, ValidationError + from schemas.fields.assets import AssetHbd, AssetHive, AssetVests + from schemas.fields.basic import AccountName, PublicKey + from schemas.fields.compound import Authority, HbdExchangeRate, Manabar, Price, Proposal + from schemas.fields.hex import Sha256, Signature, TransactionId + from schemas.fields.hive_datetime import HiveDateTime + from schemas.fields.hive_int import HiveInt + from schemas.fields.integers import Uint16t, Uint32t + from schemas.fields.resolvables import JsonString + from schemas.operation import Operation + from schemas.operations import ( + AccountCreateOperation, + AccountCreateWithDelegationOperation, + AccountUpdate2Operation, + AccountUpdateOperation, + AccountWitnessProxyOperation, + AccountWitnessVoteOperation, + CancelTransferFromSavingsOperation, + ChangeRecoveryAccountOperation, + ClaimAccountOperation, + ClaimRewardBalanceOperation, + CollateralizedConvertOperation, + CommentOperation, + CommentOptionsOperation, + ConvertOperation, + CreateClaimedAccountOperation, + CreateProposalOperation, + CustomBinaryOperation, + CustomJsonOperation, + CustomOperation, + DeclineVotingRightsOperation, + DelegateVestingSharesOperation, + DeleteCommentOperation, + EscrowApproveOperation, + EscrowDisputeOperation, + EscrowReleaseOperation, + EscrowTransferOperation, + FeedPublishOperation, + Hf26OperationRepresentation, + Hf26Operations, + LimitOrderCancelOperation, + LimitOrderCreate2Operation, + LimitOrderCreateOperation, + Pow2Operation, + PowOperation, + RecoverAccountOperation, + RemoveProposalOperation, + RequestAccountRecoveryOperation, + ResetAccountOperation, + SetResetAccountOperation, + SetWithdrawVestingRouteOperation, + TransferFromSavingsOperation, + TransferOperation, + TransferToSavingsOperation, + TransferToVestingOperation, + UpdateProposalOperation, + UpdateProposalVotesOperation, + VoteOperation, + WithdrawVestingOperation, + WitnessBlockApproveOperation, + WitnessSetPropertiesOperation, + WitnessUpdateOperation, + convert_to_representation, + ) + from schemas.operations.extensions.recurrent_transfer_extensions import RecurrentTransferPairId + from schemas.operations.extensions.representation_types import ( + HF26RepresentationRecurrentTransferPairIdOperationExtension, + ) + from schemas.operations.recurrent_transfer_operation import RecurrentTransferOperation + from schemas.policies import ( + ExtraFieldsPolicy, + MissingFieldsInGetConfigPolicy, + TestnetAssetsPolicy, + set_policies, + ) + from schemas.transaction import Transaction -OperationBase = Operation -OperationRepresentationUnion = Hf26OperationRepresentation -OperationUnion = Hf26Operations + # operation BASIC aliases -# find API response aliases (have nested list property which stores actual model) + OperationBase = Operation + OperationRepresentationUnion = Hf26OperationRepresentation + OperationUnion = Hf26Operations -FindRcAccounts = SchemasFindRcAccounts + # get API responses (have no unnecessary nested properties, just the model itself) -# get API responses (have no unnecessary nested properties, just the model itself) + Config = GetConfig + DynamicGlobalProperties = GetDynamicGlobalProperties + FeedHistory = GetFeedHistory + HardforkProperties = GetHardforkProperties + Version = GetVersion + WitnessSchedule = GetWitnessSchedule -Config = GetConfig -DynamicGlobalProperties = GetDynamicGlobalProperties -FeedHistory = GetFeedHistory -HardforkProperties = GetHardforkProperties -Version = GetVersion -WitnessSchedule = GetWitnessSchedule + # extensions -# extensions + RecurrentTransferPairIdExtension = RecurrentTransferPairId + RecurrentTransferPairIdRepresentation = HF26RepresentationRecurrentTransferPairIdOperationExtension -RecurrentTransferPairIdExtension = RecurrentTransferPairId -RecurrentTransferPairIdRepresentation = HF26RepresentationRecurrentTransferPairIdOperationExtension + # basic fields -# basic fields + ChainId = Sha256 -ChainId = Sha256 + # compound models -# compound models + Account = AccountItemFundament + ChangeRecoveryAccountRequest = ListChangeRecoveryAccountRequestsFundament + DeclineVotingRightsRequest = ListDeclineVotingRightsRequestsFundament + PriceFeed = Price + RecurrentTransfer = FindRecurrentTransfersFundament + SavingsWithdrawal = SavingsWithdrawalsFundament + TransactionStatus = FindTransaction + VestingDelegation = VestingDelegationsFundament + VestingDelegationExpiration = VestingDelegationExpirationsFundament + WithdrawRoute = WithdrawVestingRoutesFundament + Witness = WitnessesFundament -Account = AccountItemFundament -ChangeRecoveryAccountRequest = ListChangeRecoveryAccountRequestsFundament -DeclineVotingRightsRequest = ListDeclineVotingRightsRequestsFundament -HbdExchangeRate = SchemasHbdExchangeRate -PriceFeed = Price -Proposal = SchemasProposal -RcAccount = SchemasRcAccount -RecurrentTransfer = FindRecurrentTransfersFundament -SavingsWithdrawal = SavingsWithdrawalsFundament -TransactionStatus = FindTransaction -VestingDelegation = VestingDelegationsFundament -VestingDelegationExpiration = VestingDelegationExpirationsFundament -WithdrawRoute = WithdrawVestingRoutesFundament -Witness = WitnessesFundament +__getattr__ = lazy_module_factory( + globals(), + *aggregate_same_import( + "FindAccounts", + "FindProposals", + "FindRecurrentTransfers", + "FindSavingsWithdrawals", + "FindVestingDelegationExpirations", + "FindVestingDelegations", + "FindWitnesses", + "ListChangeRecoveryAccountRequests", + "ListDeclineVotingRightsRequests", + "ListProposals", + "ListProposalVotes", + "ListWithdrawVestingRoutes", + "ListWitnesses", + "ListWitnessVotes", + ("GetConfig", "Config"), + ("GetDynamicGlobalProperties", "DynamicGlobalProperties"), + ("GetFeedHistory", "FeedHistory"), + ("GetHardforkProperties", "HardforkProperties"), + ("GetVersion", "Version"), + ("GetWitnessSchedule", "WitnessSchedule"), + module="schemas.apis.database_api", + ), + *aggregate_same_import( + ("AccountItemFundament", "Account"), + ("FindRecurrentTransfersFundament", "RecurrentTransfer"), + ("ListChangeRecoveryAccountRequestsFundament", "ChangeRecoveryAccountRequest"), + ("ListDeclineVotingRightsRequestsFundament", "DeclineVotingRightsRequest"), + ("SavingsWithdrawalsFundament", "SavingsWithdrawal"), + ("VestingDelegationExpirationsFundament", "VestingDelegationExpiration"), + ("VestingDelegationsFundament", "VestingDelegation"), + ("WithdrawVestingRoutesFundament", "WithdrawRoute"), + ("WitnessesFundament", "Witness"), + module="schemas.apis.database_api.fundaments_of_reponses", + ), + *aggregate_same_import( + "AccountCreateOperation", + "AccountCreateWithDelegationOperation", + "AccountUpdate2Operation", + "AccountUpdateOperation", + "AccountWitnessProxyOperation", + "AccountWitnessVoteOperation", + "CancelTransferFromSavingsOperation", + "ChangeRecoveryAccountOperation", + "ClaimAccountOperation", + "ClaimRewardBalanceOperation", + "CollateralizedConvertOperation", + "CommentOperation", + "CommentOptionsOperation", + "convert_to_representation", + "ConvertOperation", + "CreateClaimedAccountOperation", + "CreateProposalOperation", + "CustomBinaryOperation", + "CustomJsonOperation", + "CustomOperation", + "DeclineVotingRightsOperation", + "DelegateVestingSharesOperation", + "DeleteCommentOperation", + "EscrowApproveOperation", + "EscrowDisputeOperation", + "EscrowReleaseOperation", + "EscrowTransferOperation", + "FeedPublishOperation", + "LimitOrderCancelOperation", + "LimitOrderCreate2Operation", + "LimitOrderCreateOperation", + "Pow2Operation", + "PowOperation", + "RecoverAccountOperation", + "RemoveProposalOperation", + "RequestAccountRecoveryOperation", + "ResetAccountOperation", + "SetResetAccountOperation", + "SetWithdrawVestingRouteOperation", + "TransferFromSavingsOperation", + "TransferOperation", + "TransferToSavingsOperation", + "TransferToVestingOperation", + "UpdateProposalOperation", + "UpdateProposalVotesOperation", + "VoteOperation", + "WithdrawVestingOperation", + "WitnessBlockApproveOperation", + "WitnessSetPropertiesOperation", + "WitnessUpdateOperation", + ("Hf26OperationRepresentation", "OperationRepresentationUnion"), + ("Hf26Operations", "OperationUnion"), + module="schemas.operations", + ), + *aggregate_same_import( + "ExtraFieldsPolicy", + "MissingFieldsInGetConfigPolicy", + "set_policies", + "TestnetAssetsPolicy", + module="schemas.policies", + ), + *aggregate_same_import( + "AssetHbd", + "AssetHive", + "AssetVests", + module="schemas.fields.assets", + ), + *aggregate_same_import( + "Authority", + "Manabar", + ("Price", "PriceFeed"), + module="schemas.fields.compound", + ), + *aggregate_same_import( + "Signature", + "TransactionId", + ("Sha256", "ChainId"), + module="schemas.fields.hex", + ), + *aggregate_same_import( + "Uint16t", + "Uint32t", + module="schemas.fields.integers", + ), + *aggregate_same_import( + "AccountName", + "PublicKey", + module="schemas.fields.basic", + ), + *aggregate_same_import( + "is_matching_model", + "validate_schema_field", + module="schemas.decoders", + ), + *aggregate_same_import( + "DecodeError", + "ValidationError", + module="schemas.errors", + ), + *aggregate_same_import( + "HbdExchangeRate", + "Proposal", + module="schemas.fields.compound", + ), + ("schemas.base", "field"), + ("schemas.apis.rc_api", "FindRcAccounts"), + ("schemas.apis.transaction_status_api", "FindTransaction", "TransactionStatus"), + ("schemas.apis.account_history_api", "GetAccountHistory"), + ( + "schemas.operations.extensions.representation_types", + "HF26RepresentationRecurrentTransferPairIdOperationExtension", + "RecurrentTransferPairIdRepresentation", + ), + ("schemas.fields.hive_datetime", "HiveDateTime"), + ("schemas.fields.hive_int", "HiveInt"), + ("schemas.fields.resolvables", "JsonString"), + ("schemas.operation", "Operation", "OperationBase"), + ("schemas._preconfigured_base_model", "PreconfiguredBaseModel"), + ("schemas.apis.rc_api.fundaments_of_responses", "RcAccount"), + ("schemas.operations.recurrent_transfer_operation", "RecurrentTransferOperation"), + ( + "schemas.operations.extensions.recurrent_transfer_extensions", + "RecurrentTransferPairId", + "RecurrentTransferPairIdExtension", + ), + ("schemas.transaction", "Transaction"), +) diff --git a/clive/__private/settings/_safe_settings.py b/clive/__private/settings/_safe_settings.py index 60ef3196fb62ea403f86ff88b93f96e1448274b4..52d2e94f7c4412e9270c73a7d235c5370d4f2101 100644 --- a/clive/__private/settings/_safe_settings.py +++ b/clive/__private/settings/_safe_settings.py @@ -5,11 +5,11 @@ from abc import ABC from dataclasses import dataclass from datetime import timedelta from pathlib import Path -from typing import Final, Literal, cast, get_args, overload +from typing import TYPE_CHECKING, Final, Literal, cast, get_args, overload -from beekeepy import Settings as BeekeepySettings -from beekeepy.handle.remote import RemoteHandleSettings -from beekeepy.interfaces import HttpUrl +import beekeepy as bk +import beekeepy.interfaces as bki +import beekeepy.settings as bks from inflection import underscore from clive.__private.core.constants.setting_identifiers import ( @@ -45,6 +45,10 @@ from clive.__private.core.formatters.humanize import humanize_validation_result from clive.__private.settings._settings import get_settings from clive.exceptions import CliveError +if TYPE_CHECKING: + from beekeepy.interfaces import HttpUrl + from beekeepy.settings import InterfaceSettings, RemoteHandleSettings + _AvailableLogLevels = Literal["DEBUG", "INFO", "WARNING", "ERROR"] _AvailableLogLevelsContainer = list[_AvailableLogLevels] _AVAILABLE_LOG_LEVELS: tuple[_AvailableLogLevels, ...] = get_args(_AvailableLogLevels) @@ -239,8 +243,8 @@ class SafeSettings: def is_session_token_set(self) -> bool: return self.session_token is not None - def settings_remote_factory(self) -> BeekeepySettings: - beekeepy_settings = BeekeepySettings() + def settings_remote_factory(self) -> InterfaceSettings: + beekeepy_settings = bk.InterfaceSettings() beekeepy_settings.working_directory = self.working_directory beekeepy_settings.http_endpoint = self.remote_address @@ -254,13 +258,13 @@ class SafeSettings: return beekeepy_settings - def settings_local_factory(self) -> BeekeepySettings: + def settings_local_factory(self) -> InterfaceSettings: beekeepy_settings = self.settings_remote_factory() beekeepy_settings.http_endpoint = None beekeepy_settings.use_existing_session = None return beekeepy_settings - def settings_factory(self) -> BeekeepySettings: + def settings_factory(self) -> InterfaceSettings: return self.settings_local_factory() if self.should_start_locally else self.settings_remote_factory() def _get_beekeeper_remote_address(self) -> HttpUrl | None: @@ -320,7 +324,7 @@ class SafeSettings: return self._get_node_communication_retries_delay_secs() def settings_factory(self, http_endpoint: HttpUrl) -> RemoteHandleSettings: - remote_handle_settings = RemoteHandleSettings(http_endpoint=http_endpoint) + remote_handle_settings = bks.RemoteHandleSettings(http_endpoint=http_endpoint) remote_handle_settings.timeout = timedelta(seconds=self.communication_timeout_total_secs) remote_handle_settings.max_retries = self.communication_attempts_amount @@ -479,7 +483,7 @@ class SafeSettings: self._assert_is_string(setting_name, value=value) value_ = cast("str", value) try: - return HttpUrl(value_) + return bki.HttpUrl(value_) except Exception as error: raise SettingsValueError(setting_name=setting_name, value=value, details=str(error)) from error diff --git a/clive/__private/ui/app.py b/clive/__private/ui/app.py index aadbc33a16db9abbc28d40b9629b854625afb362..ed70468eaa0b804ab507d0839fce22290004365b 100644 --- a/clive/__private/ui/app.py +++ b/clive/__private/ui/app.py @@ -6,7 +6,7 @@ import traceback from contextlib import asynccontextmanager, contextmanager from typing import TYPE_CHECKING, Any, ClassVar, Final, cast, get_args -from beekeepy.exceptions import CommunicationError +import beekeepy.exceptions as bke from textual import on, work from textual._context import active_app from textual.app import App @@ -431,7 +431,7 @@ class Clive(App[int]): wrapper = await self.world.commands.update_node_data(accounts=accounts) if wrapper.error_occurred: error = wrapper.error - if isinstance(error, CommunicationError) and error.response is None: + if isinstance(error, bke.CommunicationError) and error.response is None: # notify watchers when node goes offline self.trigger_node_watchers() diff --git a/clive/__private/ui/screens/unlock/unlock.py b/clive/__private/ui/screens/unlock/unlock.py index 6231971231275913cfd493b947009c5d551e62f7..f3846661f25c714427d3fe6fa26ac5fcadf45a2c 100644 --- a/clive/__private/ui/screens/unlock/unlock.py +++ b/clive/__private/ui/screens/unlock/unlock.py @@ -3,7 +3,7 @@ from __future__ import annotations from datetime import timedelta from typing import TYPE_CHECKING -from beekeepy.exceptions import InvalidPasswordError +import beekeepy.exceptions as bke from textual import on from textual.containers import Horizontal from textual.validation import Integer @@ -123,7 +123,7 @@ class Unlock(BaseScreen): permanent=lock_after_time.should_stay_unlocked, time=lock_after_time.lock_duration, ) - except InvalidPasswordError: + except bke.InvalidPasswordError: logger.error( f"Profile `{select_profile.selection_ensure}` was not unlocked " "because entered password is invalid, skipping switching modes" diff --git a/clive/__private/ui/widgets/node_widgets.py b/clive/__private/ui/widgets/node_widgets.py index 96db156a09716ba8ce7090de81872389f3fdde6e..582f1e9c8e4a59b85ba101f340ccad3a0bcf4eee 100644 --- a/clive/__private/ui/widgets/node_widgets.py +++ b/clive/__private/ui/widgets/node_widgets.py @@ -2,7 +2,7 @@ from __future__ import annotations from typing import TYPE_CHECKING -from beekeepy.interfaces import HttpUrl +import beekeepy.interfaces as bki from textual.containers import Container from textual.reactive import reactive from textual.widgets import Static @@ -13,6 +13,7 @@ from clive.__private.ui.clive_widget import CliveWidget from clive.__private.ui.widgets.clive_basic.clive_select import CliveSelect if TYPE_CHECKING: + from beekeepy.interfaces import HttpUrl from rich.console import RenderableType from textual.app import ComposeResult @@ -30,7 +31,7 @@ class SelectedNodeAddress(Static): return f"Selected node address: {self.node_address}" -class NodeSelector(CliveSelect[HttpUrl], CliveWidget): +class NodeSelector(CliveSelect[bki.HttpUrl], CliveWidget): """Select for the node address.""" def __init__(self) -> None: diff --git a/hive b/hive index 888c7b858da0da4ca12a003c97b1387d070d247a..42e5901e47562ae80c9db03ff10fe2f4e72ce461 160000 --- a/hive +++ b/hive @@ -1 +1 @@ -Subproject commit 888c7b858da0da4ca12a003c97b1387d070d247a +Subproject commit 42e5901e47562ae80c9db03ff10fe2f4e72ce461 diff --git a/poetry.lock b/poetry.lock index 409775adb17d418d5c364e88f01d9fa05f3526c7..ecea5d10dada2ed92336c54dd96ed7690f5d1741 100644 --- a/poetry.lock +++ b/poetry.lock @@ -608,19 +608,18 @@ hyperframe = ">=6.1,<7" [[package]] name = "hiveio-beekeepy" -version = "0.0.1.dev430+d766238" +version = "1.27.12rc1.dev5+843b775" description = "All in one package for beekeeper interaction via Python interface." optional = false python-versions = ">=3.12,<4.0" groups = ["main", "dev", "embeddedtestnet"] files = [ - {file = "hiveio_beekeepy-0.0.1.dev430+d766238-py3-none-any.whl", hash = "sha256:530af9ac95801e50f41e714f00b533a22c75ab313b53d075062872961c350434"}, + {file = "hiveio_beekeepy-1.27.12rc1.dev5+843b775-py3-none-any.whl", hash = "sha256:616919490118b360d7b63d8b876b16e79635c36a63b5742ae62036de8f60a014"}, ] [package.dependencies] aiohttp = "3.11.15" -hiveio-schemas = "0.0.1.dev431+2255381" -httpx = {version = "0.23.3", extras = ["http2"]} +hiveio-schemas = "1.27.12rc0" loguru = "0.7.2" psutil = "7.0.0" python-dateutil = "2.8.2" @@ -633,17 +632,17 @@ reference = "gitlab-beekeepy" [[package]] name = "hiveio-database-api" -version = "1.27.12rc3.dev8+342e53ba5" +version = "1.27.12rc4.dev16+b487bd9a1" description = "" optional = false python-versions = ">=3.12,<4.0" groups = ["main", "dev", "embeddedtestnet"] files = [ - {file = "hiveio_database_api-1.27.12rc3.dev8+342e53ba5-py3-none-any.whl", hash = "sha256:be37d44278ee793e76585ebb6852d83f70e7e321d58e0fc888fddde93f4132dd"}, + {file = "hiveio_database_api-1.27.12rc4.dev16+b487bd9a1-py3-none-any.whl", hash = "sha256:e31fd8c1646b49bc3d2c05b6d4c0a606bc369214e13b4eaa20a913e1b6c1a465"}, ] [package.dependencies] -hiveio-beekeepy = "0.0.1.dev430+d766238" +hiveio-beekeepy = "1.27.12rc1.dev5+843b775" [package.source] type = "legacy" @@ -652,17 +651,17 @@ reference = "gitlab-hive" [[package]] name = "hiveio-network-broadcast-api" -version = "1.27.12rc3.dev8+342e53ba5" +version = "1.27.12rc4.dev16+b487bd9a1" description = "" optional = false python-versions = ">=3.12,<4.0" groups = ["main", "dev", "embeddedtestnet"] files = [ - {file = "hiveio_network_broadcast_api-1.27.12rc3.dev8+342e53ba5-py3-none-any.whl", hash = "sha256:43a2fbf7f75a546f1e117169ca362d812816c3da7c35737a61c0828df1c63285"}, + {file = "hiveio_network_broadcast_api-1.27.12rc4.dev16+b487bd9a1-py3-none-any.whl", hash = "sha256:7c9c6b9a32b92433425abcbdae2d159383d457547d67d799d97d410954390084"}, ] [package.dependencies] -hiveio-beekeepy = "0.0.1.dev430+d766238" +hiveio-beekeepy = "1.27.12rc1.dev5+843b775" [package.source] type = "legacy" @@ -671,13 +670,13 @@ reference = "gitlab-hive" [[package]] name = "hiveio-schemas" -version = "0.0.1.dev431+2255381" +version = "1.27.12rc0" description = "Tools for checking if message fits expected format" optional = false python-versions = ">=3.12,<4.0" groups = ["main", "dev", "embeddedtestnet"] files = [ - {file = "hiveio_schemas-0.0.1.dev431+2255381-py3-none-any.whl", hash = "sha256:fc3cc4c51cd668ce4691398074e093eaef8439436476ad5e5bcbf1b02242f4bf"}, + {file = "hiveio_schemas-1.27.12rc0-py3-none-any.whl", hash = "sha256:c8f4bb1d93d2e1ea5139d20c647ad1ff0e41ff2eca03f184d47a536cd0f24a6f"}, ] [package.dependencies] @@ -690,18 +689,18 @@ reference = "gitlab-schemas" [[package]] name = "hiveio-wax" -version = "0.3.10.dev903+474150e0" +version = "1.27.12rc2.dev7+daf5a82a" description = "" optional = false python-versions = ">=3.12,<4.0" groups = ["main", "dev", "embeddedtestnet"] files = [ - {file = "hiveio_wax-0.3.10.dev903+474150e0-cp312-cp312-manylinux_2_39_x86_64.whl", hash = "sha256:4004e8c3e9e9a1d9f130d0b769c29f46e46099dde74f3f7cf785d827c8fb11d5"}, + {file = "hiveio_wax-1.27.12rc2.dev7+daf5a82a-cp312-cp312-manylinux_2_39_x86_64.whl", hash = "sha256:567b4b4f2d3091a9ea99488cb82215d2634d6d462e51c416af1cbf2aaeca7ab4"}, ] [package.dependencies] -hiveio-database-api = "1.27.12rc3.dev8+342e53ba5" -hiveio-network-broadcast-api = "1.27.12rc3.dev8+342e53ba5" +hiveio-database-api = "1.27.12rc4.dev16+b487bd9a1" +hiveio-network-broadcast-api = "1.27.12rc4.dev16+b487bd9a1" httpx = {version = "0.23.3", extras = ["http2"]} loguru = "0.7.2" protobuf = "4.24.4" @@ -2177,7 +2176,7 @@ develop = false [package.dependencies] abstractcp = "0.9.9" -hiveio-wax = "0.3.10.dev903+474150e0" +hiveio-wax = "1.27.12rc2.dev7+daf5a82a" loguru = "0.7.2" python-dateutil = "2.8.2" @@ -2497,4 +2496,4 @@ propcache = ">=0.2.1" [metadata] lock-version = "2.1" python-versions = ">=3.12,<3.13" -content-hash = "7933e22f4a728e7d03a0348fe625982730299a2e277d9dcab972e906fd3933f2" +content-hash = "79416977a35df78b93313c051ac95979a8de408c16a2e353cfd8346de599cd98" diff --git a/pyproject.toml b/pyproject.toml index 7ffe9321d97f5d3486baa42f8ba6092d7d822de3..799345c64d36ed5e39694cddb079481a9eba6ccb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,9 +21,9 @@ dependencies = [ 'humanize (==4.12.2)', 'toml (==0.10.2)', "pathvalidate (==3.3.1)", - 'hiveio-schemas (==0.0.1.dev431+2255381)', - 'hiveio-beekeepy (==0.0.1.dev430+d766238)', - 'hiveio-wax (==0.3.10.dev903+474150e0)', + 'hiveio-schemas (==1.27.12rc0)', + 'hiveio-beekeepy (==1.27.12rc1.dev5+843b775)', + 'hiveio-wax (==1.27.12rc2.dev7+daf5a82a)', ] [project.urls] diff --git a/testnet_node.py b/testnet_node.py index ddc977c15f396f500e1608af8a7e66507f25dfc9..9b4fa81c99ded344b31ce79931633d33e53dc3dd 100644 --- a/testnet_node.py +++ b/testnet_node.py @@ -7,8 +7,8 @@ import sys import time from typing import TYPE_CHECKING +import beekeepy.interfaces as bki import test_tools as tt -from beekeepy.interfaces import HttpUrl from clive.__private.before_launch import prepare_before_launch from clive.__private.core.constants.setting_identifiers import NODE_CHAIN_ID, SECRETS_NODE_ADDRESS @@ -58,7 +58,7 @@ def init_argparse(args: Sequence[str]) -> argparse.Namespace: def prepare_node() -> tt.RawNode: - return run_node(webserver_http_endpoint=HttpUrl.factory(port=8090)) + return run_node(webserver_http_endpoint=bki.HttpUrl.factory(port=8090)) async def prepare_profiles(node: tt.RawNode) -> None: diff --git a/tests/clive-local-tools/clive_local_tools/checkers/blockchain_checkers.py b/tests/clive-local-tools/clive_local_tools/checkers/blockchain_checkers.py index 17c46608e08dcffff784721f69132f0d35fe8bb2..5b469080779f10965810f9efdec91f8ec0d27c52 100644 --- a/tests/clive-local-tools/clive_local_tools/checkers/blockchain_checkers.py +++ b/tests/clive-local-tools/clive_local_tools/checkers/blockchain_checkers.py @@ -2,8 +2,8 @@ from __future__ import annotations from typing import TYPE_CHECKING +import beekeepy.exceptions as bke import pytest -from beekeepy.exceptions import ErrorInResponseError from click.testing import Result from clive_local_tools.helpers import get_transaction_id_from_output @@ -29,7 +29,7 @@ def assert_transaction_in_blockchain( node.wait_number_of_blocks(1) try: node.api.account_history.get_transaction(id_=transaction_id, include_reversible=True) - except ErrorInResponseError: + except bke.ErrorInResponseError: pytest.fail(f"The transaction with {transaction_id=} couldn't be found in the blockchain.") diff --git a/tests/clive-local-tools/clive_local_tools/storage_migration/regenerate_prepared_profiles.py b/tests/clive-local-tools/clive_local_tools/storage_migration/regenerate_prepared_profiles.py index a7362f67a310a7bf43aefa4295b10c4ccf2fbc25..64cd94ae4eef72ea3197df4aac30e4aa3b0bb15c 100644 --- a/tests/clive-local-tools/clive_local_tools/storage_migration/regenerate_prepared_profiles.py +++ b/tests/clive-local-tools/clive_local_tools/storage_migration/regenerate_prepared_profiles.py @@ -15,8 +15,8 @@ from contextlib import asynccontextmanager, contextmanager from pathlib import Path from typing import TYPE_CHECKING, Final +import beekeepy as bk import test_tools as tt -from beekeepy import AsyncBeekeeper from clive.__private.core.commands.create_encryption_wallet import CreateEncryptionWallet from clive.__private.core.commands.create_user_wallet import CreateUserWallet @@ -58,7 +58,9 @@ OPERATION: Final[TransferOperation] = TransferOperation( async def prepare_encryption_service() -> AsyncGenerator[EncryptionService]: account_name = PROFILE_NAME password = PROFILE_PASSWORD - async with await AsyncBeekeeper.factory(settings=safe_settings.beekeeper.settings_local_factory()) as beekeeper_cm: + async with await bk.AsyncBeekeeper.factory( + settings=safe_settings.beekeeper.settings_local_factory() + ) as beekeeper_cm: session = await beekeeper_cm.session user_wallet = await CreateUserWallet( session=session, profile_name=account_name, password=password diff --git a/tests/conftest.py b/tests/conftest.py index 011279f40fab92eaa6965c39b31b6f8fa32e5c90..5aff665841d9d268638ce87dd2896ab07250896c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,7 +9,6 @@ from typing import TYPE_CHECKING import pytest import test_tools as tt -from beekeepy import AsyncBeekeeper from test_tools.__private.scope.scope_fixtures import * # noqa: F403 from clive.__private.before_launch import ( diff --git a/tests/functional/cli/configure/test_configure_profile_delete_without_remote_address.py b/tests/functional/cli/configure/test_configure_profile_delete_without_remote_address.py index c52294c86fae2e2fd92caf413d0a04e5bd4b4734..727725096d04f56ab607b77a808be44cfda13af2 100644 --- a/tests/functional/cli/configure/test_configure_profile_delete_without_remote_address.py +++ b/tests/functional/cli/configure/test_configure_profile_delete_without_remote_address.py @@ -2,9 +2,9 @@ from __future__ import annotations from typing import TYPE_CHECKING +import beekeepy as bk +import beekeepy.exceptions as bke import pytest -from beekeepy import AsyncBeekeeper -from beekeepy.exceptions.common import InvalidatedStateByClosingBeekeeperError from clive.__private.settings import safe_settings from clive_local_tools.checkers.profile_checker import ProfileChecker @@ -13,6 +13,8 @@ from clive_local_tools.testnet_block_log import WORKING_ACCOUNT_NAME if TYPE_CHECKING: from collections.abc import AsyncGenerator + from beekeepy import AsyncBeekeeper + from clive_local_tools.cli.cli_tester import CLITester @@ -20,9 +22,9 @@ if TYPE_CHECKING: async def beekeeper_local() -> AsyncGenerator[AsyncBeekeeper]: """We need to handle error on double teardown of beekeeper.""" with pytest.raises( - InvalidatedStateByClosingBeekeeperError + bke.InvalidatedStateByClosingBeekeeperError ): # we can use fixture beekeeper_local from conftest after issue #19 in beekeepey is resolved - async with await AsyncBeekeeper.factory( + async with await bk.AsyncBeekeeper.factory( settings=safe_settings.beekeeper.settings_local_factory() ) as beekeeper_cm: yield beekeeper_cm diff --git a/tests/functional/cli/conftest.py b/tests/functional/cli/conftest.py index dbe94ba6baafae55d67ac2218197c8243a05a90a..1e6a4c0aa72c377b3af0a6ceb7386656a50ad794 100644 --- a/tests/functional/cli/conftest.py +++ b/tests/functional/cli/conftest.py @@ -3,8 +3,8 @@ from __future__ import annotations from contextlib import ExitStack from typing import TYPE_CHECKING +import beekeepy as bk import pytest -from beekeepy import AsyncBeekeeper from typer.testing import CliRunner from clive.__private.core.constants.terminal import TERMINAL_WIDTH @@ -33,6 +33,7 @@ if TYPE_CHECKING: from collections.abc import AsyncGenerator, Callable import test_tools as tt + from beekeepy import AsyncBeekeeper from clive.__private.core.profile import Profile from clive_local_tools.cli.types import CLITesterFactory, CLITesterVariant @@ -50,7 +51,9 @@ def logger_configuration_factory() -> Callable[[], None]: @pytest.fixture async def beekeeper_local() -> AsyncGenerator[AsyncBeekeeper]: """CLI tests are remotely connecting to a locally started beekeeper by this fixture.""" - async with await AsyncBeekeeper.factory(settings=safe_settings.beekeeper.settings_local_factory()) as beekeeper_cm: + async with await bk.AsyncBeekeeper.factory( + settings=safe_settings.beekeeper.settings_local_factory() + ) as beekeeper_cm: yield beekeeper_cm diff --git a/tests/functional/commands/test_transaction_status.py b/tests/functional/commands/test_transaction_status.py index db39db9350f73ef35f9429e955fd73a9be6bd024..800e0be610ed7888f654d324c99a074ac95c1981 100644 --- a/tests/functional/commands/test_transaction_status.py +++ b/tests/functional/commands/test_transaction_status.py @@ -2,8 +2,8 @@ from __future__ import annotations from typing import TYPE_CHECKING +import beekeepy.exceptions as bke import pytest -from beekeepy.exceptions import ApiNotFoundError from clive.__private.core.keys import PrivateKeyAliased from clive.__private.logger import logger @@ -58,7 +58,7 @@ async def test_transaction_status_no_api(world: World, init_node: tt.InitNode) - assert "transaction_status_api" not in init_node.config.plugin # ACT & ASSERT - with pytest.raises(ApiNotFoundError) as exc_info: + with pytest.raises(bke.ApiNotFoundError) as exc_info: await world.commands.find_transaction(transaction_id="deadbeef") assert expected_message in str(exc_info.value.response), "Got different error message than expected" diff --git a/tests/unit/profile/test_profile_loading.py b/tests/unit/profile/test_profile_loading.py index 2229aba0797d7c571bcf49ceb3157f773e5dce9e..6f424ca18e965d50d7f078f68c4e62a2727e58dd 100644 --- a/tests/unit/profile/test_profile_loading.py +++ b/tests/unit/profile/test_profile_loading.py @@ -2,8 +2,8 @@ from __future__ import annotations from typing import TYPE_CHECKING +import beekeepy as bk import pytest -from beekeepy import AsyncBeekeeper from clive.__private.cli.cli_world import CLIWorld from clive.__private.core.commands.create_profile_wallets import CreateProfileWallets @@ -16,10 +16,14 @@ from clive.__private.settings import safe_settings if TYPE_CHECKING: from collections.abc import AsyncIterator + from beekeepy import AsyncBeekeeper + @pytest.fixture async def beekeeper() -> AsyncIterator[AsyncBeekeeper]: - async with await AsyncBeekeeper.factory(settings=safe_settings.beekeeper.settings_local_factory()) as beekeeper_cm: + async with await bk.AsyncBeekeeper.factory( + settings=safe_settings.beekeeper.settings_local_factory() + ) as beekeeper_cm: yield beekeeper_cm diff --git a/tests/unit/storage/test_storage_structure.py b/tests/unit/storage/test_storage_structure.py index dd8fe6524a9fbea2882119f108a22893bd44d9ee..d4e96b6407530709f7119025b6a0557bc34503ac 100644 --- a/tests/unit/storage/test_storage_structure.py +++ b/tests/unit/storage/test_storage_structure.py @@ -2,8 +2,8 @@ from __future__ import annotations from typing import TYPE_CHECKING, Final +import beekeepy as bk import pytest -from beekeepy import AsyncBeekeeper from clive.__private.core.commands.create_profile_wallets import CreateProfileWallets from clive.__private.core.commands.save_profile import SaveProfile @@ -14,11 +14,12 @@ from clive.__private.storage.service.service import PersistentStorageService if TYPE_CHECKING: from pathlib import Path + FIRST_PROFILE_NAME: Final[str] = "first" async def _create_and_save_profile(profile_name: str) -> None: - async with await AsyncBeekeeper.factory(settings=safe_settings.beekeeper.settings_local_factory()) as beekeeper: + async with await bk.AsyncBeekeeper.factory(settings=safe_settings.beekeeper.settings_local_factory()) as beekeeper: result = await CreateProfileWallets( session=await beekeeper.session, profile_name=profile_name, password=profile_name ).execute_with_result() diff --git a/tests/unit/test_imports.py b/tests/unit/test_imports.py index d13cbf7f5e813058153686bae411fe299fcbf40c..1025ef2e0c82b3720337dd8aa3173c786ca9ff7a 100644 --- a/tests/unit/test_imports.py +++ b/tests/unit/test_imports.py @@ -1,12 +1,37 @@ from __future__ import annotations +import contextlib +import importlib +import sys +import typing +from typing import TYPE_CHECKING + import pytest from textual import __name__ as textual_package_name +import clive.__private.models.schemas as schemas_models_module from clive.__private.ui import __name__ as ui_package_name from clive_local_tools.cli.imports import get_cli_help_imports_tree from wax import __name__ as wax_package_name +if TYPE_CHECKING: + from collections.abc import Iterator + from types import ModuleType + + +@contextlib.contextmanager +def reload_module_in_type_checking_mode(module_name: str) -> Iterator[ModuleType]: + with pytest.MonkeyPatch.context() as monkeypatch: + monkeypatch.setattr(typing, "TYPE_CHECKING", True) + sys.modules.pop(module_name) + reloaded = importlib.import_module(module_name) + try: + yield reloaded + finally: + monkeypatch.setattr(typing, "TYPE_CHECKING", False) + sys.modules.pop(module_name) + importlib.import_module(module_name) + @pytest.mark.parametrize(("package_name"), [ui_package_name, textual_package_name, wax_package_name]) def test_not_imported_during_cli_help(package_name: str) -> None: @@ -15,3 +40,34 @@ def test_not_imported_during_cli_help(package_name: str) -> None: # ASSERT assert package_name not in cli_imports_tree, f"{package_name} shouldn't be imported during CLI help." + + +@pytest.mark.parametrize("name", schemas_models_module.__all__) +def test_all_schemas_models_exports_are_importable(name: str) -> None: + """ + Ensure all names listed in ``__all__`` are actually importable. + + This is especially important because schemas models rely on lazy imports + (using string-based paths and alias mappings). If an alias is wrong or a module + path changes, it would break at runtime. This test proactively triggers all + exports to catch such issues. + """ + # ACT & ASSERT + try: + getattr(schemas_models_module, name) + except Exception as error: + raise AssertionError(f"Failed to resolve `{name}` from {schemas_models_module.__name__}") from error + + +@pytest.mark.parametrize("name", schemas_models_module.__all__) +def test_schemas_imports_runtime_match_type_checking(name: str) -> None: + """Ensure all names listed in ``__all__`` point to the same object in runtime and type checking.""" + # ACT + runtime_object = getattr(schemas_models_module, name) + with reload_module_in_type_checking_mode(schemas_models_module.__name__) as reloaded: + typechecking_object = getattr(reloaded, name) + + # ASSERT + assert runtime_object is typechecking_object, ( + f"Runtime `{runtime_object}` and type checking `{typechecking_object}` objects do not match" + )