Commit 0d8d1a28b46abbb4e5c3a3dfc8b8bd62f071de99

Authored by decalage2
1 parent 0acaf934

mraptor3: import tablestream, removed tablestream3

oletools/mraptor3.py
... ... @@ -66,7 +66,7 @@ import sys, logging, optparse, re
66 66 from thirdparty.xglob import xglob
67 67  
68 68 # import the python 3 version of tablestream:
69   -from thirdparty.tablestream import tablestream3 as tablestream
  69 +from thirdparty.tablestream import tablestream
70 70  
71 71 # import the python 3 version of olevba
72 72 import olevba3 as olevba
... ...
oletools/thirdparty/tablestream/tablestream3.py deleted
1   -#!/usr/bin/env python
2   -"""
3   -tablestream
4   -
5   -tablestream can format table data for pretty printing as text,
6   -to be displayed on the console or written to any file-like object.
7   -The table data can be provided as rows, each row is an iterable of
8   -cells. The text in each cell is wrapped to fit into a maximum width
9   -set for each column.
10   -Contrary to many table pretty printing libraries, TableStream writes
11   -each row to the output as soon as it is provided, and the whole table
12   -does not need to be built in memory before printing.
13   -It is therefore suitable for large tables, or tables that take time to
14   -be processed row by row.
15   -
16   -Author: Philippe Lagadec - http://www.decalage.info
17   -License: BSD, see source code or documentation
18   -"""
19   -
20   -#=== LICENSE ==================================================================
21   -
22   -# tablestream is copyright (c) 2015-2016 Philippe Lagadec (http://www.decalage.info)
23   -# All rights reserved.
24   -#
25   -# Redistribution and use in source and binary forms, with or without modification,
26   -# are permitted provided that the following conditions are met:
27   -#
28   -# * Redistributions of source code must retain the above copyright notice, this
29   -# list of conditions and the following disclaimer.
30   -# * Redistributions in binary form must reproduce the above copyright notice,
31   -# this list of conditions and the following disclaimer in the documentation
32   -# and/or other materials provided with the distribution.
33   -#
34   -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
35   -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36   -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37   -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
38   -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39   -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
40   -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
41   -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42   -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
43   -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44   -
45   -from __future__ import print_function
46   -
47   -#------------------------------------------------------------------------------
48   -# CHANGELOG:
49   -# 2015-11-01 v0.01 PL: - first version
50   -# 2016-01-01 v0.02 PL: - added styles, color support
51   -# 2016-04-19 v0.03 PL: - enable colorclass on Windows, fixed issue #39
52   -# 2016-05-25 v0.04 PL: - updated for colorclass 2.2.0 (now a package)
53   -# 2016-07-29 v0.05 PL: - fixed oletools issue #57, bug when importing colorclass
54   -# 2016-07-31 v0.06 PL: - handle newline characters properly in each cell
55   -
56   -__version__ = '0.06'
57   -
58   -#------------------------------------------------------------------------------
59   -# TODO:
60   -# - several styles
61   -# - colorized rows or cells
62   -# - automatic width for the last column, based on max total width
63   -# - automatic width for selected columns, based on N first lines
64   -# - determine the console width
65   -
66   -# === IMPORTS =================================================================
67   -
68   -import textwrap
69   -import sys, os
70   -
71   -# add the thirdparty subfolder to sys.path (absolute+normalized path):
72   -_thismodule_dir = os.path.normpath(os.path.abspath(os.path.dirname(__file__)))
73   -# print('_thismodule_dir = %r' % _thismodule_dir)
74   -# assumption: this module is in a subfolder of thirdparty:
75   -_thirdparty_dir = os.path.normpath(os.path.join(_thismodule_dir, '..'))
76   -# print('_thirdparty_dir = %r' % _thirdparty_dir)
77   -if not _thirdparty_dir in sys.path:
78   - sys.path.insert(0, _thirdparty_dir)
79   -
80   -import colorclass
81   -
82   -# On Windows, colorclass needs to be enabled:
83   -if os.name == 'nt':
84   - colorclass.Windows.enable(auto_colors=True)
85   -
86   -
87   -# === CLASSES =================================================================
88   -
89   -
90   -class TableStyle(object):
91   - """
92   - Style for a TableStream.
93   - This base class can be derived to create new styles.
94   - Default style:
95   - +------+---+
96   - |Header| +
97   - +------+---+
98   - | | |
99   - +------+---+
100   - """
101   - # Header rows:
102   - header_top = True
103   - header_top_left = '+'
104   - header_top_horiz = '-'
105   - header_top_middle = '+'
106   - header_top_right = '+'
107   -
108   - header_vertical_left = '|'
109   - header_vertical_middle = '|'
110   - header_vertical_right = '|'
111   -
112   - # Separator line between header and normal rows:
113   - header_sep = True
114   - header_sep_left = '+'
115   - header_sep_horiz = '-'
116   - header_sep_middle = '+'
117   - header_sep_right = '+'
118   -
119   - # Top row if there is no header:
120   - noheader_top = True
121   - noheader_top_left = '+'
122   - noheader_top_horiz = '-'
123   - noheader_top_middle = '+'
124   - noheader_top_right = '+'
125   -
126   - # Normal rows
127   - vertical_left = '|'
128   - vertical_middle = '|'
129   - vertical_right = '|'
130   -
131   - # Separator line between rows:
132   - sep = False
133   - sep_left = '+'
134   - sep_horiz = '-'
135   - sep_middle = '+'
136   - sep_right = '+'
137   -
138   - # Bottom line
139   - bottom = True
140   - bottom_left = '+'
141   - bottom_horiz = '-'
142   - bottom_middle = '+'
143   - bottom_right = '+'
144   -
145   -
146   -class TableStyleSlim(object):
147   - """
148   - Style for a TableStream.
149   - Example:
150   - ------+---
151   - Header|
152   - ------+---
153   - |
154   - ------+---
155   - """
156   - # Header rows:
157   - header_top = True
158   - header_top_left = ''
159   - header_top_horiz = '-'
160   - header_top_middle = '+'
161   - header_top_right = ''
162   -
163   - header_vertical_left = ''
164   - header_vertical_middle = '|'
165   - header_vertical_right = ''
166   -
167   - # Separator line between header and normal rows:
168   - header_sep = True
169   - header_sep_left = ''
170   - header_sep_horiz = '-'
171   - header_sep_middle = '+'
172   - header_sep_right = ''
173   -
174   - # Top row if there is no header:
175   - noheader_top = True
176   - noheader_top_left = ''
177   - noheader_top_horiz = '-'
178   - noheader_top_middle = '+'
179   - noheader_top_right = ''
180   -
181   - # Normal rows
182   - vertical_left = ''
183   - vertical_middle = '|'
184   - vertical_right = ''
185   -
186   - # Separator line between rows:
187   - sep = False
188   - sep_left = ''
189   - sep_horiz = '-'
190   - sep_middle = '+'
191   - sep_right = ''
192   -
193   - # Bottom line
194   - bottom = True
195   - bottom_left = ''
196   - bottom_horiz = '-'
197   - bottom_middle = '+'
198   - bottom_right = ''
199   -
200   -
201   -
202   -class TableStream(object):
203   - """
204   - a TableStream object can format table data for pretty printing as text,
205   - to be displayed on the console or written to any file-like object.
206   - The table data can be provided as rows, each row is an iterable of
207   - cells. The text in each cell is wrapped to fit into a maximum width
208   - set for each column.
209   - Contrary to many table pretty printing libraries, TableStream writes
210   - each row to the output as soon as it is provided, and the whole table
211   - does not need to be built in memory before printing.
212   - It is therefore suitable for large tables, or tables that take time to
213   - be processed row by row.
214   - """
215   -
216   - def __init__(self, column_width, header_row=None, style=TableStyle, outfile=sys.stdout):
217   - self.column_width = column_width
218   - self.num_columns = len(column_width)
219   - self.header_row = header_row
220   - assert (header_row is None) or len(header_row) == self.num_columns
221   - self.style = style
222   - self.outfile = outfile
223   - if header_row is not None:
224   - self.write_header()
225   - elif self.style.noheader_top:
226   - self.write_noheader_top()
227   -
228   -
229   - def write(self, s):
230   - """
231   - shortcut for self.outfile.write()
232   - """
233   - self.outfile.write(s)
234   -
235   - def write_row(self, row, last=False, colors=None):
236   - assert len(row) == self.num_columns
237   - columns = []
238   - max_lines = 0
239   - for i in range(self.num_columns):
240   - cell = row[i]
241   - # Convert to string:
242   - # TODO: handle unicode properly
243   - # TODO: use only unicode for textwrapper, to avoid str length issues
244   - if isinstance(cell, bytes):
245   - # encode to UTF8, avoiding errors
246   - cell = cell.decode('utf-8', errors='replace')
247   - else:
248   - cell = cell
249   - # Wrap cell text according to the column width
250   - # TODO: use a TextWrapper object for each column instead
251   - # split the string if it contains newline characters, otherwise
252   - # textwrap replaces them with spaces:
253   - column = []
254   - for line in cell.splitlines():
255   - column.extend(textwrap.wrap(line, width=self.column_width[i]))
256   - # apply colors to each line of the cell if needed:
257   - if colors is not None and self.outfile.isatty():
258   - color = colors[i]
259   - if color:
260   - for j in range(len(column)):
261   - # print '%r: %s' % (column[j], type(column[j]))
262   - column[j] = colorclass.Color('{auto%s}%s{/%s}' % (color, column[j], color))
263   - columns.append(column)
264   - # determine which column has the highest number of lines
265   - max_lines = max(len(columns[i]), max_lines)
266   - # transpose: write output line by line
267   - for j in range(max_lines):
268   - self.write(self.style.vertical_left)
269   - for i in range(self.num_columns):
270   - column = columns[i]
271   - if j<len(column):
272   - # text to be written
273   - text_width = len(column[j])
274   - self.write(column[j] + ' '*(self.column_width[i]-text_width))
275   - else:
276   - # no more lines for this column
277   - # TODO: precompute empty cells once
278   - self.write(' '*(self.column_width[i]))
279   - if i < (self.num_columns - 1):
280   - self.write(self.style.vertical_middle)
281   - self.write(self.style.vertical_right)
282   - self.write('\n')
283   - if self.style.sep and not last:
284   - self.write_sep()
285   -
286   - def make_line(self, left, horiz, middle, right):
287   - """
288   - build a line based on the provided elements
289   - example: '+---+--+-------+'
290   - :param left:
291   - :param horiz:
292   - :param middle:
293   - :param right:
294   - :return:
295   - """
296   - return left + middle.join([horiz * width for width in self.column_width]) + right + '\n'
297   -
298   - def write_header_top(self):
299   - s = self.style
300   - line = self.make_line(left=s.header_top_left, horiz=s.header_top_horiz,
301   - middle=s.header_top_middle, right=s.header_top_right)
302   - self.write(line)
303   -
304   - def write_header_sep(self):
305   - s = self.style
306   - line = self.make_line(left=s.header_sep_left, horiz=s.header_sep_horiz,
307   - middle=s.header_sep_middle, right=s.header_sep_right)
308   - self.write(line)
309   -
310   - def write_header(self):
311   - if self.style.header_top:
312   - self.write_header_top()
313   - self.write_row(self.header_row)
314   - if self.style.header_sep:
315   - self.write_header_sep()
316   -
317   - def write_noheader_top(self):
318   - s = self.style
319   - line = self.make_line(left=s.noheader_top_left, horiz=s.noheader_top_horiz,
320   - middle=s.noheader_top_middle, right=s.noheader_top_right)
321   - self.write(line)
322   -
323   - def write_sep(self):
324   - s = self.style
325   - line = self.make_line(left=s.sep_left, horiz=s.sep_horiz,
326   - middle=s.sep_middle, right=s.sep_right)
327   - self.write(line)
328   -
329   - def write_bottom(self):
330   - s = self.style
331   - line = self.make_line(left=s.bottom_left, horiz=s.bottom_horiz,
332   - middle=s.bottom_middle, right=s.bottom_right)
333   - self.write(line)
334   -
335   - def close(self):
336   - self.write_bottom()
337   -
338   -
339   -if __name__ == '__main__':
340   - t = TableStream([10, 5, 20], header_row=['i', 'i*i', '2**i'], style=TableStyleSlim)
341   - t.write_row(['test', 'test', 'test'])
342   - cell = 'a very very long text'
343   - t.write_row([cell, cell, cell], colors=['blue', None, 'red'])
344   - for i in range(1, 11):
345   - t.write_row([i, i*i, 2**i])
346   - t.close()
347   -
348   -