[Kimchi-devel] [PATCH 1/2] Add function to convert data sizes

Paulo Ricardo Paz Vital pvital at gmail.com
Tue Mar 3 08:16:12 UTC 2015


On Mon, 2015-03-02 at 13:45 -0300, Crístian Viana wrote:
> The new function "kimchi.utils.convert_data_size" can be used to convert
> values from different units, e.g. converting 5 GiB to MiB, 1 GiB to B.
> 
> Signed-off-by: Crístian Viana <vianac at linux.vnet.ibm.com>
> ---
>  src/kimchi/i18n.py  |   2 +
>  src/kimchi/utils.py | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 147 insertions(+)
> 
> diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
> index 2af0be6..df5422f 100644
> --- a/src/kimchi/i18n.py
> +++ b/src/kimchi/i18n.py
> @@ -267,6 +267,8 @@ messages = {
>      "KCHUTILS0001E": _("Invalid URI %(uri)s"),
>      "KCHUTILS0002E": _("Timeout while running command '%(cmd)s' after %(seconds)s seconds"),
>      "KCHUTILS0003E": _("Unable to choose a virtual machine name"),
> +    "KCHUTILS0004E": _("Invalid data value '%(value)s'"),
> +    "KCHUTILS0005E": _("Invalid data unit '%(unit)s'"),
>  
>      "KCHVMSTOR0002E": _("Invalid storage type. Types supported: 'cdrom', 'disk'"),
>      "KCHVMSTOR0003E": _("The path '%(value)s' is not a valid local/remote path for the device"),
> diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
> index fc5245f..a04d3cf 100644
> --- a/src/kimchi/utils.py
> +++ b/src/kimchi/utils.py
> @@ -388,3 +388,148 @@ def get_unique_file_name(all_names, name):
>              max_num = max(max_num, int(match.group(re_group_num)))
>  
>      return u'%s (%d)' % (name, max_num + 1)
> +
> +
> +def convert_data_size(value, src_unit, dst_unit=None):

s/src_unit/src_unit=None
As explained below, both second and third arguments can be None and then
automatically converted to use DEFAULT_UNIT. 

I tried "convert_data_size(4)" and got the error: 
TypeError: convert_data_size() takes at least 2 arguments (1 given)


> +    """Convert a data value from one unit to another unit
> +    (e.g. 'MiB' -> 'GiB').
> +
> +    The data units supported by this function are made up of one prefix and one
> +    suffix, both optional. The valid prefixes are those defined in the SI
> +    (i.e. metric system) and those defined by the IEC, and the valid suffixes
> +    indicate if the base unit is bit or byte. Take a look at the tables below
> +    for the possible values:
> +
> +    Prefixes:
> +
> +    ==================================     ===================================
> +    PREFIX (SI) | DESCRIPTION | VALUE      PREFIX (IEC) | DESCRIPTION | VALUE
> +    ==================================     ===================================
> +    k           | kilo        | 1000       Ki           | kibi        | 1024
> +    ----------------------------------     -----------------------------------
> +    M           | mega        | 1000^2     Mi           | mebi        | 1024^2
> +    ----------------------------------     -----------------------------------
> +    G           | giga        | 1000^3     Gi           | gibi        | 1024^3
> +    ----------------------------------     -----------------------------------
> +    T           | tera        | 1000^4     Ti           | tebi        | 1024^4
> +    ----------------------------------     -----------------------------------
> +    P           | peta        | 1000^5     Pi           | pebi        | 1024^5
> +    ----------------------------------     -----------------------------------
> +    E           | exa         | 1000^6     Ei           | exbi        | 1024^6
> +    ----------------------------------     -----------------------------------
> +    Z           | zetta       | 1000^7     Zi           | zebi        | 1024^7
> +    ----------------------------------     -----------------------------------
> +    Y           | yotta       | 1000^8     Yi           | yobi        | 1024^8
> +    ==================================     ===================================
> +
> +    Suffixes:
> +
> +    ====================
> +    SUFFIX | DESCRIPTION
> +    ====================
> +    b      | bit
> +    --------------------
> +    B      | byte
> +    ====================
> +
> +    See http://en.wikipedia.org/wiki/Binary_prefix for more details on
> +    those units.
> +
> +    If a wrong prefix or suffix is provided, an error will be raised.
> +
> +    Examples:
> +        convert_data_size(5, 'MiB', 'KiB') -> 5120.0
> +        convert_data_size(5, 'MiB', 'M')   -> 5.24288
> +        convert_data_size(5, 'MiB', 'GiB') -> 0.0048828125
> +        convert_data_size(5, 'MiB', 'Tb')  -> 4.194304e-05
> +        convert_data_size(5, 'MiB')        -> 5242880.0
> +        convert_data_size(5, 'mib')        -> #ERROR# (invalid src_unit)
> +
> +    Parameters:
> +    value -- the value to be converted, in the unit specified by 'src_unit'.
> +             this parameter can be of any type which can be cast to float
> +             (e.g. int, float, str).
> +    src_unit -- the unit of 'value', as described above.
> +                if 'src_unit' is empty, the unit 'B' (byte) will be used.
> +    dst_unit -- the unit of the return value.
> +                if 'dst_unit' is empty, the unit 'B' (byte) will be used.
> +
> +    Return:
> +    A float number representing 'value' ('src_unit') converted to 'dst_unit'.
> +    """
> +    SI_PREFIXES = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']

I guess you can add a new line here, as you did between
SUFFIXES_WITH_MULT and DEFAULT_SUFFIX.

> +    # The IEC prefixes are the equivalent SI prefixes + 'i'
> +    # but, exceptionally, 'k' becomes 'Ki' instead of 'ki'.
> +    IEC_PREFIXES = map(lambda p: 'Ki' if p == 'k' else p + 'i', SI_PREFIXES)

New line here.

> +    PREFIXES_BY_BASE = {1000: SI_PREFIXES,
> +                        1024: IEC_PREFIXES}
> +
> +    SUFFIXES_WITH_MULT = {'b': 1,
> +                          'B': 8}
> +    DEFAULT_SUFFIX = 'B'
> +
> +    DEFAULT_UNIT = 'B'
> +
> +    # set the default units
> +    if not src_unit:
> +        src_unit = DEFAULT_UNIT
> +    if not dst_unit:
> +        dst_unit = DEFAULT_UNIT
> +
> +    # set the default suffix
> +    if src_unit[-1] not in SUFFIXES_WITH_MULT:
> +        src_unit += DEFAULT_SUFFIX
> +    if dst_unit[-1] not in SUFFIXES_WITH_MULT:
> +        dst_unit += DEFAULT_SUFFIX
> +
> +    # split prefix and suffix for better parsing
> +    src_p = src_unit[:-1]
> +    src_s = src_unit[-1]
> +    dst_p = dst_unit[:-1]
> +    dst_s = dst_unit[-1]
> +
> +    # validate parameters
> +    try:
> +        value = float(value)
> +    except TypeError:
> +        raise InvalidParameter('KCHUTILS0004E', {'value': value})
> +    if src_p != '' and src_p not in (SI_PREFIXES + IEC_PREFIXES):
> +        raise InvalidParameter('KCHUTILS0005E', {'unit': src_unit})
> +    if src_s not in SUFFIXES_WITH_MULT:
> +        raise InvalidParameter('KCHUTILS0005E', {'unit': src_unit})
> +    if dst_p != '' and dst_p not in (SI_PREFIXES + IEC_PREFIXES):
> +        raise InvalidParameter('KCHUTILS0005E', {'unit': dst_unit})
> +    if dst_s not in SUFFIXES_WITH_MULT:
> +        raise InvalidParameter('KCHUTILS0005E', {'unit': dst_unit})
> +
> +    # convert 'value' to the most basic unit (bits)...
> +    bits = value
> +
> +    for suffix, mult in SUFFIXES_WITH_MULT.iteritems():
> +        if src_s == suffix:
> +            bits *= mult
> +            break
> +
> +    if src_p != '':
> +        for base, prefixes in PREFIXES_BY_BASE.iteritems():
> +            for i, p in enumerate(prefixes):
> +                if src_p == p:
> +                    bits *= base**(i + 1)
> +                    break
> +
> +    # ...then convert the value in bits to the destination unit
> +    ret = bits
> +
> +    for suffix, mult in SUFFIXES_WITH_MULT.iteritems():
> +        if dst_s == suffix:
> +            ret /= float(mult)
> +            break
> +
> +    if dst_p != '':
> +        for base, prefixes in PREFIXES_BY_BASE.iteritems():
> +            for i, p in enumerate(prefixes):
> +                if dst_p == p:
> +                    ret /= float(base)**(i + 1)
> +                    break
> +
> +    return ret

-- 
Paulo Ricardo Paz Vital <pvital at gmail.com>




More information about the Kimchi-devel mailing list