def load(self): global reqtree self._document = reqtree.find_document(self._docId) # Requirements attributes # ----------------------- # # Requirements attributes will be the column names in the table view. # # There are: # - standard attributes # - extended attributes (within single requirement) # - extended attributes with defaults (declared in document) # - extended attributes that concur to review timestamp (declared in document) # # Attribute names are the keys of items[x]._data # We do a first loop to gather all user-defined attributes # Standard data (pulled from doorstop.item inspection) stdHeaderData = { 'path', 'root', 'active', 'normative', 'uid', 'level', 'header', 'text', 'derived', 'ref', 'references', 'reviewed', 'links' } headerData = [] for item in iter_items(self._document): headerData += list(item._data.keys()) headerData = list(set(headerData)) # drop duplicates # Non-standard data that we will display in more columns: userHeaderData = set(headerData) - stdHeaderData if userHeaderData: log.debug('[' + str(self._document) + '] Custom requirements attributes: ' + str(userHeaderData)) # And we have now the column names. # We put 'text' always to the last column because it usually is stretched. # The 'active' field is always true - inactive requirements are not shown at all. Doorstop doesn't tell us about them. self._headerData = [ 'uid', 'path', 'root', 'normative', 'derived', 'reviewed', 'level', 'header', 'ref', 'references', 'links' ] + list(userHeaderData) + ['text'] # Another loop to fill in the table rows self._data = [] for item in iter_items(self._document): row = [] for f in self._headerData: row.append(str(item.get(f))) row.append(item) # Doorstop item reference cached in the last row self._data.append(row) log.debug('[' + str(self._document) + '] Requirements reloaded')
def _table_of_contents_md(obj, linkify=None): toc = '### Table of Contents\n\n' for item in iter_items(obj): if item.depth == 1: prefix = ' * ' else: prefix = ' ' * (item.depth - 1) prefix += '* ' if item.heading: lines = item.text.splitlines() heading = lines[0] if lines else '' elif item.header: heading = "{h}".format(h=item.header) else: heading = item.uid if settings.PUBLISH_HEADING_LEVELS: level = _format_level(item.level) lbl = '{lev} {h}'.format(lev=level, h=heading) else: lbl = heading if linkify: line = '{p}[{lbl}](#{uid})\n'.format(p=prefix, lbl=lbl, uid=item.uid) else: line = '{p}{lbl}\n'.format(p=prefix, lbl=lbl) toc += line return toc
def _lines_text(obj, indent=8, width=79, **_): """Yield lines for a text report. :param obj: Item, list of Items, or Document to publish :param indent: number of spaces to indent text :param width: maximum line length :return: iterator of lines of text """ for item in iter_items(obj): level = _format_level(item.level) if item.heading: # Level and Text if settings.PUBLISH_HEADING_LEVELS: yield "{l:<{s}}{t}".format(l=level, s=indent, t=item.text) else: yield "{t}".format(t=item.text) else: # Level and UID yield "{l:<{s}}{u}".format(l=level, s=indent, u=item.uid) # Text if item.text: yield "" # break before text for line in item.text.splitlines(): yield from _chunks(line, width, indent) if not line: # pragma: no cover (integration test) yield "" # break between paragraphs # Reference if item.ref: yield "" # break before reference ref = _format_text_ref(item) yield from _chunks(ref, width, indent) # Links if item.links: yield "" # break before links if settings.PUBLISH_CHILD_LINKS: label = "Parent links: " else: label = "Links: " slinks = label + ', '.join(str(l) for l in item.links) yield from _chunks(slinks, width, indent) if settings.PUBLISH_CHILD_LINKS: links = item.find_child_links() if links: yield "" # break before links slinks = "Child links: " + ', '.join(str(l) for l in links) yield from _chunks(slinks, width, indent) yield "" # break between items
def _lines_text(obj, indent=8, width=79, **_): """Yield lines for a text report. :param obj: Item, list of Items, or Document to publish :param indent: number of spaces to indent text :param width: maximum line length :return: iterator of lines of text """ for item in iter_items(obj): level = _format_level(item.level) if item.heading: # Level and Text yield "{l:<{s}}{t}".format(l=level, s=indent, t=item.text) else: # Level and UID yield "{l:<{s}}{u}".format(l=level, s=indent, u=item.uid) # Text if item.text: yield "" # break before text for line in item.text.splitlines(): yield from _chunks(line, width, indent) if not line: # pragma: no cover (integration test) yield "" # break between paragraphs # Reference if item.ref: yield "" # break before reference ref = _format_text_ref(item) yield from _chunks(ref, width, indent) # Links if item.links: yield "" # break before links if settings.PUBLISH_CHILD_LINKS: label = "Parent links: " else: label = "Links: " slinks = label + ', '.join(str(l) for l in item.links) yield from _chunks(slinks, width, indent) if settings.PUBLISH_CHILD_LINKS: links = item.find_child_links() if links: yield "" # break before links slinks = "Child links: " + ', '.join(str(l) for l in links) yield from _chunks(slinks, width, indent) yield "" # break between items
def _lines_yaml(obj, **_): """Yield lines for a YAML export. :param obj: Item, list of Items, or Document to export :return: iterator of lines of text """ for item in iter_items(obj): data = {str(item.uid): item.data} text = yaml.dump(data, default_flow_style=False, allow_unicode=True) yield text
def _lines_yaml(obj): """Yield lines for a YAML export. :param obj: Item, list of Items, or Document to export :return: iterator of lines of text """ for item in iter_items(obj): data = {str(item.uid): item.data} text = yaml.dump(data, default_flow_style=False, allow_unicode=True) yield text
def _tabulate(obj, sep=LIST_SEP, auto=False): """Yield lines of header/data for tabular export. :param obj: Item, list of Items, or Document to export :param sep: string separating list values when joined in a string :param auto: include placeholders for new items on import :return: iterator of rows of data """ yield_header = True for item in iter_items(obj): data = item.data # Yield header if yield_header: header = ['level', 'text', 'ref', 'links'] for value in sorted(data.keys()): if value not in header: header.append(value) yield ['uid'] + header yield_header = False # Yield row row = [item.uid] for key in header: value = data.get(key) if key == 'level': # some levels are floats for YAML presentation value = str(value) elif key == 'links': # separate identifiers with a delimiter value = sep.join(uid.string for uid in item.links) elif isinstance(value, str) and key not in ('reviewed', ): # remove sentence boundaries and line wrapping value = item.get(key) elif value is None: value = '' row.append(value) yield row # Yield placeholders for new items if auto: for _ in range(settings.PLACEHOLDER_COUNT): yield [settings.PLACEHOLDER]
def _tabulate(obj, sep=LIST_SEP, auto=False): """Yield lines of header/data for tabular export. :param obj: Item, list of Items, or Document to export :param sep: string separating list values when joined in a string :param auto: include placeholders for new items on import :return: iterator of rows of data """ yield_header = True for item in iter_items(obj): data = item.data # Yield header if yield_header: header = ['level', 'text', 'ref', 'links'] for value in sorted(data.keys()): if value not in header: header.append(value) yield ['uid'] + header yield_header = False # Yield row row = [item.uid] for key in header: value = data.get(key) if key == 'level': # some levels are floats for YAML presentation value = str(value) elif key == 'links': # separate identifiers with a delimiter value = sep.join(uid.string for uid in item.links) elif isinstance(value, str) and key not in ('reviewed',): # remove sentence boundaries and line wrapping value = item.get(key) elif value is None: value = '' row.append(value) yield row # Yield placeholders for new items if auto: for _ in range(settings.PLACEHOLDER_COUNT): yield [settings.PLACEHOLDER]
def _tabulate(obj, sep=LIST_SEP): """Yield lines of header/data for tabular export. :param obj: Item, list of Items, or Document to export :param sep: string separating list values when joined in a string :return: iterator of rows of data """ yield_header = True for item in iter_items(obj): data = item.data # Yield header if yield_header: header = ['level', 'text', 'ref', 'links'] for value in sorted(data.keys()): if value not in header: header.append(value) yield ['uid'] + header yield_header = False # Yield row row = [item.uid] for key in header: value = data.get(key) if key == 'level': # some levels are floats for YAML presentation value = str(value) elif key == 'links': # separate identifiers with a delimiter value = sep.join(uid.string for uid in item.links) elif value is None: value = '' row.append(value) yield row
def _lines_markdown(obj, linkify=False): """Yield lines for a Markdown report. :param obj: Item, list of Items, or Document to publish :param linkify: turn links into hyperlinks (for conversion to HTML) :return: iterator of lines of text """ for item in iter_items(obj): heading = '#' * item.depth level = _format_level(item.level) if item.heading: # Level and Text standard = "{h} {l} {t}".format(h=heading, l=level, t=item.text) attr_list = _format_md_attr_list(item, linkify) yield standard + attr_list else: # Level and UID if settings.PUBLISH_BODY_LEVELS: standard = "{h} {l} {u}".format(h=heading, l=level, u=item.uid) else: standard = "{h} {u}".format(h=heading, u=item.uid) attr_list = _format_md_attr_list(item, linkify) yield standard + attr_list # Text if item.text: yield "" # break before text yield from item.text.splitlines() # Reference if item.ref: yield "" # break before reference yield _format_md_ref(item) # Parent links if item.links: yield "" # break before links items2 = item.parent_items if settings.PUBLISH_CHILD_LINKS: label = "Parent links:" else: label = "Links:" links = _format_md_links(items2, linkify) label_links = _format_md_label_links(label, links, linkify) yield label_links # Child links if settings.PUBLISH_CHILD_LINKS: items2 = item.find_child_items() if items2: yield "" # break before links label = "Child links:" links = _format_md_links(items2, linkify) label_links = _format_md_label_links(label, links, linkify) yield label_links yield "" # break between items
def _lines_markdown(obj, **kwargs): """Yield lines for a Markdown report. :param obj: Item, list of Items, or Document to publish :param linkify: turn links into hyperlinks (for conversion to HTML) :return: iterator of lines of text """ linkify = kwargs.get('linkify', False) for item in iter_items(obj): heading = '#' * item.depth level = _format_level(item.level) if item.heading: text_lines = item.text.splitlines() # Level and Text if settings.PUBLISH_HEADING_LEVELS: standard = "{h} {lev} {t}".format( h=heading, lev=level, t=text_lines[0] if text_lines else '') else: standard = "{h} {t}".format(h=heading, t=text_lines[0] if text_lines else '') attr_list = _format_md_attr_list(item, True) yield standard + attr_list yield from text_lines[1:] else: uid = item.uid if settings.ENABLE_HEADERS: if item.header: uid = '{h} <small>{u}</small>'.format(h=item.header, u=item.uid) else: uid = '{u}'.format(u=item.uid) # Level and UID if settings.PUBLISH_BODY_LEVELS: standard = "{h} {lev} {u}".format(h=heading, lev=level, u=uid) else: standard = "{h} {u}".format(h=heading, u=uid) attr_list = _format_md_attr_list(item, True) yield standard + attr_list # Text if item.text: yield "" # break before text yield from item.text.splitlines() # Reference if item.ref: yield "" # break before reference yield _format_md_ref(item) # Parent links if item.links: yield "" # break before links items2 = item.parent_items if settings.PUBLISH_CHILD_LINKS: label = "Parent links:" else: label = "Links:" links = _format_md_links(items2, linkify) label_links = _format_md_label_links(label, links, linkify) yield label_links # Child links if settings.PUBLISH_CHILD_LINKS: items2 = item.find_child_items() if items2: yield "" # break before links label = "Child links:" links = _format_md_links(items2, linkify) label_links = _format_md_label_links(label, links, linkify) yield label_links yield "" # break between items
def _lines_markdown(obj, **kwargs): """Yield lines for a Markdown report. :param obj: Item, list of Items, or Document to publish :param linkify: turn links into hyperlinks (for conversion to HTML) :return: iterator of lines of text """ linkify = kwargs.get('linkify', False) for item in iter_items(obj): heading = '#' * item.depth level = _format_level(item.level) if item.heading: text_lines = item.text.splitlines() # Level and Text if settings.PUBLISH_HEADING_LEVELS: standard = "{h} {lev} {t}".format( h=heading, lev=level, t=text_lines[0] if text_lines else '' ) else: standard = "{h} {t}".format( h=heading, t=text_lines[0] if text_lines else '' ) attr_list = _format_md_attr_list(item, True) yield standard + attr_list yield from text_lines[1:] else: uid = item.uid if settings.ENABLE_HEADERS: if item.header: uid = '{h} <small>{u}</small>'.format(h=item.header, u=item.uid) else: uid = '{u}'.format(u=item.uid) # Level and UID if settings.PUBLISH_BODY_LEVELS: standard = "{h} {lev} {u}".format(h=heading, lev=level, u=uid) else: standard = "{h} {u}".format(h=heading, u=uid) attr_list = _format_md_attr_list(item, True) yield standard + attr_list # Text if item.text: yield "" # break before text yield from item.text.splitlines() # Reference if item.ref: yield "" # break before reference yield _format_md_ref(item) # Parent links if item.links: yield "" # break before links items2 = item.parent_items if settings.PUBLISH_CHILD_LINKS: label = "Parent links:" else: label = "Links:" links = _format_md_links(items2, linkify) label_links = _format_md_label_links(label, links, linkify) yield label_links # Child links if settings.PUBLISH_CHILD_LINKS: items2 = item.find_child_items() if items2: yield "" # break before links label = "Child links:" links = _format_md_links(items2, linkify) label_links = _format_md_label_links(label, links, linkify) yield label_links yield "" # break between items
def _tabulate(obj, sep=LIST_SEP, auto=False): """Yield lines of header/data for tabular export. :param obj: Item, list of Items, or Document to export :param sep: string separating list values when joined in a string :param auto: include placeholders for new items on import :return: iterator of rows of data """ header = ['level', 'text', 'ref', 'links'] # 'at_least_one_ref' detects if at least one of the items still have a deprecated 'ref' field. # If there is none, 'ref' header is excluded from the headers and is not exported. at_least_one_ref = False for item in iter_items(obj): data = item.data for value in sorted(data.keys()): if value not in header: header.append(value) ref_value = data.get('ref') if ref_value: at_least_one_ref = True try: reference_index = header.index('references') # Inserting 'references' header after the 'ref' header. header.insert(3, header.pop(reference_index)) if not at_least_one_ref: header.remove('ref') except ValueError: pass yield ['uid'] + header for item in iter_items(obj): data = item.data # Yield row row = [item.uid] for key in header: value = data.get(key) if key == 'level': # some levels are floats for YAML presentation value = str(value) elif key == 'links': # separate identifiers with a delimiter value = sep.join(uid.string for uid in item.links) elif key == 'references': if value is None: value = '' else: ref_strings = [] for ref_item in value: ref_type = ref_item['type'] ref_path = ref_item['path'] ref_string = "type:{},path:{}".format( ref_type, ref_path) if 'keyword' in ref_item: keyword = ref_item['keyword'] ref_string += ",keyword:{}".format(keyword) ref_strings.append(ref_string) value = '\n'.join(ref_string for ref_string in ref_strings) elif isinstance(value, str) and key not in ('reviewed', ): # remove sentence boundaries and line wrapping value = item.get(key) elif value is None: value = '' row.append(value) yield row # Yield placeholders for new items if auto: for _ in range(settings.PLACEHOLDER_COUNT): yield [settings.PLACEHOLDER]