Skip to content

Commit ad243e0

Browse files
author
Gyan Ranjan Panda
committed
Fix #1980: Support all core output formats in run command
Centralize output formats in pipes/output.py and ensure only stdout streaming compatible formats are enabled for the run command.
1 parent b966b47 commit ad243e0

4 files changed

Lines changed: 74 additions & 11 deletions

File tree

scanpipe/management/commands/output.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,7 @@
2424

2525
from scanpipe.management.commands import ProjectCommand
2626
from scanpipe.pipes import output
27-
28-
SUPPORTED_FORMATS = [
29-
"json",
30-
"csv",
31-
"xlsx",
32-
"attribution",
33-
"spdx",
34-
"cyclonedx",
35-
"ort-package-list",
36-
]
27+
from scanpipe.pipes.output import SUPPORTED_FORMATS
3728

3829

3930
class Command(ProjectCommand):

scanpipe/management/commands/run.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
from scanpipe.management.commands import extract_tag_from_input_file
3232
from scanpipe.pipes.fetch import SCHEME_TO_FETCHER_MAPPING
33+
from scanpipe.pipes.output import PRINT_SUPPORTED_FORMATS
3334

3435

3536
class Command(BaseCommand):
@@ -59,7 +60,7 @@ def add_arguments(self, parser):
5960
parser.add_argument(
6061
"--format",
6162
default="json",
62-
choices=["json", "spdx", "cyclonedx", "attribution", "ort-package-list"],
63+
choices=PRINT_SUPPORTED_FORMATS,
6364
help="Specifies the output serialization format for the results.",
6465
)
6566

scanpipe/pipes/output.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,27 @@
6868

6969
scanpipe_app = apps.get_app_config("scanpipe")
7070

71+
# All formats supported by the `output` management command.
72+
SUPPORTED_FORMATS = [
73+
"json",
74+
"csv",
75+
"xlsx",
76+
"attribution",
77+
"spdx",
78+
"cyclonedx",
79+
"ort-package-list",
80+
]
81+
82+
# Subset of formats compatible with stdout streaming (--print mode).
83+
# Excludes binary formats (xlsx) and multi-file formats (csv).
84+
PRINT_SUPPORTED_FORMATS = [
85+
"json",
86+
"spdx",
87+
"cyclonedx",
88+
"attribution",
89+
"ort-package-list",
90+
]
91+
7192

7293
def safe_filename(filename):
7394
"""Convert the provided `filename` to a safe filename."""

scanpipe/tests/test_commands.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
from scanpipe.models import WebhookSubscription
4949
from scanpipe.pipes import flag
5050
from scanpipe.pipes import purldb
51+
from scanpipe.pipes.output import PRINT_SUPPORTED_FORMATS
52+
from scanpipe.pipes.output import SUPPORTED_FORMATS as PIPE_SUPPORTED_FORMATS
5153
from scanpipe.tests import filter_warnings
5254
from scanpipe.tests import make_dependency
5355
from scanpipe.tests import make_mock_response
@@ -756,6 +758,29 @@ def test_scanpipe_management_command_output(self):
756758
self.assertIn('"bomFormat": "CycloneDX"', out_value)
757759
self.assertIn('"specVersion": "1.5",', out_value)
758760

761+
def test_supported_formats_sync(self):
762+
"""
763+
Ensure SUPPORTED_FORMATS in management/commands/output.py always matches
764+
the canonical list in pipes/output.py, and that PRINT_SUPPORTED_FORMATS
765+
is a strict subset of SUPPORTED_FORMATS (never includes csv or xlsx).
766+
"""
767+
from scanpipe.management.commands.output import SUPPORTED_FORMATS as CMD_FORMATS
768+
769+
self.assertEqual(
770+
set(PIPE_SUPPORTED_FORMATS),
771+
set(CMD_FORMATS),
772+
"SUPPORTED_FORMATS in management/commands/output.py is out of sync "
773+
"with pipes/output.py. Update one of them.",
774+
)
775+
# PRINT_SUPPORTED_FORMATS must be a subset of SUPPORTED_FORMATS
776+
self.assertTrue(
777+
set(PRINT_SUPPORTED_FORMATS).issubset(set(PIPE_SUPPORTED_FORMATS)),
778+
"PRINT_SUPPORTED_FORMATS contains formats not in SUPPORTED_FORMATS.",
779+
)
780+
# csv and xlsx must never be in PRINT_SUPPORTED_FORMATS (--print incompatible)
781+
self.assertNotIn("csv", PRINT_SUPPORTED_FORMATS)
782+
self.assertNotIn("xlsx", PRINT_SUPPORTED_FORMATS)
783+
759784
def test_scanpipe_management_command_delete_project(self):
760785
project = make_project(name="my_project")
761786
work_path = project.work_path
@@ -984,6 +1009,31 @@ def test_scanpipe_management_command_run(self):
9841009
json_data = json.loads(out.getvalue())
9851010
self.assertEqual(3, len(json_data["files"]))
9861011

1012+
# Test --format spdx
1013+
out = StringIO()
1014+
with redirect_stdout(out):
1015+
call_command("run", "do_nothing", input_location, "--format", "spdx")
1016+
out_value = out.getvalue()
1017+
self.assertIn('"spdxVersion":', out_value)
1018+
1019+
# Test --format cyclonedx
1020+
out = StringIO()
1021+
with redirect_stdout(out):
1022+
call_command("run", "do_nothing", input_location, "--format", "cyclonedx")
1023+
out_value = out.getvalue()
1024+
self.assertIn('"bomFormat": "CycloneDX"', out_value)
1025+
1026+
# Test --format ort-package-list
1027+
# do_nothing pipeline doesn't find packages, so it generates an empty list, but it shouldn't crash
1028+
out = StringIO()
1029+
with redirect_stdout(out):
1030+
call_command("run", "do_nothing", input_location, "--format", "ort-package-list")
1031+
1032+
# Test incompatible streaming formats are rejected by argparse choices
1033+
expected = "Error: argument --format: invalid choice: 'csv'"
1034+
with self.assertRaisesMessage(CommandError, expected):
1035+
call_command("run", "do_nothing", input_location, "--format", "csv")
1036+
9871037
# Multiple pipeline and selected_groups are supported
9881038
out = StringIO()
9891039
with redirect_stdout(out):

0 commit comments

Comments
 (0)