Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config command improvements #22

Merged
merged 3 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 122 additions & 15 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import asyncio
import os.path
import re
from typing import Optional, Coroutine
from typing import Optional, Coroutine, cast

from bittensor_wallet import Wallet
from git import Repo
Expand All @@ -20,7 +20,6 @@
from src.bittensor.async_substrate_interface import SubstrateRequestException
from src.utils import console, err_console


__version__ = "8.0.0"

_version_split = __version__.split(".")
Expand Down Expand Up @@ -208,6 +207,7 @@ def __init__(self):
"wallet_hotkey": None,
"network": None,
"chain": None,
"no_cache": False,
}
self.not_subtensor = None

Expand Down Expand Up @@ -280,6 +280,7 @@ def __init__(self):
# config commands
self.config_app.command("set")(self.set_config)
self.config_app.command("get")(self.get_config)
self.config_app.command("clear")(self.del_config)

# wallet commands
self.wallet_app.command("list")(self.wallet_list)
Expand Down Expand Up @@ -427,7 +428,11 @@ def set_config(
help="Path to root of wallets",
),
wallet_hotkey: Optional[str] = typer.Option(
None, "--wallet-hotkey", "--hotkey", "-k", help="Path to root of wallets"
None,
"--wallet-hotkey",
"--hotkey",
"-k",
help="name of the wallet hotkey file",
),
network: Optional[str] = typer.Option(
None,
Expand All @@ -439,32 +444,104 @@ def set_config(
None,
"--chain",
"-c",
help="Chain name",
help="chain endpoint for the network (e.g. ws://127.0.0.1:9945, "
"wss://entrypoint-finney.opentensor.ai:443)",
),
no_cache: Optional[bool] = typer.Option(
False,
"--no-cache",
help="Disable caching of certain commands. This will disable the `--reuse-last` and `html` flags on "
"commands such as `subnets metagraph`, `stake show` and `subnets list`.",
),
):
"""
Sets values in config file
:param wallet_name: name of the wallet
:param wallet_path: root path of the wallets
:param wallet_hotkey: name of the wallet hotkey file
:param network: name of the network (e.g. finney, test, local)
:param chain: chain endpoint for the network (e.g. ws://127.0.0.1:9945,
wss://entrypoint-finney.opentensor.ai:443)
"""
args = locals()
for arg in ["wallet_name", "wallet_path", "wallet_hotkey", "network", "chain"]:
if network and network.startswith("ws"):
if not Confirm.ask(
"[yellow]Warning[/yellow] your 'network' appears to be a chain endpoint. "
"Verify this is intentional"
):
raise typer.Exit()
for arg in [
"wallet_name",
"wallet_path",
"wallet_hotkey",
"network",
"chain",
"no_cache",
]:
if val := args.get(arg):
self.config[arg] = val
with open(os.path.expanduser("~/.bittensor/config.yml"), "w") as f:
safe_dump(self.config, f)

def del_config(
self,
wallet_name: bool = typer.Option(
False,
"--wallet-name",
),
wallet_path: bool = typer.Option(
False,
"--wallet-path",
),
wallet_hotkey: bool = typer.Option(
False,
"--wallet-hotkey",
),
network: bool = typer.Option(
False,
"--network",
),
chain: bool = typer.Option(False, "--chain"),
no_cache: bool = typer.Option(
False,
"--no-cache",
),
all_items: bool = typer.Option(False, "--all"),
):
"""
# config clear
Setting the flags in this command will clear those items from your config file

## Usage

- To clear the chain and network:
```
btcli config clear --chain --network
```

- To clear your config entirely:
```
btcli config clear --all
```
"""
if all_items:
self.config = {}
else:
args = locals()
for arg in [
"wallet_name",
"wallet_path",
"wallet_hotkey",
"network",
"chain",
"no_cache",
]:
if args.get(arg):
self.config[arg] = None
with open(os.path.expanduser("~/.bittensor/config.yml"), "w") as f:
safe_dump(self.config, f)

def get_config(self):
"""
Prints the current config file in a table
"""
table = Table(Column("Name"), Column("Value"))
for k, v in self.config.items():
table.add_row(*[k, v])
table.add_row(*[k, str(v)])
console.print(table)

