tools/qvm-ls: kill fixed column width

Calculate column width dynamically, besed on actual contents.
This commit is contained in:
Marek Marczykowski-Górecki 2017-03-11 01:47:12 +01:00
parent fea3d3391f
commit 435a465d70
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
2 changed files with 35 additions and 38 deletions

View File

@ -497,7 +497,7 @@ class VmNameGroup(argparse._MutuallyExclusiveGroup):
self.add_argument('VMNAME', action=vm_action, nargs='*', default=[])
def print_table(table):
def print_table(table, stream=None):
''' Uses the unix column command to print pretty table.
:param str text: list of lists/sets
@ -507,13 +507,16 @@ def print_table(table):
text_table = '\n'.join([unit_separator.join(row) for row in table])
text_table += '\n'
if stream is None:
stream = sys.stdout
# for tests...
if sys.stdout != sys.__stdout__:
if stream != sys.__stdout__:
p = subprocess.Popen(cmd + ['-c', '80'], stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.stdin.write(text_table.encode())
(out, _) = p.communicate()
sys.stdout.write(out.decode())
stream.write(out.decode())
else:
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
p.communicate(text_table.encode())

View File

@ -41,11 +41,10 @@ import qubesmgmt.vm
#
class Column(object):
'''A column in qvm-ls output characterised by its head, a width and a way
'''A column in qvm-ls output characterised by its head and a way
to fetch a parameter describing the domain.
:param str head: Column head (usually uppercase).
:param int width: Column width.
:param str attr: Attribute, possibly complex (containing ``.``). This may \
also be a callable that gets as its only argument the domain.
:param str doc: Description of column (will be visible in --help-columns).
@ -54,9 +53,8 @@ class Column(object):
#: collection of all columns
columns = {}
def __init__(self, head, width=0, attr=None, doc=None):
def __init__(self, head, attr=None, doc=None):
self.ls_head = head
self.ls_width = max(width, len(self.ls_head) + 1)
self.__doc__ = doc if doc is None else qubesmgmt.utils.format_doc(doc)
# intentionally not always do set self._attr,
@ -77,12 +75,12 @@ class Column(object):
:py:meth:`Column.format` method instead.
:param qubes.vm.qubesvm.QubesVM: Domain to get a value from.
:returns: string that is at least as wide as needed to fill table row.
:returns: string to display
:rtype: str
'''
value = self.format(vm) or '-'
return value.ljust(self.ls_width)
return value
def format(self, vm):
@ -117,8 +115,8 @@ class Column(object):
return ret
def __repr__(self):
return '{}(head={!r}, width={!r})'.format(self.__class__.__name__,
self.ls_head, self.ls_width)
return '{}(head={!r})'.format(self.__class__.__name__,
self.ls_head)
def __eq__(self, other):
@ -200,7 +198,6 @@ class StatusColumn(Column):
def __init__(self):
super(StatusColumn, self).__init__(
head='STATUS',
width=len(self.get_flags()) + 1,
doc=self.__class__.__doc__)
@ -337,41 +334,41 @@ def calc_used(vm, volume_name):
# todo maxmem
Column('GATEWAY', width=15,
Column('GATEWAY',
attr='netvm.gateway',
doc='Network gateway.')
Column('MEMORY', width=5,
Column('MEMORY',
attr=(lambda vm: vm.get_mem() / 1024 if vm.is_running() else None),
doc='Memory currently used by VM')
Column('DISK', width=5,
Column('DISK',
attr=(lambda vm: vm.storage.get_disk_utilization() / 1024 / 1024),
doc='Total disk utilisation.')
Column('PRIV-CURR', width=5,
Column('PRIV-CURR',
attr=(lambda vm: calc_usage(vm, 'private')),
doc='Disk utilisation by private image (/home, /usr/local).')
Column('PRIV-MAX', width=5,
Column('PRIV-MAX',
attr=(lambda vm: calc_size(vm, 'private')),
doc='Maximum available space for private image.')
Column('PRIV-USED', width=5,
Column('PRIV-USED',
attr=(lambda vm: calc_used(vm, 'private')),
doc='Disk utilisation by private image as a percentage of available space.')
Column('ROOT-CURR', width=5,
Column('ROOT-CURR',
attr=(lambda vm: calc_usage(vm, 'root')),
doc='Disk utilisation by root image (/usr, /lib, /etc, ...).')
Column('ROOT-MAX', width=5,
Column('ROOT-MAX',
attr=(lambda vm: calc_size(vm, 'root')),
doc='Maximum available space for root image.')
Column('ROOT-USED', width=5,
Column('ROOT-USED',
attr=(lambda vm: calc_used(vm, 'root')),
doc='Disk utilisation by root image as a percentage of available space.')
@ -391,21 +388,13 @@ class Table(object):
self.raw_data = raw_data
def format_head(self):
'''Format table head (all column heads).'''
return ''.join('{head:{width}s}'.format(
head=col.ls_head, width=col.ls_width)
for col in self.columns[:-1]) + \
self.columns[-1].ls_head
def format_row(self, vm):
'''Format single table row (all columns for one domain).'''
if self.raw_data:
return '|'.join(col.format(vm) for col in self.columns)
else:
return ''.join(col.cell(vm) for col in self.columns)
def get_head(self):
'''Get table head data (all column heads).'''
return [col.ls_head for col in self.columns]
def get_row(self, vm):
'''Get single table row data (all columns for one domain).'''
return [col.cell(vm) for col in self.columns]
def write_table(self, stream=sys.stdout):
'''Write whole table to file-like object.
@ -413,10 +402,15 @@ class Table(object):
:param file stream: Stream to write the table to.
'''
table_data = []
if not self.raw_data:
stream.write(self.format_head() + '\n')
for vm in self.app.domains:
stream.write(self.format_row(vm) + '\n')
table_data.append(self.get_head())
for vm in self.app.domains:
table_data.append(self.get_row(vm))
qubesmgmt.tools.print_table(table_data, stream=stream)
else:
for vm in self.app.domains:
stream.write('|'.join(self.get_row(vm)) + '\n')
#: Available formats. Feel free to plug your own one.