Skip to content

Commit 4f96566

Browse files
committed
CM-46137 - Add visual separators of row groups; reorder columns
1 parent da80ead commit 4f96566

File tree

3 files changed

+34
-19
lines changed

3 files changed

+34
-19
lines changed

cycode/cli/printers/tables/sca_table_printer.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from collections import defaultdict
2-
from typing import TYPE_CHECKING, Dict, List
2+
from typing import TYPE_CHECKING, Dict, List, Set, Tuple
33

44
import typer
55

@@ -37,9 +37,12 @@ def _print_results(self, local_scan_results: List['LocalScanResult']) -> None:
3737
for policy_id, detections in detections_per_policy_id.items():
3838
table = self._get_table(policy_id)
3939

40-
for detection in self._sort_and_group_detections(detections):
40+
resulting_detections, group_separator_indexes = self._sort_and_group_detections(detections)
41+
for detection in resulting_detections:
4142
self._enrich_table_with_values(policy_id, table, detection)
4243

44+
table.set_group_separator_indexes(group_separator_indexes)
45+
4346
self._print_summary_issues(len(detections), self._get_title(policy_id))
4447
self._print_table(table)
4548

@@ -76,7 +79,7 @@ def __package_sort_key(detection: Detection) -> int:
7679
def _sort_detections_by_package(self, detections: List[Detection]) -> List[Detection]:
7780
return sorted(detections, key=self.__package_sort_key)
7881

79-
def _sort_and_group_detections(self, detections: List[Detection]) -> List[Detection]:
82+
def _sort_and_group_detections(self, detections: List[Detection]) -> Tuple[List[Detection], Set[int]]:
8083
"""Sort detections by severity and group by repository, code project and package name.
8184
8285
Note:
@@ -85,7 +88,8 @@ def _sort_and_group_detections(self, detections: List[Detection]) -> List[Detect
8588
Grouping by code projects also groups by ecosystem.
8689
Because manifest files are unique per ecosystem.
8790
"""
88-
result = []
91+
resulting_detections = []
92+
group_separator_indexes = set()
8993

