# Gabe Black
# metric prefixes
-exa = 1.0e18
-peta = 1.0e15
-tera = 1.0e12
-giga = 1.0e9
-mega = 1.0e6
-kilo = 1.0e3
-
-milli = 1.0e-3
-micro = 1.0e-6
-nano = 1.0e-9
-pico = 1.0e-12
-femto = 1.0e-15
atto = 1.0e-18
+femto = 1.0e-15
+pico = 1.0e-12
+nano = 1.0e-9
+micro = 1.0e-6
+milli = 1.0e-3
+
+kilo = 1.0e3
+mega = 1.0e6
+giga = 1.0e9
+tera = 1.0e12
+peta = 1.0e15
+exa = 1.0e18
# power of 2 prefixes
kibi = 1024
pebi = tebi * 1024
exbi = pebi * 1024
-# memory size configuration stuff
-def toFloat(value):
+metric_prefixes = {
+ 'Ei': exbi,
+ 'E': exa,
+ 'Pi': pebi,
+ 'P': peta,
+ 'Ti': tebi,
+ 'T': tera,
+ 'Gi': gibi,
+ 'G': giga,
+ 'M': mega,
+ 'ki': kibi,
+ 'k': kilo,
+ 'Mi': mebi,
+ 'm': milli,
+ 'u': micro,
+ 'n': nano,
+ 'p': pico,
+ 'f': femto,
+ 'a': atto,
+}
+
+binary_prefixes = {
+ 'Ei': exbi,
+ 'E' : exbi,
+ 'Pi': pebi,
+ 'P' : pebi,
+ 'Ti': tebi,
+ 'T' : tebi,
+ 'Gi': gibi,
+ 'G' : gibi,
+ 'Mi': mebi,
+ 'M' : mebi,
+ 'ki': kibi,
+ 'k' : kibi,
+}
+
+def assertStr(value):
if not isinstance(value, str):
raise TypeError, "wrong type '%s' should be str" % type(value)
- if value.endswith('Ei'):
- return float(value[:-2]) * exbi
- elif value.endswith('Pi'):
- return float(value[:-2]) * pebi
- elif value.endswith('Ti'):
- return float(value[:-2]) * tebi
- elif value.endswith('Gi'):
- return float(value[:-2]) * gibi
- elif value.endswith('Mi'):
- return float(value[:-2]) * mebi
- elif value.endswith('ki'):
- return float(value[:-2]) * kibi
- elif value.endswith('E'):
- return float(value[:-1]) * exa
- elif value.endswith('P'):
- return float(value[:-1]) * peta
- elif value.endswith('T'):
- return float(value[:-1]) * tera
- elif value.endswith('G'):
- return float(value[:-1]) * giga
- elif value.endswith('M'):
- return float(value[:-1]) * mega
- elif value.endswith('k'):
- return float(value[:-1]) * kilo
- elif value.endswith('m'):
- return float(value[:-1]) * milli
- elif value.endswith('u'):
- return float(value[:-1]) * micro
- elif value.endswith('n'):
- return float(value[:-1]) * nano
- elif value.endswith('p'):
- return float(value[:-1]) * pico
- elif value.endswith('f'):
- return float(value[:-1]) * femto
- else:
+
+# memory size configuration stuff
+def toFloat(value, target_type='float', units=None, prefixes=[]):
+ assertStr(value)
+
+ if units and not value.endswith(units):
+ units = None
+ if not units:
+ try:
+ return float(value)
+ except ValueError:
+ raise ValueError, "cannot convert '%s' to %s" % \
+ (value, target_type)
+
+ value = value[:-len(units)]
+
+ prefix = next((p for p in prefixes.keys() if value.endswith(p)), None)
+ if not prefix:
return float(value)
+ value = value[:-len(prefix)]
+
+ return float(value) * prefixes[prefix]
+
+def toMetricFloat(value, target_type='float', units=None):
+ return toFloat(value, target_type, units, metric_prefixes)
-def toInteger(value):
- value = toFloat(value)
+def toBinaryFloat(value, target_type='float', units=None):
+ return toFloat(value, target_type, units, binary_prefixes)
+
+def toInteger(value, target_type='integer', units=None, prefixes=[]):
+ value = toFloat(value, target_type, units, prefixes)
result = long(value)
if value != result:
- raise ValueError, "cannot convert '%s' to integer" % value
+ raise ValueError, "cannot convert '%s' to integer %s" % \
+ (value, target_type)
return result
-_bool_dict = {
- 'true' : True, 't' : True, 'yes' : True, 'y' : True, '1' : True,
- 'false' : False, 'f' : False, 'no' : False, 'n' : False, '0' : False
- }
+def toMetricInteger(value, target_type='integer', units=None):
+ return toInteger(value, target_type, units, metric_prefixes)
+
+def toBinaryInteger(value, target_type='integer', units=None):
+ return toInteger(value, target_type, units, binary_prefixes)
def toBool(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
+ assertStr(value)
value = value.lower()
- result = _bool_dict.get(value, None)
- if result == None:
- raise ValueError, "cannot convert '%s' to bool" % value
+ if value in ('true', 't', 'yes', 'y', '1'):
+ return True
+ if value in ('false', 'f', 'no', 'n', '0'):
+ return False
return result
def toFrequency(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('THz'):
- return float(value[:-3]) * tera
- elif value.endswith('GHz'):
- return float(value[:-3]) * giga
- elif value.endswith('MHz'):
- return float(value[:-3]) * mega
- elif value.endswith('kHz'):
- return float(value[:-3]) * kilo
- elif value.endswith('Hz'):
- return float(value[:-2])
-
- raise ValueError, "cannot convert '%s' to frequency" % value
+ return toMetricFloat(value, 'frequency', 'Hz')
def toLatency(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('ps'):
- return float(value[:-2]) * pico
- elif value.endswith('ns'):
- return float(value[:-2]) * nano
- elif value.endswith('us'):
- return float(value[:-2]) * micro
- elif value.endswith('ms'):
- return float(value[:-2]) * milli
- elif value.endswith('s'):
- return float(value[:-1])
-
- raise ValueError, "cannot convert '%s' to latency" % value
+ return toMetricFloat(value, 'latency', 's')
def anyToLatency(value):
"""result is a clock period"""
-
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
try:
- val = toFrequency(value)
- if val != 0:
- val = 1 / val
- return val
- except ValueError:
+ return 1 / toFrequency(value)
+ except ValueError, ZeroDivisionError:
pass
try:
- val = toLatency(value)
- return val
+ return toLatency(value)
except ValueError:
pass
def anyToFrequency(value):
"""result is a clock period"""
-
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
try:
- val = toFrequency(value)
- return val
+ return toFrequency(value)
except ValueError:
pass
try:
- val = toLatency(value)
- if val != 0:
- val = 1 / val
- return val
- except ValueError:
+ return 1 / toLatency(value)
+ except ValueError, ZeroDivisionError:
pass
raise ValueError, "cannot convert '%s' to clock period" % value
def toNetworkBandwidth(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('Tbps'):
- return float(value[:-4]) * tera
- elif value.endswith('Gbps'):
- return float(value[:-4]) * giga
- elif value.endswith('Mbps'):
- return float(value[:-4]) * mega
- elif value.endswith('kbps'):
- return float(value[:-4]) * kilo
- elif value.endswith('bps'):
- return float(value[:-3])
- else:
- return float(value)
-
- raise ValueError, "cannot convert '%s' to network bandwidth" % value
+ return toMetricFloat(value, 'network bandwidth', 'bps')
def toMemoryBandwidth(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('PB/s'):
- return float(value[:-4]) * pebi
- elif value.endswith('TB/s'):
- return float(value[:-4]) * tebi
- elif value.endswith('GB/s'):
- return float(value[:-4]) * gibi
- elif value.endswith('MB/s'):
- return float(value[:-4]) * mebi
- elif value.endswith('kB/s'):
- return float(value[:-4]) * kibi
- elif value.endswith('B/s'):
- return float(value[:-3])
-
- raise ValueError, "cannot convert '%s' to memory bandwidth" % value
+ return toBinaryFloat(value, 'memory bandwidth', 'B/s')
def toMemorySize(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('PB'):
- return long(value[:-2]) * pebi
- elif value.endswith('TB'):
- return long(value[:-2]) * tebi
- elif value.endswith('GB'):
- return long(value[:-2]) * gibi
- elif value.endswith('MB'):
- return long(value[:-2]) * mebi
- elif value.endswith('kB'):
- return long(value[:-2]) * kibi
- elif value.endswith('B'):
- return long(value[:-1])
-
- raise ValueError, "cannot convert '%s' to memory size" % value
+ return toBinaryInteger(value, 'memory size', 'B')
def toIpAddress(value):
if not isinstance(value, str):
return (ip, int(port))
def toVoltage(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('mV'):
- return float(value[:-2]) * milli
- elif value.endswith('V'):
- return float(value[:-1])
-
- raise ValueError, "cannot convert '%s' to voltage" % value
+ return toMetricFloat(value, 'voltage', 'V')
def toCurrent(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('A'):
- return toFloat(value[:-1])
-
- raise ValueError, "cannot convert '%s' to current" % value
+ return toMetricFloat(value, 'current', 'A')