[Git][NTPsec/ntpsec][master] Unit bug fixes

Gary E. Miller gitlab at mg.gitlab.com
Thu Apr 13 16:48:37 UTC 2017


Gary E. Miller pushed to branch master at NTPsec / ntpsec


Commits:
609b1225 by Ian Bruene at 2017-04-13T16:47:45+00:00
Unit bug fixes

- - - - -


4 changed files:

- ntpclients/ntpmon
- ntpclients/ntpq
- pylib/util.py
- tests/pylib/test_util.py


Changes:

=====================================
ntpclients/ntpmon
=====================================
--- a/ntpclients/ntpmon
+++ b/ntpclients/ntpmon
@@ -103,21 +103,18 @@ def peer_detail(variables, showunits=False):
         for name in ntp.util.MS_VARS:
             if name in vcopy:
                 vcopy[name] = ntp.util.unitify(vcopyraw[name],
-                                               ntp.util.UNITS_SEC,
                                                ntp.util.UNIT_MS,
                                                strip=True,
                                                width=None)
         for name in ntp.util.PPM_VARS:
             if name in vcopy:
                 vcopy[name] = ntp.util.unitify(vcopyraw[name],
-                                               ntp.util.UNITS_PPX,
                                                ntp.util.UNIT_PPM,
                                                strip=True,
                                                width=None)
         for name in ntp.util.S_VARS:
             if name in vcopy:
                 vcopy[name] = ntp.util.unitify(vcopyraw[name],
-                                               ntp.util.UNITS_SEC,
                                                ntp.util.UNIT_S,
                                                strip=True,
                                                width=None)


=====================================
ntpclients/ntpq
=====================================
--- a/ntpclients/ntpq
+++ b/ntpclients/ntpq
@@ -228,7 +228,12 @@ Called when a line that starts with ! is entered in response to the prompt.
         return
 
     def say(self, msg):
-        sys.stdout.write(polystr(msg))
+        try:
+            sys.stdout.write(polystr(msg))
+        except UnicodeEncodeError as e:
+            print("Unicode failure:", e)
+            print("msg:\n", repr(msg))
+            raise e
         sys.stdout.flush()    # In case we're piping the output
 
     def warn(self, msg):
@@ -466,7 +471,9 @@ usage: timeout [ msec ]
     def collect_display(self, associd, variables, decodestatus):
         "Query and display a collection of variables from the system."
         try:
-            queried = self.session.readvar(associd, [v[0] for v in variables])
+            queried = self.session.readvar(associd,
+                                           [v[0] for v in variables],
+                                           raw=True)
         except ntp.packet.ControlException as e:
             if ntp.control.CERR_UNKNOWNVAR == e.errorcode:
                 self.warn("Unknown variable.  Trying one at a time.\n")
@@ -477,7 +484,7 @@ usage: timeout [ msec ]
                         queried = self.session.readvar(associd, [var],
                                                        raw=True)
                         for (name, (value, rawvalue)) in queried.items():
-                            items.append((name, value))
+                            items.append((name, (value, rawvalue)))
                     except ntp.packet.ControlException as e:
                         if ntp.control.CERR_UNKNOWNVAR == e.errorcode:
                             items.append((var, "???"))
@@ -505,7 +512,8 @@ usage: timeout [ msec ]
             for (name, legend, fmt) in variables:
                 if name not in queried:
                     continue
-                value = queried[name]
+                value = queried[name][0]
+                rawvalue = queried[name][1]
                 if fmt in (NTP_ADD, NTP_ADP):
                     if self.showhostnames:
                         if self.debug:
@@ -519,7 +527,12 @@ usage: timeout [ msec ]
                     if value:
                         self.say("%s  %s\n" % (legend, value))
                 elif fmt in (NTP_UINT, NTP_INT, NTP_FLOAT):
-                    self.say("%s  %s\n" % (legend, value))
+                    if self.showunits:
+                        displayvalue = ntp.util.unitifyvar(rawvalue, name,
+                                                           strip=True)
+                    else:
+                        displayvalue = value
+                    self.say("%s  %s\n" % (legend, displayvalue))
                 elif fmt == NTP_LFP:
                     self.say("%s  %s\n" % (legend, ntp.ntpc.prettydate(value)))
                 elif fmt == NTP_2BIT:


