Repository: statsmodels/statsmodels

Issue:
SimpleTable: add repr html for ipython notebook
summary() can be displayed as html in an ipython notebook, but not a SimpleTable itself



Discussion:
this works for tukeyhsd  (based on ipython docs, nothing fancy)

```
from IPython.display import HTML
s = res2s_001.summary().as_html()
h = HTML(s); h
```

Same problem for the `t_test` summary() which returns a `SimpleTable`

`Summary` class has

```
def _repr_html_(self):
        '''Display as HTML in IPython notebook.'''
        return self.as_html()
```


Resolving patch:
diff --git a/statsmodels/iolib/table.py b/statsmodels/iolib/table.py
--- a/statsmodels/iolib/table.py
+++ b/statsmodels/iolib/table.py
@@ -75,7 +75,8 @@ def mylabeller(cell):
 :note: current version
 :note: HTML data format currently specifies tags
 :todo: support a bit more of http://www.oasis-open.org/specs/tr9503.html
-:todo: add labels2formatters method, that associates a cell formatter with a datatype
+:todo: add labels2formatters method, that associates a cell formatter with a
+       datatype
 :todo: add colspan support to Cell
 :since: 2008-12-21
 :change: 2010-05-02 eliminate newlines that came before and after table
@@ -83,14 +84,14 @@ def mylabeller(cell):
 """
 
 from __future__ import division
-from statsmodels.compat.python import (lmap, lrange, zip, next, iteritems, zip_longest,
-                                range)
+from statsmodels.compat.python import (lmap, lrange, zip, next, iteritems,
+                                       zip_longest, range)
 import logging
 
 from itertools import cycle
-from collections import defaultdict
 import csv
 
+
 def csv2st(csvfile, headers=False, stubs=False, title=None):
     """Return SimpleTable instance,
     created from the data in `csvfile`,
@@ -100,22 +101,19 @@ def csv2st(csvfile, headers=False, stubs=False, title=None):
     Can also supply headers and stubs as tuples of strings.
     """
     rows = list()
-    with open(csvfile,'r') as fh:
+    with open(csvfile, 'r') as fh:
         reader = csv.reader(fh)
         if headers is True:
-            try:
-                headers = next(reader)
-            except NameError: #must be Python 2.5 or earlier
-                headers = next(reader)
+            headers = next(reader)
         elif headers is False:
-            headers=()
+            headers = ()
         if stubs is True:
             stubs = list()
             for row in reader:
                 if row:
                     stubs.append(row[0])
                     rows.append(row[1:])
-        else: #no stubs, or stubs provided
+        else:  # no stubs, or stubs provided
             for row in reader:
                 if row:
                     rows.append(row)
@@ -123,7 +121,7 @@ def csv2st(csvfile, headers=False, stubs=False, title=None):
             stubs = ()
     nrows = len(rows)
     ncols = len(rows[0])
-    if any(len(row)!=ncols for row in rows):
+    if any(nrows != ncols for row in rows):
         raise IOError('All rows of CSV file must have same length.')
     return SimpleTable(data=rows, headers=headers, stubs=stubs)
 
@@ -155,10 +153,8 @@ class SimpleTable(list):
             fh.write( tbl.as_latex_tabular() )
     """
     def __init__(self, data, headers=None, stubs=None, title='',
-        datatypes=None,
-        csv_fmt=None, txt_fmt=None, ltx_fmt=None, html_fmt=None,
-        celltype= None, rowtype=None,
-        **fmt_dict):
+                 datatypes=None, csv_fmt=None, txt_fmt=None, ltx_fmt=None,
+                 html_fmt=None, celltype=None, rowtype=None, **fmt_dict):
         """
         Parameters
         ----------
@@ -187,21 +183,20 @@ def __init__(self, data, headers=None, stubs=None, title='',
         fmt_dict : dict
             general formatting options
         """
-        #self._raw_data = data
         self.title = title
         self._datatypes = datatypes or lrange(len(data[0]))
-        #start with default formatting
+        # start with default formatting
         self._txt_fmt = default_txt_fmt.copy()
         self._latex_fmt = default_latex_fmt.copy()
         self._csv_fmt = default_csv_fmt.copy()
         self._html_fmt = default_html_fmt.copy()
