Blame src/python/bytesize.py

Packit Service af52df
import ctypes
Packit Service af52df
from ctypes import POINTER, byref
Packit Service af52df
Packit Service af52df
import six
Packit Service af52df
from decimal import Decimal
Packit Service af52df
Packit Service af52df
import locale
Packit Service af52df
Packit Service af52df
import gettext
Packit Service af52df
_ = lambda x: gettext.translation("libbytesize", fallback=True).gettext(x) if x != "" else ""
Packit Service af52df
Packit Service af52df
"""
Packit Service af52df
Python bindings for the libbytesize library and it's BSSize "class". These
Packit Service af52df
bindings provide a real Python class :class:`Size` which wraps the libbytesize
Packit Service af52df
functionality and provides all the features one would expect from a numeric type
Packit Service af52df
in Python.
Packit Service af52df
Packit Service af52df
.. note::
Packit Service af52df
  ``None`` is treated as ``Size(0)`` in mathematical operations.
Packit Service af52df
Packit Service af52df
"""
Packit Service af52df
Packit Service af52df
c_bytesize = ctypes.CDLL("libbytesize.so.1")
Packit Service af52df
Packit Service af52df
B = 0
Packit Service af52df
KiB = 1
Packit Service af52df
MiB = 2
Packit Service af52df
GiB = 3
Packit Service af52df
TiB = 4
Packit Service af52df
PiB = 5
Packit Service af52df
EiB = 6
Packit Service af52df
ZiB = 7
Packit Service af52df
YiB = 8
Packit Service af52df
KB = 21
Packit Service af52df
MB = 22
Packit Service af52df
GB = 23
Packit Service af52df
TB = 24
Packit Service af52df
PB = 25
Packit Service af52df
EB = 26
Packit Service af52df
ZB = 27
Packit Service af52df
YB = 28
Packit Service af52df
Packit Service af52df
ROUND_UP = 0
Packit Service af52df
ROUND_DOWN = 1
Packit Service af52df
ROUND_HALF_UP = 2
Packit Service af52df
Packit Service af52df
MAXUINT64 = 2**64 - 1
Packit Service af52df
Packit Service af52df
unit_strs = {
Packit Service af52df
    "B": B, "KiB": KiB, "MiB": MiB, "GiB": GiB, "TiB": TiB, "PiB": PiB, "EiB": EiB, "ZiB": ZiB, "YiB": YiB,
Packit Service af52df
    "KB": KB, "MB": MB, "GB": GB, "TB": TB, "PB": PB, "EB": EB, "ZB": ZB, "YB": YB,
Packit Service af52df
    }
Packit Service af52df
Packit Service af52df
def unit_str(unit, xlate=False):
Packit Service af52df
    for (u_str, u) in unit_strs.items():
Packit Service af52df
        if u == unit:
Packit Service af52df
            return _(u_str) if xlate else u_str
Packit Service af52df
Packit Service af52df
class SizeErrorStruct(ctypes.Structure):
Packit Service af52df
    _fields_ = [("code", ctypes.c_int),
Packit Service af52df
                ("msg", ctypes.c_char_p)]
Packit Service af52df
Packit Service af52df
class SizeError(Exception):
Packit Service af52df
    pass
Packit Service af52df
Packit Service af52df
class InvalidSpecError(SizeError):
Packit Service af52df
    pass
Packit Service af52df
Packit Service af52df
class OverflowError(SizeError):
Packit Service af52df
    pass
Packit Service af52df
Packit Service af52df
class ZeroDivisionError(SizeError):
Packit Service af52df
    pass
Packit Service af52df
Packit Service af52df
_error_code_clss = (InvalidSpecError, OverflowError, ZeroDivisionError)
Packit Service af52df
Packit Service af52df
def get_error(err):
Packit Service af52df
    if not err:
Packit Service af52df
        return None
Packit Service af52df
    if six.PY3:
Packit Service af52df
        msg = str(err.contents.msg, "utf-8")
Packit Service af52df
    else:
Packit Service af52df
        msg = err.contents.msg
Packit Service af52df
    ex = _error_code_clss[err.contents.code](msg)