=====================================
pylib/util.py
=====================================
--- a/pylib/util.py
+++ b/pylib/util.py
@@ -33,21 +33,22 @@ OLD_CTL_PST_SEL_SYSPEER = 3
 
 
 # Units for formatting
-UNIT_NS = 0
-UNIT_US = 1
-UNIT_MS = 2
-UNIT_S = 3
-UNIT_KS = 4
-UNITS_SEC = ["ns", u"\u03bcs", "ms", "s", "ks"]
-UNIT_PPT = 0
-UNIT_PPB = 1
-UNIT_PPM = 2
-UNIT_PPK = 3
-UNITS_PPX = ["ppt", "ppb", "ppm", "ppk"]
+UNIT_NS = "ns"
+UNIT_US = u"\u03bcs"
+UNIT_MS = "ms"
+UNIT_S = "s"
+UNIT_KS = "ks"
+UNITS_SEC = (UNIT_NS, UNIT_US, UNIT_MS, UNIT_S, UNIT_KS)
+UNIT_PPT = "ppt"
+UNIT_PPB = "ppb"
+UNIT_PPM = "ppm"
+UNIT_PPK = "ppk"
+UNITS_PPX = (UNIT_PPT, UNIT_PPB, UNIT_PPM, UNIT_PPK)
+unitgroups = (UNITS_SEC, UNITS_PPX)
 
 
 # Variables that have units
