summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Pokorný <jpokorny@redhat.com>2012-03-09 15:25:39 +0100
committerJan Pokorný <jpokorny@redhat.com>2012-03-09 15:25:39 +0100
commit486635d185284f6ee99fc3e6a208acef5e5dbee3 (patch)
treea914faa9cc14eb0577d693fe0403514d80111ad3
parentda9c29a6b924b7b2373d1ab176bd90489e2aef30 (diff)
downloadwatch-bz-486635d185284f6ee99fc3e6a208acef5e5dbee3.tar.gz
watch-bz-486635d185284f6ee99fc3e6a208acef5e5dbee3.tar.xz
watch-bz-486635d185284f6ee99fc3e6a208acef5e5dbee3.zip
add missing table-data script
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
-rwxr-xr-xtable_data114
1 files changed, 114 insertions, 0 deletions
diff --git a/table_data b/table_data
new file mode 100755
index 0000000..2206e0e
--- /dev/null
+++ b/table_data
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+# pretty much copy of http://code.activestate.com/recipes/267662/
+# with some other changes
+from sys import stdin, argv
+import cStringIO,operator
+from threading import Timer, RLock
+
+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]
+ # 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__':
+ def timer(lock, data):
+ with lock:
+ data.append[False]
+
+ lock = RLock()
+ ret, data = True, [True]
+
+ while ret and (not len(data) or data[-1] != ''): # EOF
+ t = Timer(15, timer, args=(lock, data))
+ while ret and data[-1]:
+ ret = stdin.readline()
+ #print "read", ret
+ with lock:
+ if not isinstance(data[-1], str):
+ data = data[:-1]
+ data.append(ret)
+ t.cancel()
+ #if not isinstance(data[-1], str):
+ # data = data[:-1]
+ sep = ','
+ if len(argv) > 1:
+ sep = argv[1]
+ rows = [row.strip().split(sep) for row in data]
+
+ #print 'Without wrapping function\n'
+ print indent(rows, hasHeader=False)
+ # 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(rows, hasHeader=False, separateRows=True,
+ # prefix='| ', postfix=' |',
+ # wrapfunc=lambda x: wrapper(x,width))