mirror of https://github.com/nucypher/nucypher.git
Improve UX of selecting configuration file - additional table column with filename, echo message when defaulting to the lone configuration file.
parent
4b1a7fd07c
commit
0c660fc233
|
@ -14,14 +14,12 @@
|
||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
import glob
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
from json.decoder import JSONDecodeError
|
||||||
|
from typing import Optional, Type, List
|
||||||
|
|
||||||
import click
|
import click
|
||||||
from json.decoder import JSONDecodeError
|
|
||||||
from nucypher.config.base import CharacterConfiguration
|
|
||||||
from typing import Optional, Type
|
|
||||||
|
|
||||||
from nucypher.characters.control.emitters import StdoutEmitter
|
from nucypher.characters.control.emitters import StdoutEmitter
|
||||||
from nucypher.characters.lawful import Ursula
|
from nucypher.characters.lawful import Ursula
|
||||||
|
@ -38,7 +36,9 @@ from nucypher.cli.literature import (
|
||||||
CONFIRM_URSULA_IPV4_ADDRESS
|
CONFIRM_URSULA_IPV4_ADDRESS
|
||||||
)
|
)
|
||||||
from nucypher.cli.types import WORKER_IP
|
from nucypher.cli.types import WORKER_IP
|
||||||
|
from nucypher.config.base import CharacterConfiguration
|
||||||
from nucypher.config.characters import StakeHolderConfiguration
|
from nucypher.config.characters import StakeHolderConfiguration
|
||||||
|
from nucypher.config.constants import DEFAULT_CONFIG_ROOT
|
||||||
from nucypher.utilities.networking import InvalidWorkerIP, validate_worker_ip
|
from nucypher.utilities.networking import InvalidWorkerIP, validate_worker_ip
|
||||||
from nucypher.utilities.networking import determine_external_ip_address, UnknownIPAddress
|
from nucypher.utilities.networking import determine_external_ip_address, UnknownIPAddress
|
||||||
|
|
||||||
|
@ -50,6 +50,23 @@ def forget(emitter: StdoutEmitter, configuration: CharacterConfiguration) -> Non
|
||||||
emitter.message(SUCCESSFUL_FORGET_NODES, color='red')
|
emitter.message(SUCCESSFUL_FORGET_NODES, color='red')
|
||||||
|
|
||||||
|
|
||||||
|
def get_config_filepaths(config_class: Type[CharacterConfiguration], config_root: str = None) -> List:
|
||||||
|
#
|
||||||
|
# Scrape disk for configuration files
|
||||||
|
#
|
||||||
|
config_root = config_root or DEFAULT_CONFIG_ROOT
|
||||||
|
default_config_file = glob.glob(config_class.default_filepath(config_root=config_root))
|
||||||
|
|
||||||
|
# updated glob pattern for secondary configuration files accommodates for:
|
||||||
|
# 1. configuration files with "0x..." checksum address as suffix - including older ursula config files
|
||||||
|
# 2. newer (ursula) configuration files which use signing_pub_key[:8] as hex as the suffix
|
||||||
|
glob_pattern = f'{config_root}/{config_class.NAME}-[0-9a-fA-f]*.{config_class._CONFIG_FILE_EXTENSION}'
|
||||||
|
|
||||||
|
secondary_config_files = sorted(glob.glob(glob_pattern)) # sort list to make order deterministic
|
||||||
|
config_files = [*default_config_file, *secondary_config_files]
|
||||||
|
return config_files
|
||||||
|
|
||||||
|
|
||||||
def get_or_update_configuration(emitter: StdoutEmitter,
|
def get_or_update_configuration(emitter: StdoutEmitter,
|
||||||
filepath: str,
|
filepath: str,
|
||||||
config_class: Type[CharacterConfiguration],
|
config_class: Type[CharacterConfiguration],
|
||||||
|
|
|
@ -15,9 +15,8 @@
|
||||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import glob
|
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Optional, Tuple, Type
|
from typing import Optional, Tuple, Type
|
||||||
|
|
||||||
|
@ -33,6 +32,7 @@ from nucypher.blockchain.eth.registry import InMemoryContractRegistry, BaseContr
|
||||||
from nucypher.blockchain.eth.signers.base import Signer
|
from nucypher.blockchain.eth.signers.base import Signer
|
||||||
from nucypher.blockchain.eth.token import NU, Stake
|
from nucypher.blockchain.eth.token import NU, Stake
|
||||||
from nucypher.characters.control.emitters import StdoutEmitter
|
from nucypher.characters.control.emitters import StdoutEmitter
|
||||||
|
from nucypher.cli.actions.configure import get_config_filepaths
|
||||||
from nucypher.cli.literature import (
|
from nucypher.cli.literature import (
|
||||||
GENERIC_SELECT_ACCOUNT,
|
GENERIC_SELECT_ACCOUNT,
|
||||||
NO_CONFIGURATIONS_ON_DISK,
|
NO_CONFIGURATIONS_ON_DISK,
|
||||||
|
@ -48,7 +48,7 @@ from nucypher.cli.literature import (
|
||||||
from nucypher.cli.painting.policies import paint_cards
|
from nucypher.cli.painting.policies import paint_cards
|
||||||
from nucypher.cli.painting.staking import paint_stakes
|
from nucypher.cli.painting.staking import paint_stakes
|
||||||
from nucypher.config.base import CharacterConfiguration
|
from nucypher.config.base import CharacterConfiguration
|
||||||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT, NUCYPHER_ENVVAR_WORKER_ADDRESS
|
from nucypher.config.constants import NUCYPHER_ENVVAR_WORKER_ADDRESS, DEFAULT_CONFIG_ROOT
|
||||||
from nucypher.policy.identity import Card
|
from nucypher.policy.identity import Card
|
||||||
|
|
||||||
|
|
||||||
|
@ -228,20 +228,8 @@ def select_config_file(emitter: StdoutEmitter,
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#
|
|
||||||
# Scrape Disk Configurations
|
|
||||||
#
|
|
||||||
|
|
||||||
config_root = config_root or DEFAULT_CONFIG_ROOT
|
config_root = config_root or DEFAULT_CONFIG_ROOT
|
||||||
default_config_file = glob.glob(config_class.default_filepath(config_root=config_root))
|
config_files = get_config_filepaths(config_class=config_class, config_root=config_root)
|
||||||
|
|
||||||
# updated glob pattern for secondary configuration files accommodates for:
|
|
||||||
# 1. configuration files with "0x..." checksum address as suffix - including older ursula config files
|
|
||||||
# 2. newer (ursula) configuration files which use signing_pub_key[:8] as hex as the suffix
|
|
||||||
glob_pattern = f'{config_root}/{config_class.NAME}-[0-9a-fA-f]*.{config_class._CONFIG_FILE_EXTENSION}'
|
|
||||||
|
|
||||||
secondary_config_files = glob.glob(glob_pattern)
|
|
||||||
config_files = [*default_config_file, *secondary_config_files]
|
|
||||||
if not config_files:
|
if not config_files:
|
||||||
emitter.message(NO_CONFIGURATIONS_ON_DISK.format(name=config_class.NAME.capitalize(),
|
emitter.message(NO_CONFIGURATIONS_ON_DISK.format(name=config_class.NAME.capitalize(),
|
||||||
command=config_class.NAME), color='red')
|
command=config_class.NAME), color='red')
|
||||||
|
@ -249,8 +237,8 @@ def select_config_file(emitter: StdoutEmitter,
|
||||||
|
|
||||||
checksum_address = checksum_address or os.environ.get(NUCYPHER_ENVVAR_WORKER_ADDRESS, None) # TODO: Deprecate worker_address in favor of checksum_address
|
checksum_address = checksum_address or os.environ.get(NUCYPHER_ENVVAR_WORKER_ADDRESS, None) # TODO: Deprecate worker_address in favor of checksum_address
|
||||||
|
|
||||||
parsed_addresses = list()
|
|
||||||
parsed_config_files = list()
|
parsed_config_files = list()
|
||||||
|
parsed_addresses_and_filenames = list()
|
||||||
# parse configuration files for checksum address values
|
# parse configuration files for checksum address values
|
||||||
for fp in config_files:
|
for fp in config_files:
|
||||||
try:
|
try:
|
||||||
|
@ -259,8 +247,8 @@ def select_config_file(emitter: StdoutEmitter,
|
||||||
# matching configuration file found, no need to continue - return filepath
|
# matching configuration file found, no need to continue - return filepath
|
||||||
return fp
|
return fp
|
||||||
|
|
||||||
parsed_addresses.append([config_checksum_address])
|
|
||||||
parsed_config_files.append(fp)
|
parsed_config_files.append(fp)
|
||||||
|
parsed_addresses_and_filenames.append([config_checksum_address, Path(fp).name]) # store checksum & filename
|
||||||
except config_class.OldVersion:
|
except config_class.OldVersion:
|
||||||
# no use causing entire usage to crash if file can't be used anyway - inform the user; they can
|
# no use causing entire usage to crash if file can't be used anyway - inform the user; they can
|
||||||
# decide for themself
|
# decide for themself
|
||||||
|
@ -280,11 +268,13 @@ def select_config_file(emitter: StdoutEmitter,
|
||||||
#
|
#
|
||||||
# Interactive
|
# Interactive
|
||||||
#
|
#
|
||||||
parsed_addresses = tuple(parsed_addresses) # must be tuple-of-iterables for tabulation
|
emitter.echo(f"\nConfiguration Directory: {config_root}\n")
|
||||||
|
|
||||||
|
parsed_addresses_and_filenames = tuple(parsed_addresses_and_filenames) # must be tuple-of-iterables for tabulation
|
||||||
|
|
||||||
# Display account info
|
# Display account info
|
||||||
headers = ['Account']
|
headers = ['Account', 'Configuration File']
|
||||||
emitter.echo(tabulate(parsed_addresses, headers=headers, showindex='always'))
|
emitter.echo(tabulate(parsed_addresses_and_filenames, headers=headers, showindex='always'))
|
||||||
|
|
||||||
# Prompt the user for selection, and return
|
# Prompt the user for selection, and return
|
||||||
prompt = f"Select {config_class.NAME} configuration"
|
prompt = f"Select {config_class.NAME} configuration"
|
||||||
|
@ -295,6 +285,7 @@ def select_config_file(emitter: StdoutEmitter,
|
||||||
else:
|
else:
|
||||||
# Default: Only one config file, use it.
|
# Default: Only one config file, use it.
|
||||||
config_file = parsed_config_files[0]
|
config_file = parsed_config_files[0]
|
||||||
|
emitter.echo(f"Defaulting to {config_class.NAME} configuration file: {config_file}")
|
||||||
|
|
||||||
return config_file
|
return config_file
|
||||||
|
|
||||||
|
|
|
@ -325,7 +325,7 @@ nucypher {init_command}
|
||||||
|
|
||||||
SELECT_NETWORK = "Select Network"
|
SELECT_NETWORK = "Select Network"
|
||||||
|
|
||||||
NO_CONFIGURATIONS_ON_DISK = "No {name} configurations found. run 'nucypher {command} init' then try again."
|
NO_CONFIGURATIONS_ON_DISK = "No {name} configurations found. Run 'nucypher {command} init' then try again."
|
||||||
|
|
||||||
SUCCESSFUL_UPDATE_CONFIGURATION_VALUES = "Updated configuration values: {fields}"
|
SUCCESSFUL_UPDATE_CONFIGURATION_VALUES = "Updated configuration values: {fields}"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue