Example #1
0
    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')
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
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
Example #8
0
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]
Example #9
0
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]
Example #10
0
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
Example #11
0
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
Example #12
0
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
Example #13
0
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
Example #14
0
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
Example #15
0
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]