# -*- coding: utf-8 -*- from hostinfo import prefix from hostinfo import utils from typing import Iterable, Optional, Any, Union def _get_full_key(prev_key, key): if prev_key == '': return key return "%s.%s" % (prev_key, key) def _sort_with_list(iterable: Iterable, sort: list[str]): def helper(value) -> str: if sort is None: return value (key, _) = value if key in sort: return str(sort.index(key)) return "%d %s" % (len(sort), key) return sorted(iterable, key=helper) def _space(filter_key: Optional[str], full_key: str, printer: prefix.Printer, force=False): if filter_key is None and full_key == '': printer.space(force) class Printer: labels = { 'hostname': 'Hostname', 'arch': 'Architecture', 'os': 'Operating System', 'addresses': 'IPs', 'ports': 'Ports', 'vserver': 'VServer', 'services': 'Services', 'maintainers': 'Maintainers', 'description': 'Description' } ignore = ['vserver_host', 'groups'] def __init__(self, data, flags): self.data = data self.flags = flags prefix.Printer.flags = flags def _should_display(self, full_key, filter_key: Optional[str] = None): if full_key not in self.ignore: return True if filter_key is not None and filter_key.startswith(full_key): return True return False def _print(self, value: Union[str, dict[str, Any], list[str]], printer: prefix.Printer, filter_key: Optional[str] = None, sort=None, force=False): if isinstance(value, str): self._print_list(value.strip().splitlines(), printer, filter_key) elif isinstance(value, dict): self._print_dict(value, printer, filter_key, sort, force) elif isinstance(value, list): self._print_list(value, printer, filter_key) elif value is None: if self.flags.verbose: printer.pprint('') else: self._print_value(value, printer, filter_key) def _print_key(self, key: str, value: str, printer: prefix.Printer, filter_key): sort = None try: method = getattr(self, 'cb_print_%s' % key.replace('.', '_')) result = method(value, printer.full_key, filter_key) if isinstance(result, tuple): value, sort = result else: value = result except AttributeError: pass self._print(value, printer, filter_key, sort) def _print_value(self, value: str, printer: prefix.Printer, filter_key: Optional[str]): full_key = _get_full_key(printer.full_key, value) if self._should_display(full_key, filter_key) and \ filter_key is None or full_key == filter_key: printer.pprint(value) def _print_list(self, values: list[str], printer: prefix.Printer, filter_key: Optional[str]): for value in values: if isinstance(value, str): self._print_value(value, printer, filter_key) else: self._print(value, printer, filter_key) def _print_dict(self, value: dict[str, str], printer: prefix.Printer, filter_key: Optional[str], sort: list, force: bool): keys = _sort_with_list( [(key, full_key) for key in list(value.keys()) for full_key in [_get_full_key(printer.full_key, key)] if self._should_display(full_key, filter_key)], sort) if len(keys) == 0: return maxlength = max([len(self._get_label(key, full_key)) for (key, full_key) in keys]) _space(filter_key, printer.full_key, printer, True) found = False for (key, full_key) in keys: new_filter_key = None if filter_key is not None: if filter_key.startswith(full_key + '.'): new_filter_key = filter_key elif full_key != filter_key: continue found = True new_printer = prefix.Printer(full_key, printer) if filter_key is None: new_printer.set_label(self._get_label(key, full_key), maxlength) self._print_key(full_key, value[key], new_printer, new_filter_key) _space(filter_key, printer.full_key, new_printer) if force and not found: printer.pprint('') def _get_label(self, key: str, full_key: str): if full_key in self.labels: return self.labels[full_key] return key def info(self, key: Optional[str], label: Optional[str] = None, maxlength=0, force=False): printer = prefix.Printer() if label is not None: printer.set_label(label, maxlength) self._print(self.data, printer, filter_key=key, force=force, sort=['hostname', 'arch', 'os', 'addresses', 'ports'])