9094
# we sort detections by package name to make persist output order
9195
sorted_detections = self._sort_detections_by_package(detections)
@@ -96,9 +100,10 @@ def _sort_and_group_detections(self, detections: List[Detection]) -> List[Detect
96100
for code_project_group in grouped_by_code_project.values():
97101
grouped_by_package = self.__group_by(code_project_group, 'package_name')
98102
for package_group in grouped_by_package.values():
99-
result.extend(self._sort_detections_by_severity(package_group))
103+
group_separator_indexes.add(len(resulting_detections) - 1) # indexing starts from 0
104+
resulting_detections.extend(self._sort_detections_by_severity(package_group))
100105

101-
return result
106+
return resulting_detections, group_separator_indexes
102107

103108
def _get_table(self, policy_id: str) -> Table:
104109
table = Table()

cycode/cli/printers/tables/table.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import urllib.parse
2-
from typing import TYPE_CHECKING, Dict, List, Optional
2+
from typing import TYPE_CHECKING, Dict, List, Optional, Set
33

44
from rich.markup import escape
55
from rich.table import Table as RichTable
@@ -12,6 +12,8 @@ class Table:
1212
"""Helper class to manage columns and their values in the right order and only if the column should be presented."""
1313

1414
def __init__(self, column_infos: Optional[List['ColumnInfo']] = None) -> None:
15+
self._group_separator_indexes: Set[int] = set()
16+
1517
self._columns: Dict['ColumnInfo', List[str]] = {}
1618
if column_infos:
1719
self._columns = {columns: [] for columns in column_infos}
@@ -35,6 +37,9 @@ def add_file_path_cell(self, column: 'ColumnInfo', path: str) -> None:
3537
escaped_path = escape(encoded_path)
3638
self._add_cell_no_error(column, f'[link file://{escaped_path}]{path}')
3739

40+
def set_group_separator_indexes(self, group_separator_indexes: Set[int]) -> None:
41+
self._group_separator_indexes = group_separator_indexes
42+
3843
def _get_ordered_columns(self) -> List['ColumnInfo']:
3944
# we are sorting columns by index to make sure that columns will be printed in the right order
4045
return sorted(self._columns, key=lambda column_info: column_info.index)
@@ -53,7 +58,7 @@ def get_table(self) -> 'RichTable':
5358
extra_args = column.column_opts if column.column_opts else {}
5459
table.add_column(header=column.name, overflow='fold', **extra_args)
5560

56-
for raw in self.get_rows():
57-
table.add_row(*raw)
61+
for index, raw in enumerate(self.get_rows()):
62+
table.add_row(*raw, end_section=index in self._group_separator_indexes)
5863

5964
return table

cycode/cli/printers/tables/table_printer.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from collections import defaultdict
2-
from typing import TYPE_CHECKING, List, Tuple
2+
from typing import TYPE_CHECKING, List, Set, Tuple
33

44
from cycode.cli.cli_types import SeverityOption
55
from cycode.cli.consts import SECRET_SCAN_TYPE
@@ -18,12 +18,12 @@
1818
SEVERITY_COLUMN = column_builder.build(name='Severity')
1919
ISSUE_TYPE_COLUMN = column_builder.build(name='Issue Type')
2020
FILE_PATH_COLUMN = column_builder.build(name='File Path', highlight=False)
21+
LINE_NUMBER_COLUMN = column_builder.build(name='Line')
22+
COLUMN_NUMBER_COLUMN = column_builder.build(name='Column')
23+
VIOLATION_COLUMN = column_builder.build(name='Violation', highlight=False)
24+
VIOLATION_LENGTH_COLUMN = column_builder.build(name='Length')
2125
SECRET_SHA_COLUMN = column_builder.build(name='Secret SHA')
2226
COMMIT_SHA_COLUMN = column_builder.build(name='Commit SHA')
23-
LINE_NUMBER_COLUMN = column_builder.build(name='Line Number')
24-
COLUMN_NUMBER_COLUMN = column_builder.build(name='Column Number')
25-
VIOLATION_LENGTH_COLUMN = column_builder.build(name='Violation Length')
26-
VIOLATION_COLUMN = column_builder.build(name='Violation', highlight=False)
2727

2828

2929
class TablePrinter(TablePrinterBase):
@@ -37,9 +37,12 @@ def _print_results(self, local_scan_results: List['LocalScanResult']) -> None:
3737
[(detection, document_detections.document) for detection in document_detections.detections]
3838
)
3939

40-
for detection, document in self._sort_and_group_detections(detections_with_documents):
40+
detections, group_separator_indexes = self._sort_and_group_detections(detections_with_documents)
41+
for detection, document in detections:
4142
self._enrich_table_with_values(table, detection, document)
4243

44+
table.set_group_separator_indexes(group_separator_indexes)
45+
4346
self._print_table(table)
4447
self._print_report_urls(local_scan_results, self.ctx.obj.get('aggregation_report_url'))
4548

@@ -66,9 +69,10 @@ def _sort_detections_by_file_path(
6669

6770
def _sort_and_group_detections(
6871
self, detections_with_documents: List[Tuple[Detection, Document]]
69-
) -> List[Tuple[Detection, Document]]:
72+
) -> Tuple[List[Tuple[Detection, Document]], Set[int]]:
7073
"""Sort detections by severity and group by file name."""
71-
result = []
74+
detections = []
75+
group_separator_indexes = set()
7276

7377
# we sort detections by file path to make persist output order
7478
sorted_detections = self._sort_detections_by_file_path(detections_with_documents)
@@ -78,9 +82,10 @@ def _sort_and_group_detections(
7882
grouped_by_file_path[document.path].append((detection, document))
7983

8084
for file_path_group in grouped_by_file_path.values():
81-
result.extend(self._sort_detections_by_severity(file_path_group))
85+
group_separator_indexes.add(len(detections) - 1) # indexing starts from 0
86+
detections.extend(self._sort_detections_by_severity(file_path_group))
8287

83-
return result
88+
return detections, group_separator_indexes
8489

8590
def _get_table(self) -> Table:
8691
table = Table()

0 commit comments

Comments
 (0)