-        #substitute any general user specified formatting
-        #:note: these will be overridden by output specific arguments
+        # substitute any general user specified formatting
+        # :note: these will be overridden by output specific arguments
         self._csv_fmt.update(fmt_dict)
         self._txt_fmt.update(fmt_dict)
         self._latex_fmt.update(fmt_dict)
         self._html_fmt.update(fmt_dict)
-        #substitute any output-type specific formatting
+        # substitute any output-type specific formatting
         self._csv_fmt.update(csv_fmt or dict())
         self._txt_fmt.update(txt_fmt or dict())
         self._latex_fmt.update(ltx_fmt or dict())
@@ -211,17 +206,23 @@ def __init__(self, data, headers=None, stubs=None, title='',
             csv=self._csv_fmt,
             html=self._html_fmt,
             latex=self._latex_fmt
-            )
+        )
         self._Cell = celltype or Cell
         self._Row = rowtype or Row
         rows = self._data2rows(data)  # a list of Row instances
         list.__init__(self, rows)
         self._add_headers_stubs(headers, stubs)
         self._colwidths = dict()
+
     def __str__(self):
         return self.as_text()
+
     def __repr__(self):
         return str(type(self))
+
+    def _repr_html_(self, **fmt_dict):
+        return self.as_html(**fmt_dict)
+
     def _add_headers_stubs(self, headers, stubs):
         """Return None.  Adds headers and stubs to table,
         if these were provided at initialization.
@@ -238,6 +239,7 @@ def _add_headers_stubs(self, headers, stubs):
             self.insert_header_row(0, headers, dec_below='header_dec_below')
         if stubs:
             self.insert_stubs(0, stubs)
+
     def insert(self, idx, row, datatype=None):
         """Return None.  Insert a row into a table.
         """
@@ -248,13 +250,14 @@ def insert(self, idx, row, datatype=None):
                 pass
         row = self._Row(row, datatype=datatype, table=self)
         list.insert(self, idx, row)
+
     def insert_header_row(self, rownum, headers, dec_below='header_dec_below'):
         """Return None.  Insert a row of headers,
         where ``headers`` is a sequence of strings.
         (The strings may contain newlines, to indicated multiline headers.)
         """
         header_rows = [header.split('\n') for header in headers]
-        #rows in reverse order
+        # rows in reverse order
         rows = list(zip_longest(*header_rows, **dict(fillvalue='')))
         rows.reverse()
         for i, row in enumerate(rows):
@@ -263,6 +266,7 @@ def insert_header_row(self, rownum, headers, dec_below='header_dec_below'):
                 self[rownum].dec_below = dec_below
             else:
                 self[rownum].dec_below = None
+
     def insert_stubs(self, loc, stubs):
         """Return None.  Insert column of stubs at column `loc`.
         If there is a header row, it gets an empty cell.
@@ -277,10 +281,9 @@ def insert_stubs(self, loc, stubs):
             else:
                 try:
                     row.insert_stub(loc, next(stubs))
-                except NameError: #Python 2.5 or earlier
-                    row.insert_stub(loc, next(stubs))
                 except StopIteration:
                     raise ValueError('length of stubs must match table length')
