Beispiel #1
0
def write_source_line(w, line, nchar=0):
    part1 = xml_escape(line[:nchar].decode('utf-8'))
    char = xml_escape(line[nchar:nchar+1].decode('utf-8'))
    part2 = xml_escape(line[nchar+1:].decode('utf-8'))

    w.write('  ')
    w.write(part1)
    w.write('<span class="highlight">{}</span>'.format(char))
    w.write(part2)
    w.write('\n\n')
Beispiel #2
0
def write_source_line(w, line, nchar=0):
    part1 = xml_escape(line[:nchar].decode('utf-8'))
    char = xml_escape(line[nchar:nchar+1].decode('utf-8'))
    part2 = xml_escape(line[nchar+1:].decode('utf-8'))

    w.write('  ')
    w.write(part1)
    w.write(f'<span class="highlight">{char}</span>')
    w.write(part2)
    w.write('\n\n')
Beispiel #3
0
def test_escape_xml():
    s = writer.xml_escape('This & That')
    assert type(s) == str
    assert s == 'This &amp; That'

    s = writer.xml_escape(1)
    assert type(s) == str
    assert s == '1'

    s = writer.xml_escape(b'This & That')
    assert type(s) == bytes
    assert s == b'This &amp; That'
Beispiel #4
0
def write_votlint_warning(w, line, xml_lines):
    match = re.search(r"(WARNING|ERROR|INFO) \(l.(?P<line>[0-9]+), c.(?P<column>[0-9]+)\): (?P<rest>.*)", line)
    if match:
        w.write('Line {:d}: {}\n'.format(
                int(match.group('line')), xml_escape(match.group('rest'))))
        write_source_line(
            w, xml_lines[int(match.group('line')) - 1],
            int(match.group('column')) - 1)
    else:
        w.data(line)
        w.data('\n')
Beispiel #5
0
def write_votlint_warning(w, line, xml_lines):
    match = re.search(r"(WARNING|ERROR|INFO) \(l.(?P<line>[0-9]+), c.(?P<column>[0-9]+)\): (?P<rest>.*)", line)
    if match:
        w.write('Line {:d}: {}\n'.format(
                int(match.group('line')), xml_escape(match.group('rest'))))
        write_source_line(
            w, xml_lines[int(match.group('line')) - 1],
            int(match.group('column')) - 1)
    else:
        w.data(line)
        w.data('\n')
Beispiel #6
0
def write_warning(w, line, xml_lines):
    warning = exceptions.parse_vowarning(line)
    if not warning['is_something']:
        w.data(line)
    else:
        w.write(f"Line {warning['nline']:d}: ")
        if warning['warning']:
            w.write('<a href="{}/{}">{}</a>: '.format(
                online_docs_root, warning['doc_url'], warning['warning']))
        msg = warning['message']
        if not isinstance(warning['message'], str):
            msg = msg.decode('utf-8')
        w.write(xml_escape(msg))
        w.write('\n')
        if 1 <= warning['nline'] < len(xml_lines):
            write_source_line(w, xml_lines[warning['nline'] - 1], warning['nchar'])
Beispiel #7
0
def write_warning(w, line, xml_lines):
    warning = exceptions.parse_vowarning(line)
    if not warning['is_something']:
        w.data(line)
    else:
        w.write('Line {:d}: '.format(warning['nline']))
        if warning['warning']:
            w.write('<a href="{}/{}">{}</a>: '.format(
                online_docs_root, warning['doc_url'], warning['warning']))
        msg = warning['message']
        if not isinstance(warning['message'], str):
            msg = msg.decode('utf-8')
        w.write(xml_escape(msg))
        w.write('\n')
        if 1 <= warning['nline'] < len(xml_lines):
            write_source_line(w, xml_lines[warning['nline'] - 1], warning['nchar'])
