devices, flavours, config: add "inherited from ABC" to "selected by XYZ" output

This commit is contained in:
InsanePrawn 2023-06-25 16:04:35 +02:00
parent 7425356f10
commit 60b38d895c
3 changed files with 43 additions and 46 deletions

View file

@ -4,9 +4,9 @@ import logging
from copy import deepcopy from copy import deepcopy
from typing import Any, Callable, Iterable, Mapping, Optional, Union from typing import Any, Callable, Iterable, Mapping, Optional, Union
from devices.device import get_devices from devices.device import get_devices, sanitize_device_name
from flavours.flavour import get_flavours from flavours.flavour import get_flavours
from utils import color_str, colors_supported, color_mark_selected from utils import color_bold, colors_supported, color_mark_selected
from wrapper import execute_without_exit from wrapper import execute_without_exit
from .scheme import Profile from .scheme import Profile
@ -98,16 +98,24 @@ def prompt_profile(
changed = False changed = False
for key, current in profile.items(): for key, current in profile.items():
current = profile[key] current = profile[key]
text = f'{name}.{key}' text = f'profiles.{name}.{key}'
if not no_parse and key in PARSEABLE_FIELDS: if not no_parse and key in PARSEABLE_FIELDS:
parse_prompt = None parse_prompt = None
sanitize_func = None
if key == 'device': if key == 'device':
parse_prompt = prompt_profile_device parse_prompt = prompt_profile_device
sanitize_func = sanitize_device_name
elif key == 'flavour': elif key == 'flavour':
parse_prompt = prompt_profile_flavour parse_prompt = prompt_profile_flavour
else: else:
raise Exception(f'config: Unhandled parseable field {key}, this is a bug in kupferbootstrap.') raise Exception(f'config: Unhandled parseable field {key}, this is a bug in kupferbootstrap.')
result, _changed = parse_prompt(current=current, profile_name=name, sparse_profiles=config.file.profiles) # type: ignore result, _changed = parse_prompt(
current=current,
profile_name=name,
sparse_profiles=config.file.profiles,
use_colors=config.runtime.colors,
sanitize_func=sanitize_func,
) # type: ignore
else: else:
result, _changed = prompt_config(text=text, default=current, field_type=type(PROFILE_DEFAULTS[key])) # type: ignore result, _changed = prompt_config(text=text, default=current, field_type=type(PROFILE_DEFAULTS[key])) # type: ignore
if _changed: if _changed:
@ -139,31 +147,23 @@ def prompt_wrappable(
current: Optional[str], current: Optional[str],
profile_name: str, profile_name: str,
sparse_profiles: Mapping[str, SparseProfile], sparse_profiles: Mapping[str, SparseProfile],
sanitize_func: Optional[Callable[[str], str]] = None,
use_colors: Optional[bool] = None, use_colors: Optional[bool] = None,
) -> tuple[str, bool]: ) -> tuple[str, bool]:
use_colors = colors_supported(use_colors) use_colors = colors_supported(use_colors)
def bold(s: str, _bold=True, **kwargs): print(color_bold(f"Pick your {attr_name}!\nThese are the available choices:", use_colors=use_colors))
return color_str(s, use_colors=use_colors, bold=_bold, **kwargs)
def green(s: str, _bold=True):
return bold(s, fg="bright_green", _bold=_bold)
print(bold(f"Pick your {attr_name}!\nThese are the available choices:"))
items = execute_without_exit(native_cmd, cli_cmd) items = execute_without_exit(native_cmd, cli_cmd)
selected, inherited_from = resolve_profile_field(current, profile_name, attr_name, sparse_profiles)
logging.debug(f"Acquired {attr_name=}={selected} from {inherited_from}")
if items is None: if items is None:
logging.warning("(wrapper mode, input for this field will not be checked for correctness)") logging.warning("(wrapper mode, input for this field will not be checked for correctness)")
return prompt_config(text=f'{profile_name}.{attr_name}', default=current) return prompt_config(text=f'profiles.{profile_name}.{attr_name}', default=current)
selected, inherited_from = resolve_profile_field(current, profile_name, attr_name, sparse_profiles)
if selected and sanitize_func:
selected = sanitize_func(selected)
for key in sorted(items.keys()): for key in sorted(items.keys()):
text = items[key].nice_str(newlines=True, colors=use_colors) text = items[key].nice_str(newlines=True, colors=use_colors)
if key == selected: if key == selected:
inherit_suffix = '' text = color_mark_selected(text, profile_name, inherited_from)
if inherited_from not in [None, profile_name]:
quote = '"'
inherit_suffix = f'{bold(" (inherited from profile "+quote)}{green(inherited_from)}{bold(quote+")")}'
text = color_mark_selected(text, f'"{green(profile_name)}"{inherit_suffix}')
print(text + '\n') print(text + '\n')
return prompt_choice(current, f'profiles.{profile_name}.{attr_name}', items.keys()) return prompt_choice(current, f'profiles.{profile_name}.{attr_name}', items.keys())