+
     def _data2rows(self, raw_data):
         """Return list of Row,
         the raw data as rows of cells.
@@ -293,17 +296,16 @@ def _data2rows(self, raw_data):
             dtypes = cycle(self._datatypes)
             newrow = _Row(datarow, datatype='data', table=self, celltype=_Cell)
             for cell in newrow:
-                try:
-                    cell.datatype = next(dtypes)
-                except NameError: #Python 2.5 or earlier
-                    cell.datatype = next(dtypes)
-                cell.row = newrow  #a cell knows its row
+                cell.datatype = next(dtypes)
+                cell.row = newrow  # a cell knows its row
             rows.append(newrow)
         logging.debug('Exit SimpleTable.data2rows.')
         return rows
+
     def pad(self, s, width, align):
         """DEPRECATED: just use the pad function"""
         return pad(s, width, align)
+
     def _get_colwidths(self, output_format, **fmt_dict):
         """Return list, the calculated widths of each column."""
         output_format = get_output_format(output_format)
@@ -311,20 +313,21 @@ def _get_colwidths(self, output_format, **fmt_dict):
         fmt.update(fmt_dict)
         ncols = max(len(row) for row in self)
         request = fmt.get('colwidths')
-        if request is 0: #assume no extra space desired (e.g, CSV)
+        if request is 0:  # assume no extra space desired (e.g, CSV)
             return [0] * ncols
-        elif request is None: #assume no extra space desired (e.g, CSV)
+        elif request is None:  # assume no extra space desired (e.g, CSV)
             request = [0] * ncols
         elif isinstance(request, int):
             request = [request] * ncols
         elif len(request) < ncols:
-            request = [request[i%len(request)] for i in range(ncols)]
+            request = [request[i % len(request)] for i in range(ncols)]
         min_widths = []
         for col in zip(*self):
-            maxwidth = max(len(c.format(0,output_format,**fmt)) for c in col)
+            maxwidth = max(len(c.format(0, output_format, **fmt)) for c in col)
             min_widths.append(maxwidth)
         result = lmap(max, min_widths, request)
         return result
+
     def get_colwidths(self, output_format, **fmt_dict):
         """Return list, the widths of each column."""
         call_args = [output_format]
@@ -339,68 +342,74 @@ def get_colwidths(self, output_format, **fmt_dict):
         try:
             return self._colwidths[key]
         except KeyError:
-            self._colwidths[key] = self._get_colwidths(output_format, **fmt_dict)
+            self._colwidths[key] = self._get_colwidths(output_format,
+                                                       **fmt_dict)
             return self._colwidths[key]
+
     def _get_fmt(self, output_format, **fmt_dict):
         """Return dict, the formatting options.
         """
         output_format = get_output_format(output_format)
-        #first get the default formatting
+        # first get the default formatting
         try:
             fmt = self.output_formats[output_format].copy()
         except KeyError:
             raise ValueError('Unknown format: %s' % output_format)
-        #then, add formatting specific to this call
+        # then, add formatting specific to this call
         fmt.update(fmt_dict)
         return fmt
+
     def as_csv(self, **fmt_dict):
         """Return string, the table in CSV format.
         Currently only supports comma separator."""
-        #fetch the format, which may just be default_csv_format
+        # fetch the format, which may just be default_csv_format
         fmt = self._get_fmt('csv', **fmt_dict)
         return self.as_text(**fmt)
+
     def as_text(self, **fmt_dict):
         """Return string, the table as text."""
-        #fetch the text format, override with fmt_dict
+        # fetch the text format, override with fmt_dict
         fmt = self._get_fmt('txt', **fmt_dict)
-        #get rows formatted as strings
-        formatted_rows = [ row.as_string('text', **fmt) for row in self ]
-        rowlen = len(formatted_rows[-1]) #don't use header row
+        # get rows formatted as strings
+        formatted_rows = [row.as_string('text', **fmt) for row in self]
+        rowlen = len(formatted_rows[-1])  # don't use header row
 
-        #place decoration above the table body, if desired
-        table_dec_above = fmt.get('table_dec_above','=')
+        # place decoration above the table body, if desired
+        table_dec_above = fmt.get('table_dec_above', '=')
         if table_dec_above:
             formatted_rows.insert(0, table_dec_above * rowlen)
-        #next place a title at the very top, if desired
-        #:note: user can include a newlines at end of title if desired
+        # next place a title at the very top, if desired
+        # :note: user can include a newlines at end of title if desired
         title = self.title
         if title:
-            title = pad(self.title, rowlen, fmt.get('title_align','c'))
+            title = pad(self.title, rowlen, fmt.get('title_align', 'c'))
             formatted_rows.insert(0, title)
-        #add decoration below the table, if desired
-        table_dec_below = fmt.get('table_dec_below','-')
+        # add decoration below the table, if desired
+        table_dec_below = fmt.get('table_dec_below', '-')
         if table_dec_below:
             formatted_rows.append(table_dec_below * rowlen)
         return '\n'.join(formatted_rows)
+
     def as_html(self, **fmt_dict):
         """Return string.
         This is the default formatter for HTML tables.
         An HTML table formatter must accept as arguments
         a table and a format dictionary.
         """
-        #fetch the text format, override with fmt_dict
+        # fetch the text format, override with fmt_dict
         fmt = self._get_fmt('html', **fmt_dict)
         formatted_rows = ['<table class="simpletable">']
         if self.title:
             title = '<caption>%s</caption>' % self.title
             formatted_rows.append(title)
-        formatted_rows.extend( row.as_string('html', **fmt) for row in self )
+        formatted_rows.extend(row.as_string('html', **fmt) for row in self)
         formatted_rows.append('</table>')
         return '\n'.join(formatted_rows)
+
     def as_latex_tabular(self, center=True, **fmt_dict):
         '''Return string, the table as a LaTeX tabular environment.
         Note: will require the booktabs package.'''
-        #fetch the text format, override with fmt_dict
+        # fetch the text format, override with fmt_dict
         fmt = self._get_fmt('latex', **fmt_dict)
 
         if center:
@@ -422,33 +431,26 @@ def as_latex_tabular(self, center=True, **fmt_dict):
                 if prev_aligns:
                     # ... if there is a tabular to close, close it...
                     formatted_rows.append(table_dec_below)
-                    formatted_rows.append( r'\end{tabular}' )
+                    formatted_rows.append(r'\end{tabular}')
                 if aligns:
                     # ... and if there are more lines, open a new one:
-                    formatted_rows.append( r'\begin{tabular}{%s}' % aligns )
+                    formatted_rows.append(r'\begin{tabular}{%s}' % aligns)
                     if not prev_aligns:
                         # (with a nice line if it's the top of the whole table)
                         formatted_rows.append(table_dec_above)
             if row != last:
                 formatted_rows.append(
-                    row.as_string(output_format='latex', **fmt) )
+                    row.as_string(output_format='latex', **fmt))
             prev_aligns = aligns
-        #tabular does not support caption, but make it available for figure environment
+        # tabular does not support caption, but make it available for
+        # figure environment
         if self.title:
             title = r'%%\caption{%s}' % self.title
             formatted_rows.append(title)
         if center:
-            formatted_rows.append( "\\end{center}" )
+            formatted_rows.append("\\end{center}")
         return '\n'.join(formatted_rows)
-        """
-        if fmt_dict['strip_backslash']:
-            ltx_stubs = [stub.replace('\\',r'$\backslash$') for stub in self.stubs]
-            ltx_headers = [header.replace('\\',r'$\backslash$') for header in self.headers]
-            ltx_headers = self.format_headers(fmt_dict, ltx_headers)
-        else:
-            ltx_headers = self.format_headers(fmt_dict)
-        ltx_stubs = self.format_stubs(fmt_dict, ltx_stubs)
-        """
+
     def extend_right(self, table):
         """Return None.
         Extend each row of `self` with corresponding row of `table`.
