def test_argument_prefix(self): n = Float(1e6, prefix='metric') self.assertEqual(str(n), '1M') n = Float(2**20, prefix='binary') self.assertEqual(str(n), '1Mi') n = Float(1e6, prefix='none') self.assertEqual(str(n), '1000000')
def test_argument_unit(self): n = Float(100, unit='A') self.assertEqual(n.with_unit, '100A') self.assertEqual(n.without_unit, '100') n = Float(100) self.assertEqual(n.with_unit, '100') self.assertEqual(n.without_unit, '100')
def test_passing_other_Float_instance_copies_behaviour(self): for orig_prefix in ('binary', 'metric'): for orig_unit in ('A', 'B'): for orig_hide_unit in (True, False): orig = Float(1e3, unit=orig_unit, prefix=orig_prefix, hide_unit=orig_hide_unit) copy = Float(orig) self.assertEqual(str(orig), str(copy)) # Override prefix for new_prefix in ('metric', 'binary'): copy = Float(orig, prefix=new_prefix) self.assertEqual(copy, 1e3) exp_string = '1k' if new_prefix == 'metric' else '1000' exp_string += orig_unit if not orig_hide_unit else '' self.assertEqual(str(copy), exp_string) # Override unit copy = Float(orig, unit='Z') self.assertEqual(copy, 1e3) exp_string = '1k' if orig_prefix == 'metric' else '1000' exp_string += 'Z' if not orig_hide_unit else '' self.assertEqual(str(copy), exp_string) # Override hide_unit for new_hide_unit in (True, False): copy = Float(orig, hide_unit=new_hide_unit) self.assertEqual(copy, 1e3) exp_string = '1k' if orig_prefix == 'metric' else '1000' exp_string += orig_unit if not new_hide_unit else '' self.assertEqual(str(copy), exp_string)
def test_argument_autolimit(self): with self.assert_raises(ValueError, 'Too big (maximum is 10)'): Float(11, max=10, autolimit=False) self.assertEqual(Float(11, max=10, autolimit=True), 10) with self.assert_raises(ValueError, 'Too small (minimum is 10)'): Float(9, min=10, autolimit=False) self.assertEqual(Float(9, min=10, autolimit=True), 10)
def test_arithmetic_operation_ensures_common_unit(self): a = Float(10e3, unit='B', prefix='metric') b = Float(1024 * 10, unit='b', prefix='binary') c = a + b self.assertEqual(c, 10e3 + (10240 / 8)) self.assertEqual(c.unit, 'B') self.assertEqual(c.prefix, 'metric') self.assertEqual(str(c), '11.3kB')
def test_arithmetic_operation_with_base_types(self): x = Float('10k', unit='B', prefix='metric') + 2000 self.assertEqual(str(x), '12kB') x = Float('10k', unit='B', prefix='metric') - 2000 self.assertEqual(str(x), '8kB') x = Float('10k', unit='B', prefix='metric') / 2 self.assertEqual(str(x), '5kB') x = Float('10k', unit='B', prefix='metric') * 2 self.assertEqual(str(x), '20kB')
def test_argument_convert_to(self): n = Float(1000, unit='B', convert_to='b') self.assertEqual(str(n), '8kb') n = Float('1000b', convert_to='b') self.assertEqual(str(n), '1kb') n = Float(1000, unit='b', convert_to='B') self.assertEqual(str(n), '125B') n = Float('1000B', convert_to='B') self.assertEqual(str(n), '1kB')
def test_argument_hide_unit(self): n = Float(1e6, unit='f', hide_unit=True) self.assertEqual(str(n), '1M') self.assertEqual(n.without_unit, '1M') self.assertEqual(n.with_unit, '1Mf') n = Float(1e6, unit='f', hide_unit=False) self.assertEqual(str(n), '1Mf') self.assertEqual(n.without_unit, '1M') self.assertEqual(n.with_unit, '1Mf')
def test_string_has_reasonable_number_of_decimal_points(self): self.assertEqual(str(Float(0)), '0') self.assertEqual(str(Float(0.009)), '0.01') self.assertEqual(str(Float(0.09123)), '0.09') self.assertEqual(str(Float(5.001)), '5') self.assertEqual(str(Float(8.999)), '9') self.assertEqual(str(Float(9.09123)), '9.09') self.assertEqual(str(Float(10.09123)), '10.1') self.assertEqual(str(Float(79.999)), '80') self.assertEqual(str(Float(99.09123)), '99.1') self.assertEqual(str(Float(99.95)), '100')
def test_parsing_signs(self): for string, exp_num in ( ('-10', -10), ('+10', 10), ('-10Ki', -10 * (2**10)), ('+10k', 10e3), ('-17Mx', -17e6), ('+99Tiy', 99 * (2**40)), ): n = Float(string) self.assertEqual(n, exp_num) self.assertEqual(str(n), string.lstrip('+'))
def test_valid_value_behaves_like_subclass_instance(self): mt = multitype(Float.partial(min=10), String) x = mt(15) self.assertEqual(x, 15.0) self.assertEqual(x + 5, 20.0) with self.assert_raises(TypeError): x + '!' x = mt('hello') self.assertEqual(x, 'hello') self.assertEqual(x + '!', 'hello!') with self.assert_raises(TypeError): x + 5
def test_parsing_strings(self): for string, exp_num in ( ('1 Apple', 1), ('10.3x', 10.3), ('2kT', 2 * 1e3), ('3 KiB', 3 * (2**10)), ('4 MJ', 4 * 1e6), ('10.5Mib', 10.5 * 2**20), ('50Gp', 50 * 1e9), ('62.7Gi', 62.7 * 2**30), ('7.19TB', 7.19 * 1e12), ('8.9TiV', 8.9 * 2**40), ): n = Float(string) self.assertEqual(n, exp_num) self.assertEqual(str(n), string.replace(' ', ''))
def test_arithmetic_operation_returns_correct_type(self): self.assertIsInstance(Float(2.5) + 1.5, Int) self.assertIsInstance(Float(2.5) - 1.5, Int) self.assertIsInstance(Float(2.5) * 2, Int) self.assertIsInstance(Float(10) % 1, Int) self.assertIsInstance(Int(5) + 4.3, Float) self.assertIsInstance(Int(5) - 0.1, Float) self.assertIsInstance(Int(5) / 2, Float) self.assertIsInstance(Int(5) % 0.3, Float) self.assertIsInstance(round(Float(5.4)), Int) self.assertIsInstance(Float('inf') / 2, Float)
def test_parsing_with_conflicting_units(self): n = Float('123kF', unit='B') self.assertEqual(n, 123000) self.assertEqual(str(n), '123kF')
def test_arithmetic_operation_copies_from_first_value(self): for prfx, exp_string in (('metric', '1.25M'), ('binary', '1.19Mi')): n = (Float(1e6, prefix=prfx, hide_unit=False) + Float(250e3, prefix='metric', hide_unit=True)) self.assertEqual(n, 1.25e6) self.assertEqual(str(n), exp_string)
def test_arithmetic_operation_copies_hide_unit(self): for hide_unit, exp_string in ((True, '500'), (False, '500u')): n = Float(5, unit='u', hide_unit=hide_unit) * 100 self.assertEqual(str(n), exp_string)
def test_arithmetic_operation_copies_prefix(self): for prfx, factor, exp_string in (('metric', 1e6, '5M'), ('binary', 2**20, '5Mi')): n = Float(5, prefix=prfx) * factor self.assertEqual(str(n), exp_string)
def test_arithmetic_operation_copies_unit(self): n = Float(5, unit='X') / 100 self.assertEqual(str(n), '0.05X')
def test_infinity_has_correct_sign(self): self.assertEqual(str(Float(float('inf'))), '∞') self.assertEqual(str(Float(-float('inf'))), '-∞')
def test_syntax(self): self.assertEqual(Float('1').syntax, '<NUMBER>[Ti|Gi|Mi|Ki|T|G|M|k]')
def test_not_a_number(self): for value in ('foo', '25xx02', [1, 2, 3], print): with self.assert_raises(ValueError, 'Not a number'): Float(value)
def test_argument_min(self): Float(100, min=100) with self.assert_raises(ValueError, 'Too small (minimum is 100)'): Float(99.9, min=100)
def test_argument_max(self): Float(100, max=100) with self.assert_raises(ValueError, 'Too big (maximum is 100)'): Float(100.1, max=100)
def test_classname(self): mt = multitype(Bool, Float.partial(max=100), String) self.assertEqual(mt.__name__, 'BoolOrFloatOrString')
def test_unit_conversion(self): self.conv.unit = 'B' self.conv.prefix = 'metric' self.assertEqual(self.conv(Float('100kB')).with_unit, '100kB') self.assertEqual(self.conv(Float('100kb')).with_unit, '12.5kB') self.assertEqual(self.conv(Float('100KiB')).with_unit, '102kB') self.assertEqual(self.conv(Float('100Kib')).with_unit, '12.8kB') self.conv.unit = 'b' self.conv.prefix = 'metric' self.assertEqual(self.conv(Float('100kB')).with_unit, '800kb') self.assertEqual(self.conv(Float('100kb')).with_unit, '100kb') self.assertEqual(self.conv(Float('100KiB')).with_unit, '819kb') self.assertEqual(self.conv(Float('100Kib')).with_unit, '102kb') self.conv.unit = 'B' self.conv.prefix = 'binary' self.assertEqual(self.conv(Float('100kB')).with_unit, '97.7KiB') self.assertEqual(self.conv(Float('100kb')).with_unit, '12.2KiB') self.assertEqual(self.conv(Float('100KiB')).with_unit, '100KiB') self.assertEqual(self.conv(Float('100Kib')).with_unit, '12.5KiB') self.conv.unit = 'b' self.conv.prefix = 'binary' self.assertEqual(self.conv(Float('100kB')).with_unit, '781Kib') self.assertEqual(self.conv(Float('100kb')).with_unit, '97.7Kib') self.assertEqual(self.conv(Float('100KiB')).with_unit, '800Kib') self.assertEqual(self.conv(Float('100Kib')).with_unit, '100Kib')