beautifier detect whether it can use unicode chars in stats table; asciified output of beautifier in test suite;

closes gh-3750
pull/3775/head
sebres 5 months ago
parent 6fce23e7ba
commit ab9d41e530

@ -21,8 +21,10 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko"
__license__ = "GPL" __license__ = "GPL"
import sys
from ..exceptions import UnknownJailException, DuplicateJailException from ..exceptions import UnknownJailException, DuplicateJailException
from ..helpers import getLogger, logging from ..helpers import getLogger, logging, PREFER_ENC
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = getLogger(__name__) logSys = getLogger(__name__)
@ -36,6 +38,11 @@ logSys = getLogger(__name__)
class Beautifier: class Beautifier:
stdoutEnc = PREFER_ENC
if sys.stdout and sys.stdout.encoding is not None:
stdoutEnc = sys.stdout.encoding
encUtf = 1 if stdoutEnc.lower() == 'utf-8' else 0
def __init__(self, cmd = None): def __init__(self, cmd = None):
self.__inputCmd = cmd self.__inputCmd = cmd
@ -104,7 +111,11 @@ class Beautifier:
jail_stat(j, " " if i == len(jstat) else " | ") jail_stat(j, " " if i == len(jstat) else " | ")
msg = "\n".join(msg) msg = "\n".join(msg)
elif inC[0:1] == ['stats'] or inC[0:1] == ['statistics']: elif inC[0:1] == ['stats'] or inC[0:1] == ['statistics']:
def _statstable(response): chrTable = [
['|', '-', '|', 'x', 'x', '-', '|', '-'], ## ascii
["\u2551", "\u2550", "\u255F", "\u256B", "\u256C", "\u2569", "\u2502", "\u2500"] ## utf-8
];
def _statstable(response, ct):
tophead = ["Jail", "Backend", "Filter", "Actions"] tophead = ["Jail", "Backend", "Filter", "Actions"]
headers = ["", "", "cur", "tot", "cur", "tot"] headers = ["", "", "cur", "tot", "cur", "tot"]
minlens = [8, 8, 3, 3, 3, 3] minlens = [8, 8, 3, 3, 3, 3]
@ -120,29 +131,31 @@ class Beautifier:
f = "%%%ds" if ralign[i] else "%%-%ds" f = "%%%ds" if ralign[i] else "%%-%ds"
rfmt.append(f % lens[i]) rfmt.append(f % lens[i])
hfmt.append(f % lens[i]) hfmt.append(f % lens[i])
rfmt = [rfmt[0], rfmt[1], "%s \u2502 %s" % (rfmt[2], rfmt[3]), "%s \u2502 %s" % (rfmt[4], rfmt[5])] rfmt = [rfmt[0], rfmt[1], "%s %s %s" % (rfmt[2], ct[6], rfmt[3]), "%s %s %s" % (rfmt[4], ct[6], rfmt[5])]
hfmt = [hfmt[0], hfmt[1], "%s \u2502 %s" % (hfmt[2], hfmt[3]), "%s \u2502 %s" % (hfmt[4], hfmt[5])] hfmt = [hfmt[0], hfmt[1], "%s %s %s" % (hfmt[2], ct[6], hfmt[3]), "%s %s %s" % (hfmt[4], ct[6], hfmt[5])]
tlens = [lens[0], lens[1], 3 + lens[2] + lens[3], 3 + lens[4] + lens[5]] tlens = [lens[0], lens[1], 3 + lens[2] + lens[3], 3 + lens[4] + lens[5]]
tfmt = [hfmt[0], hfmt[1], "%%-%ds" % (tlens[2],), "%%-%ds" % (tlens[3],)] tfmt = [hfmt[0], hfmt[1], "%%-%ds" % (tlens[2],), "%%-%ds" % (tlens[3],)]
tsep = tfmt[0:2] tsep = tfmt[0:2]
rfmt = " \u2551 ".join(rfmt) rfmt = (" "+ct[0]+" ").join(rfmt)
hfmt = " \u2551 ".join(hfmt) hfmt = (" "+ct[0]+" ").join(hfmt)
tfmt = " \u2551 ".join(tfmt) tfmt = (" "+ct[0]+" ").join(tfmt)
tsep = " \u2551 ".join(tsep) tsep = (" "+ct[0]+" ").join(tsep)
separator = ((tsep % tuple(tophead[0:2])) + " \u255F\u2500" + separator = ((tsep % tuple(tophead[0:2])) + " "+ct[2]+ct[7] +
("\u2500\u256B\u2500".join(['\u2500' * n for n in tlens[2:]])) + '\u2500') ((ct[7]+ct[3]+ct[7]).join([ct[7] * n for n in tlens[2:]])) + ct[7])
ret = [] ret = []
ret.append(tfmt % tuple(["", ""]+tophead[2:])) ret.append(" "+tfmt % tuple(["", ""]+tophead[2:]))
ret.append(separator) ret.append(" "+separator)
ret.append(hfmt % tuple(headers)) ret.append(" "+hfmt % tuple(headers))
separator = "\u2550\u256C\u2550".join(['\u2550' * n for n in tlens]) + '\u2550' separator = (ct[1]+ct[4]+ct[1]).join([ct[1] * n for n in tlens]) + ct[1]
ret.append(separator) ret.append(ct[1]+separator)
for row in rows: for row in rows:
ret.append(rfmt % tuple(row)) ret.append(" "+rfmt % tuple(row))
separator = "\u2550\u2569\u2550".join(['\u2550' * n for n in tlens]) + '\u2550' separator = (ct[1]+ct[5]+ct[1]).join([ct[1] * n for n in tlens]) + ct[1]
ret.append(separator) ret.append(ct[1]+separator)
return ret return ret
msg = "\n".join(_statstable(response)) if not response:
return "No jails found."
msg = "\n".join(_statstable(response, chrTable[self.encUtf]))
elif len(inC) < 2: elif len(inC) < 2:
pass # to few cmd args for below pass # to few cmd args for below
elif inC[1] == "syslogsocket": elif inC[1] == "syslogsocket":