@@ -462,6 +464,7 @@ def extend_right(self, table):
         """
         for row1, row2 in zip(self, table):
             row1.extend(row2)
+
     def label_cells(self, func):
         """Return None.  Labels cells based on `func`.
         If ``func(cell) is None`` then its datatype is
@@ -472,10 +475,11 @@ def label_cells(self, func):
                 label = func(cell)
                 if label is not None:
                     cell.datatype = label
+
     @property
     def data(self):
         return [row.data for row in self]
-#END: class SimpleTable
+
 
 def pad(s, width, align):
     """Return string padded with spaces,
@@ -515,9 +519,10 @@ def __init__(self, seq, datatype='data', table=None, celltype=None,
                 celltype = table._Cell
         self._Cell = celltype
         self._fmt = fmt_dict
-        self.special_fmts = dict() #special formatting for any output format
+        self.special_fmts = dict()  # special formatting for any output format
         self.dec_below = dec_below
-        list.__init__(self, (celltype(cell,row=self) for cell in seq))
+        list.__init__(self, (celltype(cell, row=self) for cell in seq))
+
     def add_format(self, output_format, **fmt_dict):
         """
         Return None. Adds row-instance specific formatting
@@ -528,6 +533,7 @@ def add_format(self, output_format, **fmt_dict):
         if output_format not in self.special_fmts:
             self.special_fmts[output_format] = dict()
         self.special_fmts[output_format].update(fmt_dict)
+
     def insert_stub(self, loc, stub):
         """Return None.  Inserts a stub cell
         in the row at `loc`.
@@ -537,32 +543,35 @@ def insert_stub(self, loc, stub):
             stub = stub
             stub = _Cell(stub, datatype='stub', row=self)
         self.insert(loc, stub)
+
     def _get_fmt(self, output_format, **fmt_dict):
         """Return dict, the formatting options.
         """
         output_format = get_output_format(output_format)
-        #first get the default formatting
+        # first get the default formatting
         try:
             fmt = default_fmts[output_format].copy()
         except KeyError:
             raise ValueError('Unknown format: %s' % output_format)
-        #second get table specific formatting (if possible)
+        # second get table specific formatting (if possible)
         try:
             fmt.update(self.table.output_formats[output_format])
         except AttributeError:
             pass
-        #finally, add formatting for this row and this call
+        # finally, add formatting for this row and this call
         fmt.update(self._fmt)
         fmt.update(fmt_dict)
         special_fmt = self.special_fmts.get(output_format, None)
         if special_fmt is not None:
             fmt.update(special_fmt)
         return fmt
+
     def get_aligns(self, output_format, **fmt_dict):
         """Return string, sequence of column alignments.
         Ensure comformable data_aligns in `fmt_dict`."""
         fmt = self._get_fmt(output_format, **fmt_dict)
-        return ''.join( cell.alignment(output_format, **fmt) for cell in self )
+        return ''.join(cell.alignment(output_format, **fmt) for cell in self)
+
     def as_string(self, output_format='txt', **fmt_dict):
         """Return string: the formatted row.
         This is the default formatter for rows.
@@ -573,7 +582,7 @@ def as_string(self, output_format='txt', **fmt_dict):
         """
         fmt = self._get_fmt(output_format, **fmt_dict)
 
-        #get column widths
+        # get column widths
         try:
             colwidths = self.table.get_colwidths(output_format, **fmt)
         except AttributeError:
@@ -582,17 +591,20 @@ def as_string(self, output_format='txt', **fmt_dict):
             colwidths = (0,) * len(self)
 
         colsep = fmt['colsep']
-        row_pre = fmt.get('row_pre','')
-        row_post = fmt.get('row_post','')
+        row_pre = fmt.get('row_pre', '')
+        row_post = fmt.get('row_post', '')
         formatted_cells = []
         for cell, width in zip(self, colwidths):
             content = cell.format(width, output_format=output_format, **fmt)
             formatted_cells.append(content)
         formatted_row = row_pre + colsep.join(formatted_cells) + row_post
-        formatted_row = self._decorate_below(formatted_row, output_format, **fmt)
+        formatted_row = self._decorate_below(formatted_row, output_format,
+                                             **fmt)
         return formatted_row
+
     def _decorate_below(self, row_as_string, output_format, **fmt_dict):
-        """This really only makes sense for the text and latex output formats."""
+        """This really only makes sense for the text and latex output formats.
+        """
         dec_below = fmt_dict.get(self.dec_below, None)
         if dec_below is None:
             result = row_as_string
@@ -600,18 +612,20 @@ def _decorate_below(self, row_as_string, output_format, **fmt_dict):
             output_format = get_output_format(output_format)
             if output_format == 'txt':
                 row0len = len(row_as_string)
-                dec_len = len (dec_below)
+                dec_len = len(dec_below)
                 repeat, addon = divmod(row0len, dec_len)
-                result = row_as_string + "\n" + (dec_below * repeat + dec_below[:addon])
+                result = row_as_string + "\n" + (dec_below * repeat +
+                                                 dec_below[:addon])
             elif output_format == 'latex':
                 result = row_as_string + "\n" + dec_below
             else:
-                raise ValueError("I can't decorate a %s header."%output_format)
+                raise ValueError("I can't decorate a %s header." %
+                                 output_format)
         return result
+
     @property
     def data(self):
         return [cell.data for cell in self]
-#END class Row
 
 
 class Cell(object):
@@ -619,56 +633,60 @@ class Cell(object):
     A cell can belong to a Row, but does not have to.
     """
     def __init__(self, data='', datatype=None, row=None, **fmt_dict):
-        try: #might have passed a Cell instance
+        try:  # might have passed a Cell instance
             self.data = data.data
             self._datatype = data.datatype
             self._fmt = data._fmt
-        except (AttributeError, TypeError): #passed ordinary data
+        except (AttributeError, TypeError):  # passed ordinary data
             self.data = data
             self._datatype = datatype
             self._fmt = dict()
         self._fmt.update(fmt_dict)
         self.row = row
+
     def __str__(self):
         return '%s' % self.data
+
     def _get_fmt(self, output_format, **fmt_dict):
         """Return dict, the formatting options.
         """
         output_format = get_output_format(output_format)
-        #first get the default formatting
+        # first get the default formatting
         try:
             fmt = default_fmts[output_format].copy()
         except KeyError:
             raise ValueError('Unknown format: %s' % output_format)
-        #then get any table specific formtting
+        # then get any table specific formtting
         try:
             fmt.update(self.row.table.output_formats[output_format])
         except AttributeError:
             pass
-        #then get any row specific formtting
+        # then get any row specific formtting
         try:
             fmt.update(self.row._fmt)
         except AttributeError:
             pass
-        #finally add formatting for this instance and call
+        # finally add formatting for this instance and call
         fmt.update(self._fmt)
         fmt.update(fmt_dict)
         return fmt
+
     def alignment(self, output_format, **fmt_dict):
         fmt = self._get_fmt(output_format, **fmt_dict)
         datatype = self.datatype
-        data_aligns = fmt.get('data_aligns','c')
+        data_aligns = fmt.get('data_aligns', 'c')
         if isinstance(datatype, int):
             align = data_aligns[datatype % len(data_aligns)]
         elif datatype == 'stub':
-            #still support deprecated `stubs_align`
-            align = fmt.get('stubs_align') or fmt.get('stub_align','l')
+            # still support deprecated `stubs_align`
+            align = fmt.get('stubs_align') or fmt.get('stub_align', 'l')
         elif datatype in fmt:
             label_align = '%s_align' % datatype
-            align = fmt.get(label_align,'c')
+            align = fmt.get(label_align, 'c')
         else:
-            raise ValueError('Unknown cell datatype: %s'%datatype)
+            raise ValueError('Unknown cell datatype: %s' % datatype)
         return align
+
     def format(self, width, output_format='txt', **fmt_dict):
         """Return string.
         This is the default formatter for cells.
@@ -685,47 +703,44 @@ def format(self, width, output_format='txt', **fmt_dict):
         datatype = self.datatype
         data_fmts = fmt.get('data_fmts')
         if data_fmts is None:
-            #chk allow for deprecated use of data_fmt
+            # chk allow for deprecated use of data_fmt
             data_fmt = fmt.get('data_fmt')
             if data_fmt is None:
                 data_fmt = '%s'
             data_fmts = [data_fmt]
-        data_aligns = fmt.get('data_aligns','c')
         if isinstance(datatype, int):
-            datatype = datatype % len(data_fmts) #constrain to indexes
+            datatype = datatype % len(data_fmts)  # constrain to indexes
             content = data_fmts[datatype] % (data,)
         elif datatype in fmt:
             if "replacements" in fmt:
-                if isinstance( data, str ):
+                if isinstance(data, str):
                     for repl in fmt["replacements"]:
-                        data = data.replace( repl, fmt["replacements"][repl] )
+                        data = data.replace(repl, fmt["replacements"][repl])
 
             dfmt = fmt.get(datatype)
             try:
                 content = dfmt % (data,)
-            except TypeError: #dfmt is not a substitution string
+            except TypeError:  # dfmt is not a substitution string
                 content = dfmt
         else:
-            raise ValueError('Unknown cell datatype: %s'%datatype)
+            raise ValueError('Unknown cell datatype: %s' % datatype)
         align = self.alignment(output_format, **fmt)
         return pad(content, width, align)
+
     def get_datatype(self):
-        if self._datatype == None:
+        if self._datatype is None:
             dtype = self.row.datatype
         else:
             dtype = self._datatype
         return dtype
+
     def set_datatype(self, val):
-        #TODO: add checking
+        # TODO: add checking
         self._datatype = val
     datatype = property(get_datatype, set_datatype)
-#END class Cell
-
 
 
-
-
-#########  begin: default formats for SimpleTable  ##############
+# begin: default formats for SimpleTable
 """ Some formatting suggestions:
 
 - if you want rows to have no extra spacing,
