Merge pull request #34 from ltworf/colourstr

Pretty printing
This commit is contained in:
Salvo 'LtWorf' Tomaselli 2020-08-26 21:22:22 +02:00 committed by GitHub
commit 8270e6517c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 99 additions and 65 deletions

108
driver.py
View File

@ -55,7 +55,7 @@ def load_relations():
# Naming the relation # Naming the relation
relname = i[:-4] relname = i[:-4]
print ("Loading relation %s with name %s..." % (i, relname)) print("Loading relation %s with name %s..." % (i, relname))
rels[relname] = relation.Relation.load_csv('%s%s' % (examples_path, i)) rels[relname] = relation.Relation.load_csv('%s%s' % (examples_path, i))
print('done') print('done')
@ -102,45 +102,45 @@ def execute_tests():
else: else:
f_bad += 1 f_bad += 1
print (colorize("Resume of the results", COLOR_CYAN)) print(colorize("Resume of the results", COLOR_CYAN))
print (colorize("Query tests", COLOR_MAGENTA)) print(colorize("Query tests", COLOR_MAGENTA))
print ("Total test count: %d" % q_tot) print("Total test count: %d" % q_tot)
print ("Passed tests: %d" % q_good) print("Passed tests: %d" % q_good)
if q_bad > 0: if q_bad > 0:
print (colorize("Failed tests count: %d" % q_bad, COLOR_RED)) print(colorize("Failed tests count: %d" % q_bad, COLOR_RED))
print (colorize("Python tests", COLOR_MAGENTA)) print(colorize("Python tests", COLOR_MAGENTA))
print ("Total test count: %d" % py_tot) print("Total test count: %d" % py_tot)
print ("Passed tests: %d" % py_good) print("Passed tests: %d" % py_good)
if py_bad > 0: if py_bad > 0:
print (colorize("Failed tests count: %d" % py_bad, COLOR_RED)) print(colorize("Failed tests count: %d" % py_bad, COLOR_RED))
print (colorize("Execute Python tests", COLOR_MAGENTA)) print(colorize("Execute Python tests", COLOR_MAGENTA))
print ("Total test count: %d" % ex_tot) print("Total test count: %d" % ex_tot)
print ("Passed tests: %d" % ex_good) print("Passed tests: %d" % ex_good)
if ex_bad > 0: if ex_bad > 0:
print (colorize("Failed tests count: %d" % ex_bad, COLOR_RED)) print(colorize("Failed tests count: %d" % ex_bad, COLOR_RED))
print (colorize("Execute fail tests", COLOR_MAGENTA)) print(colorize("Execute fail tests", COLOR_MAGENTA))
print ("Total test count: %d" % f_tot) print("Total test count: %d" % f_tot)
print ("Passed tests: %d" % f_good) print("Passed tests: %d" % f_good)
if f_bad > 0: if f_bad > 0:
print (colorize("Failed tests count: %d" % f_bad, COLOR_RED)) print(colorize("Failed tests count: %d" % f_bad, COLOR_RED))
print (colorize("Total results", COLOR_CYAN)) print(colorize("Total results", COLOR_CYAN))
if f_bad + q_bad + py_bad + ex_bad == 0: if f_bad + q_bad + py_bad + ex_bad == 0:
print (colorize("No failed tests", COLOR_GREEN)) print(colorize("No failed tests", COLOR_GREEN))
return 0 return 0
else: else:
print (colorize("There are %d failed tests" % print(colorize("There are %d failed tests" %
(f_bad + py_bad + q_bad + ex_bad), COLOR_RED)) (f_bad + py_bad + q_bad + ex_bad), COLOR_RED))
return 1 return 1
def run_exec_test(testname): def run_exec_test(testname):
'''Runs a python test, which executes code directly rather than queries''' '''Runs a python test, which executes code directly rather than queries'''
print ("Running python test: " + colorize(testname, COLOR_MAGENTA)) print("Running python test: " + colorize(testname, COLOR_MAGENTA))
glob = rels.copy() glob = rels.copy()
exp_result = {} exp_result = {}
@ -149,19 +149,19 @@ def run_exec_test(testname):
try: try:
exec(expr, glob) # Evaluating the expression exec(expr, glob) # Evaluating the expression
print (colorize('Test passed', COLOR_GREEN)) print(colorize('Test passed', COLOR_GREEN))
return True return True
except Exception as e: except Exception as e:
print (colorize('ERROR', COLOR_RED)) print(colorize('ERROR', COLOR_RED))
print (colorize('=====================================', COLOR_RED)) print(colorize('=====================================', COLOR_RED))
traceback.print_exc(file=sys.stdout) traceback.print_exc(file=sys.stdout)
print (colorize('=====================================', COLOR_RED)) print(colorize('=====================================', COLOR_RED))
return False return False
def run_py_test(testname): def run_py_test(testname):
'''Runs a python test, which evaluates expressions directly rather than queries''' '''Runs a python test, which evaluates expressions directly rather than queries'''
print ("Running expression python test: " + print("Running expression python test: " +
colorize(testname, COLOR_MAGENTA)) colorize(testname, COLOR_MAGENTA))
exp_result = None exp_result = None
result = None result = None
@ -174,21 +174,21 @@ def run_py_test(testname):
exp_result = eval(expr, rels) exp_result = eval(expr, rels)
if result == exp_result: if result == exp_result:
print (colorize('Test passed', COLOR_GREEN)) print(colorize('Test passed', COLOR_GREEN))
return True return True
except: except:
pass pass
print (colorize('ERROR', COLOR_RED)) print(colorize('ERROR', COLOR_RED))
print (colorize('=====================================', COLOR_RED)) print(colorize('=====================================', COLOR_RED))
print ("Expected %s" % exp_result) print("Expected %s" % exp_result.pretty_string(tty=True))
print ("Got %s" % result) print("Got %s" % result.pretty_string(tty=True))
print (colorize('=====================================', COLOR_RED)) print(colorize('=====================================', COLOR_RED))
return False return False
def run_fail_test(testname): def run_fail_test(testname):
'''Runs a test, which executes a query that is supposed to fail''' '''Runs a test, which executes a query that is supposed to fail'''
print ("Running fail test: " + colorize(testname, COLOR_MAGENTA)) print("Running fail test: " + colorize(testname, COLOR_MAGENTA))
query = readfile('%s%s.fail' % (tests_path, testname)).strip() query = readfile('%s%s.fail' % (tests_path, testname)).strip()
test_succeed = True test_succeed = True
@ -216,9 +216,9 @@ def run_fail_test(testname):
pass pass
if test_succeed: if test_succeed:
print (colorize('Test passed', COLOR_GREEN)) print(colorize('Test passed', COLOR_GREEN))
else: else:
print (colorize('Test failed (by not raising any exception)', COLOR_RED)) print(colorize('Test failed (by not raising any exception)', COLOR_RED))
return test_succeed return test_succeed
def run_test(testname): def run_test(testname):
@ -228,7 +228,7 @@ def run_test(testname):
testname.result testname.result
The query will be executed both unoptimized and The query will be executed both unoptimized and
optimized''' optimized'''
print ("Running test: " + colorize(testname, COLOR_MAGENTA)) print("Running test: " + colorize(testname, COLOR_MAGENTA))
query = None query = None
expr = None expr = None
@ -254,32 +254,32 @@ def run_test(testname):
c_result = eval(c_expr, rels) c_result = eval(c_expr, rels)
if (o_result == result_rel) and (result == result_rel) and (c_result == result_rel): if (o_result == result_rel) and (result == result_rel) and (c_result == result_rel):
print (colorize('Test passed', COLOR_GREEN)) print(colorize('Test passed', COLOR_GREEN))
return True return True
except Exception as inst: except Exception as inst:
traceback.print_exc(file=sys.stdout) traceback.print_exc(file=sys.stdout)
print (inst) print(inst)
pass pass
print (colorize('ERROR', COLOR_RED)) print(colorize('ERROR', COLOR_RED))
print ("Query: %s -> %s" % (query, expr)) print("Query: %s -> %s" % (query, expr))
print ("Optimized query: %s -> %s" % (o_query, o_expr)) print("Optimized query: %s -> %s" % (o_query, o_expr))
print (colorize('=====================================', COLOR_RED)) print(colorize('=====================================', COLOR_RED))
print (colorize("Expected result", COLOR_GREEN)) print(colorize("Expected result", COLOR_GREEN))
print (result_rel) print(result_rel.pretty_string(tty=True))
print (colorize("Result", COLOR_RED)) print(colorize("Result", COLOR_RED))
print (result) print(result.pretty_string(tty=True))
print (colorize("Optimized result", COLOR_RED)) print(colorize("Optimized result", COLOR_RED))
print (o_result) print(o_result.pretty_string(tty=True))
print (colorize("optimized result match %s" % print(colorize("optimized result match %s" %
str(result_rel == o_result), COLOR_MAGENTA)) str(result_rel == o_result), COLOR_MAGENTA))
print (colorize("result match %s" % print(colorize("result match %s" %
str(result == result_rel), COLOR_MAGENTA)) str(result == result_rel), COLOR_MAGENTA))
print (colorize('=====================================', COLOR_RED)) print(colorize('=====================================', COLOR_RED))
return False return False
if __name__ == '__main__': if __name__ == '__main__':
print ("-> Starting testsuite for relational") print("-> Starting testsuite for relational")
load_relations() load_relations()
print ("-> Starting tests") print("-> Starting tests")
exit(execute_tests()) exit(execute_tests())