View file

@ -5,9 +5,10 @@ from json import dumps as json_dump
from typing import Optional from typing import Optional
from config.state import config from config.state import config
from utils import colors_supported, color_str from config.cli import resolve_profile_field
from utils import color_mark_selected, colors_supported
from .device import get_devices, get_profile_device from .device import get_devices, get_device
@click.command(name='devices') @click.command(name='devices')
@ -36,12 +37,14 @@ def cmd_devices(
if not devices: if not devices:
raise Exception("No devices found!") raise Exception("No devices found!")
profile_device = None profile_device = None
profile_name = config.file.profiles.current
selected, inherited_from = None, None
try: try:
dev = get_profile_device() selected, inherited_from = resolve_profile_field(None, profile_name, 'device', config.file.profiles)
assert dev if selected:
profile_device = dev profile_device = get_device(selected)
except Exception as ex: except Exception as ex:
logging.debug(f"Failed to get profile device for visual highlighting, not a problem: {ex}") logging.debug(f"Failed to get profile device for marking as currently selected, continuing anyway. Exception: {ex}")
output = [''] output = ['']
json_output = {} json_output = {}
interactive_json = json and not output_file interactive_json = json and not output_file
@ -49,8 +52,6 @@ def cmd_devices(
json = True json = True
use_colors = colors_supported(False if interactive_json else config.runtime.colors) use_colors = colors_supported(False if interactive_json else config.runtime.colors)
for name in sorted(devices.keys()): for name in sorted(devices.keys()):
prefix = ''
suffix = ''
device = devices[name] device = devices[name]
assert device assert device
if force_parse_deviceinfo in [None, True]: if force_parse_deviceinfo in [None, True]:
@ -66,14 +67,9 @@ def cmd_devices(
json_output[name] = device.get_summary().toDict() json_output[name] = device.get_summary().toDict()
if interactive_json: if interactive_json:
continue continue
snippet = device.nice_str(colors=use_colors, newlines=True)
if profile_device and profile_device.name == device.name: if profile_device and profile_device.name == device.name:
prefix = color_str('>>> ', bold=True, fg="bright_green", use_colors=use_colors) snippet = color_mark_selected(snippet, profile_name or '[unknown]', inherited_from)
suffix = '\n\n'
suffix += color_str('Currently selected by profile', bold=True, use_colors=use_colors) + " "
suffix += color_str(f'"{config.file.profiles.current}"', bold=True, fg="bright_green", use_colors=use_colors)
snippet = f'{device.nice_str(colors=use_colors, newlines=True)}{suffix}'
# prefix each line in the snippet
snippet = '\n'.join([f'{prefix}{line}' for line in snippet.split('\n')])
output.append(f"{snippet}\n") output.append(f"{snippet}\n")
if interactive_json: if interactive_json:
output = ['\n' + json_dump(json_output, indent=4)] output = ['\n' + json_dump(json_output, indent=4)]

View file

@ -4,10 +4,11 @@ import logging
from json import dumps as json_dump from json import dumps as json_dump
from typing import Optional from typing import Optional
from config.cli import resolve_profile_field
from config.state import config from config.state import config
from utils import colors_supported, color_str from utils import color_mark_selected, colors_supported
from .flavour import get_flavours, get_profile_flavour from .flavour import get_flavours, get_flavour
profile_option = click.option('-p', '--profile', help="name of the profile to use", required=False, default=None) profile_option = click.option('-p', '--profile', help="name of the profile to use", required=False, default=None)
@ -23,13 +24,17 @@ def cmd_flavours(json: bool = False, output_file: Optional[str] = None):
flavours = get_flavours() flavours = get_flavours()
interactive_json = json and not output_file interactive_json = json and not output_file
use_colors = colors_supported(config.runtime.colors) and not interactive_json use_colors = colors_supported(config.runtime.colors) and not interactive_json
profile_name = config.file.profiles.current
selected, inherited_from = None, None
if output_file: if output_file:
json = True json = True
if not flavours: if not flavours:
raise Exception("No flavours found!") raise Exception("No flavours found!")
if not interactive_json: if not interactive_json:
try: try:
profile_flavour = get_profile_flavour() selected, inherited_from = resolve_profile_field(None, profile_name, 'flavour', config.file.profiles)
if selected:
profile_flavour = get_flavour(selected)
except Exception as ex: except Exception as ex:
logging.debug(f"Failed to get profile flavour for marking as currently selected, continuing anyway. Exception: {ex}") logging.debug(f"Failed to get profile flavour for marking as currently selected, continuing anyway. Exception: {ex}")
for name in sorted(flavours.keys()): for name in sorted(flavours.keys()):
@ -39,15 +44,11 @@ def cmd_flavours(json: bool = False, output_file: Optional[str] = None):
except Exception as ex: except Exception as ex:
logging.debug(f"A problem happened while parsing flavourinfo for {name}, continuing anyway. Exception: {ex}") logging.debug(f"A problem happened while parsing flavourinfo for {name}, continuing anyway. Exception: {ex}")
if not interactive_json: if not interactive_json:
block = [*f.nice_str(newlines=True, colors=use_colors).split('\n'), ''] snippet = f.nice_str(newlines=True, colors=use_colors)
if profile_flavour == f: if profile_flavour == f:
prefix = color_str('>>> ', bold=True, fg='bright_green', use_colors=use_colors) snippet = color_mark_selected(snippet, profile_name or '[unknown]', inherited_from)
block += [ snippet += '\n'
color_str("Currently selected by profile ", bold=True, use_colors=use_colors) + results += snippet.split('\n')
color_str(f'"{config.file.profiles.current}"\n', bold=True, fg="bright_green")
]
block = [prefix + line for line in block]
results += block
if json: if json:
d = dict(f) d = dict(f)
d["description"] = f.flavour_info.description if (f.flavour_info and f.flavour_info.description) else f.description d["description"] = f.flavour_info.description if (f.flavour_info and f.flavour_info.description) else f.description
@ -58,7 +59,7 @@ def cmd_flavours(json: bool = False, output_file: Optional[str] = None):
d["pkgbuild"] = f.pkgbuild.path if f.pkgbuild else None d["pkgbuild"] = f.pkgbuild.path if f.pkgbuild else None
d["package"] = f.pkgbuild.name d["package"] = f.pkgbuild.name
d["arches"] = sorted(f.pkgbuild.arches) if f.pkgbuild else None d["arches"] = sorted(f.pkgbuild.arches) if f.pkgbuild else None
json_results[d["name"]] = d json_results[name] = d
print() print()
if output_file: if output_file:
with open(output_file, 'w') as fd: with open(output_file, 'w') as fd: