Skip to content

Commit

Permalink
No code changes - just pep8 whitespace cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
kstrauser committed Sep 20, 2011
1 parent ba63885 commit c79a895
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 48 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,2 +1,3 @@
*.pyc *.pyc
dist/ dist/
MANIFEST
105 changes: 57 additions & 48 deletions TableFactory.py
Expand Up @@ -73,14 +73,15 @@
from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer
from reportlab.platypus.tables import TableStyle, Table from reportlab.platypus.tables import TableStyle, Table



class StyleAttributes(object): class StyleAttributes(object):
"""StyleAttribute objects represent the formatting that will be """StyleAttribute objects represent the formatting that will be
applied to a cell. Current properties are: applied to a cell. Current properties are:
bold: bool, display a cell in bold bold: bool, display a cell in bold
money: bool, display the cell right-aligned money: bool, display the cell right-aligned
width: float, the width of a column in inches width: float, the width of a column in inches
span: integer, the number of columns the cell should span span: integer, the number of columns the cell should span
Expand All @@ -92,7 +93,7 @@ class StyleAttributes(object):
calculations until they're needed, we don't do any unnecessary calculations until they're needed, we don't do any unnecessary
work or have to worry about values being updated after they're work or have to worry about values being updated after they're
calculated.""" calculated."""

def __init__(self, **properties): def __init__(self, **properties):
"""Save the value of keyword/dict properties""" """Save the value of keyword/dict properties"""
self.properties = properties self.properties = properties
Expand All @@ -106,15 +107,16 @@ def __getattr__(self, key):
if key == 'span' and value is None: if key == 'span' and value is None:
return 1 return 1
return value return value



class Cell(object): class Cell(object):
"""Cell objects represent a single table cell""" """Cell objects represent a single table cell"""


def __init__(self, value, style=None): def __init__(self, value, style=None):
"""'value' is the displayed value of the cell. 'properties' is """'value' is the displayed value of the cell. 'properties' is
a dict of cell styles that each table generator may interpret a dict of cell styles that each table generator may interpret
as appropriate.""" as appropriate."""

self.value = value self.value = value
if style is None: if style is None:
self.style = StyleAttributes() self.style = StyleAttributes()
Expand All @@ -125,6 +127,7 @@ def __repr__(self):
"""Human-readable Cell representation""" """Human-readable Cell representation"""
return '<Cell(%s)>' % self.value return '<Cell(%s)>' % self.value



class TableRow(object): class TableRow(object):
"""A TableRow is a list of cells""" """A TableRow is a list of cells"""


Expand All @@ -140,11 +143,12 @@ def __iter__(self):
"""Return each of the row's cells in turn""" """Return each of the row's cells in turn"""
for cell in self.cells: for cell in self.cells:
yield cell yield cell



class ColumnSpec(object): class ColumnSpec(object):
"""A ColumnSpec describes the source of values for a particular """A ColumnSpec describes the source of values for a particular
column, as well as the properties of each of its cells""" column, as well as the properties of each of its cells"""

def __init__(self, attribute, title=None, **properties): def __init__(self, attribute, title=None, **properties):
"""'attribute' is the name of the attribute or dictionary key """'attribute' is the name of the attribute or dictionary key
that will be pulled from a row object to find a cell's that will be pulled from a row object to find a cell's
Expand Down Expand Up @@ -173,6 +177,7 @@ def __repr__(self):
"""Human-readable ColumnSpec representation""" """Human-readable ColumnSpec representation"""
return '<ColumnSpec(%s)>' % self.title return '<ColumnSpec(%s)>' % self.title



