[Git][NTPsec/ntpsec][master] Fixed tests and functions where appropriate.
Eric S. Raymond
gitlab at mg.gitlab.com
Tue Apr 4 03:59:24 UTC 2017
Eric S. Raymond pushed to branch master at NTPsec / ntpsec
Commits:
5b70d40d by Ian Bruene at 2017-04-04T03:57:55+00:00
Fixed tests and functions where appropriate.
- - - - -
2 changed files:
- pylib/util.py
- tests/pylib/test_util.py
Changes:
=====================================
pylib/util.py
=====================================
--- a/pylib/util.py
+++ b/pylib/util.py
@@ -31,8 +31,6 @@ OLD_CTL_PST_SEL_SYNCCAND = 2
OLD_CTL_PST_SEL_SYSPEER = 3
-timefuzz = 1e-9 # Time variables have max precision of 1ns. Use for x==0.0.
-
# Units for formatting
UNIT_NS = 0
UNIT_US = 1
@@ -90,6 +88,11 @@ def portsplit(hostname):
return (hostname, portsuffix)
+def zerowiggle(ooms):
+ "Generate a wiggle value for float==0 comparisons"
+ return 10 ** -ooms
+
+
def filtcooker(data):
"Cooks the string of space seperated numbers with units"
parts = data.split()
@@ -99,7 +102,7 @@ def filtcooker(data):
for part in parts:
part = float(part)
floatyparts.append(part)
- value, oom = scaleforunit(part)
+ value, oom = scaleforunit(part, oomsbetweenunits(UNIT_MS, UNIT_NS))
oomcount[oom] = oomcount.get(oom, 0) + 1
# Find the most common unit
mostcommon = None
@@ -109,15 +112,16 @@ def filtcooker(data):
if count > highestcount:
mostcommon = key
highestcount = count
- newunit = mostcommon + UNIT_MS
+ newunit = UNITS_SEC[mostcommon + UNIT_MS]
+ oomstobase = (mostcommon * 3) + 6 # 6 == UNIT_MS distance from base
# Shift all values to the new unit
cooked = []
for part in floatyparts:
part = rescaleunit(part, mostcommon)
- fmt = formatdigitsplit(part, 7)
+ fmt = formatdigitsplit(part, 7, oomstobase)
temp = fmt % part
cooked.append(temp)
- rendered = " ".join(cooked) + " " + UNITS_SEC[newunit]
+ rendered = " ".join(cooked) + " " + newunit
return rendered
@@ -128,9 +132,11 @@ def rescaleunit(f, units):
return f
-def scaleforunit(f):
+def scaleforunit(f, oomstobase):
"Scales a number by units to keep it in the range 0.000-999.9"
- if -timefuzz < f < timefuzz: # if sufficiently close to zero do nothing
+ f = round(f, oomstobase) # pre-round to base unit to filter float folly
+ wiggle = zerowiggle(oomstobase)
+ if -wiggle < f < wiggle: # if sufficiently close to zero do nothing
return (f, 0)
unitsmoved = 0
af = abs(f)
@@ -140,29 +146,33 @@ def scaleforunit(f):
oom = math.log10(af) # Orders Of Magnitude
oom -= oom % 3 # We only want to move in groups of 3 ooms
multiplier = 10 ** -oom # Reciprocol because floating * more accurate
- unitsmoved = oom // 3
+ unitsmoved = int(oom // 3)
f *= multiplier
- f = round(f, 13) # Min round to catch something like 191.20000000000002
- return (f, int(unitsmoved))
+ roundooms = (unitsmoved * 3) + oomstobase
+ f = round(f, roundooms) # Filter out any float folly we introduced here
+ return (f, unitsmoved)
-def formatdigitsplit(f, fieldsize):
+def roundsubzero(f, oomstobase):
+ "Rounds a number at it's base unit"
+ mul = 10 ** oomstobase
+ f *= mul
+ f = round(f)
+ return f
+
+
+def formatdigitsplit(f, fieldsize, oomstobase):
"Create a format string for a float without adding fake precision."
af = abs(f)
- if f.is_integer() or (af < timefuzz):
- return "%" + str(fieldsize) + "d"
if af >= 100.0:
maxdigits = fieldsize - 4 # xxx.
elif af >= 10.0:
maxdigits = fieldsize - 3 # xx.
- elif af >= 1.0:
+ else:
maxdigits = fieldsize - 2 # x.
- else: # Yes, this can happen with filts
- maxdigits = fieldsize - 2 # 0.
if f < 0.0:
maxdigits -= 1 # need to fit a negative symbol
- sig = len(str(f).split(".")[1]) # count digits after the decimal point
- subdigits = min(sig, maxdigits) # use min so we don't add fake data
+ subdigits = min(oomstobase, maxdigits) # use min so we don't add fake data
formatter = "%" + str(fieldsize) + "." + str(subdigits) + "f"
return formatter
@@ -180,17 +190,19 @@ def unitformatter(f, unitgroup, startingunit, baseunit=None,
strip = True
if baseunit is None:
baseunit = 0 # Assume that the lowest unit is equal to LSB
- if -timefuzz < f < timefuzz: # Zero, don't show decimals
- unit = unitgroup[baseunit] # all the way to the lsb
- rendered = "0" + unit
+ oomsfrombase = oomsbetweenunits(startingunit, baseunit)
+ wiggle = zerowiggle(oomsfrombase)
+ if -wiggle < f < wiggle: # Zero, don't show decimals
+ unit = unitgroup[baseunit] # go all the way to the lsb
+ f = roundsubzero(f, oomsfrombase)
+ rendered = ("%d" % f) + unit
if not strip:
rendered = padder(rendered)
return rendered
oldf = f # keep this in case we don't fit in the units
- f, unitsmoved = scaleforunit(f)
+ f, unitsmoved = scaleforunit(f, oomsfrombase)
unitget = startingunit + unitsmoved
- rounddigits = oomsbetweenunits(unitget, baseunit)
- f = round(f, rounddigits)
+ oomsfrombase = oomsbetweenunits(unitget, baseunit) # will need this later
if (0 <= unitget < len(unitgroup)):
unit = unitgroup[unitget]
if width is None: # Don't care about size, just display everything
@@ -207,7 +219,7 @@ def unitformatter(f, unitgroup, startingunit, baseunit=None,
if unitget == baseunit: # Don't want fake decimals
formatter = "%" + str(displaysize) + "d"
else:
- formatter = formatdigitsplit(f, displaysize)
+ formatter = formatdigitsplit(f, displaysize, oomsfrombase)
rendered = (formatter % f) + unit
if strip:
rendered = rendered.strip()
=====================================
tests/pylib/test_util.py
=====================================
--- a/tests/pylib/test_util.py
+++ b/tests/pylib/test_util.py
@@ -47,26 +47,30 @@ class TestPylibUtilMethods(unittest.TestCase):
-0.000001)
def test_scaleforunit(self):
- self.assertEqual(ntp.util.scaleforunit(1.0),
+ self.assertEqual(ntp.util.scaleforunit(1.0, 9),
(1.0, 0))
- self.assertEqual(ntp.util.scaleforunit(999.2342),
+ self.assertEqual(ntp.util.scaleforunit(999.2342, 9),
(999.2342, 0))
- self.assertEqual(ntp.util.scaleforunit(5042.7),
+ self.assertEqual(ntp.util.scaleforunit(5042.7, 9),
(5.0427, 1))
- self.assertEqual(ntp.util.scaleforunit(0.1912),
+ self.assertEqual(ntp.util.scaleforunit(0.1912, 9),
(191.2, -1))
- self.assertEqual(ntp.util.scaleforunit(0.00000042),
+ self.assertEqual(ntp.util.scaleforunit(0.00000042, 9),
(420.0, -3))
- self.assertEqual(ntp.util.scaleforunit(-1.0),
+ self.assertEqual(ntp.util.scaleforunit(-1.0, 9),
(-1.0, 0))
- self.assertEqual(ntp.util.scaleforunit(-999.2342),
+ self.assertEqual(ntp.util.scaleforunit(-999.2342, 9),
(-999.2342, 0))
- self.assertEqual(ntp.util.scaleforunit(-5042.7),
+ self.assertEqual(ntp.util.scaleforunit(-5042.7, 9),
(-5.0427, 1))
- self.assertEqual(ntp.util.scaleforunit(-0.1912),
+ self.assertEqual(ntp.util.scaleforunit(-0.1912, 9),
(-191.2, -1))
- self.assertEqual(ntp.util.scaleforunit(-0.00000042),
+ self.assertEqual(ntp.util.scaleforunit(-0.00000042, 9),
(-420.0, -3))
+ self.assertEqual(ntp.util.scaleforunit(1.0000004, 6),
+ (1.0, 0))
+ self.assertEqual(ntp.util.scaleforunit(1.0000005, 6),
+ (1.000001, 0))
def test_oomsbetweenunits(self):
self.assertEqual(ntp.util.oomsbetweenunits(3, 2),
@@ -77,23 +81,23 @@ class TestPylibUtilMethods(unittest.TestCase):
def test_filtcooker(self):
self.assertEqual(ntp.util.filtcooker(
"1.02 34.5 0.67835 -23.0 9 6.7 1.0 .1"),
- " 1.02 34.5 0.67835 -23 9 6.7 1 0.1 ms"
+ "1.02000 34.5000 0.67835 -23.000 9.00000 6.70000 1.00000 0.10000 ms"
)
def test_formatdigitsplit(self):
- self.assertEqual(ntp.util.formatdigitsplit(10.0, 5),
- "%5d")
- self.assertEqual(ntp.util.formatdigitsplit(100.52, 5),
+ self.assertEqual(ntp.util.formatdigitsplit(10.0, 5, 9),
+ "%5.2f")
+ self.assertEqual(ntp.util.formatdigitsplit(100.52, 5, 9),
"%5.1f")
- self.assertEqual(ntp.util.formatdigitsplit(10.123456789, 8),
+ self.assertEqual(ntp.util.formatdigitsplit(10.123456789, 8, 9),
"%8.5f")
- self.assertEqual(ntp.util.formatdigitsplit(1.123456789, 8),
+ self.assertEqual(ntp.util.formatdigitsplit(1.123456789, 8, 9),
"%8.6f")
- self.assertEqual(ntp.util.formatdigitsplit(0.123456789, 8),
+ self.assertEqual(ntp.util.formatdigitsplit(0.123456789, 8, 9),
"%8.6f")
- self.assertEqual(ntp.util.formatdigitsplit(1.234, 10),
- "%10.3f")
- self.assertEqual(ntp.util.formatdigitsplit(-1.23456789, 6),
+ self.assertEqual(ntp.util.formatdigitsplit(1.234, 10, 9),
+ "%10.8f")
+ self.assertEqual(ntp.util.formatdigitsplit(-1.23456789, 6, 9),
"%6.3f")
def test_unitformatter(self):
@@ -105,8 +109,8 @@ class TestPylibUtilMethods(unittest.TestCase):
[1.0000000005, "1.00000s"],
# -1.0000000005 s rounds to 1s
[-1.0000000005, "-1.0000s"],
- # 0.999999 s round to 1s
- [0.999999, "1.00000s"],
+ # 0.9999999999 s round to 1s
+ [0.9999999999, "1.00000s"],
# 0.00000000049 s rounds to 0ns
[0.00000000049, " 0ns"],
# 0.00000000051 s rounds to 1ns
@@ -118,22 +122,24 @@ class TestPylibUtilMethods(unittest.TestCase):
# 0.4 ms rounds to 0ns
self.assertEqual(f(0.0000004, usec, ntp.util.UNIT_MS),
- " 0ns") # Checking timefuzz
+ " 0ns")
# 0.5 ms rounds to 1ns
self.assertEqual(f(0.0000005, usec, ntp.util.UNIT_MS),
- " 1ns") # Checking timefuzz
- # 0.5 ms rounds to 1ns
+ " 1ns")
+ # 0.5 ms rounds to 1ns, with strip
self.assertEqual(f(0.0000005, usec, ntp.util.UNIT_MS, strip=True),
- "0ns") # Checking timefuzz, strip
+ "1ns")
self.assertEqual(f(12.45, usec, ntp.util.UNIT_MS),
- " 12.45ms") # Checking normal
+ "12.450ms") # Checking normal
self.assertEqual(f(12.45, usec, ntp.util.UNIT_MS, strip=True),
- "12.45ms") # Checking normal, strip
+ "12.450ms") # Checking normal, strip
# 12.499999 ms rounds to 12.45 ms
- self.assertEqual(f(12.499999, usec, ntp.util.UNIT_MS, strip=True),
- "12.45ms") # Checking normal, strip
+ self.assertEqual(f(12.499999, usec, ntp.util.UNIT_MS,
+ strip=True, width=6),
+ "12.5ms") # Checking normal, strip
# 12.451 ms rounds to 12.45 ms
- self.assertEqual(f(12.451, usec, ntp.util.UNIT_MS, strip=True),
+ self.assertEqual(f(12.451, usec, ntp.util.UNIT_MS,
+ strip=True, width=7),
"12.45ms") # Checking normal, strip
self.assertEqual(f(123456789.1234, usec, ntp.util.UNIT_MS, width=None),
"123.4567891234ks") # Checking normal, no width
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/5b70d40df3e40e40d9a52fb35f1433d2526885e9
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20170404/e18bebda/attachment.html>
More information about the vc
mailing list