#!/bin/python3 ''' Class and utilities to parse and export examples of data models in TOSCA ''' import re import traceback from docx.text.paragraph import Paragraph from docx.table import Table class Example(): def __init__(self, filename, text): self.filename = filename self.text = text def is_start_of_example(line: str): ''' Returns true if the line marks the start of an examples. Check if lines starts with "tosca_definitions_version:" ''' if not isinstance(line, str): raise ValueError("NOT A STRING") return line.startswith("tosca_definitions_version:") def is_body_of_example(line: str): ''' Returns true if the line is part of the body of an example. ''' return line == "" or \ line.startswith("\n") or \ line.startswith(".") or \ line.startswith("#") or \ line.startswith(" ") or \ bool(re.match(r'^[a-zA-Z_]*:',line)) def is_last_line(line: str, txt): ''' Returns true if it is the last line of the text. ''' return line == txt[len(txt)-1] def get_example_file_name(line: str): ''' Looks for the YAML filename in the line of text ''' matches = re.search(r'[a-zA-Z0-9_.]*.yaml', line) if matches is not None: return matches.group(0) return "" def is_heading(txt :str): ''' Returns true if text is a heading, i.e. the text starts with 'A.' (Previously this predicate was used: ("Heading" in line.style.name) but not all headings have the correct style ''' return (txt.startswith("A.")) or (txt.startswith("E.")) def is_example_table(tab): return len(tab.rows) == 1 and len(tab.rows[0].cells) == 1 def parse_all_examples(txt): ''' Parses TOSCA examples. Txt is a list of Docx items (Paragraph, etc.). Returns a list of Example objects ''' res = [] new_example = "" filename = "" i = 1 clause = "" for line in txt: if isinstance(line, Paragraph): linetext = str(line.text) if is_heading(linetext): clause = linetext.split("\t")[0] i = 1 elif isinstance(line, Table): if is_example_table(line): linetext = str(line.rows[0].cells[0].text) elif isinstance(line, str): if line != '\r\n' and line != '\n': linetext = line else: continue if is_start_of_example(linetext): filename = get_example_file_name(previous_line) if filename == "": filename = "{:02d}".format(i) + ".yaml" i = i + 1 filename = clause+"-"+filename new_example = "# " + filename + "\n" + linetext elif new_example != "" and is_body_of_example(linetext): new_example = new_example + "\n" + linetext if is_last_line(line, txt): res.append(Example(filename, new_example)) elif len(new_example) > 0: res.append(Example(filename, new_example)) new_example = "" previous_line = linetext return res def generate_examples_between(a_id, b_id, content, EXAMPLES): try: examples = parse_all_examples(content[a_id:b_id]) except: track = traceback.format_exc() print(track) return 0 for example in examples: EXAMPLES[example.filename] = example return len(examples)