Skip to content

Commit 9940c92

Browse files
authored
CM-28830 - Fix traceback printing to stderr instead of stdout (#212)
1 parent 3f472b0 commit 9940c92

File tree

5 files changed

+27
-14
lines changed

5 files changed

+27
-14
lines changed

cycode/cli/commands/auth/auth_command.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import traceback
2-
31
import click
42

53
from cycode.cli.commands.auth.auth_manager import AuthManager
@@ -54,16 +52,14 @@ def authorization_check(context: click.Context) -> None:
5452
printer.print_result(passed_auth_check_res)
5553
return
5654
except (NetworkError, HttpUnauthorizedError):
57-
if context.obj['verbose']:
58-
click.secho(f'Error: {traceback.format_exc()}', fg='red')
55+
ConsolePrinter(context).print_exception()
5956

6057
printer.print_result(failed_auth_check_res)
6158
return
6259

6360

6461
def _handle_exception(context: click.Context, e: Exception) -> None:
65-
if context.obj['verbose']:
66-
click.secho(f'Error: {traceback.format_exc()}', fg='red')
62+
ConsolePrinter(context).print_exception()
6763

6864
errors: CliErrors = {
6965
AuthProcessError: CliError(

cycode/cli/exceptions/handle_report_sbom_errors.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import traceback
21
from typing import Optional
32

43
import click
@@ -9,8 +8,7 @@
98

109

1110
def handle_report_exception(context: click.Context, err: Exception) -> Optional[CliError]:
12-
if context.obj['verbose']:
13-
click.secho(f'Error: {traceback.format_exc()}', fg='red')
11+
ConsolePrinter(context).print_exception()
1412

1513
errors: CliErrors = {
1614
custom_exceptions.NetworkError: CliError(

cycode/cli/exceptions/handle_scan_errors.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import traceback
21
from typing import Optional
32

43
import click
@@ -14,8 +13,7 @@ def handle_scan_exception(
1413
) -> Optional[CliError]:
1514
context.obj['did_fail'] = True
1615

17-
if context.obj['verbose']:
18-
click.secho(f'Error: {traceback.format_exc()}', fg='red')
16+
ConsolePrinter(context).print_exception()
1917

2018
errors: CliErrors = {
2119
custom_exceptions.NetworkError: CliError(

cycode/cli/printers/console_printer.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import TYPE_CHECKING, ClassVar, Dict, List, Optional
1+
from typing import TYPE_CHECKING, ClassVar, Dict, List, Optional, Type
22

33
import click
44

@@ -15,7 +15,7 @@
1515

1616

1717
class ConsolePrinter:
18-
_AVAILABLE_PRINTERS: ClassVar[Dict[str, 'PrinterBase']] = {
18+
_AVAILABLE_PRINTERS: ClassVar[Dict[str, Type['PrinterBase']]] = {
1919
'text': TextPrinter,
2020
'json': JsonPrinter,
2121
'table': TablePrinter,
@@ -53,3 +53,8 @@ def print_result(self, result: CliResult) -> None:
5353

5454
def print_error(self, error: CliError) -> None:
5555
self._printer_class(self.context).print_error(error)
56+
57+
def print_exception(self, e: Optional[BaseException] = None, force_print: bool = False) -> None:
58+
"""Print traceback message in stderr if verbose mode is set."""
59+
if force_print or self.context.obj.get('verbose', False):
60+
self._printer_class(self.context).print_exception(e)

cycode/cli/printers/printer_base.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import traceback
12
from abc import ABC, abstractmethod
23
from typing import TYPE_CHECKING, Dict, List, Optional
34

@@ -30,3 +31,18 @@ def print_result(self, result: CliResult) -> None:
3031
@abstractmethod
3132
def print_error(self, error: CliError) -> None:
3233
pass
34+
35+
def print_exception(self, e: Optional[BaseException] = None) -> None:
36+
"""We are printing it in stderr so, we don't care about supporting JSON and TABLE outputs.
37+
38+
Note:
39+
Called only when the verbose flag is set.
40+
"""
41+
if e is None:
42+
# gets the most recent exception caught by an except clause
43+
message = f'Error: {traceback.format_exc()}'
44+
else:
45+
traceback_message = ''.join(traceback.format_exception(e))
46+
message = f'Error: {traceback_message}'
47+
48+
click.secho(message, err=True, fg=self.RED_COLOR_NAME)

0 commit comments

Comments
 (0)