From 7ac25158eb4c2ca7918ba96ad8166510d8ccdfb4 Mon Sep 17 00:00:00 2001 From: Markus Zolliker Date: Fri, 6 Oct 2023 17:24:05 +0200 Subject: [PATCH] [WIP] improvements overview/test --- frappyman.py | 99 ++++++++++++++++++++++++++++++++---------------- test_proposed.py | 17 +++++++-- 2 files changed, 79 insertions(+), 37 deletions(-) diff --git a/frappyman.py b/frappyman.py index 3dc1840..c2f5e2f 100644 --- a/frappyman.py +++ b/frappyman.py @@ -25,7 +25,7 @@ import os import re import builtins from glob import glob -from collections import defaultdict +from itertools import zip_longest from os.path import join, isdir, basename, expanduser, exists from configparser import ConfigParser from .base import ServiceManager, ServiceDown, UsageError @@ -62,7 +62,14 @@ class Namespace(dict): __builtins__ = builtins -def make_proposed(givencfgs, ourcfgs, seacfgs, sea_info, strict=False): +SEAEXT = {'main': '.config', 'stick': '.stick'} + + +def get_service(key): + return key if key in ('main', 'stick') else 'addons' + + +def make_proposed(givencfgs, ourcfgs, seacfgs, sea_info, strict=False, giventitle='nicos'): overview = {} for service in 'main', 'stick': given = givencfgs.get(service) @@ -80,43 +87,67 @@ def make_proposed(givencfgs, ourcfgs, seacfgs, sea_info, strict=False): if addon: overview.setdefault(addon, {})['frappy'] = addon + seacfgfiles = [(c or '') + SEAEXT.get(s, '.addon') + for c, s in zip_longest(seacfgs, FrappyManager.services)] + seacfgset = set(seacfgfiles) + inverted_sea_info = {k: [] for k in seacfgfiles} + for cfg, seacfg in sea_info.items(): + if seacfg in seacfgset: + inverted_sea_info[seacfg].append(cfg) error = False result = {} addons = set() - for i, seacfg in enumerate(seacfgs): - if i == 0: - key, ext = 'main', '.config' - elif i == 1: - key, ext = 'stick', '.stick' - else: - key, ext = None, '.addon' - available = sea_info.get(seacfg + ext, ()) + for seacfg, seacfgfile, key in zip_longest(seacfgs, seacfgfiles, ('main', 'stick')): + service = key or 'addons' + if not seacfg: + continue + available = inverted_sea_info[seacfgfile] if available: - proposed = list(available)[0] if len(available) == 1 else None + proposed = available[0] if len(available) == 1 else None if not proposed: + running = None for item in available: if item == overview.get(key or item, {}).get('given'): proposed = item if item == overview.get(key or item, {}).get('frappy'): - frappy = item - if frappy and not proposed: - proposed = frappy + running = item + if running and not proposed: + proposed = running if proposed: itemdict = overview.setdefault(key or proposed, {}) given = itemdict.get('given') - itemdict.update(name=(key or 'addon'), sea=seacfg, - remark='ok' if given == proposed else f'change to {proposed}') - if key: - result[key] = given + running = overview.get(key or proposed, {}).get('frappy') + if running == proposed: + remark = '' if given == running else 'reconnect' else: - addons.add(given) + remark = f'restart' + + itemdict.update(name=service, sea=seacfg, remark=remark) + if key: + result[key] = proposed + else: + addons.add(proposed) else: for item in available: - overview.setdefault(item, {}).update(name=item, remark='ambiguous', sea=seacfg) + overview.setdefault(item, {}).update(name=service, frappy=item, remark='ambiguous', sea=seacfg) error = True else: - overview.setdefault(key or seacfg, {}).update(name=key or '', sea=seacfg, remark='missing frappy config') + overview.setdefault(key or seacfg, {}).update(name=service, sea=seacfg, + remark='missing frappy config') error = True + restart = set() + for key, itemdict in overview.items(): + running = itemdict.get('frappy') + if running: + service = get_service(key) + if service == 'addons': + addons.add(running) + if not itemdict.get('sea'): + if sea_info.get(running): + restart.add(service) + itemdict['remark'] = f'restart to start sea' + elif itemdict.get('given') != running: + itemdict['remark'] = f'reconnect' if addons: result['addons'] = ','.join(addons) @@ -125,18 +156,17 @@ def make_proposed(givencfgs, ourcfgs, seacfgs, sea_info, strict=False): result = {} else: for service, cfg in ourcfgs.items(): - key = cfg if service is 'addons' else service if cfg: prop = result.get(service, '') - if prop == cfg: + if prop == cfg and service not in restart: result[service] = True columns = ['name', 'given', 'frappy', 'sea', 'remark'] - rows = [columns[:-1] + [' ']] + [[d.get(c) or '' for c in columns] for d in overview.values()] + rows = [['', giventitle, 'frappy', 'sea', '']] + [[d.get(c) or '' for c in columns] for d in overview.values()] wid = [max(len(v) for v in column) for column in zip(*rows)] # insert title lines - rows.insert(1, ['-' * w for w in wid]) - return result, [' '.join(v.ljust(w) for w, v in zip(wid, row)) for row in rows] + rows.insert(1, [''] + ['-' * w for w in wid[1:-1]] + ['']) + return result, [' '.join(v.ljust(w) for w, v in zip(wid, row)) for row in rows] class FrappyManager(ServiceManager): @@ -284,7 +314,8 @@ class FrappyManager(ServiceManager): :param service: service nor None for all services :param list_info: None or a dict to collect info in the form dict of of - :param sea_info: None or a dict of set() to be populated + :param sea_info: None or a dict of with info about sea configs + in frappy cfgs to be populated :return: set of available config """ all_cfg = set() @@ -305,6 +336,7 @@ class FrappyManager(ServiceManager): if cfg not in all_cfg: if sea_cfg and sea_info is not None: sea_info.setdefault(sea_cfg, set()).add(cfg) + sea_info[cfg] = sea_cfg all_cfg.add(cfg) if list_info is not None: list_info.setdefault(cfgdir, {})[cfg] = desc.split('\n', 1)[0] @@ -320,11 +352,10 @@ class FrappyManager(ServiceManager): else: for service in self.services: self.all_cfg(ins, service, list_info, sea_info) - sea_ambig = {} # collect info about ambiguous sea info seacfgpat = re.compile(r'(.*)(\.config|\.stick|\.addon)') - for seacfg, cfgset in sea_info.items(): - name, ext = seacfgpat.match(seacfg).groups() - sea_ambig.update({k: (name, ext, len(cfgset)) for k in cfgset}) + sea_ambig = {} # collect info about ambiguous sea info + for cfg, seacfg in sea_info.items(): + sea_ambig.setdefault(seacfg, set()).add(cfg) ambiguous = 0 keylen = max(max(len(k) for k in cfgs) for cfgs in list_info.values()) for cfgdir, cfgs in list_info.items(): @@ -332,12 +363,14 @@ class FrappyManager(ServiceManager): prt('') prt('--- %s:' % cfgdir) for cfg, desc in cfgs.items(): - if cfg in sea_ambig: - name, ext, n = sea_ambig[cfg] + seacfg = sea_info.get(cfg) + if seacfg: + name, ext = seacfgpat.match(seacfg).groups() if name == cfg or name + 'stick' == cfg: prefix = '* ' else: prefix = f'* ({name}{ext}) ' + n = len(sea_ambig.get(seacfg)) if n > 1: prefix = '!' + prefix[1:] ambiguous += 1 diff --git a/test_proposed.py b/test_proposed.py index 2cf3c29..4aafb58 100644 --- a/test_proposed.py +++ b/test_proposed.py @@ -2,10 +2,13 @@ import pytest from servicemanager.frappyman import make_proposed sea_info = { - 'ma10.config': {'ma10'}, - 'ma10.stick': {'ma10stick', 'ma10'}, - 'rt.addon': {'rt', 'roomt'}, - 'befilter.addon': {'befilter'}, + 'ma10': 'ma10.config', + 'ma10stick': 'ma10.stick', + 'ma11': 'ma11.config', + 'ma11stick': 'ma11.stick', + 'roomt': 'rt.addon', + 'rt': 'rt.addon', + 'befilter': 'befilter.addon', } given = dict(main='ma10', stick='ma10stick') @@ -22,3 +25,9 @@ def test_proposed(given, current, seacfg, output, proposed, proposedstrict): props, overview = make_proposed(given, current, seacfg, sea_info, True) assert overview == output assert props == proposedstrict + + +def do(): + prop, tab = make_proposed(given, cfgs, seacfg, sea_info) + print(prop) + print('\n'.join(tab)) \ No newline at end of file