View File

@ -412,22 +412,49 @@ class Relation:
def __len__(self): def __len__(self):
return len(self.content) return len(self.content)
def __str__(self): def __str__(self) -> str:
m_len = [len(i) for i in self.header] # Maximum lenght string return self.pretty_string(tty=False)
def pretty_string(self, tty: bool) -> str:
'''
Returns a printable string.
If tty is enabled, it will attempt to add ANSI color codes
'''
c = lambda i, ansi: i
if not tty:
colorize = c
else:
from os import isatty
if isatty(1) and isatty(2):
try:
from xtermcolor import colorize # type: ignore
except ModuleNotFoundError:
colorize = c
else:
colorize = c
m_len = [len(i) + 2 for i in self.header] # Maximum lenght string
for f in self.content: for f in self.content:
for col, i in enumerate(str(val) for val in f): for col, k in enumerate(str(val) for val in f):
if len(i) > m_len[col]: if len(k) + 2 > m_len[col]:
m_len[col] = len(i) m_len[col] = len(k) + 2
res = "" res = ""
for f, attr in enumerate(self.header): for j, attr in enumerate(self.header):
res += attr.ljust(2 + m_len[f]) res += colorize(attr.ljust(m_len[j]), ansi=3)
for r in self.content: for r in self.content:
res += "\n" res += "\n"
for col, i in enumerate(str(val) for val in r): for col, i in enumerate(r):
res += i.ljust(2 + m_len[col]) cell = str(i).ljust(m_len[col])
if isinstance(i, (int, float)):
cell = colorize(cell, ansi=4)
elif i is None:
cell = colorize(cell, ansi=1)
elif not isinstance(i, str):
cell = colorize(cell, ansi=15)
res += cell
return res return res

