diff --git a/glance/cmd/cache_manage.py b/glance/cmd/cache_manage.py index 96b8459a26..e5197e29c3 100755 --- a/glance/cmd/cache_manage.py +++ b/glance/cmd/cache_manage.py @@ -20,6 +20,7 @@ A simple cache management utility for Glance. """ from __future__ import print_function +import datetime import functools import optparse import os @@ -27,9 +28,8 @@ import sys import time from oslo_utils import encodeutils +import prettytable -from glance.common import timeutils -from glance.common import utils from six.moves import input # If ../glance/__init__.py exists, add ../ to Python search path, so that @@ -93,33 +93,32 @@ List all images currently cached. print("Found %d cached images..." % len(images)) - pretty_table = utils.PrettyTable() - pretty_table.add_column(36, label="ID") - pretty_table.add_column(19, label="Last Accessed (UTC)") - pretty_table.add_column(19, label="Last Modified (UTC)") - # 1 TB takes 13 characters to display: len(str(2**40)) == 13 - pretty_table.add_column(14, label="Size", just="r") - pretty_table.add_column(10, label="Hits", just="r") - - print(pretty_table.make_header()) + pretty_table = prettytable.PrettyTable(("ID", + "Last Accessed (UTC)", + "Last Modified (UTC)", + "Size", + "Hits")) + pretty_table.align['Size'] = "r" + pretty_table.align['Hits'] = "r" for image in images: - last_modified = image['last_modified'] - last_modified = timeutils.iso8601_from_timestamp(last_modified) - last_accessed = image['last_accessed'] if last_accessed == 0: last_accessed = "N/A" else: - last_accessed = timeutils.iso8601_from_timestamp(last_accessed) + last_accessed = datetime.datetime.utcfromtimestamp( + last_accessed).isoformat() - print(pretty_table.make_row( + pretty_table.add_row(( image['image_id'], last_accessed, - last_modified, + datetime.datetime.utcfromtimestamp( + image['last_modified']).isoformat(), image['size'], image['hits'])) + print(pretty_table.get_string()) + @catch_error('show queued images') def list_queued(options, args): @@ -135,13 +134,12 @@ List all images currently queued for caching. print("Found %d queued images..." % len(images)) - pretty_table = utils.PrettyTable() - pretty_table.add_column(36, label="ID") - - print(pretty_table.make_header()) + pretty_table = prettytable.PrettyTable(("ID",)) for image in images: - print(pretty_table.make_row(image)) + pretty_table.add_row((image,)) + + print(pretty_table.get_string()) @catch_error('queue the specified image for caching') diff --git a/glance/common/utils.py b/glance/common/utils.py index df1502a1df..2b8b6f12a0 100644 --- a/glance/common/utils.py +++ b/glance/common/utils.py @@ -349,68 +349,6 @@ def safe_mkdirs(path): raise -class PrettyTable(object): - """Creates an ASCII art table for use in bin/glance - - Example: - - ID Name Size Hits - --- ----------------- ------------ ----- - 122 image 22 0 - """ - def __init__(self): - self.columns = [] - - def add_column(self, width, label="", just='l'): - """Add a column to the table - - :param width: number of characters wide the column should be - :param label: column heading - :param just: justification for the column, 'l' for left, - 'r' for right - """ - self.columns.append((width, label, just)) - - def make_header(self): - label_parts = [] - break_parts = [] - for width, label, just in self.columns: - # NOTE(sirp): headers are always left justified - label_part = self._clip_and_justify(label, width, 'l') - label_parts.append(label_part) - - break_part = '-' * width - break_parts.append(break_part) - - label_line = ' '.join(label_parts) - break_line = ' '.join(break_parts) - return '\n'.join([label_line, break_line]) - - def make_row(self, *args): - row = args - row_parts = [] - for data, (width, label, just) in zip(row, self.columns): - row_part = self._clip_and_justify(data, width, just) - row_parts.append(row_part) - - row_line = ' '.join(row_parts) - return row_line - - @staticmethod - def _clip_and_justify(data, width, just): - # clip field to column width - clipped_data = str(data)[:width] - - if just == 'r': - # right justify - justified = clipped_data.rjust(width) - else: - # left justify - justified = clipped_data.ljust(width) - - return justified - - def mutating(func): """Decorator to enforce read-only logic""" @functools.wraps(func) diff --git a/glance/tests/unit/api/test_cmd_cache_manage.py b/glance/tests/unit/api/test_cmd_cache_manage.py index 7462922955..3cffeeafe1 100644 --- a/glance/tests/unit/api/test_cmd_cache_manage.py +++ b/glance/tests/unit/api/test_cmd_cache_manage.py @@ -14,6 +14,7 @@ import optparse import sys import mock +import prettytable from six.moves import StringIO from glance.cmd import cache_manage @@ -62,7 +63,7 @@ class TestGlanceCmdManage(test_utils.BaseTestCase): @mock.patch.object(glance.image_cache.client.CacheClient, 'get_cached_images') - @mock.patch.object(glance.common.utils.PrettyTable, 'make_row') + @mock.patch.object(prettytable.PrettyTable, 'add_row') def test_list_cached_images(self, mock_row_create, mock_images): """ Verify that list_cached() method correctly processes images with all @@ -95,7 +96,7 @@ class TestGlanceCmdManage(test_utils.BaseTestCase): @mock.patch.object(glance.image_cache.client.CacheClient, 'get_queued_images') - @mock.patch.object(glance.common.utils.PrettyTable, 'make_row') + @mock.patch.object(prettytable.PrettyTable, 'add_row') def test_list_queued_images(self, mock_row_create, mock_images): """Verify that list_queued() method correctly processes images.""" diff --git a/glance/tests/unit/common/test_utils.py b/glance/tests/unit/common/test_utils.py index 0a684190c4..7fc2d2558b 100644 --- a/glance/tests/unit/common/test_utils.py +++ b/glance/tests/unit/common/test_utils.py @@ -251,24 +251,6 @@ class TestUtils(test_utils.BaseTestCase): mashup_dict['min_ram']) self.assertEqual(image_meta['min_ram'], mashup_dict['min_ram']) - def test_create_pretty_table(self): - class MyPrettyTable(utils.PrettyTable): - def __init__(self): - self.columns = [] - - # Test add column - my_pretty_table = MyPrettyTable() - my_pretty_table.add_column(1, label='test') - # Test make header - test_res = my_pretty_table.make_header() - self.assertEqual('t\n-', test_res) - # Test make row - result = my_pretty_table.make_row('t') - self.assertEqual("t", result) - result = my_pretty_table._clip_and_justify( - data='test', width=4, just=1) - self.assertEqual("test", result) - def test_mutating(self): class FakeContext(object): def __init__(self): diff --git a/requirements.txt b/requirements.txt index d7af90d053..d2155da47c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -25,6 +25,7 @@ taskflow>=1.25.0 # Apache-2.0 keystoneauth1>=2.1.0 # Apache-2.0 keystonemiddleware!=4.1.0,>=4.0.0 # Apache-2.0 WSME>=0.8 # MIT +PrettyTable>=0.7,<0.8 # BSD # For paste.util.template used in keystone.common.template Paste # MIT