diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 16:04:21 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 16:04:21 +0000 |
commit | 8a754e0858d922e955e71b253c139e071ecec432 (patch) | |
tree | 527d16e74bfd1840c85efd675fdecad056c54107 /lib/ansible/module_utils/common/text/formatters.py | |
parent | Initial commit. (diff) | |
download | ansible-core-8a754e0858d922e955e71b253c139e071ecec432.tar.xz ansible-core-8a754e0858d922e955e71b253c139e071ecec432.zip |
Adding upstream version 2.14.3.upstream/2.14.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/ansible/module_utils/common/text/formatters.py')
-rw-r--r-- | lib/ansible/module_utils/common/text/formatters.py | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/lib/ansible/module_utils/common/text/formatters.py b/lib/ansible/module_utils/common/text/formatters.py new file mode 100644 index 0000000..94ca5a3 --- /dev/null +++ b/lib/ansible/module_utils/common/text/formatters.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019 Ansible Project +# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +import re + +from ansible.module_utils.six import iteritems + +SIZE_RANGES = { + 'Y': 1 << 80, + 'Z': 1 << 70, + 'E': 1 << 60, + 'P': 1 << 50, + 'T': 1 << 40, + 'G': 1 << 30, + 'M': 1 << 20, + 'K': 1 << 10, + 'B': 1, +} + + +def lenient_lowercase(lst): + """Lowercase elements of a list. + + If an element is not a string, pass it through untouched. + """ + lowered = [] + for value in lst: + try: + lowered.append(value.lower()) + except AttributeError: + lowered.append(value) + return lowered + + +def human_to_bytes(number, default_unit=None, isbits=False): + """Convert number in string format into bytes (ex: '2K' => 2048) or using unit argument. + + example: human_to_bytes('10M') <=> human_to_bytes(10, 'M'). + + When isbits is False (default), converts bytes from a human-readable format to integer. + example: human_to_bytes('1MB') returns 1048576 (int). + The function expects 'B' (uppercase) as a byte identifier passed + as a part of 'name' param string or 'unit', e.g. 'MB'/'KB'/etc. + (except when the identifier is single 'b', it is perceived as a byte identifier too). + if 'Mb'/'Kb'/... is passed, the ValueError will be rased. + + When isbits is True, converts bits from a human-readable format to integer. + example: human_to_bytes('1Mb', isbits=True) returns 8388608 (int) - + string bits representation was passed and return as a number or bits. + The function expects 'b' (lowercase) as a bit identifier, e.g. 'Mb'/'Kb'/etc. + if 'MB'/'KB'/... is passed, the ValueError will be rased. + """ + m = re.search(r'^\s*(\d*\.?\d*)\s*([A-Za-z]+)?', str(number), flags=re.IGNORECASE) + if m is None: + raise ValueError("human_to_bytes() can't interpret following string: %s" % str(number)) + try: + num = float(m.group(1)) + except Exception: + raise ValueError("human_to_bytes() can't interpret following number: %s (original input string: %s)" % (m.group(1), number)) + + unit = m.group(2) + if unit is None: + unit = default_unit + + if unit is None: + ''' No unit given, returning raw number ''' + return int(round(num)) + range_key = unit[0].upper() + try: + limit = SIZE_RANGES[range_key] + except Exception: + raise ValueError("human_to_bytes() failed to convert %s (unit = %s). The suffix must be one of %s" % (number, unit, ", ".join(SIZE_RANGES.keys()))) + + # default value + unit_class = 'B' + unit_class_name = 'byte' + # handling bits case + if isbits: + unit_class = 'b' + unit_class_name = 'bit' + # check unit value if more than one character (KB, MB) + if len(unit) > 1: + expect_message = 'expect %s%s or %s' % (range_key, unit_class, range_key) + if range_key == 'B': + expect_message = 'expect %s or %s' % (unit_class, unit_class_name) + + if unit_class_name in unit.lower(): + pass + elif unit[1] != unit_class: + raise ValueError("human_to_bytes() failed to convert %s. Value is not a valid string (%s)" % (number, expect_message)) + + return int(round(num * limit)) + + +def bytes_to_human(size, isbits=False, unit=None): + base = 'Bytes' + if isbits: + base = 'bits' + suffix = '' + + for suffix, limit in sorted(iteritems(SIZE_RANGES), key=lambda item: -item[1]): + if (unit is None and size >= limit) or unit is not None and unit.upper() == suffix[0]: + break + + if limit != 1: + suffix += base[0] + else: + suffix = base + + return '%.2f %s' % (size / limit, suffix) |