-S_VARS = ("tai",)
+S_VARS = ("tai", "poll")
 MS_VARS = ("rootdelay", "rootdisp", "offset", "sys_jitter", "clk_jitter",
            "leapsmearoffset", "authdelay", "koffset", "kmaxerr", "kesterr",
            "kprecis", "kppsjitter", "fuzz", "clk_wander_threshold", "tick",
@@ -111,7 +112,7 @@ def stringfiltcooker(data):
         if count > highestcount:
             mostcommon = key
             highestcount = count
-    newunit = UNITS_SEC[mostcommon + UNIT_MS]
+    newunit = UNITS_SEC[mostcommon + 2]  # 2==UNIT_MS
     # Shift all values to the new unit
     cooked = []
     for part in parts:
@@ -206,8 +207,21 @@ def formatdigitsplit(f, fieldsize, oomstobase):
     return formatter
 
 
+def getunitgroup(unit):
+    for group in unitgroups:
+        if unit in group:
+            return group
+
+
 def oomsbetweenunits(a, b):
-    return abs((a - b) * 3)
+    group = getunitgroup(a)
+    if b is None:  # asking for baseunit
+        return group.index(a)
+    elif b in group:
+        ia = group.index(a)
+        ib = group.index(b)
+        return abs((ia - ib) * 3)
+    return None
 
 
 def breaknumberstring(value):
@@ -355,27 +369,55 @@ def isstringzero(value):
     return True
 
 
-def unitify(value, unitgroup, startingunit, baseunit=0,
-            strip=False, width=8):
+def unitrelativeto(unit, move):
+    "Returns a unit at a different scale from the input unit"
+    for group in unitgroups:
+        if unit in group:
+            if move is None:  # asking for the base unit
+                return group[0]
+            else:
+                index = group.index(unit)
+                index += move  # index of the new unit
+                if 0 <= index < len(group):  # found the new unit
+                    return group[index]
+                else:  # not in range
+                    return None
+    return None  # couldn't find anything
+
+
+def unitifyvar(value, varname, baseunit=None, strip=False, width=8):
+    if varname in S_VARS:
+        start = UNIT_S
+    elif varname in MS_VARS:
+        start = UNIT_MS
+    elif varname in PPM_VARS:
+        start = UNIT_PPM
+    else:
+        return value
+    return unitify(value, start, baseunit, strip, width)
+
+
+def unitify(value, startingunit, baseunit=None, strip=False, width=8):
     "Formats a numberstring with relevant units. Attemps to fit in width."
+    if baseunit is None:
+        baseunit = getunitgroup(startingunit)[0]
     if isstringzero(value) is True:  # display highest precision zero
-        base = unitgroup[baseunit]
         if strip is False:
-            value = fitinfield("0", width - len(base)) + base
+            value = fitinfield("0", width - len(baseunit))
+        value = value + baseunit
         return value
     ooms = oomsbetweenunits(startingunit, baseunit)
     newvalue = cropprecision(value, ooms)
     newvalue, unitsmoved = scalestring(newvalue)
-    unitget = startingunit + unitsmoved
-    if 0 <= unitget < len(unitgroup):  # We have a unit
-        unit = unitgroup[unitget]
+    unitget = unitrelativeto(startingunit, unitsmoved)
+    if unitget is not None:  # We have a unit
         if width is None:
             realwidth = None
         else:
-            realwidth = width - len(unit)
-        newvalue = fitinfield(newvalue, realwidth) + unit
+            realwidth = width - len(unitget)
+        newvalue = fitinfield(newvalue, realwidth) + unitget
     else:  # don't have a replacement unit, use original
-        newvalue = value + unitgroup[startingunit]
+        newvalue = value + startingunit
     if strip is True:
         newvalue = newvalue.strip()
     return newvalue
@@ -667,19 +709,19 @@ def cook(variables, showunits=False):
             #   missing variables here.
             #  Completion cannot occur until all units are tracked down.
             if showunits:
-                item += unitify(rawvalue, UNITS_SEC, UNIT_MS, UNIT_NS,
+                item += unitify(rawvalue, UNIT_MS, UNIT_NS,
                                 True, width=None)
             else:
                 item += repr(value)
         elif name in S_VARS:
             if showunits:
-                item += unitify(rawvalue, UNITS_SEC, UNIT_S, UNIT_NS,
+                item += unitify(rawvalue, UNIT_S, UNIT_NS,
                                 True, width=None)
             else:
                 item += repr(value)
         elif name in PPM_VARS:
             if showunits:
-                item += unitify(rawvalue, UNITS_PPX, UNIT_PPM,
+                item += unitify(rawvalue, UNIT_PPM,
                                 strip=True, width=None)
             else:
                 item += repr(value)
@@ -933,9 +975,9 @@ class PeerSummary:
                 if self.showunits:
                     line += (
                         " %s %s %s" %
-                        (unitify(estdelay, UNITS_SEC, UNIT_MS),
-                         unitify(estoffset, UNITS_SEC, UNIT_MS),
-                         unitify(jd, UNITS_SEC, UNIT_MS)))
+                        (unitify(estdelay, UNIT_MS),
+                         unitify(estoffset, UNIT_MS),
+                         unitify(jd, UNIT_MS)))
                 else:
                     line += (
                         " %s %s %s" %
@@ -946,9 +988,9 @@ class PeerSummary:
                 if self.showunits:
                     line += (
                         " %s %s %s" %
-                        (unitify(estdelay, UNITS_SEC, UNIT_MS),
-                         unitify(estoffset, UNITS_SEC, UNIT_MS),
-                         unitify(jd, UNITS_SEC, UNIT_MS)))
+                        (unitify(estdelay, UNIT_MS),
+                         unitify(estoffset, UNIT_MS),
+                         unitify(jd, UNIT_MS)))
                 else:
                     line += (
                         " %s %s %s" %


=====================================
tests/pylib/test_util.py
=====================================
--- a/tests/pylib/test_util.py
+++ b/tests/pylib/test_util.py
@@ -73,10 +73,10 @@ class TestPylibUtilMethods(unittest.TestCase):
                          (1.000001, 0))
 
     def test_oomsbetweenunits(self):
-        self.assertEqual(ntp.util.oomsbetweenunits(3, 2),
-                         3)
-        self.assertEqual(ntp.util.oomsbetweenunits(2, 3),
-                         3)
+        f = ntp.util.oomsbetweenunits
+
+        self.assertEqual(f(ntp.util.UNIT_KS, ntp.util.UNIT_MS), 6)
+        self.assertEqual(f(ntp.util.UNIT_PPM, ntp.util.UNIT_PPB), 3)
 
     def test_filtcooker(self):
         self.assertEqual(ntp.util.filtcooker(
@@ -288,44 +288,35 @@ class TestPylibUtilMethods(unittest.TestCase):
         nu = ntp.util
 
         # Zero
-        self.assertEqual(f("0.000", nu.UNITS_SEC, nu.UNIT_MS),
-                         "     0ns")
+        self.assertEqual(f("0.000", nu.UNIT_MS), "     0ns")
         # Standard, width=8
-        self.assertEqual(f("1.234", nu.UNITS_SEC, nu.UNIT_MS),
-                         " 1.234ms")
+        self.assertEqual(f("1.234", nu.UNIT_MS), " 1.234ms")
         # ditto, negative
-        self.assertEqual(f("-1.234", nu.UNITS_SEC, nu.UNIT_MS),
-                         "-1.234ms")
+        self.assertEqual(f("-1.234", nu.UNIT_MS), "-1.234ms")
         # Scale to larger unit, width=8
-        self.assertEqual(f("1234.5", nu.UNITS_SEC, nu.UNIT_MS),
-                         " 1.2345s")
+        self.assertEqual(f("1234.5", nu.UNIT_MS), " 1.2345s")
         # ditto, negative
-        self.assertEqual(f("-1234.5", nu.UNITS_SEC, nu.UNIT_MS),
-                         "-1.2345s")
+        self.assertEqual(f("-1234.5", nu.UNIT_MS), "-1.2345s")
         # Scale to smaller unit, width=8
-        self.assertEqual(f("0.01234", nu.UNITS_SEC, nu.UNIT_MS),
-                         u" 12.34\u03bcs")
+        self.assertEqual(f("0.01234", nu.UNIT_MS), u" 12.34\u03bcs")
         # ditto, negative
-        self.assertEqual(f("-0.01234", nu.UNITS_SEC, nu.UNIT_MS),
-                         u"-12.34\u03bcs")
+        self.assertEqual(f("-0.01234", nu.UNIT_MS), u"-12.34\u03bcs")
         # At baseunit
-        self.assertEqual(f("12.0", nu.UNITS_SEC, nu.UNIT_NS),
-                         "    12ns")
+        self.assertEqual(f("12.0", nu.UNIT_NS), "    12ns")
         # Scale to baseunit
-        self.assertEqual(f(".042", nu.UNITS_SEC, nu.UNIT_US),
-                         "    42ns")
+        self.assertEqual(f(".042", nu.UNIT_US), "    42ns")
         # Below baseunit
-        self.assertEqual(f("23.42", nu.UNITS_SEC, nu.UNIT_NS),
-                         "    23ns")
+        self.assertEqual(f("23.42", nu.UNIT_NS), "    23ns")
         # Different units
-        self.assertEqual(f("12.345", nu.UNITS_PPX, nu.UNIT_PPM),
-                         "12.35ppm")
+        self.assertEqual(f("12.345", nu.UNIT_PPM), "12.35ppm")
         # Strip
-        self.assertEqual(f("1.23", nu.UNITS_SEC, nu.UNIT_MS, strip=True),
-                         "1.23ms")
+        self.assertEqual(f("1.23", nu.UNIT_MS, strip=True), "1.23ms")
         # Different width
-        self.assertEqual(f("1.234", nu.UNITS_SEC, nu.UNIT_MS, width=12),
-                         "     1.234ms")
+        self.assertEqual(f("1.234", nu.UNIT_MS, width=12), "     1.234ms")
+        # Outside of available units
+        self.assertEqual(f("1234.5", nu.UNIT_KS), "1234.5ks")
+        # Seconds
+        self.assertEqual(f("42.23", nu.UNIT_S), "  42.23s")
 
     def test_stringfiltcooker(self):
         # No scale
@@ -339,5 +330,21 @@ class TestPylibUtilMethods(unittest.TestCase):
             "1.00002  3.4005 0.00068 -0.0230   9.001  0.0067 0.00100   1.234 s"
         )
 
+    def test_unitrelativeto(self):
+        f = ntp.util.unitrelativeto
+
+        # Scale to smaller unit
+        self.assertEqual(f(ntp.util.UNIT_S, -1), ntp.util.UNIT_MS)
+        # Scale to larger unit
+        self.assertEqual(f(ntp.util.UNIT_S, 1), ntp.util.UNIT_KS)
+        # Scale smaller, outside of range
+        self.assertEqual(f(ntp.util.UNIT_S, -10), None)
+        # Scale larger, outside of range
+        self.assertEqual(f(ntp.util.UNIT_NS, 10), None)
+        # Get base unit
+        self.assertEqual(f(ntp.util.UNIT_KS, None), ntp.util.UNIT_NS)
+        # Different unitgroup
+        self.assertEqual(f(ntp.util.UNIT_PPM, -1), ntp.util.UNIT_PPB)
+
 if __name__ == '__main__':
     unittest.main()



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/609b1225b071e19cb86f43d72b7aecf68739b520

---
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/609b1225b071e19cb86f43d72b7aecf68739b520
You're receiving this email because of your account on gitlab.com.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20170413/e3280ac3/attachment.html>


More information about the vc mailing list