MemoryUnit Incorrectly normalizes to uppercase

As per GNU standard, modified scalar units dictionary in utils.py.
Validating scalar unit size and if not followed GNU standard,
converting given scalar unit to GNU standard value after displaying
a warning message.

Modified scalar unit dictionaries in scalarunit.py
Added validation for scalar input unit
Added testcases in test_utils.py

Modified the code to avoid displaying warning message multiple times

Change-Id: Ie038e797f0bedb5da8f97e0f4688b961242b9015
This commit is contained in:
Madhurya 2015-08-12 10:55:06 +05:30
parent 9d8fce01c7
commit 4a6eaedf3c
6 changed files with 103 additions and 52 deletions

View File

@ -28,10 +28,10 @@ log = logging.getLogger('tosca')
class MemoryUnit(object):
UNIT_SIZE_DEFAULT = 'B'
UNIT_SIZE_DICT = {'B': 1, 'KB': 1000, 'KIB': 1024, 'MB': 1000000,
'MIB': 1048576, 'GB': 1000000000,
'GIB': 1073741824, 'TB': 1000000000000,
'TIB': 1099511627776}
UNIT_SIZE_DICT = {'B': 1, 'kB': 1000, 'KiB': 1024, 'MB': 1000000,
'MiB': 1048576, 'GB': 1000000000,
'GiB': 1073741824, 'TB': 1000000000000,
'TiB': 1099511627776}
@staticmethod
def convert_unit_size_to_num(size, unit=None):
@ -42,29 +42,38 @@ class MemoryUnit(object):
:param unit: unit to be converted to e.g GB
:return: converted number e.g. 1000 for 1 TB size and unit GB
"""
if unit:
MemoryUnit.validate_unit(unit)
unit = MemoryUnit.validate_unit(unit)
else:
unit = MemoryUnit.UNIT_SIZE_DEFAULT
log.info(_('A memory unit is not provided for size; using the '
'default unit %(default)s') % {'default': 'B'})
regex = re.compile('(\d*)\s*(\w*)')
result = regex.match(str(size)).groups()
if result[1]:
MemoryUnit.validate_unit(result[1])
unit_size = MemoryUnit.validate_unit(result[1])
converted = int(str_to_num(result[0])
* MemoryUnit.UNIT_SIZE_DICT[result[1].upper()]
* MemoryUnit.UNIT_SIZE_DICT[unit_size]
* math.pow(MemoryUnit.UNIT_SIZE_DICT
[unit.upper()], -1))
[unit], -1))
log.info(_('Given size %(size)s is converted to %(num)s '
'%(unit)s') % {'size': size,
'num': converted, 'unit': unit})
else:
converted = (str_to_num(result[0]))
return converted
@staticmethod
def validate_unit(unit):
if unit.upper() not in MemoryUnit.UNIT_SIZE_DICT.keys():
msg = _('Provided unit "{0}" is not valid. The valid units are '
'{1}').format(unit, MemoryUnit.UNIT_SIZE_DICT.keys())
if unit in MemoryUnit.UNIT_SIZE_DICT.keys():
return unit
else:
for key in MemoryUnit.UNIT_SIZE_DICT.keys():
if key.upper() == unit.upper():
return key
msg = _('Provided unit "{0}" is not valid. The valid units are'
' {1}').format(unit, MemoryUnit.UNIT_SIZE_DICT.keys())
raise ValueError(msg)

View File

@ -51,6 +51,32 @@ class CommonUtilsTest(TestCase):
isinstance(err, ValueError))
self.assertEqual(exp_msg, err.__str__())
def test_unit_size_conversion_to_GNU_standard(self):
unit = 'gB'
standard_unit = 'GB'
converted_unit = self.MemoryUnit.validate_unit(unit)
self.assertEqual(converted_unit, standard_unit)
unit = 'KB'
standard_unit = 'kB'
converted_unit = self.MemoryUnit.validate_unit(unit)
self.assertEqual(converted_unit, standard_unit)
unit = 'kb'
standard_unit = 'kB'
converted_unit = self.MemoryUnit.validate_unit(unit)
self.assertEqual(converted_unit, standard_unit)
unit = 'kB'
standard_unit = 'kB'
converted_unit = self.MemoryUnit.validate_unit(unit)
self.assertEqual(converted_unit, standard_unit)
unit = 'MIB'
standard_unit = 'MiB'
converted_unit = self.MemoryUnit.validate_unit(unit)
self.assertEqual(converted_unit, standard_unit)
def test_str_to_num_value_error(self):
str_to_convert = '55063.000000'
expected_output = 55063.0

View File

@ -119,7 +119,8 @@ class DataEntity(object):
elif type == Schema.BOOLEAN:
return validateutils.validate_boolean(value)
elif type == Schema.TIMESTAMP:
return validateutils.validate_timestamp(value)
validateutils.validate_timestamp(value)
return value
elif type == Schema.LIST:
validateutils.validate_list(value)
if entry_schema:

View File

@ -10,11 +10,14 @@
# License for the specific language governing permissions and limitations
# under the License.
import logging
import re
from translator.toscalib.utils.gettextutils import _
from translator.toscalib.utils import validateutils
log = logging.getLogger('tosca')
class ScalarUnit(object):
'''Parent class for scalar-unit type.'''
@ -28,23 +31,42 @@ class ScalarUnit(object):
def __init__(self, value):
self.value = value
def _check_unit_in_scalar_standard_units(self, input_unit):
"""Check whether the input unit is following specified standard
If unit is not following specified standard, convert it to standard
unit after displaying a warning message.
"""
if input_unit in self.SCALAR_UNIT_DICT.keys():
return input_unit
else:
for key in self.SCALAR_UNIT_DICT.keys():
if key.upper() == input_unit.upper():
log.warning(_('Given unit %(unit)s does not follow scalar '
'unit standards; using %(key)s instead.') % {
'unit': input_unit, 'key': key})
return key
msg = (_('Provided unit "%(unit)s" is not valid. The valid units'
' are %(valid_units)s') % {'unit': input_unit,
'valid_units': sorted(self.SCALAR_UNIT_DICT.keys())})
raise ValueError(msg)
def validate_scalar_unit(self):
regex = re.compile('([0-9.]+)\s*(\w+)')
try:
result = regex.match(str(self.value)).groups()
validateutils.str_to_num(result[0])
scalar_unit = self._check_unit_in_scalar_standard_units(result[1])
self.value = ' '.join([result[0], scalar_unit])
return self.value
except Exception:
raise ValueError(_('"%s" is not a valid scalar-unit')
% self.value)
if result[1].upper() in self.SCALAR_UNIT_DICT.keys():
return self.value
raise ValueError(_('"%s" is not a valid scalar-unit') % self.value)
def get_num_from_scalar_unit(self, unit=None):
if unit:
if unit.upper() not in self.SCALAR_UNIT_DICT.keys():
raise ValueError(_('input unit "%s" is not a valid unit')
% unit)
unit = self._check_unit_in_scalar_standard_units(unit)
else:
unit = self.SCALAR_UNIT_DEFAULT
self.validate_scalar_unit()
@ -52,45 +74,34 @@ class ScalarUnit(object):
regex = re.compile('([0-9.]+)\s*(\w+)')
result = regex.match(str(self.value)).groups()
converted = (float(validateutils.str_to_num(result[0]))
* self.SCALAR_UNIT_DICT[result[1].upper()]
/ self.SCALAR_UNIT_DICT[unit.upper()])
* self.SCALAR_UNIT_DICT[result[1]]
/ self.SCALAR_UNIT_DICT[unit])
if converted - int(converted) < 0.0000000000001:
converted = int(converted)
return converted
def get_unit_from_scalar_unit(self, unit=None):
if unit:
if unit.upper() not in self.SCALAR_UNIT_DICT.keys():
raise ValueError(_('input unit "%s" is not a valid unit')
% unit)
return unit
else:
regex = re.compile('([0-9.]+)\s*(\w+)')
result = regex.match(str(self.value)).groups()
return result[1].upper()
class ScalarUnit_Size(ScalarUnit):
SCALAR_UNIT_DEFAULT = 'B'
SCALAR_UNIT_DICT = {'B': 1, 'KB': 1000, 'KIB': 1024, 'MB': 1000000,
'MIB': 1048576, 'GB': 1000000000,
'GIB': 1073741824, 'TB': 1000000000000,
'TIB': 1099511627776}
SCALAR_UNIT_DICT = {'B': 1, 'kB': 1000, 'KiB': 1024, 'MB': 1000000,
'MiB': 1048576, 'GB': 1000000000,
'GiB': 1073741824, 'TB': 1000000000000,
'TiB': 1099511627776}
class ScalarUnit_Time(ScalarUnit):
SCALAR_UNIT_DEFAULT = 'MS'
SCALAR_UNIT_DICT = {'D': 86400, 'H': 3600, 'M': 60, 'S': 1,
'MS': 0.001, 'US': 0.000001, 'NS': 0.000000001}
SCALAR_UNIT_DEFAULT = 'ms'
SCALAR_UNIT_DICT = {'d': 86400, 'h': 3600, 'm': 60, 's': 1,
'ms': 0.001, 'us': 0.000001, 'ns': 0.000000001}
class ScalarUnit_Frequency(ScalarUnit):
SCALAR_UNIT_DEFAULT = 'GHZ'
SCALAR_UNIT_DICT = {'HZ': 1, 'KHZ': 1000,
'MHZ': 1000000, 'GHZ': 1000000000}
SCALAR_UNIT_DEFAULT = 'GHz'
SCALAR_UNIT_DICT = {'Hz': 1, 'kHz': 1000,
'MHz': 1000000, 'GHz': 1000000000}
scalarunit_mapping = {

View File

@ -65,8 +65,9 @@ class Property(object):
if not is_function(self.value):
if self.type == Schema.STRING:
self.value = str(self.value)
DataEntity.validate_datatype(self.type, self.value,
self.entry_schema, self.custom_def)
self.value = DataEntity.validate_datatype(self.type, self.value,
self.entry_schema,
self.custom_def)
self._validate_constraints()
def _validate_constraints(self):

View File

@ -48,7 +48,7 @@ class ScalarUnitPositiveTest(TestCase):
mem_size: 1 GB
''',
property='mem_size',
expected='1 GB')
expected='1 GB')
),
(
# tpl_snippet with mem_size given as number+tiB
@ -62,7 +62,7 @@ class ScalarUnitPositiveTest(TestCase):
mem_size: 1tiB
''',
property='mem_size',
expected='1tiB')
expected='1 TiB')
),
(
# tpl_snippet with mem_size given as number+Spaces+GIB
@ -76,7 +76,7 @@ class ScalarUnitPositiveTest(TestCase):
mem_size: 1 GIB
''',
property='mem_size',
expected='1 GIB')
expected='1 GiB')
),
(
# tpl_snippet with mem_size given as number+Space+tib
@ -90,7 +90,7 @@ class ScalarUnitPositiveTest(TestCase):
mem_size: 1 tib
''',
property='mem_size',
expected='1 tib')
expected='1 TiB')
),
(
'cpu_frequency_is_float_Space_GHz',
@ -243,7 +243,9 @@ class GetNumFromScalarUnitSizeNegative(TestCase):
get_num_from_scalar_unit(self.UserInputUnit))
except Exception as error:
self.assertTrue(isinstance(error, ValueError))
self.assertEqual('input unit "qB" is not a valid unit',
self.assertEqual('Provided unit "qB" is not valid. The valid units'
' are [\'B\', \'GB\', \'GiB\', \'KiB\', \'MB\','
' \'MiB\', \'TB\', \'TiB\', \'kB\']',
error.__str__())
@ -258,7 +260,8 @@ class GetNumFromScalarUnitFrequencyNegative(TestCase):
get_num_from_scalar_unit(self.UserInputUnit))
except Exception as error:
self.assertTrue(isinstance(error, ValueError))
self.assertEqual('input unit "Jz" is not a valid unit',
self.assertEqual('Provided unit "Jz" is not valid. The valid'
' units are [\'GHz\', \'Hz\', \'MHz\', \'kHz\']',
error.__str__())
@ -273,7 +276,7 @@ class GetNumFromScalarUnitTimeNegative(TestCase):
get_num_from_scalar_unit(self.UserInputUnit))
except Exception as error:
self.assertTrue(isinstance(error, ValueError))
self.assertEqual('input unit "Jz" is not a valid unit',
self.assertEqual('"Jz" is not a valid scalar-unit',
error.__str__())