From: Stavros Sachtouris Date: Tue, 22 Jan 2013 12:32:21 +0000 (+0200) Subject: Format data size units, use it in quota commands X-Git-Tag: v0.6.3.3~1^2~9^2 X-Git-Url: https://code.grnet.gr/git/kamaki/commitdiff_plain/001200c3c68b4690abcf849111a45397e4e3ad8d?ds=sidebyside Format data size units, use it in quota commands quota returns value in units (KiB, MiB, etc) new argument -b, --bytes to return value in bytes setquota can accept a unit string setquota 2.3GB --- diff --git a/kamaki/cli/commands/pithos_cli.py b/kamaki/cli/commands/pithos_cli.py index 7f8c575..13f39f8 100644 --- a/kamaki/cli/commands/pithos_cli.py +++ b/kamaki/cli/commands/pithos_cli.py @@ -36,6 +36,7 @@ from kamaki.cli.command_tree import CommandTree from kamaki.cli.errors import raiseCLIError, CLISyntaxError from kamaki.cli.utils import ( format_size, + to_bytes, print_dict, pretty_keys, page_hold, @@ -88,7 +89,7 @@ def raise_connection_errors(e): '- total quota: /store quota', '- container quota: /store quota ', 'Users shall set a higher container quota, if available:', - '- /store setquota ' + '- /store setquota [unit] ' ]) @@ -1780,7 +1781,11 @@ class store_delmeta(_store_container_command): @command(pithos_cmds) class store_quota(_store_account_command): - """Get quota (in KB) for account or container""" + """Get quota for account or container""" + + arguments = dict( + in_bytes=FlagArgument('Show result in bytes', ('-b', '--bytes')) + ) def main(self, container=None): super(self.__class__, self).main() @@ -1799,15 +1804,47 @@ class store_quota(_store_account_command): raiseCLIError(err) except Exception as err: raiseCLIError(err) + if not self['in_bytes']: + for k in reply: + reply[k] = format_size(reply[k]) print_dict(pretty_keys(reply, '-')) @command(pithos_cmds) class store_setquota(_store_account_command): - """Set new quota (in KB) for account or container""" + """Set new quota for account or container + By default, quota is set in bytes + Users may specify a different unit, e.g: + /store setquota 2.3GB mycontainer + Accepted units: B, KiB (1024 B), KB (1000 B), MiB, MB, GiB, GB, TiB, TB + """ + + def _calculate_quota(self, user_input): + quota = 0 + try: + quota = int(user_input) + except ValueError: + index = 0 + digits = [str(num) for num in range(0, 10)] + ['.'] + while user_input[index] in digits: + index += 1 + quota = user_input[:index] + format = user_input[index:] + try: + return to_bytes(quota, format) + except Exception as qe: + raiseCLIError(qe, + 'Failed to convert %s to bytes' % user_input, + details=['Syntax: setquota [format] [container]', + 'e.g.: setquota 2.3GB mycontainer', + 'Acceptable formats:', + '(*1024): B, KiB, MiB, GiB, TiB', + '(*1000): B, KB, MB, GB, TB']) + return quota def main(self, quota, container=None): super(self.__class__, self).main() + quota = self._calculate_quota(quota) try: if container is None: self.client.set_account_quota(quota) diff --git a/kamaki/cli/utils.py b/kamaki/cli/utils.py index 9f2dc50..e3551f5 100644 --- a/kamaki/cli/utils.py +++ b/kamaki/cli/utils.py @@ -257,7 +257,7 @@ def print_items(items, def format_size(size): - units = ('B', 'K', 'M', 'G', 'T') + units = ('B', 'KiB', 'MiB', 'GiB', 'TiB') try: size = float(size) except ValueError as err: @@ -265,13 +265,37 @@ def format_size(size): for unit in units: if size < 1024: break - size /= 1024 - s = ('%.1f' % size) - if '.0' == s[-2:]: - s = s[:-2] + size /= 1024.0 + s = ('%.2f' % size) + while '.' in s and s[-1] in ('0', '.'): + s = s[:-1] return s + unit +def to_bytes(size, format): + """ + :param size: (float) the size in the given format + :param format: (case insensitive) KiB, KB, MiB, MB, GiB, GB, TiB, TB + + :returns: (int) the size in bytes + """ + format = format.upper() + if format == 'B': + return int(size) + size = float(size) + units_dc = ('KB', 'MB', 'GB', 'TB') + units_bi = ('KIB', 'MIB', 'GIB', 'TIB') + + factor = 1024 if format in units_bi else 1000 if format in units_dc else 0 + if not factor: + raise ValueError('Invalid data size format %s' % format) + for prefix in ('K', 'M', 'G', 'T'): + size *= factor + if format.startswith(prefix): + break + return int(size) + + def dict2file(d, f, depth=0): for k, v in d.items(): f.write('%s%s: ' % ('\t' * depth, k)) @@ -325,14 +349,14 @@ def split_input(line): return terms -def ask_user(msg, true_responses=('Y', 'y')): +def ask_user(msg, true_resp=['Y', 'y']): """Print msg and read user response - :param true_responses: (tuple of chars) + :param true_resp: (tuple of chars) :returns: (bool) True if reponse in true responses, False otherwise """ - stdout.write('%s (%s for yes):' % (msg, true_responses)) + stdout.write('%s (%s or enter for yes):' % (msg, ', '.join(true_resp))) stdout.flush() - user_response = stdin.read(1) - return user_response[0] in true_responses + user_response = stdin.readline() + return user_response[0] in true_resp + ['\n']