Skip to content

Commit

Permalink
Make tables look less awful
Browse files Browse the repository at this point in the history
  • Loading branch information
acbart committed Mar 16, 2024
1 parent 107b56e commit be92319
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 34 deletions.
8 changes: 3 additions & 5 deletions pedal/core/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
Utilities and classes related to formatting a Feedback Message.
"""
from pedal.core.location import Location
from pedal.utilities.text import inject_line
from pedal.utilities.text import inject_line, render_table


def chomp_spec(format_spec, word):
""" Return a new version of format_spec without the ``word`` and
Expand Down Expand Up @@ -126,10 +127,7 @@ def exception(self, exception):
return self.pre(exception)

def table(self, rows, columns):
result = [" | ".join(columns)]
for row in rows:
result.append(" | ".join(row))
return "\n" + ("\n".join(result))
return "\n" + render_table(rows, columns, " | ")

def check_mark(self):
# TODO: should be ✓, right?
Expand Down
11 changes: 11 additions & 0 deletions pedal/environments/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
from pedal.resolvers.simple import resolve
from pedal.core.formatting import Formatter

try:
import tabulate
except ImportError:
tabulate = None

RESET = "\033[0;0m"
REVERSE = "\033[;7m"
UNDERLINE = "\033[4m"
Expand Down Expand Up @@ -42,6 +47,12 @@ def filename(self, filename):
filename = os.path.basename(filename)
return f"{UNDERLINE}{filename}{RESET}"

def table(self, rows, columns):
if tabulate:
return self.pre(tabulate.tabulate(rows, headers=columns, tablefmt="plain"))
else:
return super().table(rows, columns)


@make_resolver
def resolve_on_terminal(report=MAIN_REPORT):
Expand Down
32 changes: 32 additions & 0 deletions pedal/utilities/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,35 @@ def inject_line(code, line_number, new_line):
lines = code.split("\n")
lines.insert(line_number, new_line)
return "\n".join(lines)


def render_table(rows, headers=None, separator=" | ", max_width=120):
"""
Simple function to render table with fixed width.
TODO: Try to resize table to make it fit comfortably within 120 characters,
e.g., by removing separators, or by wrapping text.
Based on: https://stackoverflow.com/a/52247284/1718155
"""
table = [headers] + rows if headers else rows
longest_cols = [
(max([len(str(row[i])) for row in table]))
for i in range(len(table[0]))
]
total_width = sum(longest_cols) + (len(longest_cols)-1) * len(separator)
if max_width is not None:
if total_width > max_width:
# Maybe we can trim the separator?
if separator:
shorter_separator = separator.strip()
# Oops, we already tried stripping. What about removing it?
if shorter_separator == separator:
shorter_separator = ""
return render_table(rows, headers, shorter_separator, max_width)
row_format = separator.join(["{:>" + str(longest_col) + "}"
for longest_col in longest_cols])
result = [row_format.format(*row) for row in table]
if headers:
result.insert(1, "="*total_width)
return "\n".join(result)
48 changes: 27 additions & 21 deletions tests/test_assertion_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,13 @@ def test_unit_test_partial_credit_true(self):
You passed 3/5 tests.
I ran your function add on some new arguments.
| Arguments | Returned | Expected
× | 1, 2 | 2 | 3
| 0, 0 | 0 | 0
| 0, 3 | 3 | 3
| 0, 5 | 5 | 5
× | 1, 3 | 3 | 4""")
| Arguments | Returned | Expected
===================================
× | 1, 2 | 2 | 3
| 0, 0 | 0 | 0
| 0, 3 | 3 | 3
| 0, 5 | 5 | 5
× | 1, 3 | 3 | 4""")

