diff --git a/src/.gitignore b/src/.gitignore index 2d7c3ea..3000943 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,2 +1,2 @@ __pycache__/ -_output/ +_test/ diff --git a/src/batch.py b/src/batch.py new file mode 100644 index 0000000..aee9322 --- /dev/null +++ b/src/batch.py @@ -0,0 +1,7 @@ +import yaml2wireviz + +# TODO: make examples (progressively more complex), batch process all of them +yaml2wireviz.parse('../examples/example1.yml') +yaml2wireviz.parse('../examples/example2.yml') +yaml2wireviz.parse('../examples/ferrules.yml') +yaml2wireviz.parse('../examples/bundles.yml') diff --git a/src/yaml2wireviz.py b/src/yaml2wireviz.py old mode 100644 new mode 100755 index 2275e3c..2cab55f --- a/src/yaml2wireviz.py +++ b/src/yaml2wireviz.py @@ -1,18 +1,8 @@ +#!/usr/bin/env python3 +import os import yaml import wireviz -filename = '../examples/example1.yml' -filename = '../examples/example2.yml' -filename = '../examples/ferrules.yml' -filename = '../examples/bundles.yml' - -def check_designators(what, where): - for i, x in enumerate(what): - # print('Looking for {} in {}'.format(x,where[i])) - if x not in input[where[i]]: - return False - return True - def expand(input): # input can be: # - a singleton (normally str or int) @@ -41,140 +31,170 @@ def expand(input): output.append(x) return output -with open(filename, 'r') as stream: - try: - input = yaml.safe_load(stream) - except yaml.YAMLError as exc: - print(exc) +def _parse(file_in, file_out): -h = wireviz.Harness() + def check_designators(what, where): + for i, x in enumerate(what): + # print('Looking for {} in {}'.format(x,where[i])) + if x not in input[where[i]]: + return False + return True -# add items -sections = ['nodes','wires','ferrules','connections'] -types = [dict, dict, dict, list] -for sec, ty in zip(sections, types): - if sec in input and type(input[sec]) == ty: - if len(input[sec]) > 0: - if ty == dict: - for k, o in input[sec].items(): - if sec == 'nodes': - h.add_node(name=k, **o) - elif sec == 'wires': - h.add_cable(name=k, **o) - elif sec == 'ferrules': - pass + with open(file_in, 'r') as stream: + try: + input = yaml.safe_load(stream) + except yaml.YAMLError as exc: + print(exc) + + h = wireviz.Harness() + + # add items + sections = ['nodes','wires','ferrules','connections'] + types = [dict, dict, dict, list] + for sec, ty in zip(sections, types): + if sec in input and type(input[sec]) == ty: + if len(input[sec]) > 0: + if ty == dict: + for k, o in input[sec].items(): + if sec == 'nodes': + h.add_node(name=k, **o) + elif sec == 'wires': + h.add_cable(name=k, **o) + elif sec == 'ferrules': + pass + else: + print('{} section empty'.format(sec)) else: - print('{} section empty'.format(sec)) - else: - print('No {} section found'.format(sec)) - if ty == dict: - input[sec] = {} - elif ty == list: - input[sec] = [] + print('No {} section found'.format(sec)) + if ty == dict: + input[sec] = {} + elif ty == list: + input[sec] = [] -# add connections -ferrule_counter = 0 -for con in input['connections']: - if len(con) == 3: # format: connector -- wire -- conector + # add connections + ferrule_counter = 0 + for con in input['connections']: + if len(con) == 3: # format: connector -- wire -- conector - for c in con: - if len(list(c.keys())) != 1: # check that each entry in con has only one key, which is the designator - raise Exception('Too many keys') - - from_name = list(con[0].keys())[0] - via_name = list(con[1].keys())[0] - to_name = list(con[2].keys())[0] - - if not check_designators([from_name,via_name,to_name],('nodes','wires','nodes')): - raise Exception('Bad connection definition (3)') - - from_pins = expand(con[0][from_name]) - via_pins = expand(con[1][via_name]) - to_pins = expand(con[2][to_name]) - - if len(from_pins) != len(via_pins) or len(via_pins) != len(to_pins): - raise Exception('List length mismatch') - - for (from_pin, via_pin, to_pin) in zip(from_pins, via_pins, to_pins): - h.connect(from_name, from_pin, via_name, via_pin, to_name, to_pin) - - elif len(con) == 2: - - for c in con: - if type(c) is dict: + for c in con: if len(list(c.keys())) != 1: # check that each entry in con has only one key, which is the designator raise Exception('Too many keys') - # hack to make the format for ferrules compatible with the formats for connectors and wires - if type(con[0]) == str: - name = con[0] - con[0] = {} - con[0][name] = name - if type(con[1]) == str: - name = con[1] - con[1] = {} - con[1][name] = name + from_name = list(con[0].keys())[0] + via_name = list(con[1].keys())[0] + to_name = list(con[2].keys())[0] - from_name = list(con[0].keys())[0] - to_name = list(con[1].keys())[0] + if not check_designators([from_name,via_name,to_name],('nodes','wires','nodes')): + raise Exception('Bad connection definition (3)') - n_w = check_designators([from_name, to_name],('nodes','wires')) - w_n = check_designators([from_name, to_name],('wires','nodes')) - n_n = check_designators([from_name, to_name],('nodes','nodes')) + from_pins = expand(con[0][from_name]) + via_pins = expand(con[1][via_name]) + to_pins = expand(con[2][to_name]) - - f_w = check_designators([from_name, to_name],('ferrules','wires')) - w_f = check_designators([from_name, to_name],('wires','ferrules')) - - if not n_w and not w_n and not n_n and not f_w and not w_f: - raise Exception('Wrong designators') - - from_pins = expand(con[0][from_name]) - to_pins = expand(con[1][to_name]) - - if n_w or w_n or n_n: - if len(from_pins) != len(to_pins): + if len(from_pins) != len(via_pins) or len(via_pins) != len(to_pins): raise Exception('List length mismatch') - if n_w or w_n: - for (from_pin, to_pin) in zip(from_pins, to_pins): - if n_w: - h.connect(from_name, from_pin, to_name, to_pin, None, None) - else: # w_n - h.connect(None, None, from_name, from_pin, to_name, to_pin) - elif n_n: - con_name = list(con[0].keys())[0] + for (from_pin, via_pin, to_pin) in zip(from_pins, via_pins, to_pins): + h.connect(from_name, from_pin, via_name, via_pin, to_name, to_pin) + + elif len(con) == 2: + + for c in con: + if type(c) is dict: + if len(list(c.keys())) != 1: # check that each entry in con has only one key, which is the designator + raise Exception('Too many keys') + + # hack to make the format for ferrules compatible with the formats for connectors and wires + if type(con[0]) == str: + name = con[0] + con[0] = {} + con[0][name] = name + if type(con[1]) == str: + name = con[1] + con[1] = {} + con[1][name] = name + + from_name = list(con[0].keys())[0] + to_name = list(con[1].keys())[0] + + n_w = check_designators([from_name, to_name],('nodes','wires')) + w_n = check_designators([from_name, to_name],('wires','nodes')) + n_n = check_designators([from_name, to_name],('nodes','nodes')) + + + f_w = check_designators([from_name, to_name],('ferrules','wires')) + w_f = check_designators([from_name, to_name],('wires','ferrules')) + + if not n_w and not w_n and not n_n and not f_w and not w_f: + raise Exception('Wrong designators') + from_pins = expand(con[0][from_name]) - to_pins = expand(con[1][to_name]) + to_pins = expand(con[1][to_name]) - for (from_pin, to_pin) in zip(from_pins, to_pins): - h.loop(con_name, from_pin, to_pin) - if f_w or w_f: - from_pins = expand(con[0][from_name]) - to_pins = expand(con[1][to_name]) + if n_w or w_n or n_n: + if len(from_pins) != len(to_pins): + raise Exception('List length mismatch') - if f_w: - ferrule_name = from_name - wire_name = to_name - wire_pins = to_pins - else: - ferrule_name = to_name - wire_name = from_name - wire_pins = from_pins + if n_w or w_n: + for (from_pin, to_pin) in zip(from_pins, to_pins): + if n_w: + h.connect(from_name, from_pin, to_name, to_pin, None, None) + else: # w_n + h.connect(None, None, from_name, from_pin, to_name, to_pin) + elif n_n: + con_name = list(con[0].keys())[0] + from_pins = expand(con[0][from_name]) + to_pins = expand(con[1][to_name]) - ferrule_params = input['ferrules'][ferrule_name] - for wire_pin in wire_pins: - ferrule_counter = ferrule_counter + 1 - ferrule_id = 'F{}'.format(ferrule_counter) - h.add_node(ferrule_id, **ferrule_params) + for (from_pin, to_pin) in zip(from_pins, to_pins): + h.loop(con_name, from_pin, to_pin) + if f_w or w_f: + from_pins = expand(con[0][from_name]) + to_pins = expand(con[1][to_name]) if f_w: - h.connect(ferrule_id, 1, wire_name, wire_pin, None, None) + ferrule_name = from_name + wire_name = to_name + wire_pins = to_pins else: - h.connect(None, None, wire_name, wire_pin, ferrule_id, 1) + ferrule_name = to_name + wire_name = from_name + wire_pins = from_pins + + ferrule_params = input['ferrules'][ferrule_name] + for wire_pin in wire_pins: + ferrule_counter = ferrule_counter + 1 + ferrule_id = 'F{}'.format(ferrule_counter) + h.add_node(ferrule_id, **ferrule_params) + + if f_w: + h.connect(ferrule_id, 1, wire_name, wire_pin, None, None) + else: + h.connect(None, None, wire_name, wire_pin, ferrule_id, 1) + else: + raise Exception('Wrong number of connection parameters') + + h.output(filename=file_out, format=('png','svg'), view=False) + +def parse(filename_in, filename_out=None): + fin = os.path.abspath(filename_in) + if filename_out: + fout = filename_out else: - raise Exception('Wrong number of connection parameters') + fout = fin + pre, ext = os.path.splitext(fout) + fout = pre # extension will be added by graphviz output function + fout = os.path.abspath(fout) -h.output(filename='output', format=('png','svg'), view=False) + _parse(fin, fout) + +if __name__ == '__main__': + import argparse + ap = argparse.ArgumentParser() + ap.add_argument('file_input', nargs='?', default='_test/test.yml') + ap.add_argument('file_output', nargs='?', default=None) + args = ap.parse_args() + + parse(args.file_input, args.file_output)