@@ -742,144 +757,145 @@ def set_datatype(self, val):
         data_aligns = "r",
 """
 default_txt_fmt = dict(
-        fmt = 'txt',
-        #basic table formatting
-        table_dec_above='=',
-        table_dec_below='-',
-        title_align='c',
-        #basic row formatting
-        row_pre = '',
-        row_post = '',
-        header_dec_below = '-',
-        row_dec_below = None,
-        colwidths = None,
-        colsep=' ',
-        data_aligns = "c",
-        #data formats
-        #data_fmt = "%s",  #deprecated; use data_fmts
-        data_fmts = ["%s"],
-        #labeled alignments
-        #stubs_align = 'l',   #deprecated; use data_fmts
-        stub_align = 'l',
-        header_align = 'c',
-        #labeled formats
-        header_fmt = '%s', #deprecated; just use 'header'
-        stub_fmt = '%s', #deprecated; just use 'stub'
-        header='%s',
-        stub='%s',
-        empty_cell = '', #deprecated; just use 'empty'
-        empty = '',
-        missing='--',
-        )
+    fmt='txt',
+    # basic table formatting
+    table_dec_above='=',
+    table_dec_below='-',
+    title_align='c',
+    # basic row formatting
+    row_pre='',
+    row_post='',
+    header_dec_below='-',
+    row_dec_below=None,
+    colwidths=None,
+    colsep=' ',
+    data_aligns="c",
+    # data formats
+    # data_fmt="%s",  #deprecated; use data_fmts
+    data_fmts=["%s"],
+    # labeled alignments
+    # stubs_align='l',   #deprecated; use data_fmts
+    stub_align='l',
+    header_align='c',
+    # labeled formats
+    header_fmt='%s',  # deprecated; just use 'header'
+    stub_fmt='%s',  # deprecated; just use 'stub'
+    header='%s',
+    stub='%s',
+    empty_cell='',  # deprecated; just use 'empty'
+    empty='',
+    missing='--',
+)
 
 default_csv_fmt = dict(
-        fmt = 'csv',
-        table_dec_above = None, #'',
-        table_dec_below = None, #'',
-        #basic row formatting
-        row_pre = '',
-        row_post = '',
-        header_dec_below = None, #'',
-        row_dec_below = None,
-        title_align = '',
-        data_aligns = "l",
-        colwidths = None,
-        colsep = ',',
-        #data formats
-        data_fmt = '%s',  #deprecated; use data_fmts
-        data_fmts = ['%s'],
-        #labeled alignments
-        #stubs_align = 'l',   #deprecated; use data_fmts
-        stub_align = "l",
-        header_align = 'c',
-        #labeled formats
-        header_fmt = '"%s"', #deprecated; just use 'header'
-        stub_fmt = '"%s"', #deprecated; just use 'stub'
-        empty_cell = '', #deprecated; just use 'empty'
-        header='%s',
-        stub='%s',
-        empty = '',
-        missing='--',
-        )
+    fmt='csv',
+    table_dec_above=None,  # '',
+    table_dec_below=None,  # '',
+    # basic row formatting
+    row_pre='',
+    row_post='',
+    header_dec_below=None,  # '',
+    row_dec_below=None,
+    title_align='',
+    data_aligns="l",
+    colwidths=None,
+    colsep=',',
+    # data formats
+    data_fmt='%s',  # deprecated; use data_fmts
+    data_fmts=['%s'],
+    # labeled alignments
+    # stubs_align='l',   # deprecated; use data_fmts
+    stub_align="l",
+    header_align='c',
+    # labeled formats
+    header_fmt='"%s"',  # deprecated; just use 'header'
+    stub_fmt='"%s"',  # deprecated; just use 'stub'
+    empty_cell='',  # deprecated; just use 'empty'
+    header='%s',
+    stub='%s',
+    empty='',
+    missing='--',
+)
 
 default_html_fmt = dict(
-        #basic table formatting
-        table_dec_above=None,
-        table_dec_below=None,
-        header_dec_below=None,
-        row_dec_below = None,
-        title_align='c',
-        #basic row formatting
-        colwidths = None,
-        colsep=' ',
-        row_pre = '<tr>\n  ',
-        row_post = '\n</tr>',
-        data_aligns = "c",
-        #data formats
-        data_fmts = ['<td>%s</td>'],
-        data_fmt = "<td>%s</td>",  #deprecated; use data_fmts
-        #labeled alignments
-        #stubs_align = 'l',   #deprecated; use data_fmts
-        stub_align = 'l',
-        header_align = 'c',
-        #labeled formats
-        header_fmt = '<th>%s</th>', #deprecated; just use `header`
-        stub_fmt = '<th>%s</th>', #deprecated; just use `stub`
-        empty_cell = '<td></td>', #deprecated; just use `empty`
-        header='<th>%s</th>',
-        stub='<th>%s</th>',
-        empty = '<td></td>',
-        missing='<td>--</td>',
-        )
+    # basic table formatting
+    table_dec_above=None,
+    table_dec_below=None,
+    header_dec_below=None,
+    row_dec_below=None,
+    title_align='c',
+    # basic row formatting
+    colwidths=None,
+    colsep=' ',
+    row_pre='<tr>\n  ',
+    row_post='\n</tr>',
+    data_aligns="c",
+    # data formats
+    data_fmts=['<td>%s</td>'],
+    data_fmt="<td>%s</td>",  # deprecated; use data_fmts
+    # labeled alignments
+    # stubs_align='l',   #deprecated; use data_fmts
+    stub_align='l',
+    header_align='c',
+    # labeled formats
+    header_fmt='<th>%s</th>',  # deprecated; just use `header`
+    stub_fmt='<th>%s</th>',  # deprecated; just use `stub`
+    empty_cell='<td></td>',  # deprecated; just use `empty`
+    header='<th>%s</th>',
+    stub='<th>%s</th>',
+    empty='<td></td>',
+    missing='<td>--</td>',
+)
 
 default_latex_fmt = dict(
-        fmt = 'ltx',
-        #basic table formatting
-        table_dec_above = r'\toprule',
-        table_dec_below = r'\bottomrule',
-        header_dec_below = r'\midrule',
-        row_dec_below = None,
-        strip_backslash = True,  # NotImplemented
-        #row formatting
-        row_post = r'  \\',
-        data_aligns = 'c',
-        colwidths = None,
-        colsep = ' & ',
-        #data formats
-        data_fmts = ['%s'],
-        data_fmt = '%s',  #deprecated; use data_fmts
-        #labeled alignments
-        #stubs_align = 'l',   #deprecated; use data_fmts
-        stub_align = 'l',
-        header_align = 'c',
-        empty_align = 'l',
-        #labeled formats
-        header_fmt = r'\textbf{%s}', #deprecated; just use 'header'
-        stub_fmt = r'\textbf{%s}', #deprecated; just use 'stub'
-        empty_cell = '', #deprecated; just use 'empty'
-        header = r'\textbf{%s}',
-        stub = r'\textbf{%s}',
-        empty = '',
-        missing = '--',
-        replacements = {"%" : "\%", ">" : "$>$", "|" : "$|$"}
-        )
+    fmt='ltx',
+    # basic table formatting
+    table_dec_above=r'\toprule',
+    table_dec_below=r'\bottomrule',
+    header_dec_below=r'\midrule',
+    row_dec_below=None,
+    strip_backslash=True,  # NotImplemented
+    # row formatting
+    row_post=r'  \\',
+    data_aligns='c',
+    colwidths=None,
+    colsep=' & ',
+    # data formats
+    data_fmts=['%s'],
+    data_fmt='%s',  # deprecated; use data_fmts
+    # labeled alignments
+    # stubs_align='l',   # deprecated; use data_fmts
+    stub_align='l',
+    header_align='c',
+    empty_align='l',
+    # labeled formats
+    header_fmt=r'\textbf{%s}',  # deprecated; just use 'header'
+    stub_fmt=r'\textbf{%s}',  # deprecated; just use 'stub'
+    empty_cell='',  # deprecated; just use 'empty'
+    header=r'\textbf{%s}',
+    stub=r'\textbf{%s}',
+    empty='',
+    missing='--',
+    replacements={"%" : "\%", ">" : "$>$", "|" : "$|$"}
+)
+
 default_fmts = dict(
-html= default_html_fmt,
-txt=default_txt_fmt,
-latex=default_latex_fmt,
-csv=default_csv_fmt
+    html=default_html_fmt,
+    txt=default_txt_fmt,
+    latex=default_latex_fmt,
+    csv=default_csv_fmt
 )
 output_format_translations = dict(
-htm='html',
-text='txt',
-ltx='latex'
+    htm='html',
+    text='txt',
+    ltx='latex'
 )
+
+
 def get_output_format(output_format):
     if output_format not in ('html', 'txt', 'latex', 'csv'):
-        try: output_format = output_format_translations[output_format]
-        except KeyError: raise ValueError('unknown output format %s'%output_format)
+        try:
+            output_format = output_format_translations[output_format]
+        except KeyError:
+            raise ValueError('unknown output format %s' % output_format)
     return output_format
-
-#########  end: default formats  ##############
-
-


Test patch: