From e11d4f231f6b09676ea099166e6a7683d0f1dcee Mon Sep 17 00:00:00 2001 From: Alexis Date: Mon, 15 Apr 2024 15:19:32 +0200 Subject: [PATCH 1/8] Add a new parameter `max_width` to MyPrettyTable to enhance its display for CLI usage This PR adds a `max_width` parameter to MyPrettyTable to restrict the maximum width of its underlying table. The value can be an integer, "max" (detect automatically the correct width) or None (no width limit) --- slither/utils/command_line.py | 6 ++++-- slither/utils/myprettytable.py | 27 ++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py index f03ced834..330de58ba 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -306,7 +306,9 @@ def output_detectors(detector_classes: List[Type[AbstractDetector]]) -> None: impact = detector.IMPACT confidence = classification_txt[detector.CONFIDENCE] detectors_list.append((argument, help_info, impact, confidence)) - table = MyPrettyTable(["Num", "Check", "What it Detects", "Impact", "Confidence"]) + table = MyPrettyTable( + ["Num", "Check", "What it Detects", "Impact", "Confidence"], max_width="max" + ) # Sort by impact, confidence, and name detectors_list = sorted( @@ -388,7 +390,7 @@ def output_printers(printer_classes: List[Type[AbstractPrinter]]) -> None: argument = printer.ARGUMENT help_info = printer.HELP printers_list.append((argument, help_info)) - table = MyPrettyTable(["Num", "Printer", "What it Does"]) + table = MyPrettyTable(["Num", "Printer", "What it Does"], max_width="max") # Sort by impact, confidence, and name printers_list = sorted(printers_list, key=lambda element: (element[0])) diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index b33fb9c5f..c34a4035d 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -1,4 +1,5 @@ -from typing import List, Dict, Union +from shutil import get_terminal_size +from typing import List, Dict, Union, Literal from prettytable import PrettyTable from prettytable.colortable import ColorTable, Themes @@ -7,7 +8,12 @@ class MyPrettyTable: - def __init__(self, field_names: List[str], pretty_align: bool = True): # TODO: True by default? + def __init__( + self, + field_names: List[str], + pretty_align: bool = True, + max_width: Union[int, Literal["max"], None] = None, + ): self._field_names = field_names self._rows: List = [] self._options: Dict = {} @@ -19,6 +25,16 @@ def __init__(self, field_names: List[str], pretty_align: bool = True): # TODO: else: self._options["set_alignment"] = [] + self.max_width = None + if max_width == "max": + # We use (0,0) as a fallback to detect if we are not attached to a terminal + # In this case, we fall back to the default behavior (i.e. printing as much as possible) + terminal_column = get_terminal_size((0, 0)).columns + if terminal_column != 0: + self.max_width = terminal_column - 2 + else: + self.max_width = max_width + def add_row(self, row: List[Union[str, List[str]]]) -> None: self._rows.append(row) @@ -28,6 +44,9 @@ def to_pretty_table(self) -> PrettyTable: else: table = PrettyTable(self._field_names) + if self.max_width is not None: + table.max_table_width = self.max_width + for row in self._rows: table.add_row(row) if len(self._options["set_alignment"]): @@ -63,7 +82,5 @@ def make_pretty_table( table_row = [row] + [body[row][key] for key in headers[1:]] table.add_row(table_row) if totals: - table.add_row( - [total_header] + [sum([body[row][key] for row in body]) for key in headers[1:]] - ) + table.add_row([total_header] + [sum(body[row][key] for row in body) for key in headers[1:]]) return table From 08d981715cfd7c8da5bcae726b81f56aa8b60548 Mon Sep 17 00:00:00 2001 From: Alexis Date: Mon, 15 Apr 2024 15:54:32 +0200 Subject: [PATCH 2/8] Fix the description of the Loc printer, and adjust the maximal width. --- slither/printers/summary/loc.py | 4 ++-- slither/utils/command_line.py | 4 +++- slither/utils/myprettytable.py | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/slither/printers/summary/loc.py b/slither/printers/summary/loc.py index 35bb20fc4..886803e8e 100644 --- a/slither/printers/summary/loc.py +++ b/slither/printers/summary/loc.py @@ -17,8 +17,8 @@ class LocPrinter(AbstractPrinter): ARGUMENT = "loc" - HELP = """Count the total number lines of code (LOC), source lines of code (SLOC), \ - and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), \ + HELP = """Count the total number lines of code (LOC), source lines of code (SLOC), + and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).""" WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#loc" diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py index 330de58ba..21d136a36 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -396,8 +396,10 @@ def output_printers(printer_classes: List[Type[AbstractPrinter]]) -> None: printers_list = sorted(printers_list, key=lambda element: (element[0])) idx = 1 for (argument, help_info) in printers_list: - table.add_row([str(idx), argument, help_info]) + # Clean multi line HELP info + table.add_row([str(idx), argument, " ".join(x.strip() for x in help_info.splitlines())]) idx = idx + 1 + print(table) diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index c34a4035d..ab26e358a 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -31,7 +31,8 @@ def __init__( # In this case, we fall back to the default behavior (i.e. printing as much as possible) terminal_column = get_terminal_size((0, 0)).columns if terminal_column != 0: - self.max_width = terminal_column - 2 + # We reduce slightly the max-width to take into account inconsistencies in terminals + self.max_width = terminal_column - 3 else: self.max_width = max_width From dbe67f318f8514f7d47b1faa85624103fa6e3d49 Mon Sep 17 00:00:00 2001 From: Alexis Date: Tue, 11 Jun 2024 14:49:08 +0200 Subject: [PATCH 3/8] Update requirement on prettytable. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a669b82a3..b3031bd4f 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ python_requires=">=3.8", install_requires=[ "packaging", - "prettytable>=3.3.0", + "prettytable>=3.10.0", "pycryptodome>=3.4.6", "crytic-compile>=0.3.7,<0.4.0", # "crytic-compile@git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile", From f533843e18f672ee9721730ee27c09ef3f8552b5 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 12 Jul 2024 09:00:12 -0500 Subject: [PATCH 4/8] bump prettytable --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b3031bd4f..2446cc6ba 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ python_requires=">=3.8", install_requires=[ "packaging", - "prettytable>=3.10.0", + "prettytable>=3.10.1", "pycryptodome>=3.4.6", "crytic-compile>=0.3.7,<0.4.0", # "crytic-compile@git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile", From 209c23ae36b514044a9a1ec6a5cd2127e1ed78c3 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 12 Jul 2024 12:42:40 -0500 Subject: [PATCH 5/8] bump prettytable Co-authored-by: dm --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 2446cc6ba..3b361d605 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ python_requires=">=3.8", install_requires=[ "packaging", - "prettytable>=3.10.1", + "prettytable>=3.10.2", "pycryptodome>=3.4.6", "crytic-compile>=0.3.7,<0.4.0", # "crytic-compile@git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile", From 562301851465f0608086c668de41eeaf9beaf46f Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 18 Jul 2024 09:34:47 -0500 Subject: [PATCH 6/8] default all prettytable's to fit within max terminal width --- slither/utils/command_line.py | 6 ++---- slither/utils/myprettytable.py | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py index 6e00b6ed0..b8888cb85 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -272,9 +272,7 @@ def output_detectors(detector_classes: List[Type[AbstractDetector]]) -> None: impact = detector.IMPACT confidence = classification_txt[detector.CONFIDENCE] detectors_list.append((argument, help_info, impact, confidence)) - table = MyPrettyTable( - ["Num", "Check", "What it Detects", "Impact", "Confidence"], max_width="max" - ) + table = MyPrettyTable(["Num", "Check", "What it Detects", "Impact", "Confidence"]) # Sort by impact, confidence, and name detectors_list = sorted( @@ -356,7 +354,7 @@ def output_printers(printer_classes: List[Type[AbstractPrinter]]) -> None: argument = printer.ARGUMENT help_info = printer.HELP printers_list.append((argument, help_info)) - table = MyPrettyTable(["Num", "Printer", "What it Does"], max_width="max") + table = MyPrettyTable(["Num", "Printer", "What it Does"]) # Sort by impact, confidence, and name printers_list = sorted(printers_list, key=lambda element: (element[0])) diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index ab26e358a..a5c65d68d 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -12,7 +12,7 @@ def __init__( self, field_names: List[str], pretty_align: bool = True, - max_width: Union[int, Literal["max"], None] = None, + max_width: Union[int, None] = "max", # Default value is "max" ): self._field_names = field_names self._rows: List = [] @@ -25,7 +25,6 @@ def __init__( else: self._options["set_alignment"] = [] - self.max_width = None if max_width == "max": # We use (0,0) as a fallback to detect if we are not attached to a terminal # In this case, we fall back to the default behavior (i.e. printing as much as possible) From 12a5888bb8c228f2eec79282979346b85d070af1 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 18 Jul 2024 09:38:11 -0500 Subject: [PATCH 7/8] handle if terminal is unavail --- slither/utils/myprettytable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index a5c65d68d..6106af8f4 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -25,6 +25,7 @@ def __init__( else: self._options["set_alignment"] = [] + self.max_width = None if max_width == "max": # We use (0,0) as a fallback to detect if we are not attached to a terminal # In this case, we fall back to the default behavior (i.e. printing as much as possible) From a98f68f9b3144595211bdf93e48a2f211f12987b Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 18 Jul 2024 09:46:57 -0500 Subject: [PATCH 8/8] pylint --- slither/utils/myprettytable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index 6106af8f4..ac666a501 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -1,5 +1,5 @@ from shutil import get_terminal_size -from typing import List, Dict, Union, Literal +from typing import List, Dict, Union from prettytable import PrettyTable from prettytable.colortable import ColorTable, Themes