diff frontends/src/jp/common.py @ 2345:c57bc0fe17d9

jp (common): added use_buffer argument in Table: when use_buffer is True, the Table is not printed but put in a buffer. A unicode string can then be computed when string property is used.
author Goffi <goffi@goffi.org>
date Wed, 23 Aug 2017 00:10:09 +0200
parents 78ffb9ce57a4
children 3c0a3fae1862
line wrap: on
line diff
--- a/frontends/src/jp/common.py	Wed Aug 23 00:08:30 2017 +0200
+++ b/frontends/src/jp/common.py	Wed Aug 23 00:10:09 2017 +0200
@@ -505,7 +505,7 @@
 
 class Table(object):
 
-    def __init__(self, host, data, headers=None, filters=None):
+    def __init__(self, host, data, headers=None, filters=None, use_buffer=False):
         """
         @param data(list[list]): table data
             all lines must have the same number of columns
@@ -515,8 +515,10 @@
             the callable will get col value as argument and must return a string
             if it's unicode, it will be used with .format and must countain u'{}' which will be replaced with the string
             if not None, must have same number of columns as data
+        @param use_buffer(bool): if True, bufferise output instead of printing it directly
         """
         self.host = host
+        self._buffer = [] if use_buffer else None
         # headers are columns names/titles, can be None
         self.headers = headers
         # sizes fof columns without headers,
@@ -559,6 +561,12 @@
             # the table is empty, we print headers at their lenght
             self.sizes = [len(h) for h in headers]
 
+    @property
+    def string(self):
+        if self._buffer is None:
+            raise exceptions.InternalError(u'buffer must be used to get a string')
+        return u'\n'.join(self._buffer)
+
     @staticmethod
     def readDictValues(data, keys, defaults=None):
         if defaults is None:
@@ -626,6 +634,13 @@
             headers.append(rendered)
         return head_sep.join(headers)
 
+    def _disp(self, data):
+        """output data (can be either bufferised or printed)"""
+        if self._buffer is not None:
+            self._buffer.append(data)
+        else:
+            self.host.disp(data)
+
     def display(self,
                 head_alignment = u'left',
                 columns_alignment = u'left',
@@ -647,7 +662,7 @@
                 bottom_left=u'└',
                 bottom=None,
                 bottom_sep=u'─┴─',
-                bottom_right=u'┘'
+                bottom_right=u'┘',
                 ):
         """Print the table
 
@@ -657,6 +672,8 @@
         @param columns_alignment(unicode): how to align columns, can be left, center or right
         @param col_sep(unicode): separator betweens columns
         @param head_line(unicode): character to use to make line under head
+        @param disp(callable, None): method to use to display the table
+            None to use self.host.disp
         """
         col_sep_size = len(regex.ansiRemove(col_sep))
         if right is None:
@@ -673,7 +690,7 @@
             left = right = head_line_left = head_line_right = u''
         # top border
         if show_borders:
-            self.host.disp(
+            self._disp(
                 top_left
                 + top_sep.join([top*size for size in self.sizes])
                 + top_right
@@ -681,13 +698,13 @@
 
         # headers
         if show_header:
-            self.host.disp(
+            self._disp(
                 left
                 + self._headers(head_sep, head_alignment, head_style)
                 + right
                 )
             # header line
-            self.host.disp(
+            self._disp(
                 head_line_left
                 + head_line_sep.join([head_line*size for size in self.sizes])
                 + head_line_right
@@ -704,20 +721,22 @@
             raise exceptions.InternalError(u'bad columns alignment argument')
 
         for row in self.rows:
-            self.host.disp(left + col_sep.join([alignment(idx,c) for idx,c in enumerate(row)]) + right)
+            self._disp(left + col_sep.join([alignment(idx,c) for idx,c in enumerate(row)]) + right)
 
         if show_borders:
             # bottom border
-            self.host.disp(
+            self._disp(
                 bottom_left
                 + bottom_sep.join([bottom*size for size in self.sizes])
                 + bottom_right
                 )
+        # we return self so string can be used after display (table.display().string)
+        return self
 
     def display_blank(self, **kwargs):
         """Display table without visible borders"""
         kwargs_ = {'col_sep':u' ', 'head_line_sep':u' ', 'show_borders':False}
         kwargs_.update(kwargs)
-        self.display(self,
-                     **kwargs_
-                     )
+        return self.display(self,
+                            **kwargs_
+                            )