avocado.utils: Add output module

Add avocado.utils.output, a library with utility functions
for user friendly display of information.
Signed-off-by: NLucas Meneghel Rodrigues <lmr@redhat.com>
上级 fc4c1bbb
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See LICENSE for more details.
#
# This code was inspired in the autotest project,
#
# client/shared/utils.py
# Original author: Cleber Rosa <crosa@redhat.com>
#
# Copyright: Red Hat Inc. 2015
# Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
"""
Utility functions for user friendly display of information.
"""
import sys
def display_data_size(size):
"""
Display data size in human readable units (SI).
:param size: Data size, in Bytes.
:type size: int
:return: Human readable string with data size, using SI prefixes.
"""
prefixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
factor = float(1000)
i = 0
while size >= factor:
if i >= len(prefixes) - 1:
break
size /= factor
i += 1
return '%.2f %s' % (size, prefixes[i])
class ProgressBar(object):
"""
Displays interactively the progress of a given task
Inspired/adapted from https://gist.github.com/t0xicCode/3306295
"""
def __init__(self, minimum=0, maximum=100, width=75, title=''):
"""
Initializes a new progress bar
:type minimum: integer
:param minimum: minimum (initial) value on the progress bar
:type maximum: integer
:param maximum: maximum (final) value on the progress bar
:type width: integer
:param with: number of columns, that is screen width
"""
assert maximum > minimum
self.prog_bar = ''
self.old_prog_bar = ''
if title:
width -= len(title)
self.minimum = minimum
self.maximum = maximum
self.range = maximum - minimum
self.width = width
self.title = title
self.current_amount = minimum
self.update_amount(minimum)
def append_amount(self, amount):
"""
Increments the current amount value.
"""
self.update_amount(self.current_amount + amount)
def update_percentage(self, percentage):
"""
Updates the progress bar to the new percentage.
"""
self.update_amount((percentage * float(self.maximum)) / 100.0)
def update_amount(self, amount):
"""
Performs sanity checks and update the current amount.
"""
if amount < self.minimum:
amount = self.minimum
if amount > self.maximum:
amount = self.maximum
self.current_amount = amount
self._update_progress_bar()
self.draw()
def _update_progress_bar(self):
"""
Builds the actual progress bar text.
"""
diff = float(self.current_amount - self.minimum)
done = (diff / float(self.range)) * 100.0
done = int(round(done))
all_full = self.width - 2
hashes = (done / 100.0) * all_full
hashes = int(round(hashes))
if hashes == 0:
screen_text = "[>%s]" % (' '*(all_full-1))
elif hashes == all_full:
screen_text = "[%s]" % ('='*all_full)
else:
screen_text = "[%s>%s]" % ('='*(hashes-1), ' '*(all_full-hashes))
percent_string = str(done) + "%"
# slice the percentage into the bar
screen_text = ' '.join([screen_text, percent_string])
if self.title:
screen_text = '%s: %s' % (self.title,
screen_text)
self.prog_bar = screen_text
def draw(self):
"""
Prints the updated text to the screen.
"""
if self.prog_bar != self.old_prog_bar:
self.old_prog_bar = self.prog_bar
sys.stdout.write('\r' + self.prog_bar)
sys.stdout.flush()
def __str__(self):
"""
Returns the current progress bar.
"""
return str(self.prog_bar)
import unittest
import os
import sys
# simple magic for using scripts within a source tree
basedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
basedir = os.path.dirname(basedir)
if os.path.isdir(os.path.join(basedir, 'avocado')):
sys.path.append(basedir)
from avocado.utils import output
class UtilsOutputTest(unittest.TestCase):
def testDisplayDataSizeFactor1024(self):
self.assertEqual(output.display_data_size(103), '103.00 B')
self.assertEqual(output.display_data_size(1024**1), '1.02 KB')
self.assertEqual(output.display_data_size(1024**2), '1.05 MB')
self.assertEqual(output.display_data_size(1024**3), '1.07 GB')
self.assertEqual(output.display_data_size(1024**4), '1.10 TB')
self.assertEqual(output.display_data_size(1024**5), '1.13 PB')
self.assertEqual(output.display_data_size(1024**6), '1152.92 PB')
def testDisplayDataSizeFactor1000(self):
self.assertEqual(output.display_data_size(1000**1), '1.00 KB')
self.assertEqual(output.display_data_size(1000**2), '1.00 MB')
self.assertEqual(output.display_data_size(1000**3), '1.00 GB')
self.assertEqual(output.display_data_size(1000**4), '1.00 TB')
self.assertEqual(output.display_data_size(1000**5), '1.00 PB')
self.assertEqual(output.display_data_size(1000**6), '1000.00 PB')
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册