From 28489ce10a4b051fc7cbeffed2a5ee69055715e4 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Wed, 28 Sep 2022 15:37:07 +0200 Subject: [PATCH] Add the old state-parser It's ugly, not layered at all and even more PoC :-) --- stateparser.py | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 stateparser.py diff --git a/stateparser.py b/stateparser.py new file mode 100644 index 0000000..b9ca3c3 --- /dev/null +++ b/stateparser.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 + +# Simple as of now. + +import re + +def _dumbload(f) -> list[tuple[int, str]]: + """Loads file into list of lines with their indentations""" + tabs = re.compile(r'^\t*') + return [(tabs.match(line).end(), line[tabs.match(line).end():]) for line in f] + +def _load(f): + """Loads state file into tuples of the sections""" + dumb = _dumbload(f) + maxdepth = max(x[0] for x in dumb) + state = [None] * (maxdepth+1) + result = [] + for depth, line in dumb: + line = line.strip() + if line == '': continue + state[depth] = line + for x in range(depth+1, maxdepth+1): + state[x] = None + result.append(state.copy()) # It's all strings, so OK. + return result + +def load(f) -> dict[tuple[str, str], list[str]]: + """Loads state file into dictionaries area+router/network -> list of parameters""" + # FIXME: Shouldn't we just create a ton of ordered dictionaries? + # i.e. area -> router -> param -> None; all string. + params = _load(f) + result = {} + for x in params: + if x[-1] is None: continue # FIXME: Not working for general output. + k = (x[0], x[1]) + if k not in result: + result[k] = [] + result[k].append(' '.join(x[2:])) + return result + +def create_graph(d): + """takes the dict from load() and returns list of edges. + + The graph is bipartite, one part is the routers, other is the networks""" + edges = [] + names = {} + for k, v in d.items(): + v1 = k[1] + for l in v: + # UGLY! + if v1.startswith('router') and l.startswith(('network', 'stubnet', 'external')): + m = re.match(r'^([^ ]+ [^ ]+) metric ([0-9]+)$', l) + v2 = m.group(1) + metric = int(m.group(2)) + edges.append((v1, v2, metric)) + if v1.startswith('network') and l.startswith('address'): + names[v1] = l + # NOTE: Not all networks have reasonable address (external, stubnets), so they will not be listed. + return edges, names + +if __name__ == '__main__': + #from pprint import pprint + #pprint(create_graph(load(open('state')))) + edges, names = create_graph(load(open('state'))) + + # Prologue: + print(r'graph "Visualisation" {') + + for edge in edges: + print(f'"{edge[0]}" -- "{edge[1]}" [label={edge[2]}];') + + for ident,name in names.items(): + print(f'"{ident}" [label="{name}"]') + # Dot falls back to vertex name, so this solves the missing keys in names. + + # Epi: + print('}')