class RowSpec(object): class RowSpec(object):
"""A RowSpec is a list of ColumnSpecs. It has two main uses: """A RowSpec is a list of ColumnSpecs. It has two main uses:
Expand All @@ -186,7 +191,7 @@ class RowSpec(object):
TableRows as it's easy and it also guarantees that your column TableRows as it's easy and it also guarantees that your column
titles (see #1 above) will match their contents. titles (see #1 above) will match their contents.
""" """

def __init__(self, *columnspecs): def __init__(self, *columnspecs):
"""Store the given list of ColumnSpecs""" """Store the given list of ColumnSpecs"""
self.columnspecs = columnspecs self.columnspecs = columnspecs
Expand Down Expand Up @@ -220,12 +225,13 @@ def makeall(self, rowobjects):
"""Create a list of TableRows from a list of source objects""" """Create a list of TableRows from a list of source objects"""
return [self(rowobject) for rowobject in rowobjects] return [self(rowobject) for rowobject in rowobjects]



class TableBase(object): class TableBase(object):
"""Base class implementing common functionality for all table """Base class implementing common functionality for all table
classes.""" classes."""


castfunctions = {} castfunctions = {}

def __init__(self, title=None, explanation=None, headers=None): def __init__(self, title=None, explanation=None, headers=None):
"""A rowset is either a TableRow or a collection of """A rowset is either a TableRow or a collection of
TableRows. 'rowsets' is a collection of rowsets. Passing TableRows. 'rowsets' is a collection of rowsets. Passing
Expand Down Expand Up @@ -270,6 +276,7 @@ def _cast(self, cell):
castfunction = self.castfunctions.get(type(value), unicode) castfunction = self.castfunctions.get(type(value), unicode)
return cgi.escape(castfunction(value)) return cgi.escape(castfunction(value))



class PDFTable(TableBase): class PDFTable(TableBase):
"""Table generator that yields a PDF representation of the data""" """Table generator that yields a PDF representation of the data"""


Expand All @@ -280,26 +287,26 @@ class PDFTable(TableBase):


# Every table starts off with this style # Every table starts off with this style
tablebasestyle = TableStyle([ tablebasestyle = TableStyle([
('TOPPADDING', (0,0), (-1,-1), 0), ('TOPPADDING', (0, 0), (-1, -1), 0),
('BOTTOMPADDING', (0,0), (-1,-1), 0), ('BOTTOMPADDING', (0, 0), (-1, -1), 0),
('LEFTPADDING', (0,0), (-1,-1), 0), ('LEFTPADDING', (0, 0), (-1, -1), 0),
('RIGHTPADDING', (0,0), (-1,-1), 0), ('RIGHTPADDING', (0, 0), (-1, -1), 0),
('VALIGN', (0,0), (-1,-1), 'TOP'), ('VALIGN', (0, 0), (-1, -1), 'TOP'),
('INNERGRID', (0,0), (-1,-1), 1, gridcolor), ('INNERGRID', (0, 0), (-1, -1), 1, gridcolor),
]) ])


# The parent table is the outside wrapper around everything # The parent table is the outside wrapper around everything
tableparentstyle = TableStyle([ tableparentstyle = TableStyle([
('ROWBACKGROUNDS', (0,0), (-1,-1), [rowoddcolor, rowevencolor]), ('ROWBACKGROUNDS', (0, 0), (-1, -1), [rowoddcolor, rowevencolor]),
('LINEABOVE', (0,1), (-1,-2), 1, colors.black), ('LINEABOVE', (0, 1), (-1, -2), 1, colors.black),
('LINEBELOW', (0,1), (-1,-2), 1, colors.black), ('LINEBELOW', (0, 1), (-1, -2), 1, colors.black),
('BOX', (0,0), (-1,-1), 1, colors.black), ('BOX', (0, 0), (-1, -1), 1, colors.black),
]) ])


# Give content rows a little bit of side padding # Give content rows a little bit of side padding
tablerowstyle = TableStyle([ tablerowstyle = TableStyle([
('LEFTPADDING', (0,0), (-1,-1), 3), ('LEFTPADDING', (0, 0), (-1, -1), 3),
('RIGHTPADDING', (0,0), (-1,-1), 3), ('RIGHTPADDING', (0, 0), (-1, -1), 3),
]) ])


tableheaderstyle = TableStyle([ tableheaderstyle = TableStyle([
Expand All @@ -316,7 +323,7 @@ def _rendercell(self, cell):
"""Render data as a Paragraph""" """Render data as a Paragraph"""


value = self._cast(cell) value = self._cast(cell)

# Wrap the cell's contents in onion-tag goodness # Wrap the cell's contents in onion-tag goodness
if cell.style.bold: if cell.style.bold:
value = '<b>%s</b>' % value value = '<b>%s</b>' % value
Expand All @@ -326,7 +333,7 @@ def _rendercell(self, cell):
else: else:
style = self.contentcellstyle style = self.contentcellstyle
return Paragraph(value, style) return Paragraph(value, style)

def render(self, rowsets): def render(self, rowsets):
"""Return the data as a binary string holding a PDF""" """Return the data as a binary string holding a PDF"""


Expand Down Expand Up @@ -382,7 +389,8 @@ def render(self, rowsets):
rightMargin=.5 * inch, leftMargin=.5 * inch) rightMargin=.5 * inch, leftMargin=.5 * inch)
doc.build(components) doc.build(components)
return stringbuf.getvalue() return stringbuf.getvalue()



class SpreadsheetTable(TableBase): class SpreadsheetTable(TableBase):
"""Table generator that yields an Excel spreadsheet representation """Table generator that yields an Excel spreadsheet representation
of the data. It will have one worksheet named with the given of the data. It will have one worksheet named with the given
Expand All @@ -395,8 +403,8 @@ class SpreadsheetTable(TableBase):
# Styles to apply to given data types. The style for None is the # Styles to apply to given data types. The style for None is the
# default when no other type is applicable. # default when no other type is applicable.
styletypemap = { styletypemap = {
None : {None: xlwt.easyxf()}, None: {None: xlwt.easyxf()},
datetime.date : {None: xlwt.easyxf(num_format_str='YYYY-MM-DD')}, datetime.date: {None: xlwt.easyxf(num_format_str='YYYY-MM-DD')},
datetime.datetime: {None: xlwt.easyxf(num_format_str='YYYY-MM-DD HH:MM:SS')}, datetime.datetime: {None: xlwt.easyxf(num_format_str='YYYY-MM-DD HH:MM:SS')},
} }


Expand Down Expand Up @@ -432,7 +440,7 @@ def _getstyle(self, cell):
# Cache the results for next time # Cache the results for next time
cellstyles[tuple(sorted(attrs))] = cellstyle cellstyles[tuple(sorted(attrs))] = cellstyle
return cellstyle return cellstyle

def render(self, rowsets): def render(self, rowsets):
"""Return the data as a binary string holding an Excel spreadsheet""" """Return the data as a binary string holding an Excel spreadsheet"""
book = xlwt.Workbook() book = xlwt.Workbook()
Expand All @@ -445,7 +453,7 @@ def render(self, rowsets):
# will take over. I have no idea why. # will take over. I have no idea why.
mainsheet.row(0).set_style(self.styletypemap[None][None]) mainsheet.row(0).set_style(self.styletypemap[None][None])
rownum += 2 rownum += 2

# Generate any header rows # Generate any header rows
if self.headers: if self.headers:
for headerrow in self.headers: for headerrow in self.headers:
Expand All @@ -471,7 +479,8 @@ def render(self, rowsets):
stringbuf = StringIO.StringIO() stringbuf = StringIO.StringIO()
book.save(stringbuf) book.save(stringbuf)
return stringbuf.getvalue() return stringbuf.getvalue()



class HTMLTable(TableBase): class HTMLTable(TableBase):
"""Table generator that yields an HTML representation of the """Table generator that yields an HTML representation of the
data. Note that this class yields *only* the table itself and not data. Note that this class yields *only* the table itself and not
Expand All @@ -490,27 +499,27 @@ class HTMLTable(TableBase):
For example, the following lines in a page's <head> section will For example, the following lines in a page's <head> section will
enable all of those client-side options: enable all of those client-side options:
<script type="text/javascript" src="/javascript/jquery-1.5.min.js"></script> <script type="text/javascript" src="/javascript/jquery-1.5.min.js"></script>
<script type="text/javascript" src="/javascript/jquery.tablesorter.min.js"></script> <script type="text/javascript" src="/javascript/jquery.tablesorter.min.js"></script>
<script type="text/javascript" src="/javascript/jquery.tablesorter.mod.js"></script> <script type="text/javascript" src="/javascript/jquery.tablesorter.mod.js"></script>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() $(document).ready(function()
{ {
$(".reporttable").tablesorter({widgets: ['zebra']}); $(".reporttable").tablesorter({widgets: ['zebra']});
} }
); );
""" """


# These are the CSS classes emitted by the renderer # These are the CSS classes emitted by the renderer
cssdefs = { cssdefs = {
'bold' : 'cell_bold', 'bold': 'cell_bold',
'money' : 'cell_money', 'money': 'cell_money',
'table' : 'reporttable', 'table': 'reporttable',
'childrow': 'expand-child', 'childrow': 'expand-child',
'zebra' : ('odd', 'even'), 'zebra': ('odd', 'even'),
} }

def _rendercell(self, cell): def _rendercell(self, cell):
"""Render data as a td""" """Render data as a td"""


Expand Down Expand Up @@ -560,7 +569,7 @@ def render(self, rowsets):
else: else:
lines.append(' <th>%s</th>' % headercolumn.title) lines.append(' <th>%s</th>' % headercolumn.title)
lines.append(' </tr>') lines.append(' </tr>')

lines.append(' </thead>') lines.append(' </thead>')
lines.append(' <tbody>') lines.append(' <tbody>')


Expand All @@ -581,7 +590,8 @@ def render(self, rowsets):
lines.append(' </tbody>') lines.append(' </tbody>')
lines.append('</table>') lines.append('</table>')
return '\n'.join(lines) return '\n'.join(lines)



def example(): def example():
"""Create a set of sample tables""" """Create a set of sample tables"""


Expand Down Expand Up @@ -610,9 +620,9 @@ def example():
</html>""" </html>"""


exampletypes = ((PDFTable, 'pdf'), (HTMLTable, 'html'), (SpreadsheetTable, 'xls')) exampletypes = ((PDFTable, 'pdf'), (HTMLTable, 'html'), (SpreadsheetTable, 'xls'))

#### Example with several row types #### Example with several row types

mainrs = RowSpec( mainrs = RowSpec(
ColumnSpec('foo', 'Column 1', width=1), ColumnSpec('foo', 'Column 1', width=1),
ColumnSpec('bar', 'Column 2', width=1), ColumnSpec('bar', 'Column 2', width=1),
Expand Down Expand Up @@ -650,7 +660,6 @@ def example():
if tableclass is HTMLTable: if tableclass is HTMLTable:
outfile.write(htmlfooter) outfile.write(htmlfooter)



#### Example of a typical "invoices" table #### Example of a typical "invoices" table


import decimal import decimal
Expand All @@ -670,7 +679,7 @@ def example():
ColumnSpec('name', 'Customer Name'), ColumnSpec('name', 'Customer Name'),
ColumnSpec('amount', 'Total', money=True)) ColumnSpec('amount', 'Total', money=True))
lines = invoicerow.makeall(rows) lines = invoicerow.makeall(rows)

for tableclass, extension in exampletypes: for tableclass, extension in exampletypes:
outfile = open('invoice.%s' % extension, 'wb') outfile = open('invoice.%s' % extension, 'wb')
if tableclass is HTMLTable: if tableclass is HTMLTable:
Expand Down

0 comments on commit c79a895

Please sign in to comment.