From 10ceb325c66c62e927cad905349f1c386b9ab33e Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Thu, 21 Nov 2024 12:26:49 -0500 Subject: [PATCH 1/3] use a class for the chia cli context data --- chia/_tests/cmds/test_click_types.py | 7 +++-- chia/_tests/cmds/test_cmd_framework.py | 8 ++++-- chia/cmds/beta.py | 11 ++++---- chia/cmds/check_wallet_db.py | 6 ++-- chia/cmds/chia.py | 5 ++-- chia/cmds/cmd_classes.py | 7 +++-- chia/cmds/configure.py | 3 +- chia/cmds/db.py | 7 +++-- chia/cmds/init.py | 4 ++- chia/cmds/keys.py | 30 ++++++++++++++------ chia/cmds/param_types.py | 7 +++-- chia/cmds/passphrase.py | 5 ++-- chia/cmds/peer.py | 3 +- chia/cmds/plots.py | 20 ++++++++++---- chia/cmds/plotters.py | 3 +- chia/cmds/show.py | 3 +- chia/cmds/sim.py | 38 +++++++++++++++++--------- chia/cmds/start.py | 3 +- chia/cmds/stop.py | 3 +- chia/cmds/util.py | 26 ++++++++++++++++++ chia/cmds/wallet.py | 3 +- 21 files changed, 142 insertions(+), 60 deletions(-) create mode 100644 chia/cmds/util.py diff --git a/chia/_tests/cmds/test_click_types.py b/chia/_tests/cmds/test_click_types.py index 6779a0d0d8b9..6aaf0a87d33b 100644 --- a/chia/_tests/cmds/test_click_types.py +++ b/chia/_tests/cmds/test_click_types.py @@ -18,6 +18,7 @@ Uint64ParamType, ) from chia.cmds.units import units +from chia.cmds.util import ChiaCliContext from chia.types.blockchain_format.sized_bytes import bytes32 from chia.util.bech32m import encode_puzzle_hash from chia.util.ints import uint64 @@ -114,7 +115,9 @@ def test_click_amount_type() -> None: def test_click_address_type() -> None: - context = cast(Context, FakeContext(obj={"expected_prefix": "xch"})) # this makes us not have to use a config file + context = cast( + Context, FakeContext(obj=ChiaCliContext(expected_prefix="xch").to_click()) + ) # this makes us not have to use a config file std_cli_address = CliAddress(burn_ph, burn_address, AddressType.XCH) nft_cli_address = CliAddress(burn_ph, burn_nft_addr, AddressType.DID) # Test CliAddress (Generally is not used) @@ -149,7 +152,7 @@ def test_click_address_type() -> None: def test_click_address_type_config(root_path_populated_with_config: Path) -> None: # set a root path in context. - context = cast(Context, FakeContext(obj={"root_path": root_path_populated_with_config})) + context = cast(Context, FakeContext(obj=ChiaCliContext(root_path=root_path_populated_with_config).to_click())) # run test that should pass assert AddressParamType().convert(burn_address, None, context) == CliAddress(burn_ph, burn_address, AddressType.XCH) assert context.obj["expected_prefix"] == "xch" # validate that the prefix was set correctly diff --git a/chia/_tests/cmds/test_cmd_framework.py b/chia/_tests/cmds/test_cmd_framework.py index f7b438269721..9bacacc41771 100644 --- a/chia/_tests/cmds/test_cmd_framework.py +++ b/chia/_tests/cmds/test_cmd_framework.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pathlib import textwrap from collections.abc import Sequence from dataclasses import asdict @@ -13,6 +14,7 @@ from chia._tests.environments.wallet import WalletTestFramework from chia._tests.wallet.conftest import * # noqa from chia.cmds.cmd_classes import ChiaCommand, Context, NeedsWalletRPC, chia_command, option +from chia.cmds.util import ChiaCliContext from chia.types.blockchain_format.sized_bytes import bytes32 @@ -143,14 +145,14 @@ def test_context_requirement() -> None: @click.group() @click.pass_context def cmd(ctx: click.Context) -> None: - ctx.obj = {"foo": "bar"} + ctx.obj = ChiaCliContext(root_path=pathlib.Path("foo", "bar")).to_click() @chia_command(cmd, "temp_cmd", "blah") class TempCMD: context: Context def run(self) -> None: - assert self.context["foo"] == "bar" + assert self.context.root_path == pathlib.Path("foo", "bar") runner = CliRunner() result = runner.invoke( @@ -385,7 +387,7 @@ def run(self) -> None: expected_command = TempCMD( rpc_info=NeedsWalletRPC( - context={"root_path": wallet_environments.environments[0].node.root_path}, + context=ChiaCliContext(root_path=wallet_environments.environments[0].node.root_path), wallet_rpc_port=port, fingerprint=fingerprint, ), diff --git a/chia/cmds/beta.py b/chia/cmds/beta.py index 31c436fa36af..74d0643cce0a 100644 --- a/chia/cmds/beta.py +++ b/chia/cmds/beta.py @@ -19,6 +19,7 @@ validate_beta_path, validate_metrics_log_interval, ) +from chia.cmds.util import ChiaCliContext from chia.util.beta_metrics import metrics_log_interval_default from chia.util.config import lock_and_load_config, save_config @@ -37,7 +38,7 @@ def beta_cmd() -> None: @click.option("-i", "--interval", help="System metrics will be logged based on this interval", type=int, required=False) @click.pass_context def configure(ctx: click.Context, path: Optional[str], interval: Optional[int]) -> None: - root_path = ctx.obj["root_path"] + root_path = ChiaCliContext.from_click(ctx).root_path with lock_and_load_config(root_path, "config.yaml") as config: if "beta" not in config: raise click.ClickException("beta test mode is not enabled, enable it first with `chia beta enable`") @@ -79,7 +80,7 @@ def configure(ctx: click.Context, path: Optional[str], interval: Optional[int]) @click.option("-p", "--path", help="The beta mode root path", type=str, required=False) @click.pass_context def enable_cmd(ctx: click.Context, force: bool, path: Optional[str]) -> None: - root_path = ctx.obj["root_path"] + root_path = ChiaCliContext.from_click(ctx).root_path with lock_and_load_config(root_path, "config.yaml") as config: if config.get("beta", {}).get("enabled", False): raise click.ClickException("beta test mode is already enabled") @@ -107,7 +108,7 @@ def enable_cmd(ctx: click.Context, force: bool, path: Optional[str]) -> None: @beta_cmd.command("disable", help="Disable beta test mode") @click.pass_context def disable_cmd(ctx: click.Context) -> None: - root_path = ctx.obj["root_path"] + root_path = ChiaCliContext.from_click(ctx).root_path with lock_and_load_config(root_path, "config.yaml") as config: if not config.get("beta", {}).get("enabled", False): raise click.ClickException("beta test mode is not enabled") @@ -121,7 +122,7 @@ def disable_cmd(ctx: click.Context) -> None: @beta_cmd.command("prepare_submission", help="Prepare the collected log data for submission") @click.pass_context def prepare_submission_cmd(ctx: click.Context) -> None: - with lock_and_load_config(ctx.obj["root_path"], "config.yaml") as config: + with lock_and_load_config(ChiaCliContext.from_click(ctx).root_path, "config.yaml") as config: beta_root_path = config.get("beta", {}).get("path", None) if beta_root_path is None: raise click.ClickException("beta test mode not enabled. Run `chia beta enable` first.") @@ -173,7 +174,7 @@ def add_files(paths: list[Path]) -> int: @beta_cmd.command("status", help="Show the current beta configuration") @click.pass_context def status(ctx: click.Context) -> None: - with lock_and_load_config(ctx.obj["root_path"], "config.yaml") as config: + with lock_and_load_config(ChiaCliContext.from_click(ctx).root_path, "config.yaml") as config: beta_config = config.get("beta") if beta_config is None: raise click.ClickException("beta test mode is not enabled, enable it first with `chia beta enable`") diff --git a/chia/cmds/check_wallet_db.py b/chia/cmds/check_wallet_db.py index 480a02e4f6ae..0ea417a565b1 100644 --- a/chia/cmds/check_wallet_db.py +++ b/chia/cmds/check_wallet_db.py @@ -397,9 +397,9 @@ async def scan(self, db_path: Path) -> int: return len(errors) -async def scan(root_path: str, db_path: Optional[str] = None, *, verbose: bool = False) -> None: +async def scan(root_path: Path, db_path: Optional[str] = None, *, verbose: bool = False) -> None: if db_path is None: - wallet_db_path = Path(root_path) / "wallet" / "db" + wallet_db_path = root_path / "wallet" / "db" wallet_db_paths = list(wallet_db_path.glob("blockchain_wallet_*.sqlite")) else: wallet_db_paths = [Path(db_path)] @@ -417,4 +417,4 @@ async def scan(root_path: str, db_path: Optional[str] = None, *, verbose: bool = if __name__ == "__main__": loop = asyncio.get_event_loop() - loop.run_until_complete(scan("", sys.argv[1])) + loop.run_until_complete(scan(Path(""), sys.argv[1])) diff --git a/chia/cmds/chia.py b/chia/cmds/chia.py index 3c7291a72de1..333a3d58e3fd 100644 --- a/chia/cmds/chia.py +++ b/chia/cmds/chia.py @@ -26,6 +26,7 @@ from chia.cmds.show import show_cmd from chia.cmds.start import start_cmd from chia.cmds.stop import stop_cmd +from chia.cmds.util import ChiaCliContext from chia.cmds.wallet import wallet_cmd from chia.util.default_root import DEFAULT_KEYS_ROOT_PATH, DEFAULT_ROOT_PATH from chia.util.errors import KeychainCurrentPassphraseIsInvalid @@ -55,7 +56,7 @@ def cli( from pathlib import Path ctx.ensure_object(dict) - ctx.obj["root_path"] = Path(root_path) + ctx.obj.update(ChiaCliContext(root_path=Path(root_path)).to_click()) # keys_root_path and passphrase_file will be None if the passphrase options have been # scrubbed from the CLI options @@ -107,7 +108,7 @@ def run_daemon_cmd(ctx: click.Context, wait_for_unlock: bool) -> None: wait_for_unlock = wait_for_unlock and Keychain.is_keyring_locked() - asyncio.run(async_run_daemon(ctx.obj["root_path"], wait_for_unlock=wait_for_unlock)) + asyncio.run(async_run_daemon(ChiaCliContext.from_click(ctx).root_path, wait_for_unlock=wait_for_unlock)) cli.add_command(keys_cmd) diff --git a/chia/cmds/cmd_classes.py b/chia/cmds/cmd_classes.py index 04462a5a6f36..038957bb05f5 100644 --- a/chia/cmds/cmd_classes.py +++ b/chia/cmds/cmd_classes.py @@ -13,6 +13,7 @@ from typing_extensions import dataclass_transform from chia.cmds.cmds_util import get_wallet_client +from chia.cmds.util import ChiaCliContext from chia.rpc.wallet_rpc_client import WalletRpcClient from chia.types.blockchain_format.sized_bytes import bytes32 from chia.util.byte_types import hexstr_to_bytes @@ -256,7 +257,7 @@ def command_helper(cls: type[Any]) -> type[Any]: return new_cls -Context = dict[str, Any] +Context = ChiaCliContext @dataclass(frozen=True) @@ -268,7 +269,7 @@ class WalletClientInfo: @command_helper class NeedsWalletRPC: - context: Context = field(default_factory=dict) + context: Context = field(default_factory=ChiaCliContext) client_info: Optional[WalletClientInfo] = None wallet_rpc_port: Optional[int] = option( "-wp", @@ -294,7 +295,7 @@ async def wallet_rpc(self, **kwargs: Any) -> AsyncIterator[WalletClientInfo]: yield self.client_info else: if "root_path" not in kwargs: - kwargs["root_path"] = self.context["root_path"] + kwargs["root_path"] = self.context.root_path async with get_wallet_client(self.wallet_rpc_port, self.fingerprint, **kwargs) as ( wallet_client, fp, diff --git a/chia/cmds/configure.py b/chia/cmds/configure.py index fd91e6e93a28..59ff05f1379b 100644 --- a/chia/cmds/configure.py +++ b/chia/cmds/configure.py @@ -6,6 +6,7 @@ import click import yaml +from chia.cmds.util import ChiaCliContext from chia.server.outbound_message import NodeType from chia.util.config import ( initial_config_file, @@ -313,7 +314,7 @@ def configure_cmd( seeder_nameserver: str, ) -> None: configure( - ctx.obj["root_path"], + ChiaCliContext.from_click(ctx).root_path, set_farmer_peer, set_node_introducer, set_fullnode_port, diff --git a/chia/cmds/db.py b/chia/cmds/db.py index 6a4619632a29..09d753bb7590 100644 --- a/chia/cmds/db.py +++ b/chia/cmds/db.py @@ -8,6 +8,7 @@ from chia.cmds.db_backup_func import db_backup_func from chia.cmds.db_upgrade_func import db_upgrade_func from chia.cmds.db_validate_func import db_validate_func +from chia.cmds.util import ChiaCliContext @click.group("db", help="Manage the blockchain database") @@ -41,7 +42,7 @@ def db_upgrade_cmd( ) -> None: try: db_upgrade_func( - Path(ctx.obj["root_path"]), + ChiaCliContext.from_click(ctx).root_path, None if in_db_path is None else Path(in_db_path), None if out_db_path is None else Path(out_db_path), no_update_config=no_update_config, @@ -63,7 +64,7 @@ def db_upgrade_cmd( def db_validate_cmd(ctx: click.Context, in_db_path: Optional[str], validate_blocks: bool) -> None: try: db_validate_func( - Path(ctx.obj["root_path"]), + ChiaCliContext.from_click(ctx).root_path, None if in_db_path is None else Path(in_db_path), validate_blocks=validate_blocks, ) @@ -78,7 +79,7 @@ def db_validate_cmd(ctx: click.Context, in_db_path: Optional[str], validate_bloc def db_backup_cmd(ctx: click.Context, db_backup_file: Optional[str], no_indexes: bool) -> None: try: db_backup_func( - Path(ctx.obj["root_path"]), + ChiaCliContext.from_click(ctx).root_path, None if db_backup_file is None else Path(db_backup_file), no_indexes=no_indexes, ) diff --git a/chia/cmds/init.py b/chia/cmds/init.py index ce53a197d4dc..cc67a917f8d7 100644 --- a/chia/cmds/init.py +++ b/chia/cmds/init.py @@ -2,6 +2,8 @@ import click +from chia.cmds.util import ChiaCliContext + @click.command("init", help="Create or migrate the configuration") @click.option( @@ -55,7 +57,7 @@ def init_cmd( init( Path(create_certs) if create_certs is not None else None, - ctx.obj["root_path"], + ChiaCliContext.from_click(ctx).root_path, fix_ssl_permissions, testnet, v1_db, diff --git a/chia/cmds/keys.py b/chia/cmds/keys.py index 1a7194beed3f..9e789593c035 100644 --- a/chia/cmds/keys.py +++ b/chia/cmds/keys.py @@ -6,15 +6,15 @@ from chia_rs import PrivateKey from chia.cmds import options +from chia.cmds.util import ChiaCliContext @click.group("keys", help="Manage your keys") @click.pass_context def keys_cmd(ctx: click.Context) -> None: """Create, delete, view and use your key pairs""" - from pathlib import Path - root_path: Path = ctx.obj["root_path"] + root_path = ChiaCliContext.from_click(ctx).root_path if not root_path.is_dir(): raise RuntimeError("Please initialize (or migrate) your config directory with chia init") @@ -34,7 +34,7 @@ def generate_cmd(ctx: click.Context, label: Optional[str]) -> None: from .keys_funcs import generate_and_add generate_and_add(label) - check_keys(ctx.obj["root_path"]) + check_keys(ChiaCliContext.from_click(ctx).root_path) @keys_cmd.command("show", help="Displays all the keys in keychain or the key with the given fingerprint") @@ -77,7 +77,14 @@ def show_cmd( ) -> None: from .keys_funcs import show_keys - show_keys(ctx.obj["root_path"], show_mnemonic_seed, non_observer_derivation, json, fingerprint, bech32m_prefix) + show_keys( + ChiaCliContext.from_click(ctx).root_path, + show_mnemonic_seed, + non_observer_derivation, + json, + fingerprint, + bech32m_prefix, + ) @keys_cmd.command("add", help="Add a private key by mnemonic or public key as hex") @@ -109,7 +116,7 @@ def add_cmd(ctx: click.Context, filename: str, label: Optional[str]) -> None: mnemonic_or_pk = Path(filename).read_text().rstrip() query_and_add_key_info(mnemonic_or_pk, label) - check_keys(ctx.obj["root_path"]) + check_keys(ChiaCliContext.from_click(ctx).root_path) @keys_cmd.group("label", help="Manage your key labels") @@ -155,7 +162,7 @@ def delete_cmd(ctx: click.Context, fingerprint: int) -> None: from .keys_funcs import delete delete(fingerprint) - check_keys(ctx.obj["root_path"]) + check_keys(ChiaCliContext.from_click(ctx).root_path) @keys_cmd.command("delete_all", help="Delete all private keys in keychain") @@ -343,7 +350,7 @@ def search_cmd( print("Could not resolve private key from fingerprint/mnemonic file") found: bool = search_derive( - ctx.obj["root_path"], + ChiaCliContext.from_click(ctx).root_path, fingerprint, search_terms, limit, @@ -419,7 +426,14 @@ def wallet_address_cmd( return derive_wallet_address( - ctx.obj["root_path"], fingerprint, index, count, prefix, non_observer_derivation, show_hd_path, sk + ChiaCliContext.from_click(ctx).root_path, + fingerprint, + index, + count, + prefix, + non_observer_derivation, + show_hd_path, + sk, ) diff --git a/chia/cmds/param_types.py b/chia/cmds/param_types.py index 0fac199735c7..e0a1253fb66c 100644 --- a/chia/cmds/param_types.py +++ b/chia/cmds/param_types.py @@ -7,6 +7,7 @@ import click from chia.cmds.units import units +from chia.cmds.util import ChiaCliContext from chia.types.blockchain_format.sized_bytes import bytes32 from chia.util.bech32m import bech32_decode, decode_puzzle_hash from chia.util.config import load_config, selected_network_address_prefix @@ -173,9 +174,11 @@ def convert(self, value: Any, param: Optional[click.Parameter], ctx: Optional[cl hrp, _b32data = bech32_decode(value) if hrp in {"xch", "txch"}: # I hate having to load the config here addr_type: AddressType = AddressType.XCH - expected_prefix = ctx.obj.get("expected_prefix") if ctx else None # attempt to get cached prefix + expected_prefix = ( + ChiaCliContext.from_click(ctx).expected_prefix if ctx else None + ) # attempt to get cached prefix if expected_prefix is None: - root_path = ctx.obj["root_path"] if ctx is not None else DEFAULT_ROOT_PATH + root_path = ChiaCliContext.from_click(ctx).root_path if ctx is not None else DEFAULT_ROOT_PATH config = load_config(root_path, "config.yaml") expected_prefix = selected_network_address_prefix(config) diff --git a/chia/cmds/passphrase.py b/chia/cmds/passphrase.py index 1654f8079369..b620f6d5aa5d 100644 --- a/chia/cmds/passphrase.py +++ b/chia/cmds/passphrase.py @@ -7,6 +7,7 @@ import click +from chia.cmds.util import ChiaCliContext from chia.util.config import load_config @@ -70,7 +71,7 @@ def set_cmd( if success: # Attempt to update the daemon's passphrase cache - root_path = ctx.obj["root_path"] + root_path = ChiaCliContext.from_click(ctx).root_path config = load_config(root_path, "config.yaml") sys.exit(asyncio.run(async_update_daemon_passphrase_cache_if_running(root_path, config))) @@ -98,7 +99,7 @@ def remove_cmd(ctx: click.Context, current_passphrase_file: Optional[TextIOWrapp if remove_passphrase(current_passphrase): # Attempt to update the daemon's passphrase cache - root_path = ctx.obj["root_path"] + root_path = ChiaCliContext.from_click(ctx).root_path config = load_config(root_path, "config.yaml") sys.exit(asyncio.run(async_update_daemon_passphrase_cache_if_running(root_path, config))) diff --git a/chia/cmds/peer.py b/chia/cmds/peer.py index 509e34015836..4fcd7b0e627d 100644 --- a/chia/cmds/peer.py +++ b/chia/cmds/peer.py @@ -6,6 +6,7 @@ from chia.cmds.cmds_util import NODE_TYPES from chia.cmds.peer_funcs import peer_async +from chia.cmds.util import ChiaCliContext @click.command("peer", help="Show, or modify peering connections", no_args_is_help=True) @@ -42,7 +43,7 @@ def peer_cmd( peer_async( node_type, rpc_port, - ctx.obj["root_path"], + ChiaCliContext.from_click(ctx).root_path, connections, add_connection, remove_connection, diff --git a/chia/cmds/plots.py b/chia/cmds/plots.py index 52d852fb996e..2686eb9df8be 100644 --- a/chia/cmds/plots.py +++ b/chia/cmds/plots.py @@ -7,6 +7,7 @@ import click +from chia.cmds.util import ChiaCliContext from chia.plotting.util import add_plot_directory, validate_plot_size log = logging.getLogger(__name__) @@ -33,7 +34,7 @@ def plots_cmd(ctx: click.Context) -> None: """Create, add, remove and check your plots""" from chia.util.chia_logging import initialize_logging - root_path: Path = ctx.obj["root_path"] + root_path = ChiaCliContext.from_click(ctx).root_path if not root_path.is_dir(): raise RuntimeError("Please initialize (or migrate) your config directory with 'chia init'") initialize_logging("", {"log_level": "INFO", "log_stdout": True}, root_path) @@ -132,7 +133,7 @@ def create_cmd( nobitfield=nobitfield, ) - root_path: Path = ctx.obj["root_path"] + root_path = ChiaCliContext.from_click(ctx).root_path try: validate_plot_size(root_path, size, override_k) except ValueError as e: @@ -177,7 +178,14 @@ def check_cmd( ) -> None: from chia.plotting.check_plots import check_plots - check_plots(ctx.obj["root_path"], num, challenge_start, grep_string, list_duplicates, debug_show_memo) + check_plots( + ChiaCliContext.from_click(ctx).root_path, + num, + challenge_start, + grep_string, + list_duplicates, + debug_show_memo, + ) @plots_cmd.command("add", help="Adds a directory of plots") @@ -194,7 +202,7 @@ def add_cmd(ctx: click.Context, final_dir: str) -> None: from chia.plotting.util import add_plot_directory try: - add_plot_directory(ctx.obj["root_path"], final_dir) + add_plot_directory(ChiaCliContext.from_click(ctx).root_path, final_dir) print(f"Successfully added: {final_dir}") except ValueError as e: print(e) @@ -213,10 +221,10 @@ def add_cmd(ctx: click.Context, final_dir: str) -> None: def remove_cmd(ctx: click.Context, final_dir: str) -> None: from chia.plotting.util import remove_plot_directory - remove_plot_directory(ctx.obj["root_path"], final_dir) + remove_plot_directory(ChiaCliContext.from_click(ctx).root_path, final_dir) @plots_cmd.command("show", help="Shows the directory of current plots") @click.pass_context def show_cmd(ctx: click.Context) -> None: - show_plots(ctx.obj["root_path"]) + show_plots(ChiaCliContext.from_click(ctx).root_path) diff --git a/chia/cmds/plotters.py b/chia/cmds/plotters.py index 7c5b5f90f12a..719e1eeaf413 100644 --- a/chia/cmds/plotters.py +++ b/chia/cmds/plotters.py @@ -2,6 +2,7 @@ import click +from chia.cmds.util import ChiaCliContext from chia.plotters.plotters import call_plotters @@ -14,4 +15,4 @@ @click.pass_context @click.argument("args", nargs=-1) def plotters_cmd(ctx: click.Context, args: tuple[click.Argument]) -> None: - call_plotters(ctx.obj["root_path"], args) + call_plotters(ChiaCliContext.from_click(ctx).root_path, args) diff --git a/chia/cmds/show.py b/chia/cmds/show.py index 0141a33da3b9..eff18104f880 100644 --- a/chia/cmds/show.py +++ b/chia/cmds/show.py @@ -5,6 +5,7 @@ import click from chia.cmds.show_funcs import show_async +from chia.cmds.util import ChiaCliContext @click.command("show", help="Show node information", no_args_is_help=True) @@ -62,7 +63,7 @@ def show_cmd( asyncio.run( show_async( rpc_port, - ctx.obj["root_path"], + ChiaCliContext.from_click(ctx).root_path, fee, state, block_header_hash_by_height, diff --git a/chia/cmds/sim.py b/chia/cmds/sim.py index 98756e905973..7d5350867198 100644 --- a/chia/cmds/sim.py +++ b/chia/cmds/sim.py @@ -8,6 +8,7 @@ from chia.cmds import options from chia.cmds.sim_funcs import async_config_wizard, farm_blocks, print_status, revert_block_height, set_auto_farm +from chia.cmds.util import ChiaCliContext from chia.util.default_root import SIMULATOR_ROOT_PATH @@ -35,9 +36,12 @@ @click.pass_context def sim_cmd(ctx: click.Context, rpc_port: Optional[int], root_path: str, simulator_name: str) -> None: ctx.ensure_object(dict) - ctx.obj["root_path"] = Path(root_path) / simulator_name - ctx.obj["sim_name"] = simulator_name - ctx.obj["rpc_port"] = rpc_port + ctx.obj.update( + ChiaCliContext( + root_path=Path(root_path) / simulator_name, + rpc_port=rpc_port, + ) + ) @sim_cmd.command("create", help="Guides you through the process of setting up a Chia Simulator") @@ -73,13 +77,14 @@ def create_simulator_config( docker_mode: bool, no_bitfield: bool, ) -> None: - print(f"Using this Directory: {ctx.obj['root_path']}\n") + root_path = ChiaCliContext.from_click(ctx).root_path + print(f"Using this Directory: {root_path}\n") if fingerprint and mnemonic: print("You can't use both a fingerprint and a mnemonic. Please choose one.") return None asyncio.run( async_config_wizard( - ctx.obj["root_path"], + root_path, fingerprint, reward_address, plot_directory, @@ -132,10 +137,12 @@ def status_cmd( include_rewards: bool, show_addresses: bool, ) -> None: + context = ChiaCliContext.from_click(ctx) + asyncio.run( print_status( - ctx.obj["rpc_port"], - ctx.obj["root_path"], + context.rpc_port, + context.root_path, fingerprint, show_key, show_coins, @@ -174,10 +181,13 @@ def revert_cmd( if reset and blocks != 1: print("\nBlocks, '-b' must not be set if all blocks are selected by reset, '-r'. Exiting.\n") return + + context = ChiaCliContext.from_click(ctx) + asyncio.run( revert_block_height( - ctx.obj["rpc_port"], - ctx.obj["root_path"], + context.rpc_port, + context.root_path, blocks, new_blocks, reset, @@ -192,10 +202,11 @@ def revert_cmd( @click.option("-a", "--target-address", type=str, default="", help="Block reward address") @click.pass_context def farm_cmd(ctx: click.Context, blocks: int, non_transaction: bool, target_address: str) -> None: + context = ChiaCliContext.from_click(ctx) asyncio.run( farm_blocks( - ctx.obj["rpc_port"], - ctx.obj["root_path"], + context.rpc_port, + context.root_path, blocks, not non_transaction, target_address, @@ -208,10 +219,11 @@ def farm_cmd(ctx: click.Context, blocks: int, non_transaction: bool, target_addr @click.pass_context def autofarm_cmd(ctx: click.Context, set_autofarm: str) -> None: autofarm = bool(set_autofarm == "on") + context = ChiaCliContext.from_click(ctx) asyncio.run( set_auto_farm( - ctx.obj["rpc_port"], - ctx.obj["root_path"], + context.rpc_port, + context.root_path, autofarm, ) ) diff --git a/chia/cmds/start.py b/chia/cmds/start.py index 1e63d53be296..954995bdb546 100644 --- a/chia/cmds/start.py +++ b/chia/cmds/start.py @@ -2,6 +2,7 @@ import click +from chia.cmds.util import ChiaCliContext from chia.util.config import load_config from chia.util.service_groups import all_groups @@ -18,7 +19,7 @@ def start_cmd(ctx: click.Context, restart: bool, skip_keyring: bool, group: tupl from .start_funcs import async_start - root_path = ctx.obj["root_path"] + root_path = ChiaCliContext.from_click(ctx).root_path config = load_config(root_path, "config.yaml") warn_if_beta_enabled(config) asyncio.run(async_start(root_path, config, group, restart, skip_keyring=skip_keyring)) diff --git a/chia/cmds/stop.py b/chia/cmds/stop.py index a0b3621cbcc3..32ce910c4d67 100644 --- a/chia/cmds/stop.py +++ b/chia/cmds/stop.py @@ -7,6 +7,7 @@ import click +from chia.cmds.util import ChiaCliContext from chia.util.config import load_config from chia.util.service_groups import all_groups, services_for_groups @@ -54,7 +55,7 @@ async def async_stop(root_path: Path, config: dict[str, Any], group: tuple[str, def stop_cmd(ctx: click.Context, daemon: bool, group: tuple[str, ...]) -> None: from chia.cmds.beta_funcs import warn_if_beta_enabled - root_path = ctx.obj["root_path"] + root_path = ChiaCliContext.from_click(ctx).root_path config = load_config(root_path, "config.yaml") warn_if_beta_enabled(config) diff --git a/chia/cmds/util.py b/chia/cmds/util.py new file mode 100644 index 000000000000..6c05e6ed76b5 --- /dev/null +++ b/chia/cmds/util.py @@ -0,0 +1,26 @@ +from __future__ import annotations + +import dataclasses +import pathlib +from typing import ClassVar, Optional, cast, final + +import click + +from chia.util.default_root import DEFAULT_ROOT_PATH + + +@final +@dataclasses.dataclass +class ChiaCliContext: + context_dict_key: ClassVar[str] = "_chia_cli_context" + + root_path: pathlib.Path = DEFAULT_ROOT_PATH + expected_prefix: Optional[str] = None + rpc_port: Optional[int] = None + + @classmethod + def from_click(cls, ctx: click.Context) -> ChiaCliContext: + return cast(ChiaCliContext, ctx.obj[cls.context_dict_key]) + + def to_click(self) -> dict[str, object]: + return {self.context_dict_key: self} diff --git a/chia/cmds/wallet.py b/chia/cmds/wallet.py index e41bc2f0bd38..2d1c8e2d1beb 100644 --- a/chia/cmds/wallet.py +++ b/chia/cmds/wallet.py @@ -19,6 +19,7 @@ CliAmount, cli_amount_none, ) +from chia.cmds.util import ChiaCliContext from chia.types.blockchain_format.sized_bytes import bytes32 from chia.util.ints import uint32, uint64 from chia.wallet.conditions import ConditionValidTimes @@ -666,7 +667,7 @@ def check_wallet_cmd(ctx: click.Context, db_path: str, verbose: bool) -> None: from chia.cmds.check_wallet_db import scan - asyncio.run(scan(ctx.obj["root_path"], db_path, verbose=verbose)) + asyncio.run(scan(ChiaCliContext.from_click(ctx).root_path, db_path, verbose=verbose)) @wallet_cmd.group("did", help="DID related actions") From 03236e949c547d4f56f7411a8b322abf5c954327 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Thu, 21 Nov 2024 13:04:50 -0500 Subject: [PATCH 2/3] actually assign to the context properly... --- chia/cmds/cmd_classes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chia/cmds/cmd_classes.py b/chia/cmds/cmd_classes.py index 038957bb05f5..0ce2045891a3 100644 --- a/chia/cmds/cmd_classes.py +++ b/chia/cmds/cmd_classes.py @@ -119,7 +119,7 @@ def apply_decorators(self, cmd: SyncCmd) -> SyncCmd: def strip_click_context(func: SyncCmd) -> SyncCmd: def _inner(ctx: click.Context, **kwargs: Any) -> None: - context: dict[str, Any] = ctx.obj if ctx.obj is not None else {} + context: Context = ChiaCliContext.from_click(ctx) func(context=context, **kwargs) return _inner From 85e61aaa4c6849c26af0b7418a5ba72ba7b7bcfc Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Thu, 21 Nov 2024 15:19:20 -0500 Subject: [PATCH 3/3] handle the not-present case --- chia/cmds/util.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/chia/cmds/util.py b/chia/cmds/util.py index 6c05e6ed76b5..1c29ac8b152f 100644 --- a/chia/cmds/util.py +++ b/chia/cmds/util.py @@ -20,7 +20,14 @@ class ChiaCliContext: @classmethod def from_click(cls, ctx: click.Context) -> ChiaCliContext: - return cast(ChiaCliContext, ctx.obj[cls.context_dict_key]) + if ctx.obj is None: + return cls() + + existing = cast(Optional[ChiaCliContext], ctx.obj.get(cls.context_dict_key)) + if existing is None: + return cls() + + return existing def to_click(self) -> dict[str, object]: return {self.context_dict_key: self}