From 3440a6f3125d44e05f5ee8f3135f8fe885fbdf6e Mon Sep 17 00:00:00 2001 From: Thomas Druez Date: Tue, 28 Feb 2023 18:23:29 +0900 Subject: [PATCH] Add --print option to the output scanpipe command #440 Signed-off-by: Thomas Druez --- scanpipe/management/commands/output.py | 36 +++++++++++++++++++------- scanpipe/tests/test_commands.py | 21 +++++++++++++-- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/scanpipe/management/commands/output.py b/scanpipe/management/commands/output.py index 5f84a698d..240d8c23b 100644 --- a/scanpipe/management/commands/output.py +++ b/scanpipe/management/commands/output.py @@ -20,35 +20,51 @@ # ScanCode.io is a free software code scanning tool from nexB Inc. and others. # Visit https://github.com/nexB/scancode.io for support and download. +from django.core.management.base import CommandError + from scanpipe.management.commands import ProjectCommand -from scanpipe.pipes.output import to_csv -from scanpipe.pipes.output import to_json -from scanpipe.pipes.output import to_xlsx +from scanpipe.pipes import output class Command(ProjectCommand): - help = "Output project results as JSON, CSV, or XLSX." + help = "Output project results as JSON, XLSX, SPDX, and CycloneDX." def add_arguments(self, parser): super().add_arguments(parser) parser.add_argument( "--format", default="json", - choices=["json", "csv", "xlsx"], + choices=["json", "csv", "xlsx", "spdx", "cyclonedx"], help="Specifies the output serialization format for the results.", ) + parser.add_argument( + "--print", + action="store_true", + help="Print the output to stdout.", + ) def handle(self, *args, **options): super().handle(*args, **options) + print_to_stdout = options["print"] + format = options["format"] output_function = { - "json": to_json, - "csv": to_csv, - "xlsx": to_xlsx, - }.get(options["format"]) + "json": output.to_json, + "csv": output.to_csv, + "xlsx": output.to_xlsx, + "spdx": output.to_spdx, + "cyclonedx": output.to_cyclonedx, + }.get(format) + + if print_to_stdout and format in ["xlsx", "csv"]: + raise CommandError("--print is not compatible with xlsx and csv formats.") output_file = output_function(self.project) if isinstance(output_file, list): output_file = "\n".join([str(path) for path in output_file]) - self.stdout.write(str(output_file), self.style.SUCCESS) + + if options["print"]: + self.stdout.write(output_file.read_text()) + else: + self.stdout.write(str(output_file), self.style.SUCCESS) diff --git a/scanpipe/tests/test_commands.py b/scanpipe/tests/test_commands.py index 3a77fd0ef..3d5d0487e 100644 --- a/scanpipe/tests/test_commands.py +++ b/scanpipe/tests/test_commands.py @@ -411,22 +411,39 @@ def test_scanpipe_management_command_output(self): self.assertIn(filename, project.output_root) out = StringIO() + options = ["--project", project.name, "--no-color"] options.extend(["--format", "csv"]) call_command("output", *options, stdout=out) out_value = out.getvalue().strip() for output_file in out_value.split("\n"): - filename = out_value.split("/")[-1] + filename = output_file.split("/")[-1] self.assertIn(filename, project.output_root) out = StringIO() + options = ["--project", project.name, "--no-color"] options.extend(["--format", "WRONG"]) message = ( "Error: argument --format: invalid choice: 'WRONG' " - "(choose from 'json', 'csv', 'xlsx')" + "(choose from 'json', 'csv', 'xlsx', 'spdx', 'cyclonedx')" ) with self.assertRaisesMessage(CommandError, message): call_command("output", *options, stdout=out) + out = StringIO() + options = ["--project", project.name, "--no-color"] + options.extend(["--format", "xlsx", "--print"]) + message = "--print is not compatible with xlsx and csv formats." + with self.assertRaisesMessage(CommandError, message): + call_command("output", *options, stdout=out) + + out = StringIO() + options = ["--project", project.name, "--no-color"] + options.extend(["--format", "json", "--print"]) + call_command("output", *options, stdout=out) + out_value = out.getvalue().strip() + self.assertIn('"tool_name": "scanpipe"', out_value) + self.assertIn('"notice": "Generated with ScanCode.io', out_value) + def test_scanpipe_management_command_delete_project(self): project = Project.objects.create(name="my_project") work_path = project.work_path