View File

@ -165,12 +165,19 @@ def help(command: str) -> None:
p = command.split(' ', 1) p = command.split(' ', 1)
if len(p) == 1: if len(p) == 1:
print( print(
'HELP command\n' 'HELP [command]\n'
'\n'
'Comments are obtained starting with a ;\n'
'\n'
'To execute a query:\n' 'To execute a query:\n'
'[relation =] query\n' '[relation =] query\n'
'\n'
'If the 1st part is omitted, the result will be stored in the relation last_.\n' 'If the 1st part is omitted, the result will be stored in the relation last_.\n'
'\n'
'To prevent from printing the relation, append a ; to the end of the query.\n' 'To prevent from printing the relation, append a ; to the end of the query.\n'
'\n'
'To insert relational operators, type _OPNAME, they will be internally replaced with the correct symbol.\n' 'To insert relational operators, type _OPNAME, they will be internally replaced with the correct symbol.\n'
'\n'
'Rember: completion is enabled and can be very helpful if you can\'t remember something.' 'Rember: completion is enabled and can be very helpful if you can\'t remember something.'
) )
return return
@ -301,7 +308,7 @@ def exec_query(command: str) -> None:
if printrel: if printrel:
print() print()
print(result) print(result.pretty_string(tty=True))
ui.relations[relname] = result ui.relations[relname] = result