Welcome, guest | Sign In | My Account | Store | Cart
import cStringIO,operator

def indent(rows, hasHeader=False, headerChar='-', delim=' | ', justify='left',
           separateRows
=False, prefix='', postfix='', wrapfunc=lambda x:x):
   
"""Indents a table by column.
       - rows: A sequence of sequences of items, one sequence per row.
       - hasHeader: True if the first row consists of the columns' names.
       - headerChar: Character to be used for the row separator line
         (if hasHeader==True or separateRows==True).
       - delim: The column delimiter.
       - justify: Determines how are data justified in their column.
         Valid values are 'left','right' and 'center'.
       - separateRows: True if rows are to be separated by a line
         of 'headerChar's.
       - prefix: A string prepended to each printed row.
       - postfix: A string appended to each printed row.
       - wrapfunc: A function f(text) for wrapping text; each element in
         the table is first wrapped by this function."""

   
# closure for breaking logical rows to physical, using wrapfunc
   
def rowWrapper(row):
        newRows
= [wrapfunc(item).split('\n') for item in row]
       
return [[substr or '' for substr in item] for item in map(None,*newRows)]
   
# break each logical row into one or more physical ones
#    logicalRows = [rowWrapper(row) for row in rows]
    logicalRows
= [(row,) for row in rows]
   
# columns of physical rows
    columns
= map(None,*reduce(operator.add,logicalRows))
   
# get the maximum of each column by the string length of its items
    maxWidths
= [max([len(str(item)) for item in column]) for column in columns]
    rowSeparator
= headerChar * (len(prefix) + len(postfix) + sum(maxWidths) + \
                                 len
(delim)*(len(maxWidths)-1))
   
# select the appropriate justify method
    justify
= {'center':str.center, 'right':str.rjust, 'left':str.ljust}[justify.lower()]
    output
=cStringIO.StringIO()
   
if separateRows: print >> output, rowSeparator
   
for physicalRows in logicalRows:
       
for row in physicalRows:
           
print >> output, \
                prefix
\
               
+ delim.join([justify(str(item),width) for (item,width) in zip(row,maxWidths)]) \
               
+ postfix
       
if separateRows or hasHeader: print >> output, rowSeparator; hasHeader=False
   
return output.getvalue()

# written by Mike Brown
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061
def wrap_onspace(text, width):
   
"""
    A word-wrap function that preserves existing line breaks
    and most spaces in the text. Expects that existing line
    breaks are posix newlines (\n).
    """

   
return reduce(lambda line, word, width=width: '%s%s%s' %
                 
(line,
                   
' \n'[(len(line[line.rfind('\n')+1:])
                         
+ len(word.split('\n',1)[0]
                             
) >= width)],
                   word
),
                  text
.split(' ')
                 
)

import re
def wrap_onspace_strict(text, width):
   
"""Similar to wrap_onspace, but enforces the width constraint:
       words longer than width are split."""

    wordRegex
= re.compile(r'\S{'+str(width)+r',}')
   
return wrap_onspace(wordRegex.sub(lambda m: wrap_always(m.group(),width),text),width)

import math
def wrap_always(text, width):
   
"""A simple word-wrap function that wraps text on exactly width characters.
       It doesn't split the text in words."""

   
return '\n'.join([ text[width*i:width*(i+1)] \
                       
for i in xrange(int(math.ceil(1.*len(text)/width))) ])
   
if __name__ == '__main__':
    labels
= ('First Name', 'Last Name', 'Age', 'Position')
    data
= \
   
'''John,Smith,24,Software Engineer
       Mary,Brohowski,23,Sales Manager
       Aristidis,Papageorgopoulos,28,Senior Reseacher'''

    rows
= [row.strip().split(',')  for row in data.splitlines()]

   
print 'Without wrapping function\n'
   
print indent([labels]+rows, hasHeader=True)
   
# test indent with different wrapping functions
    width
= 10
   
for wrapper in (wrap_always,wrap_onspace,wrap_onspace_strict):
       
print 'Wrapping function: %s(x,width=%d)\n' % (wrapper.__name__,width)
       
print indent([labels]+rows, hasHeader=True, separateRows=True,
                     prefix
='| ', postfix=' |',
                     wrapfunc
=lambda x: wrapper(x,width))
   
   
# output:
   
#
   
#Without wrapping function
   
#
   
#First Name | Last Name        | Age | Position        
   
#-------------------------------------------------------
   
#John       | Smith            | 24  | Software Engineer
   
#Mary       | Brohowski        | 23  | Sales Manager    
   
#Aristidis  | Papageorgopoulos | 28  | Senior Reseacher
   
#
   
#Wrapping function: wrap_always(x,width=10)
   
#
   
#----------------------------------------------
   
#| First Name | Last Name  | Age | Position   |
   
#----------------------------------------------
   
#| John       | Smith      | 24  | Software E |
   
#|            |            |     | ngineer    |
   
#----------------------------------------------
   
#| Mary       | Brohowski  | 23  | Sales Mana |
   
#|            |            |     | ger        |
   
#----------------------------------------------
   
#| Aristidis  | Papageorgo | 28  | Senior Res |
   
#|            | poulos     |     | eacher     |
   
#----------------------------------------------
   
#
   
#Wrapping function: wrap_onspace(x,width=10)
   
#
   
#---------------------------------------------------
   
#| First Name | Last Name        | Age | Position  |
   
#---------------------------------------------------
   
#| John       | Smith            | 24  | Software  |
   
#|            |                  |     | Engineer  |
   
#---------------------------------------------------
   
#| Mary       | Brohowski        | 23  | Sales     |
   
#|            |                  |     | Manager   |
   
#---------------------------------------------------
   
#| Aristidis  | Papageorgopoulos | 28  | Senior    |
   
#|            |                  |     | Reseacher |
   
#---------------------------------------------------
   
#
   
#Wrapping function: wrap_onspace_strict(x,width=10)
   
#
   
#---------------------------------------------
   
#| First Name | Last Name  | Age | Position  |
   
#---------------------------------------------
   
#| John       | Smith      | 24  | Software  |
   
#|            |            |     | Engineer  |
   
#---------------------------------------------
   
#| Mary       | Brohowski  | 23  | Sales     |
   
#|            |            |     | Manager   |
   
#---------------------------------------------
   
#| Aristidis  | Papageorgo | 28  | Senior    |
   
#|            | poulos     |     | Reseacher |
   
#---------------------------------------------

History