def tabulate(data,  # type: List[List[Any]]
             header=None,  # type: Optional[List[Any]]
             col_align=None,  # type: Union[str, List[str]]
             ):
    # type: (...) -> List[str]
    """ Format data as a table without any fancy features.
    col_align: l/r/c or a list/string of l/r/c. l = left, r = right, c = center
    Return a list of strings (lines of the table).
    """
    if not data and not header:
        return []
    if data:
        n_cols = len(data[0])
    else:
        assert header is not None
        n_cols = len(header)
    if not all(len(row) == n_cols for row in data):
        raise ValueError('data is not rectangular')

    if col_align is None:
        col_align = ['l'] * n_cols
    elif isinstance(col_align, six.string_types) and len(col_align) == 1:
        col_align = [col_align] * n_cols
    else:
        col_align = list(col_align)
        if len(col_align) != n_cols:
            raise ValueError('col_align length does not match number of columns')

    if header and len(header) != n_cols:
        raise ValueError('header length does not match number of columns')

    if header:
        data = [header] + data
    data = [[six.text_type(x) for x in row] for row in data]
    col_width = [max(len(row[col_i]) for row in data) for col_i in range(n_cols)]
    if header:
        data.insert(1, ['-' * width for width in col_width])

    line_tpl = u'  '.join(
        u'{:%s%s}' % ({'l': '', 'r': '>', 'c': '^'}[align], width)
        for align, width in zip(col_align, col_width))
    return [line_tpl.format(*row) for row in data]
def tabulate ( data , header = None , col_align = None , ) : if not data and not header : return [ ] if data : n_cols = len ( data [ 0 ] ) else : assert header is not None n_cols = len ( header ) if not all ( len ( row ) == n_cols for row in data ) : raise ValueError ( 'data is not rectangular' ) if col_align is None : col_align = [ 'l' ] * n_cols elif isinstance ( col_align , six . string_types ) and len ( col_align ) == 1 : col_align = [ col_align ] * n_cols else : col_align = list ( col_align ) if len ( col_align ) != n_cols : raise ValueError ( 'col_align length does not match number of columns' ) if header and len ( header ) != n_cols : raise ValueError ( 'header length does not match number of columns' ) if header : data = [ header ] + data data = [ [ six . text_type ( x ) for x in row ] for row in data ] col_width = [ max ( len ( row [ col_i ] ) for row in data ) for col_i in range ( n_cols ) ] if header : data . insert ( 1 , [ '-' * width for width in col_width ] ) line_tpl = u'  ' . join ( u'{:%s%s}' % ( { 'l' : '' , 'r' : '>' , 'c' : '^' } [ align ] , width ) for align , width in zip ( col_align , col_width ) ) return [ line_tpl . format ( * row ) for row in data ]
Format data as a table without any fancy features.
    col_align: l/r/c or a list/string of l/r/c. l = left, r = right, c = center
    Return a list of strings (lines of the table).