From 581044887a16d37c90116da544f5d9d600faa80c Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 17 Sep 2024 16:56:36 +0200 Subject: more fixes for reqs2tex --- scripts/reqs2tex.py | 103 ++++++++++++++++++++++++++++++++++------------------ scripts/tex.py | 3 -- 2 files changed, 68 insertions(+), 38 deletions(-) diff --git a/scripts/reqs2tex.py b/scripts/reqs2tex.py index 6b7b77a..db7e174 100755 --- a/scripts/reqs2tex.py +++ b/scripts/reqs2tex.py @@ -1,17 +1,47 @@ #!/bin/python3 import sys, tomllib, tex - +from enum import StrEnum + +def label2ref(*labels): + return ",".join(["req:" + label.replace('.', ':') for label in labels]) + +class KEY(StrEnum): + LABEL = 'label' + TYPE = 'type' + ID = 'id' + INDEX = 'index' + DELETED = 'deleted' + DONE = 'done' + DESCRIPTION = 'description' + PRIORITY = 'priority' + +class REQ_TYPE(StrEnum): + SYSTEM = 'system' + USER = 'user' + +class REQ_PRIORITY(StrEnum): + MUST = 'must' + SHOULD = 'should' + COULD = 'could' + WONT = 'will not' + +# this doesn't work right def flatten(data): - if 'description' in data: - return [ data ] out = [] + # this key is a requirement + if KEY.DESCRIPTION in data: + out.append(data) + # check for children for key, value in data.items(): + # skip over reserved keys + if key in KEY: continue + items = flatten(value) for item in items: - if 'label' in item: - item['label'] = f"{key}.{item['label']}" + if KEY.LABEL in item: + item[KEY.LABEL] = f"{key}.{item[KEY.LABEL]}" else: - item['label'] = f"{key}" + item[KEY.LABEL] = f"{key}" out += items return out @@ -20,72 +50,75 @@ def make_id(item): global id_counter id_counter += 1 return "{type_short}#{counter:03d}".format( - type_short = item['type'][0].upper(), + type_short = item[KEY.TYPE][0].upper(), counter = id_counter, ) def sanitize(item, ids): def die(msg): - print(f"[{item['label']}]: {msg}") + print(f"[{item[KEY.LABEL]}]: {msg}") exit(1) # ensure properties - item['description'] = item.get('description') - item['done'] = item.get('done') - item['priority'] = item.get('priority') - item['type'] = item.get('type') + item[KEY.DESCRIPTION] = item.get(KEY.DESCRIPTION) + item[KEY.DONE] = item.get(KEY.DONE) + item[KEY.PRIORITY] = item.get(KEY.PRIORITY) + item[KEY.TYPE] = item.get(KEY.TYPE) # type checks - if item['type'] not in ['system', 'user']: - die(f"unknown or missing requirement type {repr(item['type'])}") - if item['priority'] not in ['must', 'should', 'could', 'will not']: - die(f"unknown or missing requirement priority {repr(item['type'])}") + if item[KEY.TYPE] not in REQ_TYPE: + die(f"unknown or missing requirement type: {repr(item[KEY.TYPE])}") + if item[KEY.PRIORITY] not in REQ_PRIORITY: + die(f"unknown or missing requirement priority: {repr(item[KEY.PRIORITY])}") # conversions - if isinstance(item['done'], list): + if isinstance(item[KEY.DONE], list): # safety check - if not set(item['done']).issubset(ids): + if not set(item[KEY.DONE]).issubset(ids): die("definition of done includes unknown requirement(s)") - item['done'] = tex.cmd('Cref', tex.label2ref(*item['done'])) + item[KEY.DONE] = tex.cmd('Cref', label2ref(*item[KEY.DONE])) def convert(data): reqs = flatten(data) + all_ids = [item[KEY.LABEL] for item in reqs] index = 0 for item in reqs: - item['id'] = tex.esc(make_id(item)) - item['deleted'] = item.get('deleted', False) - if item['deleted']: continue - item['index'] = index + item[KEY.ID] = tex.esc(make_id(item)) + item[KEY.DELETED] = item.get(KEY.DELETED, False) + if item[KEY.DELETED]: continue + item[KEY.INDEX] = index index += 1 - sanitize(item, [req['label'] for req in reqs]) + sanitize(item, all_ids) # skip deleted requirements (but process for make_id) - reqs = [item for item in reqs if item['deleted'] == False] + reqs = [item for item in reqs if item[KEY.DELETED] == False] return reqs def fmt_aux(data): out = [] - for req in data: - ref = tex.label2ref(req['label']) + for item in data: + ref = label2ref(item[KEY.LABEL]) out += [ - tex.cmd('newlabel', f"{ref}", tex.group(req['id'], req['id'], 'ggg', 'hhh', 'iii')), - tex.cmd('newlabel', f"{ref}@cref", tex.group(f"[requirement][aaa][bbb]{req['id']}", '[ccc][ddd][eee]fff')), + tex.cmd('newlabel', f"{ref}", tex.group(item[KEY.ID], item[KEY.ID], 'ggg', 'hhh', 'iii')), + tex.cmd('newlabel', f"{ref}@cref", tex.group(f"[requirement][aaa][bbb]{item[KEY.ID]}", '[ccc][ddd][eee]fff')), ] return "\n".join(out) def fmt_tex(data): out = [] - for req in data: + for item in data: out.append( - tex.cmd('subsection', req['id']) + "\n\n" +\ + tex.cmd('subsection', item[KEY.ID]) +\ + tex.cmd('label', label2ref(item[KEY.LABEL])) +\ + tex.cmd('par') +\ tex.env('description', - tex.cmd('item', ['Priority']) + req['priority'].title() +\ - tex.cmd('item', ['Requirement']) + req['description'] +\ - (tex.cmd('item', ['Definition of done']) + req['done'] if req['done'] is not None else "") + tex.cmd('item', ['Priority']) + item[KEY.PRIORITY].title() +\ + tex.cmd('item', ['Requirement']) + item[KEY.DESCRIPTION] +\ + (tex.cmd('item', ['Definition of done']) + item[KEY.DONE] if item[KEY.DONE] is not None else "") ) ) - return "\n\n".join(out) + return "".join(out) def main(input_file): data = {} diff --git a/scripts/tex.py b/scripts/tex.py index 2509a87..59c6895 100644 --- a/scripts/tex.py +++ b/scripts/tex.py @@ -47,6 +47,3 @@ def esc(plain): def tabrule(*cells): return "&".join(cells) + "\\\\" -def label2ref(*labels): - return ",".join(["req:" + label.replace('.', ':') for label in labels]) - -- cgit v1.2.3