def wallet_ask(
Expand Down Expand Up @@ -2396,14 +2473,26 @@ def stake_show(
This command is essential for users who wish to monitor their stake distribution and returns across various
accounts on the Bittensor network. It provides a clear and detailed overview of the user's staking activities.
"""
if (reuse_last or html_output) and self.config.get("no_cache") is True:
err_console.print(
"Unable to use `--reuse-last` or `--html` when config no-cache is set."
)
raise typer.Exit()
if not reuse_last:
subtensor = self.initialize_chain(network, chain)
wallet = Wallet()
else:
subtensor = None
wallet = self.wallet_ask(wallet_name, wallet_path, wallet_hotkey)
return self._run_command(
stake.show(wallet, subtensor, all_wallets, reuse_last, html_output)
stake.show(
wallet,
subtensor,
all_wallets,
reuse_last,
html_output,
self.config.get("no_cache", False),
)
)

def stake_add(
Expand Down Expand Up @@ -2956,12 +3045,19 @@ def subnets_list(
This command is particularly useful for users seeking an overview of the Bittensor network's structure and the
distribution of its resources and ownership information for each subnet.
"""
if (reuse_last or html_output) and self.config.get("no_cache") is True:
err_console.print(
"Unable to use `--reuse-last` or `--html` when config no-cache is set."
)
raise typer.Exit()
if reuse_last:
subtensor = None
else:
subtensor = self.initialize_chain(network, chain)
return self._run_command(
subnets.subnets_list(subtensor, reuse_last, html_output)
subnets.subnets_list(
subtensor, reuse_last, html_output, self.config.get("no_cache", False)
)
)

def subnets_lock_cost(
Expand Down Expand Up @@ -3303,6 +3399,11 @@ def subnets_metagraph(
It is useful for network analysis and diagnostics. It is intended to be used as part of the Bittensor CLI and
not as a standalone function within user code.
"""
if (reuse_last or html_output) and self.config.get("no_cache") is True:
err_console.print(
"Unable to use `--reuse-last` or `--html` when config no-cache is set."
)
raise typer.Exit()
if reuse_last:
if netuid is not None:
console.print("Cannot specify netuid when using `--reuse-last`")
Expand All @@ -3315,7 +3416,13 @@ def subnets_metagraph(
)
subtensor = self.initialize_chain(network, chain)
return self._run_command(
subnets.metagraph_cmd(subtensor, netuid, reuse_last, html_output)
subnets.metagraph_cmd(
subtensor,
netuid,
reuse_last,
html_output,
self.config.get("no_cache", False),
)
)

def weights_reveal(
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
aiohttp~=3.9.5
aiohttp~=3.10.2
backoff~=2.2.1
git+ssh://[email protected]/opentensor/btwallet.git # bittensor_wallet
GitPython>=3.0.0
Expand Down
1 change: 1 addition & 0 deletions src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class config:
"wallet_path": None,
"wallet_name": None,
"wallet_hotkey": None,
"no_cache": False,
}

class subtensor:
Expand Down
36 changes: 27 additions & 9 deletions src/bittensor/async_substrate_interface.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import json
import signal
from collections import defaultdict
from dataclasses import dataclass
from typing import Optional, Any, Union, Callable, Awaitable
Expand All @@ -18,6 +19,14 @@
ResultHandler = Callable[[dict, Any], Awaitable[tuple[dict, bool]]]


class TimeoutException(Exception):
pass


def timeout_handler(signum, frame):
raise TimeoutException("Operation timed out")


@dataclass
class Preprocessed:
queryable: str
Expand Down Expand Up @@ -404,15 +413,24 @@ async def initialize(self):
"""
async with self._lock:
if not self.substrate:
self.substrate = SubstrateInterface(
ss58_format=self.ss58_format,
use_remote_preset=True,
url=self.chain_endpoint,
type_registry=self.type_registry,
)
self.__chain = (await self.rpc_request("system_chain", [])).get(
"result"
)
# This is low-level timeout handling
# We set a timeout for 10 seconds.
# NOTE: this will not work on Windows, but it's not supported anyway
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(10) # Set timeout to 10 seconds
try:
self.substrate = SubstrateInterface(
ss58_format=self.ss58_format,
use_remote_preset=True,
url=self.chain_endpoint,
type_registry=self.type_registry,
)
finally:
# Cancel the alarm if the function completes before timeout
signal.alarm(0)

chain = await self.rpc_request("system_chain", [])
self.__chain = chain.get("result")
self.initialized = True

async def __aexit__(self, exc_type, exc_val, exc_tb):
Expand Down
30 changes: 16 additions & 14 deletions src/commands/stake.py
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,7 @@ async def show(
all_wallets: bool,
reuse_last: bool,
html_output: bool,
no_cache: bool,
):
"""Show all stake accounts."""

Expand Down Expand Up @@ -1093,7 +1094,7 @@ async def get_all_wallet_accounts(
return accounts_

if not reuse_last:
cast(subtensor, "SubtensorInterface")
cast("SubtensorInterface", subtensor)
if all_wallets:
wallets = get_coldkey_wallets_for_path(wallet.path)
else:
Expand Down Expand Up @@ -1140,25 +1141,26 @@ async def get_all_wallet_accounts(
)
total_stake += cast(Balance, value["stake"]).tao
total_rate += float(value["rate"])
create_table(
"stakeshow",
[
("COLDKEY", "TEXT"),
("BALANCE", "REAL"),
("ACCOUNT", "TEXT"),
("STAKE", "REAL"),
("RATE", "REAL"),
("CHILD", "INTEGER"),
],
db_rows,
)
metadata = {
"total_stake": "\u03c4{:.5f}".format(total_stake),
"total_balance": "\u03c4{:.5f}".format(total_balance),
"total_rate": "\u03c4{:.5f}/d".format(total_rate),
"rows": json.dumps(rows),
}
update_metadata_table("stakeshow", metadata)
if not no_cache:
create_table(
"stakeshow",
[
("COLDKEY", "TEXT"),
("BALANCE", "REAL"),
("ACCOUNT", "TEXT"),
("STAKE", "REAL"),
("RATE", "REAL"),
("CHILD", "INTEGER"),
],
db_rows,
)
update_metadata_table("stakeshow", metadata)
else:
try:
metadata = get_metadata_table("stakeshow")
Expand Down
Loading
Loading