blob: 81f574ded94fa9437636799890a771f66df85a20 [file] [log] [blame]
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
def encode(obj, encoding='UTF-8'):
"""
Check if the object supports encode() method, and if so, encodes it.
Encoding defaults to UTF-8.
For example objects of type 'int' do not support encode
"""
return obj.encode(encoding) if 'encode' in dir(obj) else obj
class Formatter:
def __init__(self, fields_tuple=(), row_tuple=(), min_width_tuple=None):
# Format to pass as first argument to the print function, e.g. '%s%s%s'
self.format = ""
# data_format will be of the form ['{!s:43}'],'{!s:39}','{!s:11}','{!s:25}']
# the widths are determined from the data in order to print output with nice format
# Each entry of the data_format list will be used by the advanced string formatter:
# "{!s:43}".format("Text")
# Advanced string formatter as detailed in here: https://www.python.org/dev/peps/pep-3101/
self.data_format = []
Formatter._assert(fields_tuple, row_tuple, min_width_tuple)
self._build_format_tuples(fields_tuple, row_tuple, min_width_tuple)
@staticmethod
def _assert(o1, o2, o3):
if len(o1) != len(o2) and (o3 is not None and len(o2) != len(o3)):
raise RuntimeError("Object collections must have the same length. "
"len(o1)={0}, len(o2)={1}, len(o3)={2}"
.format(len(o1), len(o2), -1 if o3 is None else len(o3)))
# determines the widths from the data in order to print output with nice format
@staticmethod
def _find_sizes(fields_tuple, row_tuple, min_width_tuple):
sizes = []
padding = 3
for i in range(0, len(row_tuple)):
max_len = max(len(encode(fields_tuple[i])), len(str(encode(row_tuple[i]))))
if min_width_tuple is not None:
max_len = max(max_len, min_width_tuple[i])
sizes += [max_len + padding]
return sizes
def _build_format_tuples(self, fields_tuple, row_tuple, min_width_tuple):
sizes = Formatter._find_sizes(fields_tuple, row_tuple, min_width_tuple)
for i in range(0, len(row_tuple)):
self.format += "%s"
self.data_format += ["{!s:" + str(sizes[i]) + "}"]
# Returns a tuple where each entry has a string that is the result of
# statements with the pattern "{!s:43}".format("Text")
def row_str_format(self, row_tuple):
format_with_values = [str(self.data_format[0].format(encode(row_tuple[0])))]
for i in range(1, len(row_tuple)):
format_with_values += [str(self.data_format[i].format(encode(row_tuple[i])))]
return tuple(format_with_values)