From bde5ea966cc4504ac50eabe0a1516a2b32f055ea Mon Sep 17 00:00:00 2001 From: kmochocki Date: Fri, 3 Oct 2025 01:51:55 +0000 Subject: [PATCH 1/7] Bump hive, wax, beekeepy --- .gitlab-ci.yml | 2 +- hive | 2 +- poetry.lock | 35 +++++++++++++++++------------------ pyproject.toml | 6 +++--- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 269bd046ff..d08b19b2e6 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/hive b/hive index 888c7b858d..42e5901e47 160000 --- a/hive +++ b/hive @@ -1 +1 @@ -Subproject commit 888c7b858da0da4ca12a003c97b1387d070d247a +Subproject commit 42e5901e47562ae80c9db03ff10fe2f4e72ce461 diff --git a/poetry.lock b/poetry.lock index 409775adb1..ecea5d10da 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 7ffe9321d9..799345c64d 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] -- GitLab From 76e830f898bdd65ed2057622c99bc04132083790 Mon Sep 17 00:00:00 2001 From: kmochocki Date: Fri, 3 Oct 2025 02:23:44 +0000 Subject: [PATCH 2/7] Optimize imports because of beekeepy bump --- .../cli/commands/beekeeper/beekeeper_close.py | 8 ++++---- .../cli/commands/beekeeper/beekeeper_spawn.py | 6 ++++-- .../__private/cli/commands/configure/node.py | 4 ++-- .../cli/commands/configure/profile.py | 4 ++-- clive/__private/cli/error_handlers.py | 6 +++--- clive/__private/core/beekeeper_manager.py | 10 +++++----- clive/__private/core/commands/beekeeper.py | 4 ++-- .../core/commands/create_encryption_wallet.py | 4 ++-- .../core/commands/create_user_wallet.py | 4 ++-- .../commands/data_retrieval/chain_data.py | 4 ++-- .../find_scheduled_transfers.py | 4 ++-- .../find_vesting_delegation_expirations.py | 4 ++-- .../data_retrieval/get_node_basic_info.py | 4 ++-- .../data_retrieval/hive_power_data.py | 4 ++-- .../commands/data_retrieval/proposals_data.py | 4 ++-- .../commands/data_retrieval/savings_data.py | 4 ++-- .../update_node_data/command.py | 6 +++--- .../commands/data_retrieval/witnesses_data.py | 4 ++-- clive/__private/core/commands/decrypt.py | 4 ++-- clive/__private/core/commands/encrypt.py | 4 ++-- .../get_unlocked_encryption_wallet.py | 8 ++++++-- .../core/commands/get_unlocked_user_wallet.py | 8 ++++++-- .../core/commands/is_password_valid.py | 4 ++-- clive/__private/core/commands/save_profile.py | 4 ++-- clive/__private/core/commands/unlock.py | 4 ++-- .../communication_failure_notificator.py | 13 ++++++++----- .../general_error_notificator.py | 8 ++++---- clive/__private/core/node.py | 6 +++--- clive/__private/core/profile.py | 10 ++++++---- clive/__private/settings/_safe_settings.py | 19 ++++++++++++------- clive/__private/ui/app.py | 4 ++-- clive/__private/ui/screens/unlock/unlock.py | 4 ++-- clive/__private/ui/widgets/node_widgets.py | 5 +++-- testnet_node.py | 4 ++-- .../checkers/blockchain_checkers.py | 4 ++-- .../regenerate_prepared_profiles.py | 6 ++++-- tests/conftest.py | 1 - ...e_profile_delete_without_remote_address.py | 10 ++++++---- tests/functional/cli/conftest.py | 7 +++++-- .../commands/test_transaction_status.py | 4 ++-- tests/unit/profile/test_profile_loading.py | 8 ++++++-- tests/unit/storage/test_storage_structure.py | 5 +++-- 42 files changed, 137 insertions(+), 105 deletions(-) diff --git a/clive/__private/cli/commands/beekeeper/beekeeper_close.py b/clive/__private/cli/commands/beekeeper/beekeeper_close.py index 0552b41dcb..2d2c69a275 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 6d1cf83379..975556430a 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 72c0dab220..380726f209 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 841d1fa042..434efeb393 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 116d9c2ebe..471c592e19 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 6c1f3a05e6..f41f49aa05 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 import InterfaceSettings as BeekeepySettings from clive.__private.core.wallet_container import WalletContainer @@ -108,6 +108,6 @@ class BeekeeperManager: 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 4c06705288..08be226be6 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 626300de6d..1bee7ae008 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 0568b1626e..416930772b 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 e77c940bc4..9d1bd0d6fb 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 78c1ba5018..df9dad6bba 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 496ddb52aa..241cd838bc 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 903e10825f..dea6c9ad4f 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 dfe55eaa85..711f0fdd53 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 af74971ede..e1d6ab606a 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 5380b890c1..cc8e16d0b2 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 0fcd6e6329..f325a2c0c2 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 98eb53f1f3..c69d332a06 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 b4cb00d964..148e7a3110 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 ead9879379..3a0949e33f 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 0f2334003c..2b8f76a0f2 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 9c1fcb1c06..bb0b08e4e1 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 7dad033f62..ab5cc260fd 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 c22cebf0a1..db5d8abfac 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 ed25ff0d5c..fd53d0d739 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 a66c01b25b..3ae59ef53f 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 4f01cb9e2b..be93dc8f6d 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 7e6b2fabfa..f55754b7f8 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 a4b5ab1dcd..b6750679a7 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/settings/_safe_settings.py b/clive/__private/settings/_safe_settings.py index 60ef3196fb..8f1eb66f1b 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,11 @@ 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 import InterfaceSettings as BeekeepySettings + from beekeepy.handle.remote import RemoteHandleSettings + from beekeepy.interfaces import HttpUrl + _AvailableLogLevels = Literal["DEBUG", "INFO", "WARNING", "ERROR"] _AvailableLogLevelsContainer = list[_AvailableLogLevels] _AVAILABLE_LOG_LEVELS: tuple[_AvailableLogLevels, ...] = get_args(_AvailableLogLevels) @@ -240,7 +245,7 @@ class SafeSettings: return self.session_token is not None def settings_remote_factory(self) -> BeekeepySettings: - beekeepy_settings = BeekeepySettings() + beekeepy_settings = bk.InterfaceSettings() beekeepy_settings.working_directory = self.working_directory beekeepy_settings.http_endpoint = self.remote_address @@ -320,7 +325,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 +484,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 aadbc33a16..ed70468eaa 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 6231971231..f3846661f2 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 96db156a09..582f1e9c8e 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/testnet_node.py b/testnet_node.py index ddc977c15f..9b4fa81c99 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 17c46608e0..5b46908077 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 a7362f67a3..64cd94ae4e 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 011279f40f..5aff665841 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 c52294c86f..727725096d 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 dbe94ba6ba..1e6a4c0aa7 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 db39db9350..800e0be610 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 2229aba079..6f424ca18e 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 dd8fe6524a..d4e96b6407 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() -- GitLab From 48496ca44bad0f16c9357bd98c5fde844c733045 Mon Sep 17 00:00:00 2001 From: kmochocki Date: Fri, 3 Oct 2025 03:47:39 +0000 Subject: [PATCH 3/7] Make models/schemas.py use lazy imports --- clive/__private/models/schemas.py | 464 ++++++++++++++++++++---------- 1 file changed, 313 insertions(+), 151 deletions(-) diff --git a/clive/__private/models/schemas.py b/clive/__private/models/schemas.py index 221b4c6d32..424bc45912 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"), +) -- GitLab From 25a9e37e85d54cb7999336527b64cd3b49623612 Mon Sep 17 00:00:00 2001 From: kmochocki Date: Wed, 8 Oct 2025 02:34:53 +0000 Subject: [PATCH 4/7] Use async_is_url_reachable from beekeepy --- .../cli/commands/abc/world_based_command.py | 5 ++-- clive/__private/core/url_utils.py | 25 ------------------- 2 files changed, 3 insertions(+), 27 deletions(-) delete mode 100644 clive/__private/core/url_utils.py diff --git a/clive/__private/cli/commands/abc/world_based_command.py b/clive/__private/cli/commands/abc/world_based_command.py index 2e51f4df1e..d994ccd7b7 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/core/url_utils.py b/clive/__private/core/url_utils.py deleted file mode 100644 index 1cb8d7eb36..0000000000 --- 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 -- GitLab From 988a14e3ce16b9548acbff558a1781e1be13dc76 Mon Sep 17 00:00:00 2001 From: kmochocki Date: Wed, 8 Oct 2025 02:36:45 +0000 Subject: [PATCH 5/7] Unify settings references --- clive/__private/core/beekeeper_manager.py | 6 +++--- clive/__private/settings/_safe_settings.py | 9 ++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/clive/__private/core/beekeeper_manager.py b/clive/__private/core/beekeeper_manager.py index f41f49aa05..fc4c4b41d4 100644 --- a/clive/__private/core/beekeeper_manager.py +++ b/clive/__private/core/beekeeper_manager.py @@ -9,7 +9,7 @@ from clive.exceptions import CliveError if TYPE_CHECKING: from beekeepy import AsyncBeekeeper, AsyncSession, AsyncUnlockedWallet - from beekeepy import InterfaceSettings as BeekeepySettings + 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,7 +103,7 @@ 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: diff --git a/clive/__private/settings/_safe_settings.py b/clive/__private/settings/_safe_settings.py index 8f1eb66f1b..52d2e94f7c 100644 --- a/clive/__private/settings/_safe_settings.py +++ b/clive/__private/settings/_safe_settings.py @@ -46,9 +46,8 @@ from clive.__private.settings._settings import get_settings from clive.exceptions import CliveError if TYPE_CHECKING: - from beekeepy import InterfaceSettings as BeekeepySettings - from beekeepy.handle.remote import RemoteHandleSettings from beekeepy.interfaces import HttpUrl + from beekeepy.settings import InterfaceSettings, RemoteHandleSettings _AvailableLogLevels = Literal["DEBUG", "INFO", "WARNING", "ERROR"] _AvailableLogLevelsContainer = list[_AvailableLogLevels] @@ -244,7 +243,7 @@ class SafeSettings: def is_session_token_set(self) -> bool: return self.session_token is not None - def settings_remote_factory(self) -> BeekeepySettings: + def settings_remote_factory(self) -> InterfaceSettings: beekeepy_settings = bk.InterfaceSettings() beekeepy_settings.working_directory = self.working_directory @@ -259,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: -- GitLab From f5168091a5986123d904de80474af20df5fa25cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20=C5=BBebrak?= Date: Fri, 3 Oct 2025 11:34:17 +0200 Subject: [PATCH 6/7] Add test checking all exports of models.schemas are available --- tests/unit/test_imports.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/unit/test_imports.py b/tests/unit/test_imports.py index d13cbf7f5e..70b039f795 100644 --- a/tests/unit/test_imports.py +++ b/tests/unit/test_imports.py @@ -3,6 +3,7 @@ from __future__ import annotations 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 @@ -15,3 +16,20 @@ 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 -- GitLab From cdea3d8615b54e679bad25884a20b7c2bf852f5a Mon Sep 17 00:00:00 2001 From: Marcin Sobczyk Date: Wed, 8 Oct 2025 15:12:01 +0000 Subject: [PATCH 7/7] Test checking schemas import at runtime and in type-checking mode are consistent --- tests/unit/test_imports.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/unit/test_imports.py b/tests/unit/test_imports.py index 70b039f795..1025ef2e0c 100644 --- a/tests/unit/test_imports.py +++ b/tests/unit/test_imports.py @@ -1,5 +1,11 @@ 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 @@ -8,6 +14,24 @@ 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: @@ -33,3 +57,17 @@ def test_all_schemas_models_exports_are_importable(name: str) -> None: 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" + ) -- GitLab