@ -34,6 +34,7 @@ class BeautifierTest(unittest.TestCase):
""" Call before every test case """ """ Call before every test case """
super(BeautifierTest, self).setUp() super(BeautifierTest, self).setUp()
self.b = Beautifier() self.b = Beautifier()
self.b.encUtf = 0; ## we prefer ascii in test suite (see #3750)
def tearDown(self): def tearDown(self):
""" Call after every test case """ """ Call after every test case """
@ -170,22 +171,25 @@ class BeautifierTest(unittest.TestCase):
def testStatusStats(self): def testStatusStats(self):
self.b.setInputCmd(["stats"]) self.b.setInputCmd(["stats"])
## no jails:
self.assertEqual(self.b.beautify({}), "No jails found.")
## 3 jails:
response = { response = {
"ssh": ["systemd", (3, 6), (12, 24)], "ssh": ["systemd", (3, 6), (12, 24)],
"exim4": ["pyinotify", (6, 12), (20, 20)], "exim4": ["pyinotify", (6, 12), (20, 20)],
"jail-with-long-name": ["polling", (0, 0), (0, 0)] "jail-with-long-name": ["polling", (0, 0), (0, 0)]
} }
output = ("" output = (""
+ " ? ? Filter ? Actions \n" + " | | Filter | Actions \n"
+ "Jail ? Backend ????????????????????????\n" + " Jail | Backend |-----------x-----------\n"
+ " ? ? cur ? tot ? cur ? tot\n" + " | | cur | tot | cur | tot\n"
+ "????????????????????????????????????????????????????????\n" + "---------------------x-----------x-----------x-----------\n"
+ "ssh ? systemd ? 3 ? 6 ? 12 ? 24\n" + " ssh | systemd | 3 | 6 | 12 | 24\n"
+ "exim4 ? pyinotify ? 6 ? 12 ? 20 ? 20\n" + " exim4 | pyinotify | 6 | 12 | 20 | 20\n"
+ "jail-with-long-name ? polling ? 0 ? 0 ? 0 ? 0\n" + " jail-with-long-name | polling | 0 | 0 | 0 | 0\n"
+ "????????????????????????????????????????????????????????" + "---------------------------------------------------------"
) )
response = self.b.beautify(response).encode('ascii', 'replace').decode('ascii') response = self.b.beautify(response)
self.assertEqual(response, output) self.assertEqual(response, output)

Loading…
Cancel
Save