Skip to content

Commit 8754990

Browse files
committed
move export options from root to scan command
1 parent 0707636 commit 8754990

File tree

3 files changed

+52
-43
lines changed

3 files changed

+52
-43
lines changed

cycode/cli/app.py

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import logging
2-
from pathlib import Path
32
from typing import Annotated, Optional
43

54
import typer
@@ -8,7 +7,7 @@
87

98
from cycode import __version__
109
from cycode.cli.apps import ai_remediation, auth, configure, ignore, report, scan, status
11-
from cycode.cli.cli_types import ExportTypeOption, OutputTypeOption
10+
from cycode.cli.cli_types import OutputTypeOption
1211
from cycode.cli.consts import CLI_CONTEXT_SETTINGS
1312
from cycode.cli.printers import ConsolePrinter
1413
from cycode.cli.user_settings.configuration_manager import ConfigurationManager
@@ -70,7 +69,6 @@ def export_if_needed_on_close(ctx: typer.Context) -> None:
7069

7170

7271
_COMPLETION_RICH_HELP_PANEL = 'Completion options'
73-
_EXPORT_RICH_HELP_PANEL = 'Export options'
7472

7573

7674
@app.callback()
@@ -90,27 +88,6 @@ def app_callback(
9088
Optional[str],
9189
typer.Option(hidden=True, help='Characteristic JSON object that lets servers identify the application.'),
9290
] = None,
93-
export_type: Annotated[
94-
ExportTypeOption,
95-
typer.Option(
96-
'--export-type',
97-
case_sensitive=False,
98-
help='Specify the export type. '
99-
'HTML and SVG will export terminal output and rely on --output option. '
100-
'JSON always exports JSON.',
101-
rich_help_panel=_EXPORT_RICH_HELP_PANEL,
102-
),
103-
] = ExportTypeOption.JSON,
104-
export_file: Annotated[
105-
Optional[Path],
106-
typer.Option(
107-
'--export-file',
108-
help='Export file. Path to the file where the export will be saved. ',
109-
dir_okay=False,
110-
writable=True,
111-
rich_help_panel=_EXPORT_RICH_HELP_PANEL,
112-
),
113-
] = None,
11491
_: Annotated[
11592
Optional[bool],
11693
typer.Option(
@@ -152,8 +129,6 @@ def app_callback(
152129

153130
ctx.obj['progress_bar'] = get_progress_bar(hidden=no_progress_meter, sections=SCAN_PROGRESS_BAR_SECTIONS)
154131

155-
ctx.obj['export_type'] = export_type
156-
ctx.obj['export_file'] = export_file
157132
ctx.obj['console_printer'] = ConsolePrinter(ctx)
158133
ctx.call_on_close(lambda: export_if_needed_on_close(ctx))
159134

cycode/cli/apps/scan/scan_command.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
from pathlib import Path
12
from typing import Annotated, Optional
23

34
import click
45
import typer
56

6-
from cycode.cli.cli_types import ScanTypeOption, ScaScanTypeOption, SeverityOption
7+
from cycode.cli.cli_types import ExportTypeOption, ScanTypeOption, ScaScanTypeOption, SeverityOption
78
from cycode.cli.consts import (
89
ISSUE_DETECTED_STATUS_CODE,
910
NO_ISSUES_STATUS_CODE,
@@ -13,6 +14,7 @@
1314
from cycode.cli.utils.sentry import add_breadcrumb
1415

1516
_AUTH_RICH_HELP_PANEL = 'Authentication options'
17+
_EXPORT_RICH_HELP_PANEL = 'Export options'
1618
_SCA_RICH_HELP_PANEL = 'SCA options'
1719

1820

@@ -66,6 +68,27 @@ def scan_command(
6668
'A link to the report will be displayed in the console output.',
6769
),
6870
] = False,
71+
export_type: Annotated[
72+
ExportTypeOption,
73+
typer.Option(
74+
'--export-type',
75+
case_sensitive=False,
76+
help='Specify the export type. '
77+
'HTML and SVG will export terminal output and rely on --output option. '
78+
'JSON always exports JSON.',
79+
rich_help_panel=_EXPORT_RICH_HELP_PANEL,
80+
),
81+
] = ExportTypeOption.JSON,
82+
export_file: Annotated[
83+
Optional[Path],
84+
typer.Option(
85+
'--export-file',
86+
help='Export file. Path to the file where the export will be saved. ',
87+
dir_okay=False,
88+
writable=True,
89+
rich_help_panel=_EXPORT_RICH_HELP_PANEL,
90+
),
91+
] = None,
6992
sca_scan: Annotated[
7093
list[ScaScanTypeOption],
7194
typer.Option(
@@ -124,6 +147,10 @@ def scan_command(
124147
ctx.obj['monitor'] = monitor
125148
ctx.obj['report'] = report
126149

150+
if export_file:
151+
console_printer = ctx.obj['console_printer']
152+
console_printer.enable_recording(export_type, export_file)
153+
127154
_ = no_restore, gradle_all_sub_projects # they are actually used; via ctx.params
128155

129156
_sca_scan_to_context(ctx, sca_scan)

cycode/cli/printers/console_printer.py

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
from cycode.cli.printers.text_printer import TextPrinter
1717

1818
if TYPE_CHECKING:
19+
from pathlib import Path
20+
1921
from cycode.cli.models import LocalScanResult
2022
from cycode.cli.printers.tables.table_printer_base import PrinterBase
2123

@@ -43,17 +45,9 @@ def __init__(
4345
self.console_err = console_err_override or console_err
4446
self.output_type = output_type_override or self.ctx.obj.get('output')
4547

46-
self.console_record = None
47-
48-
self.export_type = self.ctx.obj.get('export_type')
49-
self.export_file = self.ctx.obj.get('export_file')
50-
if console_override is None and self.export_type and self.export_file:
51-
self.console_record = ConsolePrinter(
52-
ctx,
53-
console_override=Console(record=True, file=io.StringIO()),
54-
console_err_override=Console(stderr=True, record=True, file=io.StringIO()),
55-
output_type_override='json' if self.export_type == 'json' else self.output_type,
56-
)
48+
self.export_type: Optional[str] = None
49+
self.export_file: Optional[Path] = None
50+
self.console_record: Optional[ConsolePrinter] = None
5751

5852
@property
5953
def scan_type(self) -> str:
@@ -76,6 +70,18 @@ def printer(self) -> 'PrinterBase':
7670

7771
return printer_class(self.ctx, self.console, self.console_err)
7872

73+
def enable_recording(self, export_type: str, export_file: 'Path') -> None:
74+
if self.console_record is None:
75+
self.export_file = export_file
76+
self.export_type = export_type
77+
78+
self.console_record = ConsolePrinter(
79+
self.ctx,
80+
console_override=Console(record=True, file=io.StringIO()),
81+
console_err_override=Console(stderr=True, record=True, file=io.StringIO()),
82+
output_type_override='json' if self.export_type == 'json' else self.output_type,
83+
)
84+
7985
def print_scan_results(
8086
self,
8187
local_scan_results: list['LocalScanResult'],
@@ -106,16 +112,17 @@ def export(self) -> None:
106112
if self.console_record is None:
107113
raise CycodeError('Console recording was not enabled. Cannot export.')
108114

109-
if not self.export_file.suffix:
115+
export_file = self.export_file
116+
if not export_file.suffix:
110117
# resolve file extension based on the export type if not provided in the file name
111-
self.export_file = self.export_file.with_suffix(f'.{self.export_type.lower()}')
118+
export_file = export_file.with_suffix(f'.{self.export_type.lower()}')
112119

113120
if self.export_type is ExportTypeOption.HTML:
114-
self.console_record.console.save_html(self.export_file)
121+
self.console_record.console.save_html(export_file)
115122
elif self.export_type is ExportTypeOption.SVG:
116-
self.console_record.console.save_svg(self.export_file, title=consts.APP_NAME)
123+
self.console_record.console.save_svg(export_file, title=consts.APP_NAME)
117124
elif self.export_type is ExportTypeOption.JSON:
118-
with open(self.export_file, 'w', encoding='UTF-8') as f:
125+
with open(export_file, 'w', encoding='UTF-8') as f:
119126
self.console_record.console.file.seek(0)
120127
f.write(self.console_record.console.file.read())
121128
else:

0 commit comments

Comments
 (0)