Migrating to Python v3

 - support for Python v3.8.x
 - support for Python v3.5.x
 - new tag, 2019.2.8
 - updates class generation and iterators
 - unittests updated with coverage >75%
 - new coverage routines
 - unittests profiling
 - full fake data for unittests
 - unittest testrun is ~1.5 seconds long

Bugfixes
 - 34834, proper use of 'sudo' option
 - multiple proper iterator use
 - 37919, show warning when installed and candidate versions
   are newer comparing to release version

Change-Id: Idd6b889f7ce94ae0c832e2f0a0346e4fdc3264a3
Related-PROD: PROD-34834 PROD-34664 PROD-34919
diff --git a/cfg_checker/reports/reporter.py b/cfg_checker/reports/reporter.py
index fa5fc72..3d3ede3 100644
--- a/cfg_checker/reports/reporter.py
+++ b/cfg_checker/reports/reporter.py
@@ -110,9 +110,7 @@
             r['arch']
         ]) + ", "
         # maintainer w/o email
-        _m = r['maintainer'][:r['maintainer'].find('<')-1]
-        _m_ascii = _m.encode('ascii', errors="xmlcharrefreplace")
-        _text += _m_ascii
+        _text += ascii(r['maintainer'][:r['maintainer'].find('<')-1])
         # newline
         _text += "<br />"
     return _text
@@ -215,17 +213,21 @@
 
     def _extend_data(self, data):
         def get_bytes(value):
-            if value[-1] == 'G':
-                return int(float(value[:-1]) * 1024 * 1024 * 1024)
-            elif value[-1] == 'M':
-                return int(float(value[:-1]) * 1024 * 1024)
-            elif value[-1] == 'K':
-                return int(float(value[:-1]) * 1024)
-            else:
+            _char = value[-1]
+            _ord = ord(_char)
+            if _ord > 47 and _ord < 58:
+                # bytes comes with no Char
                 return int(value)
+            else:
+                _sizes = ["*", "K", "M", "G", "T"]
+                _flo = float(value[:-1])
+                _pwr = 1
+                if _char in _sizes:
+                    _pwr = _sizes.index(_char)
+                return int(_flo**_pwr)
 
         def _dmidecode(_dict, type=0):
-            _key = "dmi"
+            # _key = "dmi"
             _key_r = "dmi_r"
             _f_cmd = salt_master.get_cmd_for_nodes
             _cmd = "dmidecode -t {}".format(type)
@@ -234,7 +236,7 @@
             pass
 
         def _lsblk(_dict):
-            _key = "lsblk"
+            # _key = "lsblk"
             _key_r = "lsblk_raw"
             _f_cmd = salt_master.get_cmd_for_nodes
             _columns = [
@@ -261,7 +263,7 @@
             _cmd = "lscpu | sed -n '/\\:/s/ \\+/ /gp'"
             _f_cmd(_cmd, _key_r, target_dict=_dict)
             # parse them and put into dict
-            for node, dt in _dict.iteritems():
+            for node, dt in _dict.items():
                 dt[_key] = {}
                 if dt['status'] == DOWN:
                     continue
@@ -291,7 +293,7 @@
             _cmd = "free -h | sed -n '/Mem/s/ \\+/ /gp'"
             _f_cmd(_cmd, _key_r, target_dict=_dict)
             # parse them and put into dict
-            for node, dt in _dict.iteritems():
+            for node, dt in _dict.items():
                 dt[_key] = {}
                 if dt['status'] == DOWN:
                     continue
@@ -323,7 +325,7 @@
             _f_cmd = salt_master.get_cmd_for_nodes
             _cmd = "service --status-all"
             _f_cmd(_cmd, _key_r, target_dict=_dict)
-            for node, dt in _dict.iteritems():
+            for node, dt in _dict.items():
                 dt[_key] = {}
                 if dt['status'] == DOWN:
                     continue
@@ -386,7 +388,7 @@
                     _softnet_interval
                 )
             _f_cmd(_cmd, _key_r, target_dict=_dict)
-            for node, dt in _dict.iteritems():
+            for node, dt in _dict.items():
                 _cpuindex = 1
                 _add_mode = True
                 # totals for start mark
@@ -438,7 +440,7 @@
                             dt[_key]["total"][i] += _c[i]
                     _cpuindex += 1
                 # finally, subtract initial totals
-                for k, v in dt[_key].iteritems():
+                for k, v in dt[_key].items():
                     if k != "total":
                         dt[_key][k] = [v[i] / 5. for i in range(len(v))]
                     else:
@@ -483,7 +485,7 @@
             "disk_raw",
             target_dict=data["nodes"]
         )
-        for dt in data["nodes"].itervalues():
+        for dt in data["nodes"].values():
             dt["disk"] = {}
             dt["disk_max_dev"] = None
             if dt['status'] == DOWN:
@@ -516,8 +518,8 @@
                     _d[_t[0]]['f'] = ""
 
         # prepare networks data for report
-        for net, net_v in data['map'].iteritems():
-            for node, ifs in net_v.iteritems():
+        for net, net_v in data['map'].items():
+            for node, ifs in net_v.items():
                 for d in ifs:
                     _err = "fail"
                     d['interface_error'] = _err if d['interface_error'] else ""