Skip to content

Commit b683d10

Browse files
committed
Add a TODOs sheet containing on REQUIRES_REVIEW resources in XLSX #1524
Signed-off-by: tdruez <[email protected]>
1 parent f32e77e commit b683d10

File tree

2 files changed

+79
-2
lines changed

2 files changed

+79
-2
lines changed

scanpipe/pipes/output.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
from scancodeio import SCAN_NOTICE
5454
from scancodeio import __version__ as scancodeio_version
5555
from scanpipe.pipes import docker
56+
from scanpipe.pipes import flag
5657
from scanpipe.pipes import spdx
5758

5859
scanpipe_app = apps.get_app_config("scanpipe")
@@ -96,6 +97,30 @@ def get_queryset(project, model_name):
9697
return querysets.get(model_name)
9798

9899

100+
TODO_FIELDS = [
101+
"path",
102+
"status",
103+
"size",
104+
"name",
105+
"extension",
106+
"programming_language",
107+
"mime_type",
108+
"tag",
109+
"detected_license_expression",
110+
"compliance_alert",
111+
"project__name",
112+
]
113+
114+
115+
def get_todos_data(project):
116+
"""Return the list of Resources that requires review."""
117+
return (
118+
project.codebaseresources.files()
119+
.filter(status=flag.REQUIRES_REVIEW)
120+
.values(*TODO_FIELDS)
121+
)
122+
123+
99124
def queryset_to_csv_file(queryset, fieldnames, output_file):
100125
"""
101126
Output csv content generated from the provided `queryset` objects to the
@@ -346,8 +371,12 @@ def _add_xlsx_worksheet(workbook, worksheet_name, rows, fields):
346371

347372
for row_index, record in enumerate(rows, start=1):
348373
row_errors = []
374+
record_is_dict = isinstance(record, dict)
349375
for col_index, field in enumerate(fields):
350-
value = getattr(record, field)
376+
if record_is_dict:
377+
value = record.get(field)
378+
else:
379+
value = getattr(record, field)
351380

352381
if not value:
353382
continue
@@ -481,6 +510,9 @@ def to_xlsx(project):
481510
if layers_data := docker.get_layers_data(project):
482511
_add_xlsx_worksheet(workbook, "LAYERS", layers_data, docker.layer_fields)
483512

513+
if todos_data := get_todos_data(project):
514+
_add_xlsx_worksheet(workbook, "TODOS", todos_data, TODO_FIELDS)
515+
484516
return output_file
485517

486518

scanpipe/tests/pipes/test_output.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
from django.core.management import call_command
3434
from django.test import TestCase
3535

36+
import openpyxl
3637
import xlsxwriter
3738
from licensedcode.cache import get_licensing
3839
from lxml import etree
@@ -42,10 +43,12 @@
4243
from scanpipe.models import CodebaseResource
4344
from scanpipe.models import Project
4445
from scanpipe.models import ProjectMessage
46+
from scanpipe.pipes import flag
4547
from scanpipe.pipes import output
4648
from scanpipe.tests import FIXTURES_REGEN
4749
from scanpipe.tests import make_dependency
4850
from scanpipe.tests import make_package
51+
from scanpipe.tests import make_resource_file
4952
from scanpipe.tests import mocked_now
5053
from scanpipe.tests import package_data1
5154

@@ -210,16 +213,30 @@ def test_scanpipe_pipes_outputs_to_xlsx(self):
210213
model="Model",
211214
details={},
212215
)
216+
make_resource_file(
217+
project=project, path="path/file1.ext", status=flag.REQUIRES_REVIEW
218+
)
213219

214220
output_file = output.to_xlsx(project=project)
215221
self.assertIn(output_file.name, project.output_root)
216222

217223
# Make sure the output can be generated even if the work_directory was wiped
218224
shutil.rmtree(project.work_directory)
219-
with self.assertNumQueries(8):
225+
with self.assertNumQueries(9):
220226
output_file = output.to_xlsx(project=project)
221227
self.assertIn(output_file.name, project.output_root)
222228

229+
workbook = openpyxl.load_workbook(output_file, read_only=True, data_only=True)
230+
expected_sheet_names = [
231+
"PACKAGES",
232+
"DEPENDENCIES",
233+
"RESOURCES",
234+
"RELATIONS",
235+
"MESSAGES",
236+
"TODOS",
237+
]
238+
self.assertEqual(expected_sheet_names, workbook.get_sheet_names())
239+
223240
def test_scanpipe_pipes_outputs_vulnerability_as_cyclonedx(self):
224241
component_bom_ref = "pkg:pypi/[email protected]"
225242
data = self.data / "cyclonedx/django-4.0.10-vulnerability.json"
@@ -480,6 +497,34 @@ def test_scanpipe_pipes_outputs_to_attribution(self):
480497
output_file = output.to_attribution(project=project)
481498
self.assertEqual("EMPTY_TEMPLATE", output_file.read_text())
482499

500+
def test_scanpipe_pipes_outputs_get_todos_data(self):
501+
project = Project.objects.create(name="Analysis")
502+
todos_data = output.get_todos_data(project)
503+
self.assertEqual([], list(todos_data))
504+
505+
make_resource_file(
506+
project=project, path="path/file1.ext", status=flag.REQUIRES_REVIEW
507+
)
508+
make_resource_file(project=project, path="path/file2.ext")
509+
510+
todos_data = output.get_todos_data(project)
511+
expected = [
512+
{
513+
"path": "path/file1.ext",
514+
"status": "requires-review",
515+
"size": None,
516+
"name": "file1.ext",
517+
"extension": ".ext",
518+
"programming_language": "",
519+
"mime_type": "",
520+
"tag": "path",
521+
"detected_license_expression": "",
522+
"compliance_alert": "",
523+
"project__name": "Analysis",
524+
}
525+
]
526+
self.assertEqual(expected, list(todos_data))
527+
483528

484529
class ScanPipeXLSXOutputPipesTest(TestCase):
485530
def test__add_xlsx_worksheet_does_truncates_long_strings_over_max_len(self):

0 commit comments

Comments
 (0)