From 8e446dcfb67fef8321e66ce672a58426f2bb60fe Mon Sep 17 00:00:00 2001 From: Holger Mueller Date: Mon, 25 Nov 2019 10:33:07 +0100 Subject: [PATCH] More SITools tests Added more test for SITools Value Modified parse semantic a little bit, returns Value object now --- NanoVNASaver/RFTools.py | 2 +- NanoVNASaver/SITools.py | 22 ++++++-- test/test_parseFrequency.py | 4 +- test/test_sitools.py | 104 ++++++++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 7 deletions(-) create mode 100644 test/test_sitools.py diff --git a/NanoVNASaver/RFTools.py b/NanoVNASaver/RFTools.py index 730cb1d..c5a0869 100644 --- a/NanoVNASaver/RFTools.py +++ b/NanoVNASaver/RFTools.py @@ -154,6 +154,6 @@ class RFTools: def parseFrequency(freq: str) -> int: parser = Value(0, "Hz", Format(parse_sloppy_unit=True, parse_sloppy_kilo=True)) try: - return round(parser.parse(freq)) + return round(parser.parse(freq).value) except (ValueError, IndexError): return -1 diff --git a/NanoVNASaver/SITools.py b/NanoVNASaver/SITools.py index edab569..8d6eaf6 100644 --- a/NanoVNASaver/SITools.py +++ b/NanoVNASaver/SITools.py @@ -31,6 +31,7 @@ class Format(NamedTuple): min_offset: int = -8 max_offset: int = 8 allow_strip: bool = False + allways_signed: bool = False parse_sloppy_unit: bool = False parse_sloppy_kilo: bool = False parse_clamp_min: float = -math.inf @@ -86,6 +87,8 @@ class Value: (1 if not fmt.fix_decimals and abs(real) < 100 else 0)) formstr = "." + str(max_digits - 3) + "f" + if self.fmt.allways_signed: + formstr = "+" + formstr result = format(real, formstr) if float(result) == 0.0: @@ -96,11 +99,22 @@ class Value: return result + fmt.space_str + PREFIXES[offset + 8] + self._unit - @property - def value(self): + def __float__(self): return float(self._value) - def parse(self, value: str) -> float: + @property + def value(self): + return self._value + + @value.setter + def value(self, value: Number): + self._value = decimal.Decimal(value, context=Value.CTX) + + def parse(self, value: str) -> Value: + if isinstance(value, Number): + self.value = value + return self + value = value.replace(" ", "") # Ignore spaces if self._unit and ( @@ -132,7 +146,7 @@ class Value: self._value = self.fmt.parse_clamp_min elif self._value > self.fmt.parse_clamp_max: self._value = self.fmt.parse_clamp_max - return float(self._value) + return self @property def unit(self) -> str: diff --git a/test/test_parseFrequency.py b/test/test_parseFrequency.py index 860b20b..d0f5ff7 100644 --- a/test/test_parseFrequency.py +++ b/test/test_parseFrequency.py @@ -72,8 +72,8 @@ class TestCases(unittest.TestCase): self.assertEqual(rft.parseFrequency('123EHz'), 123000000000000000000) self.assertEqual(rft.parseFrequency('123PHz'), 123000000000000000) self.assertEqual(rft.parseFrequency('123THz'), 123000000000000) - self.assertEqual(rft.parseFrequency('123YHz'), 122999999999999998473273344) - self.assertEqual(rft.parseFrequency('123ZHz'), 123000000000000002097152) + self.assertEqual(rft.parseFrequency('123YHz'), 123000000000000000000000000) + self.assertEqual(rft.parseFrequency('123ZHz'), 123000000000000000000000) self.assertEqual(rft.parseFrequency('123aHz'), 0) self.assertEqual(rft.parseFrequency('123fHz'), 0) self.assertEqual(rft.parseFrequency('123mHz'), 0) diff --git a/test/test_sitools.py b/test/test_sitools.py new file mode 100644 index 0000000..01b725d --- /dev/null +++ b/test/test_sitools.py @@ -0,0 +1,104 @@ +# NanoVNASaver +# A python program to view and export Touchstone data from a NanoVNA +# Copyright (C) 2019. Rune B. Broberg +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +import unittest + +# Import targets to be tested +from NanoVNASaver.SITools import Format, Value + +F_DEFAULT = Format() + +F_ASSERT_DIGITS_1 = Format(max_nr_digits=2) +F_ASSERT_DIGITS_2 = Format(max_nr_digits=31) +F_ASSERT_OFFSET_1 = Format(min_offset=-9) +F_ASSERT_OFFSET_2 = Format(max_offset=9) +F_ASSERT_OFFSET_3 = Format(min_offset=9) +F_ASSERT_CLAMP = Format(parse_clamp_min=10, parse_clamp_max=9) + +F_DIGITS_3 = Format(max_nr_digits=3) +F_DIGITS_4 = Format(max_nr_digits=3) +F_DIGITS_31 = Format(max_nr_digits=30) + +F_WITH_SPACE = Format(space_str=" ") +F_WITH_UNDERSCORE = Format(space_str="_") + + +class TestTSIToolsValue(unittest.TestCase): + + def test_format_asssertions(self): + self.assertRaises(AssertionError, Value, fmt=F_ASSERT_DIGITS_1) + self.assertRaises(AssertionError, Value, fmt=F_ASSERT_DIGITS_2) + self.assertRaises(AssertionError, Value, fmt=F_ASSERT_OFFSET_1) + self.assertRaises(AssertionError, Value, fmt=F_ASSERT_OFFSET_2) + self.assertRaises(AssertionError, Value, fmt=F_ASSERT_OFFSET_3) + self.assertRaises(AssertionError, Value, fmt=F_ASSERT_CLAMP) + + def test_default_format(self): + self.assertEqual(str(Value(0)), "0.00000") + self.assertEqual(str(Value(1)), "1.00000") + self.assertEqual(str(Value(10)), "10.0000") + self.assertEqual(str(Value(100)), "100.000") + self.assertEqual(str(Value(-1)), "-1.00000") + self.assertEqual(str(Value(-10)), "-10.0000") + self.assertEqual(str(Value(-100)), "-100.000") + + self.assertEqual(str(Value(1e3)), "1.00000k") + self.assertEqual(str(Value(1e4)), "10.0000k") + self.assertEqual(str(Value(1e5)), "100.000k") + self.assertEqual(str(Value(1e6)), "1.00000M") + self.assertEqual(str(Value(1e7)), "10.0000M") + self.assertEqual(str(Value(1e8)), "100.000M") + self.assertEqual(str(Value(1e9)), "1.00000G") + self.assertEqual(str(Value(1e12)), "1.00000T") + self.assertEqual(str(Value(1e15)), "1.00000P") + self.assertEqual(str(Value(1e18)), "1.00000E") + self.assertEqual(str(Value(1e21)), "1.00000Z") + self.assertEqual(str(Value(1e24)), "1.00000Y") + self.assertEqual(str(Value(1e27)), "\N{INFINITY}") + self.assertEqual(str(Value(-1e27)), "-\N{INFINITY}") + self.assertEqual(float(Value(1e27)), 1e27) + + self.assertEqual(str(Value(.1)), "100.000m") + self.assertEqual(str(Value(.01)), "10.0000m") + self.assertEqual(str(Value(.001)), "1.00000m") + self.assertEqual(str(Value(1e-6)), "1.00000ยต") + self.assertEqual(str(Value(1e-9)), "1.00000n") + self.assertEqual(str(Value(1e-12)), "1.00000p") + self.assertEqual(str(Value(1e-15)), "1.00000f") + self.assertEqual(str(Value(1e-18)), "1.00000a") + self.assertEqual(str(Value(1e-21)), "1.00000z") + self.assertEqual(str(Value(1e-24)), "1.00000y") + self.assertEqual(str(Value(1e-27)), "0.00100y") + self.assertEqual(str(Value(1e-29)), "0.00001y") + self.assertEqual(str(Value(-1e-29)), "-0.00001y") + self.assertEqual(str(Value(1e-30)), "0.00000") + self.assertEqual(float(Value(1e-30)), 1e-30) + + def test_format_digits_3(self): + v = Value(fmt=F_DIGITS_3) + self.assertEqual(str(v.parse("1")), "1") + self.assertEqual(str(v.parse("10")), "10") + self.assertEqual(str(v.parse("100")), "100") + self.assertEqual(str(v.parse("1e3")), "1k") + self.assertEqual(str(v.parse("1e4")), "10k") + self.assertEqual(str(v.parse("1e5")), "100k") + self.assertEqual(str(v.parse("1e-1")), "100m") + self.assertEqual(str(v.parse("1e-2")), "10m") + self.assertEqual(str(v.parse("1e-3")), "1m") + + +if __name__ == '__main__': + unittest.main(verbosity=2)