Packit Service af52df
    c_bytesize.bs_clear_error(byref(err))
Packit Service af52df
    raise ex
Packit Service af52df
Packit Service af52df
class SizeStruct(ctypes.Structure):
Packit Service af52df
    @classmethod
Packit Service af52df
    def new(cls):
Packit Service af52df
        return c_bytesize.bs_size_new().contents
Packit Service af52df
Packit Service af52df
    @classmethod
Packit Service af52df
    def new_from_bytes(cls, byts, sgn):
Packit Service af52df
        return c_bytesize.bs_size_new_from_bytes(byts, sgn).contents
Packit Service af52df
Packit Service af52df
    @classmethod
Packit Service af52df
    def new_from_str(cls, s):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        if six.PY3:
Packit Service af52df
            s = bytes(s, "utf-8")
Packit Service af52df
        ret = c_bytesize.bs_size_new_from_str(s, byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        return ret.contents
Packit Service af52df
Packit Service af52df
    @classmethod
Packit Service af52df
    def new_from_size(cls, sz):
Packit Service af52df
        return c_bytesize.bs_size_new_from_size(sz).contents
Packit Service af52df
Packit Service af52df
    def __del__(self):
Packit Service af52df
        # XXX: For some reason c_bytesize may be None here (probably when python
Packit Service af52df
        #      cleans up after itself) and loading it again doesn't work at that
Packit Service af52df
        #      stage. Let's just prevent ignored exceptions from happening.
Packit Service af52df
        if c_bytesize:
Packit Service af52df
            c_bytesize.bs_size_free(self)
Packit Service af52df
Packit Service af52df
    def get_bytes(self):
Packit Service af52df
        sgn = ctypes.c_int(0)
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        ret = c_bytesize.bs_size_get_bytes(self, byref(sgn), byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        return (ret, sgn.value)
Packit Service af52df
Packit Service af52df
    def get_bytes_str(self):
Packit Service af52df
        if six.PY3:
Packit Service af52df
            return str(c_bytesize.bs_size_get_bytes_str(self), "utf-8")
Packit Service af52df
        else:
Packit Service af52df
            return c_bytesize.bs_size_get_bytes_str(self)
Packit Service af52df
Packit Service af52df
    def add(self, sz):
Packit Service af52df
        return c_bytesize.bs_size_add(self, sz).contents
Packit Service af52df
Packit Service af52df
    def add_bytes(self, b):
Packit Service af52df
        return c_bytesize.bs_size_add_bytes(self, b).contents
Packit Service af52df
Packit Service af52df
    def grow(self, sz):
Packit Service af52df
        c_bytesize.bs_size_grow(self, sz)
Packit Service af52df
        return self
Packit Service af52df
Packit Service af52df
    def grow_bytes(self, b):
Packit Service af52df
        c_bytesize.bs_size_grow_bytes(self, b)
Packit Service af52df
        return self
Packit Service af52df
Packit Service af52df
    def sub(self, sz):
Packit Service af52df
        return c_bytesize.bs_size_sub(self, sz).contents
Packit Service af52df
Packit Service af52df
    def sub_bytes(self, b):
Packit Service af52df
        return c_bytesize.bs_size_sub_bytes(self, b).contents
Packit Service af52df
Packit Service af52df
    def shrink(self, sz):
Packit Service af52df
        c_bytesize.bs_size_shrink(self, sz)
Packit Service af52df
        return self
Packit Service af52df
Packit Service af52df
    def shrink_bytes(self, b):
Packit Service af52df
        c_bytesize.bs_size_shrink_bytes(self, b)
Packit Service af52df
        return self
Packit Service af52df
Packit Service af52df
    def cmp(self, sz, ign_sgn):
Packit Service af52df
        return c_bytesize.bs_size_cmp(self, sz, ign_sgn)
Packit Service af52df
Packit Service af52df
    def cmp_bytes(self, b, ign_sgn):
Packit Service af52df
        return c_bytesize.bs_size_cmp_bytes(self, b, ign_sgn)
Packit Service af52df
Packit Service af52df
    def convert_to(self, unit):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        ret = c_bytesize.bs_size_convert_to(self, unit, byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        if six.PY3:
Packit Service af52df
            ret = str(ret, "utf-8")
Packit Service af52df
        return ret
Packit Service af52df
Packit Service af52df
    def div(self, sz):
Packit Service af52df
        sgn = ctypes.c_int(0)
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        ret = c_bytesize.bs_size_div(self, sz, byref(sgn), byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        return (ret, sgn.value)
Packit Service af52df
Packit Service af52df
    def div_int(self, div):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        ret = c_bytesize.bs_size_div_int(self, div, byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        return ret.contents
Packit Service af52df
Packit Service af52df
    def shrink_div_int(self, div):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        c_bytesize.bs_size_shrink_div_int(self, div, byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        return self
Packit Service af52df
Packit Service af52df
    def human_readable(self, min_unit, max_places, xlate):
Packit Service af52df
        if six.PY3:
Packit Service af52df
            return str(c_bytesize.bs_size_human_readable(self, min_unit, max_places, xlate), "utf-8")
Packit Service af52df
        else:
Packit Service af52df
            return c_bytesize.bs_size_human_readable(self, min_unit, max_places, xlate)
Packit Service af52df
Packit Service af52df
    def sgn(self):
Packit Service af52df
        return c_bytesize.bs_size_sgn(self)
Packit Service af52df
Packit Service af52df
    def true_div(self, sz):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        ret = c_bytesize.bs_size_true_div(self, sz, byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        if six.PY3:
Packit Service af52df
            ret = str(ret, "utf-8")
Packit Service af52df
        return ret
Packit Service af52df
Packit Service af52df
    def true_div_int(self, div):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        ret = c_bytesize.bs_size_true_div_int(self, div, byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        if six.PY3:
Packit Service af52df
            ret = str(ret, "utf-8")
Packit Service af52df
        return ret
Packit Service af52df
Packit Service af52df
    def mod(self, sz):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        ret = c_bytesize.bs_size_mod(self, sz, byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        return ret.contents
Packit Service af52df
Packit Service af52df
    def mul_float_str(self, fl_str):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        if six.PY3:
Packit Service af52df
            fl_str = bytes(fl_str, "utf-8")
Packit Service af52df
        ret = c_bytesize.bs_size_mul_float_str(self, fl_str, byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        return ret.contents
Packit Service af52df
Packit Service af52df
    def grow_mul_float_str(self, fl_str):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        if six.PY3:
Packit Service af52df
            fl_str = bytes(fl_str, "utf-8")
Packit Service af52df
        c_bytesize.bs_size_grow_mul_float_str(self, fl_str, byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        return self
Packit Service af52df
Packit Service af52df
    def mul_int(self, i):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        ret = c_bytesize.bs_size_mul_int(self, i)
Packit Service af52df
        get_error(err)
Packit Service af52df
        return ret.contents
Packit Service af52df
Packit Service af52df
    def grow_mul_int(self, i):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        c_bytesize.bs_size_grow_mul_int(self, i)
Packit Service af52df
        get_error(err)
Packit Service af52df
        return self
Packit Service af52df
Packit Service af52df
    def round_to_nearest(self, sz, dir):
Packit Service af52df
        err = POINTER(SizeErrorStruct)()
Packit Service af52df
        ret = c_bytesize.bs_size_round_to_nearest(self, sz, dir, byref(err))
Packit Service af52df
        get_error(err)
Packit Service af52df
        return ret.contents
Packit Service af52df
Packit Service af52df
    def __repr__(self):
Packit Service af52df
        return "Size (%s)" % self.human_readable(B, -1, False)
Packit Service af52df
Packit Service af52df
## Constructors
Packit Service af52df
c_bytesize.bs_size_new.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_new.argtypes = []
Packit Service af52df
c_bytesize.bs_size_new_from_bytes.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_new_from_bytes.argtypes = [ctypes.c_ulonglong, ctypes.c_int]
Packit Service af52df
c_bytesize.bs_size_new_from_str.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_new_from_str.argtypes = [ctypes.c_char_p, POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
c_bytesize.bs_size_new_from_size.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_new_from_size.argtypes = [POINTER(SizeStruct)]
Packit Service af52df
Packit Service af52df
## Destructors
Packit Service af52df
c_bytesize.bs_size_free.restype = None
Packit Service af52df
c_bytesize.bs_size_free.argtypes = [POINTER(SizeStruct)]
Packit Service af52df
c_bytesize.bs_clear_error.restype = None
Packit Service af52df
c_bytesize.bs_clear_error.argtypes = [POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
Packit Service af52df
## Query methods
Packit Service af52df
c_bytesize.bs_size_get_bytes.restype = ctypes.c_ulonglong
Packit Service af52df
c_bytesize.bs_size_get_bytes.argtypes = [POINTER(SizeStruct), POINTER(ctypes.c_int), POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
c_bytesize.bs_size_sgn.restype = ctypes.c_int
Packit Service af52df
c_bytesize.bs_size_sgn.argtypes = [POINTER(SizeStruct)]
Packit Service af52df
c_bytesize.bs_size_get_bytes_str.restype = ctypes.c_char_p
Packit Service af52df
c_bytesize.bs_size_get_bytes_str.argtypes = [POINTER(SizeStruct)]
Packit Service af52df
c_bytesize.bs_size_convert_to.restype = ctypes.c_char_p
Packit Service af52df
c_bytesize.bs_size_convert_to.argtypes = [POINTER(SizeStruct), ctypes.c_int, POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
c_bytesize.bs_size_human_readable.restype = ctypes.c_char_p
Packit Service af52df
c_bytesize.bs_size_human_readable.argtypes = [POINTER(SizeStruct), ctypes.c_int, ctypes.c_int, ctypes.c_bool]
Packit Service af52df
Packit Service af52df
## Arithmetic
Packit Service af52df
c_bytesize.bs_size_add.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_add.argtypes = [POINTER(SizeStruct), POINTER(SizeStruct)]
Packit Service af52df
c_bytesize.bs_size_grow.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_grow.argtypes = [POINTER(SizeStruct), POINTER(SizeStruct)]
Packit Service af52df
c_bytesize.bs_size_add_bytes.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_add_bytes.argtypes = [POINTER(SizeStruct), ctypes.c_ulonglong]
Packit Service af52df
c_bytesize.bs_size_grow_bytes.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_grow_bytes.argtypes = [POINTER(SizeStruct), ctypes.c_ulonglong]
Packit Service af52df
c_bytesize.bs_size_sub.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_sub.argtypes = [POINTER(SizeStruct), POINTER(SizeStruct)]
Packit Service af52df
c_bytesize.bs_size_shrink.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_shrink.argtypes = [POINTER(SizeStruct), POINTER(SizeStruct)]
Packit Service af52df
c_bytesize.bs_size_sub_bytes.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_sub_bytes.argtypes = [POINTER(SizeStruct), ctypes.c_ulonglong]
Packit Service af52df
c_bytesize.bs_size_shrink_bytes.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_shrink_bytes.argtypes = [POINTER(SizeStruct), ctypes.c_ulonglong]
Packit Service af52df
c_bytesize.bs_size_mul_int.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_mul_int.argtypes = [POINTER(SizeStruct), ctypes.c_ulonglong]
Packit Service af52df
c_bytesize.bs_size_grow_mul_int.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_grow_mul_int.argtypes = [POINTER(SizeStruct), ctypes.c_ulonglong]
Packit Service af52df
c_bytesize.bs_size_mul_float_str.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_mul_float_str.argtypes = [POINTER(SizeStruct), ctypes.c_char_p, POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
c_bytesize.bs_size_grow_mul_float_str.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_grow_mul_float_str.argtypes = [POINTER(SizeStruct), ctypes.c_char_p, POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
c_bytesize.bs_size_div.restype = ctypes.c_ulonglong
Packit Service af52df
c_bytesize.bs_size_div.argtypes = [POINTER(SizeStruct), POINTER(SizeStruct), POINTER(ctypes.c_int), POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
c_bytesize.bs_size_div_int.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_div_int.argtypes = [POINTER(SizeStruct), ctypes.c_ulonglong, POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
c_bytesize.bs_size_shrink_div_int.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_shrink_div_int.argtypes = [POINTER(SizeStruct), ctypes.c_ulonglong, POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
c_bytesize.bs_size_true_div.restype = ctypes.c_char_p
Packit Service af52df
c_bytesize.bs_size_true_div.argtypes = [POINTER(SizeStruct), POINTER(SizeStruct), POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
c_bytesize.bs_size_true_div_int.restype = ctypes.c_char_p
Packit Service af52df
c_bytesize.bs_size_true_div_int.argtypes = [POINTER(SizeStruct), ctypes.c_ulonglong, POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
c_bytesize.bs_size_mod.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_mod.argtypes = [POINTER(SizeStruct), POINTER(SizeStruct), POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
c_bytesize.bs_size_round_to_nearest.restype = POINTER(SizeStruct)
Packit Service af52df
c_bytesize.bs_size_round_to_nearest.argtypes = [POINTER(SizeStruct), POINTER(SizeStruct), ctypes.c_int, POINTER(POINTER(SizeErrorStruct))]
Packit Service af52df
Packit Service af52df
## Comparisons
Packit Service af52df
c_bytesize.bs_size_cmp.restype = ctypes.c_int
Packit Service af52df
c_bytesize.bs_size_cmp.argtypes = [POINTER(SizeStruct), POINTER(SizeStruct), ctypes.c_bool]
Packit Service af52df
c_bytesize.bs_size_cmp_bytes.restype = ctypes.c_int
Packit Service af52df
c_bytesize.bs_size_cmp_bytes.argtypes = [POINTER(SizeStruct), ctypes.c_ulonglong, ctypes.c_bool]
Packit Service af52df
Packit Service af52df
Packit Service af52df
def _str_to_decimal(num_str):
Packit Service af52df
    radix = locale.nl_langinfo(locale.RADIXCHAR)
Packit Service af52df
    if radix != '.':
Packit Service af52df
        num_str = num_str.replace(radix, '.')
Packit Service af52df
Packit Service af52df
    return Decimal(num_str)
Packit Service af52df
Packit Service af52df
def neutralize_none_operand(fn):
Packit Service af52df
    def fn_with_neutralization(sz, other):
Packit Service af52df
        return fn(sz, Size(0) if other is None else other)
Packit Service af52df
    return fn_with_neutralization
Packit Service af52df
Packit Service af52df
class Size(object):
Packit Service af52df
    def __init__(self, spec=None):
Packit Service af52df
        self._c_size = None
Packit Service af52df
        try:
Packit Service af52df
            if isinstance(spec, six.string_types):
Packit Service af52df
                self._c_size = SizeStruct.new_from_str(spec)
Packit Service af52df
            elif isinstance(spec, six.integer_types):
Packit Service af52df
                abs_val = abs(spec)
Packit Service af52df
                if abs_val == spec:
Packit Service af52df
                    sgn = 1
Packit Service af52df
                else:
Packit Service af52df
                    sgn = -1
Packit Service af52df
                if abs_val <= MAXUINT64:
Packit Service af52df
                    self._c_size = SizeStruct.new_from_bytes(abs_val, sgn)
Packit Service af52df
                else:
Packit Service af52df
                    self._c_size = SizeStruct.new_from_str(str(spec))
Packit Service af52df
            elif isinstance(spec, (Decimal, float)):
Packit Service af52df
                self._c_size = SizeStruct.new_from_str(str(spec))
Packit Service af52df
            elif isinstance(spec, SizeStruct):
Packit Service af52df
                self._c_size = SizeStruct.new_from_size(spec)
Packit Service af52df
            elif isinstance(spec, Size):
Packit Service af52df
                self._c_size = SizeStruct.new_from_size(spec._c_size)
Packit Service af52df
            elif spec is None:
Packit Service af52df
                self._c_size = SizeStruct.new()
Packit Service af52df
            else:
Packit Service af52df
                raise ValueError("Cannot construct new size from '%s'" % spec)
Packit Service af52df
        except SizeError as e:
Packit Service af52df
            raise ValueError(e)
Packit Service af52df
Packit Service af52df
Packit Service af52df
    ## METHODS ##
Packit Service af52df
    def get_bytes(self):
Packit Service af52df
        try:
Packit Service af52df
            val, sgn = self._c_size.get_bytes()
Packit Service af52df
            return val * sgn
Packit Service af52df
        except SizeError:
Packit Service af52df
            return int(self._c_size.get_bytes_str())
Packit Service af52df
Packit Service af52df
    def convert_to(self, unit):
Packit Service af52df
        if isinstance(unit, six.string_types):
Packit Service af52df
            real_unit = unit_strs.get(unit)
Packit Service af52df
            if real_unit is None:
Packit Service af52df
                raise ValueError("Invalid unit specification: '%s'" % unit)
Packit Service af52df
            ret = self._c_size.convert_to(real_unit)
Packit Service af52df
        else:
Packit Service af52df
            ret = self._c_size.convert_to(unit)
Packit Service af52df
Packit Service af52df
        return _str_to_decimal(ret)
Packit Service af52df
Packit Service af52df
    def human_readable(self, min_unit=B, max_places=2, xlate=True):
Packit Service af52df
        if isinstance(min_unit, six.string_types):
Packit Service af52df
            if min_unit in unit_strs.keys():
Packit Service af52df
                min_unit = unit_strs[min_unit]
Packit Service af52df
            else:
Packit Service af52df
                raise ValueError("Invalid unit specification: '%s'" % min_unit)
Packit Service af52df
        if not isinstance(max_places, six.integer_types):
Packit Service af52df
            raise ValueError("max_places has to be an integer number")
Packit Service af52df
        return self._c_size.human_readable(min_unit, max_places, xlate)
Packit Service af52df
Packit Service af52df
    def round_to_nearest(self, round_to, rounding):
Packit Service af52df
        if isinstance(round_to, Size):
Packit Service af52df
            return self._c_size.round_to_nearest(round_to._c_size, rounding)
Packit Service af52df
Packit Service af52df
        size = None
Packit Service af52df
        # else try to create a SizeStruct instance from it
Packit Service af52df
        for (unit_str, unit) in unit_strs.items():
Packit Service af52df
            if round_to in (unit.real, unit_str):
Packit Service af52df
                size = SizeStruct.new_from_str("1 %s" % unit_str)
Packit Service af52df
                break
Packit Service af52df
        if size is not None:
Packit Service af52df
            return Size(self._c_size.round_to_nearest(size, rounding))
Packit Service af52df
        else:
Packit Service af52df
            raise ValueError("Invalid size specification: '%s'"  % round_to)
Packit Service af52df
Packit Service af52df
    def cmp(self, other, abs_vals=False):
Packit Service af52df
        if isinstance(other, six.integer_types):
Packit Service af52df
            if (other < 0 and abs_vals):
Packit Service af52df
                other = abs(other)
Packit Service af52df
            if 0 <= other <= MAXUINT64:
Packit Service af52df
                return self._c_size.cmp_bytes(other, abs_vals)
Packit Service af52df
            else:
Packit Service af52df
                other = SizeStruct.new_from_str(str(other))
Packit Service af52df
        elif isinstance(other, (Decimal, float)):
Packit Service af52df
            other = SizeStruct.new_from_str(str(other))
Packit Service af52df
        elif isinstance(other, Size):
Packit Service af52df
            other = other._c_size
Packit Service af52df
        elif other is None:
Packit Service af52df
            return 1
Packit Service af52df
Packit Service af52df
        return self._c_size.cmp(other, abs_vals)
Packit Service af52df
Packit Service af52df
Packit Service af52df
    ## INTERNAL METHODS ##
Packit Service af52df
    def __eq__(self, other):
Packit Service af52df
        return self.cmp(other, False) == 0
Packit Service af52df
Packit Service af52df
    def __ne__(self, other):
Packit Service af52df
        return self.cmp(other, False) != 0
Packit Service af52df
Packit Service af52df
    def __lt__(self, other):
Packit Service af52df
        return self.cmp(other, False) == -1
Packit Service af52df
Packit Service af52df
    def __le__(self, other):
Packit Service af52df
        return self.cmp(other, False) in (-1, 0)
Packit Service af52df
Packit Service af52df
    def __gt__(self, other):
Packit Service af52df
        return self.cmp(other, False) == 1
Packit Service af52df
Packit Service af52df
    def __ge__(self, other):
Packit Service af52df
        return self.cmp(other, False) in (1, 0)
Packit Service af52df
Packit Service af52df
    def __bool__(self):
Packit Service af52df
        return self.get_bytes() != 0
Packit Service af52df
Packit Service af52df
    __nonzero__ = __bool__
Packit Service af52df
Packit Service af52df
    def __abs__(self):
Packit Service af52df
        return Size(abs(self.get_bytes()))
Packit Service af52df
Packit Service af52df
    def __neg__(self):
Packit Service af52df
        return self.__mul__(-1)
Packit Service af52df
Packit Service af52df
    @neutralize_none_operand
Packit Service af52df
    def __add__(self, other):
Packit Service af52df
        if isinstance(other, six.integer_types):
Packit Service af52df
            if other <= MAXUINT64:
Packit Service af52df
                return Size(self._c_size.add_bytes(other))
Packit Service af52df
            else:
Packit Service af52df
                other = SizeStruct.new_from_str(str(other))
Packit Service af52df
        elif isinstance(other, (Decimal, float)):
Packit Service af52df
            other = SizeStruct.new_from_str(str(other))
Packit Service af52df
        elif isinstance(other, Size):
Packit Service af52df
            other = other._c_size
Packit Service af52df
        return Size(self._c_size.add(other))
Packit Service af52df
Packit Service af52df
    # needed to make sum() work with Size arguments
Packit Service af52df
    __radd__ = __add__
Packit Service af52df
Packit Service af52df
    @neutralize_none_operand
Packit Service af52df
    def __sub__(self, other):
Packit Service af52df
        if isinstance(other, six.integer_types):
Packit Service af52df
            if other <= MAXUINT64:
Packit Service af52df
                return Size(self._c_size.sub_bytes(other))
Packit Service af52df
            else:
Packit Service af52df
                other = SizeStruct.new_from_str(str(other))
Packit Service af52df
        elif isinstance(other, (Decimal, float)):
Packit Service af52df
            other = SizeStruct.new_from_str(str(other))
Packit Service af52df
        elif isinstance(other, Size):
Packit Service af52df
            other = other._c_size
Packit Service af52df
        return Size(self._c_size.sub(other))
Packit Service af52df
Packit Service af52df
    @neutralize_none_operand
Packit Service af52df
    def __rsub__(self, other):
Packit Service af52df
        other = SizeStruct.new_from_str(str(other))
Packit Service af52df
        return Size(SizeStruct.sub(other, self._c_size))
Packit Service af52df
Packit Service af52df
    @neutralize_none_operand
Packit Service af52df
    def __mul__(self, other):
Packit Service af52df
        if isinstance(other, (Size, SizeStruct)):
Packit Service af52df
            raise ValueError("Cannot multiply Size by Size. It just doesn't make sense.")
Packit Service af52df
        elif isinstance(other, (Decimal, float)) or (isinstance(other, six.integer_types)
Packit Service af52df
                                                     and other > MAXUINT64 or other < 0):
Packit Service af52df
            return Size(self._c_size.mul_float_str(str(other)))
Packit Service af52df
        else:
Packit Service af52df
            return Size(self._c_size.mul_int(other))
Packit Service af52df
Packit Service af52df
    __rmul__ = __mul__
Packit Service af52df
Packit Service af52df
    @neutralize_none_operand
Packit Service af52df
    def __div__(self, other):
Packit Service af52df
        if not six.PY2:
Packit Service af52df
            raise AttributeError
Packit Service af52df
Packit Service af52df
        if isinstance(other, six.integer_types):
Packit Service af52df
            if other <= MAXUINT64:
Packit Service af52df
                return Size(self._c_size.div_int(other))
Packit Service af52df
            else:
Packit Service af52df
                other = SizeStruct.new_from_str(str(other))
Packit Service af52df
                return Size(_str_to_decimal(self._c_size.true_div(other)))
Packit Service af52df
        elif isinstance(other, (Decimal, float)):
Packit Service af52df
            other = SizeStruct.new_from_str(str(other))
Packit Service af52df
            return Size(self._c_size.true_div(other))
Packit Service af52df
        else:
Packit Service af52df
            return _str_to_decimal(self._c_size.true_div(other._c_size))
Packit Service af52df
Packit Service af52df
    @neutralize_none_operand
Packit Service af52df
    def __truediv__(self, other):
Packit Service af52df
        if isinstance(other, six.integer_types):
Packit Service af52df
            if other <= MAXUINT64:
Packit Service af52df
                return Size(self._c_size.true_div_int(other))
Packit Service af52df
            else:
Packit Service af52df
                other = SizeStruct.new_from_str(str(other))
Packit Service af52df
                return Size(self._c_size.true_div(other))
Packit Service af52df
        elif isinstance(other, (Decimal, float)):
Packit Service af52df
            return Size(self._c_size.mul_float_str(str(Decimal(1)/Decimal(other))))
Packit Service af52df
Packit Service af52df
        return _str_to_decimal(self._c_size.true_div(other._c_size))
Packit Service af52df
Packit Service af52df
    def _safe_floordiv(self, other):
Packit Service af52df
        try:
Packit Service af52df
            val, sgn = self._c_size.div(other._c_size)
Packit Service af52df
            return val * sgn
Packit Service af52df
        except OverflowError:
Packit Service af52df
            return int(float(self._c_size.true_div(other._c_size)))
Packit Service af52df
Packit Service af52df
    def _safe_floordiv_int(self, other):
Packit Service af52df
        try:
Packit Service af52df
            return Size(self._c_size.div_int(other))
Packit Service af52df
        except OverflowError:
Packit Service af52df
            return Size(float(self._c_size.true_div_int(other)))
Packit Service af52df
Packit Service af52df
    @neutralize_none_operand
Packit Service af52df
    def __floordiv__(self, other):
Packit Service af52df
        if isinstance(other, six.integer_types):
Packit Service af52df
            if other <= MAXUINT64:
Packit Service af52df
                return self._safe_floordiv_int(other)
Packit Service af52df
            else:
Packit Service af52df
                other = SizeStruct.new_from_str(str(other))
Packit Service af52df
                return Size(self._safe_floordiv(other))
Packit Service af52df
        return self._safe_floordiv(other)
Packit Service af52df
Packit Service af52df
    @neutralize_none_operand
Packit Service af52df
    def __mod__(self, other):
Packit Service af52df
        return Size(self._c_size.mod(other._c_size))
Packit Service af52df
Packit Service af52df
    @neutralize_none_operand
Packit Service af52df
    def __divmod__(self, other):
Packit Service af52df
        rdiv = self.__floordiv__(other)
Packit Service af52df
        if not isinstance(other, Size):
Packit Service af52df
            rmod = self.__mod__(rdiv)
Packit Service af52df
        else:
Packit Service af52df
            rmod = self.__mod__(other)
Packit Service af52df
Packit Service af52df
        return (rdiv, rmod)
Packit Service af52df
Packit Service af52df
    def __repr__(self):
Packit Service af52df
        return "Size (%s)" % self.human_readable(B, -1, False)
Packit Service af52df
Packit Service af52df
    def __str__(self):
Packit Service af52df
        return self.human_readable()
Packit Service af52df
Packit Service af52df
    def __int__(self):
Packit Service af52df
        return self.get_bytes()
Packit Service af52df
Packit Service af52df
    def __float__(self):
Packit Service af52df
        return float(self.get_bytes())
Packit Service af52df
Packit Service af52df
    def __deepcopy__(self, memo_dict):
Packit Service af52df
        return Size(self)
Packit Service af52df
Packit Service af52df
    # pickling support for Size
Packit Service af52df
    # see https://docs.python.org/3/library/pickle.html#object.__reduce__
Packit Service af52df
    def __reduce__(self):
Packit Service af52df
        return (self.__class__, (self.get_bytes(),))
Packit Service af52df
Packit Service af52df
    def __hash__(self):
Packit Service af52df
        return self.get_bytes()