Beispiel #8
0
    def _pformat_table(self, table, max_lines=None, max_width=None,
                       show_name=True, show_unit=None, show_dtype=False,
                       html=False, tableid=None, tableclass=None, align=None):
        """Return a list of lines for the formatted string representation of
        the table.

        Parameters
        ----------
        max_lines : int or None
            Maximum number of rows to output

        max_width : int or None
            Maximum character width of output

        show_name : bool
            Include a header row for column names. Default is True.

        show_unit : bool
            Include a header row for unit.  Default is to show a row
            for units only if one or more columns has a defined value
            for the unit.

        show_dtype : bool
            Include a header row for column dtypes. Default is False.

        html : bool
            Format the output as an HTML table. Default is False.

        tableid : str or None
            An ID tag for the table; only used if html is set.  Default is
            "table{id}", where id is the unique integer id of the table object,
            id(table)

        tableclass : str or list of str or `None`
            CSS classes for the table; only used if html is set.  Default is
            none

        align : str or list or tuple
            Left/right alignment of columns. Default is '>' (right) for all
            columns. Other allowed values are '<', '^', and '0=' for left,
            centered, and 0-padded, respectively. A list of strings can be
            provided for alignment of tables with multiple columns.

        Returns
        -------
        rows : list
            Formatted table as a list of strings

        outs : dict
            Dict which is used to pass back additional values
            defined within the iterator.

        """
        # "Print" all the values into temporary lists by column for subsequent
        # use and to determine the width
        max_lines, max_width = self._get_pprint_size(max_lines, max_width)
        cols = []

        if show_unit is None:
            show_unit = any(col.info.unit for col in table.columns.values())

        # Coerce align into a correctly-sized list of alignments (if possible)
        n_cols = len(table.columns)
        if align is None or isinstance(align, str):
            align = [align] * n_cols

        elif isinstance(align, (list, tuple)):
            if len(align) != n_cols:
                raise ValueError('got {} alignment values instead of '
                                 'the number of columns ({})'
                                 .format(len(align), n_cols))
        else:
            raise TypeError('align keyword must be str or list or tuple (got {})'
                            .format(type(align)))

        for align_, col in zip(align, table.columns.values()):
            lines, outs = self._pformat_col(col, max_lines, show_name=show_name,
                                            show_unit=show_unit, show_dtype=show_dtype,
                                            align=align_)
            if outs['show_length']:
                lines = lines[:-1]
            cols.append(lines)

        if not cols:
            return ['<No columns>'], {'show_length': False}

        # Use the values for the last column since they are all the same
        n_header = outs['n_header']

        n_rows = len(cols[0])

        def outwidth(cols):
            return sum(len(c[0]) for c in cols) + len(cols) - 1

        dots_col = ['...'] * n_rows
        middle = len(cols) // 2
        while outwidth(cols) > max_width:
            if len(cols) == 1:
                break
            if len(cols) == 2:
                cols[1] = dots_col
                break
            if cols[middle] is dots_col:
                cols.pop(middle)
                middle = len(cols) // 2
            cols[middle] = dots_col

        # Now "print" the (already-stringified) column values into a
        # row-oriented list.
        rows = []
        if html:
            from astropy.utils.xml.writer import xml_escape

            if tableid is None:
                tableid = 'table{id}'.format(id=id(table))

            if tableclass is not None:
                if isinstance(tableclass, list):
                    tableclass = ' '.join(tableclass)
                rows.append('<table id="{tid}" class="{tcls}">'.format(
                    tid=tableid, tcls=tableclass))
            else:
                rows.append(f'<table id="{tableid}">')

            for i in range(n_rows):
                # _pformat_col output has a header line '----' which is not needed here
                if i == n_header - 1:
                    continue
                td = 'th' if i < n_header else 'td'
                vals = ('<{}>{}</{}>'.format(td, xml_escape(col[i].strip()), td)
                        for col in cols)
                row = ('<tr>' + ''.join(vals) + '</tr>')
                if i < n_header:
                    row = ('<thead>' + row + '</thead>')
                rows.append(row)
            rows.append('</table>')
        else:
            for i in range(n_rows):
                row = ' '.join(col[i] for col in cols)
                rows.append(row)

        return rows, outs
Beispiel #9
0
    def _pformat_col(self, col, max_lines=None, show_name=True, show_unit=None,
                     show_dtype=False, show_length=None, html=False, align=None):
        """Return a list of formatted string representation of column values.

        Parameters
        ----------
        max_lines : int
            Maximum lines of output (header + data rows)

        show_name : bool
            Include column name. Default is True.

        show_unit : bool
            Include a header row for unit.  Default is to show a row
            for units only if one or more columns has a defined value
            for the unit.

        show_dtype : bool
            Include column dtype. Default is False.

        show_length : bool
            Include column length at end.  Default is to show this only
            if the column is not shown completely.

        html : bool
            Output column as HTML

        align : str
            Left/right alignment of columns. Default is '>' (right) for all
            columns. Other allowed values are '<', '^', and '0=' for left,
            centered, and 0-padded, respectively.

        Returns
        -------
        lines : list
            List of lines with formatted column values

        outs : dict
            Dict which is used to pass back additional values
            defined within the iterator.

        """
        if show_unit is None:
            show_unit = col.info.unit is not None

        outs = {}  # Some values from _pformat_col_iter iterator that are needed here
        col_strs_iter = self._pformat_col_iter(col, max_lines, show_name=show_name,
                                               show_unit=show_unit,
                                               show_dtype=show_dtype,
                                               show_length=show_length,
                                               outs=outs)

        col_strs = list(col_strs_iter)
        if len(col_strs) > 0:
            col_width = max(len(x) for x in col_strs)

        if html:
            from astropy.utils.xml.writer import xml_escape
            n_header = outs['n_header']
            for i, col_str in enumerate(col_strs):
                # _pformat_col output has a header line '----' which is not needed here
                if i == n_header - 1:
                    continue
                td = 'th' if i < n_header else 'td'
                val = '<{}>{}</{}>'.format(td, xml_escape(col_str.strip()), td)
                row = ('<tr>' + val + '</tr>')
                if i < n_header:
                    row = ('<thead>' + row + '</thead>')
                col_strs[i] = row

            if n_header > 0:
                # Get rid of '---' header line
                col_strs.pop(n_header - 1)
            col_strs.insert(0, '<table>')
            col_strs.append('</table>')

        # Now bring all the column string values to the same fixed width
        else:
            col_width = max(len(x) for x in col_strs) if col_strs else 1

            # Center line header content and generate dashed headerline
            for i in outs['i_centers']:
                col_strs[i] = col_strs[i].center(col_width)
            if outs['i_dashes'] is not None:
                col_strs[outs['i_dashes']] = '-' * col_width

            # Format columns according to alignment.  `align` arg has precedent, otherwise
            # use `col.format` if it starts as a legal alignment string.  If neither applies
            # then right justify.
            re_fill_align = re.compile(r'(?P<fill>.?)(?P<align>[<^>=])')
            match = None
            if align:
                # If there is an align specified then it must match
                match = re_fill_align.match(align)
                if not match:
                    raise ValueError("column align must be one of '<', '^', '>', or '='")
            elif isinstance(col.info.format, str):
                # col.info.format need not match, in which case rjust gets used
                match = re_fill_align.match(col.info.format)

            if match:
                fill_char = match.group('fill')
                align_char = match.group('align')
                if align_char == '=':
                    if fill_char != '0':
                        raise ValueError("fill character must be '0' for '=' align")
                    fill_char = ''  # str.zfill gets used which does not take fill char arg
            else:
                fill_char = ''
                align_char = '>'

            justify_methods = {'<': 'ljust', '^': 'center', '>': 'rjust', '=': 'zfill'}
            justify_method = justify_methods[align_char]
            justify_args = (col_width, fill_char) if fill_char else (col_width,)

            for i, col_str in enumerate(col_strs):
                col_strs[i] = getattr(col_str, justify_method)(*justify_args)

        if outs['show_length']:
            col_strs.append('Length = {} rows'.format(len(col)))

        return col_strs, outs