def test_bad_name_error_concatenation(self):
with Execution("""
Expand Down Expand Up @@ -125,9 +126,10 @@ def add(a, b):
You passed 1/2 tests.
I ran your function add on some new arguments.
| Arguments | Returned | Expected
× | 1, 2 | -1 | 3
| 0, 0 | 0 | 0""")
| Arguments | Returned | Expected
===================================
× | 1, 2 | -1 | 3
| 0, 0 | 0 | 0""")

def test_unit_test_blocked_function(self):
with Execution("""
Expand All @@ -142,8 +144,9 @@ def summate(numbers: [int]) -> int:
You passed 0/1 tests.
I ran your function summate on some new arguments.
| Arguments | Returned | Expected
× | [1, 2, 3] | You are not allowed to call 'sum'. | 6""")
| Arguments | Returned | Expected
=================================================================
× | [1, 2, 3] | You are not allowed to call 'sum'. | 6""")

def test_unit_test_extra_context(self):
with Execution('def add(a, b): return b', run_tifa=False) as e:
Expand All @@ -163,9 +166,10 @@ def test_unit_test_extra_context(self):
data = [5, 3, 4]
I ran your function add on some new arguments.
| Arguments | Returned | Expected
× | data, 5 | 5 | 17
× | [3, 3], 3 | 3 | 9""")
| Arguments | Returned | Expected
=======================================
× | data, 5 | 5 | 17
× | [3, 3], 3 | 3 | 9""")

def test_unit_test_extra_context_run(self):
with Execution('def add(a, b): return b', run_tifa=False) as e:
Expand All @@ -187,9 +191,10 @@ def test_unit_test_extra_context_run(self):
data2 = [1,2,3]
I ran your function add on some new arguments.
| Arguments | Returned | Expected
× | data, 5 | 5 | 17
× | [3, 3], 3 | 3 | 9""")
| Arguments | Returned | Expected
=======================================
× | data, 5 | 5 | 17
× | [3, 3], 3 | 3 | 9""")

def test_unit_test_extra_context_calls(self):
with Execution('def add(a, b): return b', run_tifa=False) as e:
Expand All @@ -214,10 +219,11 @@ def test_unit_test_extra_context_calls(self):
data2 = [1,2,3]
I ran your function add on some new arguments.
| Arguments | Returned | Expected
× | data, 5 | 5 | 17
× | data2, 5 | 5 | 17
× | [3, 3], 3 | 3 | 9""")
| Arguments | Returned | Expected
=======================================
× | data, 5 | 5 | 17
× | data2, 5 | 5 | 17
× | [3, 3], 3 | 3 | 9""")

if __name__ == '__main__':
unittest.main(buffer=False)
18 changes: 10 additions & 8 deletions tests/test_assertions_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,11 @@ def test_assert_group_fails_some_errors(self):
You passed 1/3 tests.
I ran your function add on some new arguments.
| Arguments | Returned | Expected
| 1, 2 | 3 | 3
× | 1, 4 | 5 | 6
× | 1, '2' | unsupported operand type(s) for +: 'int' and 'str' | 3""")
| Arguments | Returned | Expected
==============================================================================
| 1, 2 | 3 | 3
× | 1, 4 | 5 | 6
× | 1, '2' | unsupported operand type(s) for +: 'int' and 'str' | 3""")

def test_assert_group_fails_all(self):
with Execution('def add(a, b): return a+b', run_tifa=False) as e:
Expand All @@ -272,10 +273,11 @@ def test_assert_group_fails_all(self):
You passed 0/3 tests.
I ran your function add on some new arguments.
| Arguments | Returned | Expected
× | 1, 3 | 4 | 3
× | 1, 4 | 5 | 6
× | 1, 3 | 4 | 3""")
| Arguments | Returned | Expected
===================================
× | 1, 3 | 4 | 3
× | 1, 4 | 5 | 6
× | 1, 3 | 4 | 3""")

def test_assert_group_passes(self):
with Execution('def add(a, b): return a+b', run_tifa=False) as e:
Expand Down

0 comments on commit be92319

Please sign in to comment.