Skip to content

Commit f15a4db

Browse files
committed
Rename policy related method for clarity
Signed-off-by: tdruez <[email protected]>
1 parent 4ec4e6b commit f15a4db

File tree

9 files changed

+88
-32
lines changed

9 files changed

+88
-32
lines changed

CHANGELOG.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ Changelog
44
v35.2.0 (unreleased)
55
--------------------
66

7+
- Refactor policies implementation to support more than licenses.
8+
The entire ``policies`` data is now stored on the ``ScanPipeConfig`` in place of the
9+
``license_policy_index``.
10+
Also, a new method ``get_policies_dict`` methods is now available on the ``Project``
11+
model to easily retrieve all the policies data as a dictionary.
12+
Renamed for clarity:
13+
* ``policy_index`` to ``license_policy_index``
14+
* ``policies_enabled`` to ``license_policies_enabled``
15+
https://github.com/aboutcode-org/scancode.io/pull/1718
16+
717
- Add support for SPDX license identifiers as ``license_key`` in license policies
818
``policies.yml`` file.
919
https://github.com/aboutcode-org/scancode.io/issues/1348

scanpipe/models.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,14 +1521,14 @@ def get_license_policy_index(self):
15211521
return {}
15221522

15231523
@cached_property
1524-
def policy_index(self):
1524+
def license_policy_index(self):
15251525
"""Return the cached license policy index for this project instance."""
15261526
return self.get_license_policy_index()
15271527

15281528
@property
1529-
def policies_enabled(self):
1530-
"""Return True if the policies are enabled for this project."""
1531-
return bool(self.policy_index)
1529+
def license_policies_enabled(self):
1530+
"""Return True if the license policies are available for this project."""
1531+
return bool(self.license_policy_index)
15321532

15331533

15341534
class GroupingQuerySetMixin:
@@ -2543,7 +2543,7 @@ def save(self, codebase=None, *args, **kwargs):
25432543
``codebase`` is not used in this context but required for compatibility
25442544
with the commoncode.resource.Codebase class API.
25452545
"""
2546-
if self.policies_enabled:
2546+
if self.license_policies_enabled:
25472547
loaded_license_expression = getattr(self, "_loaded_license_expression", "")
25482548
license_expression = getattr(self, self.license_expression_field, "")
25492549
if license_expression != loaded_license_expression:
@@ -2569,28 +2569,29 @@ def from_db(cls, db, field_names, values):
25692569
return new
25702570

25712571
@property
2572-
def policy_index(self):
2573-
return self.project.policy_index
2572+
def license_policy_index(self):
2573+
return self.project.license_policy_index
25742574

25752575
@cached_property
2576-
def policies_enabled(self):
2577-
return self.project.policies_enabled
2576+
def license_policies_enabled(self):
2577+
return self.project.license_policies_enabled
25782578

25792579
def compute_compliance_alert(self):
25802580
"""
25812581
Compute and return the compliance_alert value from the license policies.
25822582
Chooses the most severe compliance_alert found among licenses.
25832583
"""
25842584
license_expression = getattr(self, self.license_expression_field, "")
2585-
policy_index = self.policy_index
2586-
if not license_expression or not policy_index:
2585+
license_policy_index = self.license_policy_index
2586+
if not license_expression or not license_policy_index:
25872587
return ""
25882588

25892589
licensing = get_licensing()
25902590
parsed_symbols = licensing.parse(license_expression, simple=True).symbols
25912591

25922592
alerts = [
2593-
self.get_alert_for_symbol(policy_index, symbol) for symbol in parsed_symbols
2593+
self.get_alert_for_symbol(license_policy_index, symbol)
2594+
for symbol in parsed_symbols
25942595
]
25952596
most_severe_alert = max(alerts, key=self.COMPLIANCE_SEVERITY_MAP.get)
25962597
return most_severe_alert or self.Compliance.OK

scanpipe/pipes/output.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ def to_xlsx(project):
541541
exclude_fields = XLSX_EXCLUDE_FIELDS.copy()
542542
output_file = project.get_output_file_path("results", "xlsx")
543543

544-
if not project.policies_enabled:
544+
if not project.license_policies_enabled:
545545
exclude_fields.append("compliance_alert")
546546

547547
model_names = [

scanpipe/templates/scanpipe/forms/project_settings_form.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@
153153
<p id="policies" class="panel-heading">Policies</p>
154154
<div class="panel-block is-block px-4">
155155
<div>
156-
{% if project.policies_enabled %}
156+
{% if project.license_policies_enabled %}
157157
<i class="fa-solid fa-check"></i>
158158
Policies are <strong>enabled</strong> for this project.
159159
{% else %}

scanpipe/templates/scanpipe/project_detail.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
<div hx-get="{% url 'project_resource_license_summary' project.slug %}" hx-trigger="load" hx-swap="outerHTML"></div>
118118
</div>
119119

120-
{% if policies_enabled %}
120+
{% if license_policies_enabled %}
121121
<div class="columns">
122122
<div hx-get="{% url 'project_compliance_panel' project.slug %}" hx-trigger="load" hx-swap="outerHTML"></div>
123123
</div>

scanpipe/tests/test_models.py

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,28 @@ def test_scanpipe_project_get_input_policies_file(self):
698698
policies_file_location = str(self.project1.get_input_policies_file())
699699
self.assertTrue(policies_file_location.endswith("input/policies.yml"))
700700

701+
@patch.object(scanpipe_app, "policies", new=global_policies)
702+
def test_scanpipe_project_model_get_policies_dict(self):
703+
self.assertEqual(scanpipe_app.policies, self.project1.get_policies_dict())
704+
705+
policies_from_input_dir = {"license_policies": [{"license_key": "input_dir"}]}
706+
policies_file = self.project1.input_path / "policies.yml"
707+
policies_file.touch()
708+
policies_as_yaml = saneyaml.dump(policies_from_input_dir)
709+
policies_file.write_text(policies_as_yaml)
710+
self.assertEqual(policies_from_input_dir, self.project1.get_policies_dict())
711+
# Refresh the instance to bypass the cached_property cache.
712+
self.project1 = Project.objects.get(uuid=self.project1.uuid)
713+
self.assertTrue(self.project1.license_policies_enabled)
714+
715+
policies_from_project_env = {
716+
"license_policies": [{"license_key": "project_env"}]
717+
}
718+
config = {"policies": policies_from_project_env}
719+
self.project1.settings = config
720+
self.project1.save()
721+
self.assertEqual(policies_from_project_env, self.project1.get_policies_dict())
722+
701723
@patch.object(scanpipe_app, "policies", new=global_policies)
702724
def test_scanpipe_project_model_get_license_policy_index(self):
703725
self.assertEqual(
@@ -715,7 +737,7 @@ def test_scanpipe_project_model_get_license_policy_index(self):
715737
)
716738
# Refresh the instance to bypass the cached_property cache.
717739
self.project1 = Project.objects.get(uuid=self.project1.uuid)
718-
self.assertTrue(self.project1.policies_enabled)
740+
self.assertTrue(self.project1.license_policies_enabled)
719741

720742
policies_from_project_env = {
721743
"license_policies": [{"license_key": "project_env"}]
@@ -728,6 +750,23 @@ def test_scanpipe_project_model_get_license_policy_index(self):
728750
expected_index_from_env, self.project1.get_license_policy_index()
729751
)
730752

753+
def test_scanpipe_models_license_policies_enabled(self):
754+
resource1 = make_resource_file(self.project1, path="example")
755+
package1 = make_package(self.project1, "pkg:type/a")
756+
757+
self.assertFalse(self.project1.license_policies_enabled)
758+
self.assertFalse(resource1.license_policies_enabled)
759+
self.assertFalse(package1.license_policies_enabled)
760+
761+
with patch.object(scanpipe_app, "policies", new=global_policies):
762+
# Refresh the instance to bypass the cached_property cache.
763+
self.project1 = Project.objects.get(uuid=self.project1.uuid)
764+
resource1 = self.project1.codebaseresources.get()
765+
package1 = self.project1.discoveredpackages.get()
766+
self.assertTrue(self.project1.license_policies_enabled)
767+
self.assertTrue(resource1.license_policies_enabled)
768+
self.assertTrue(package1.license_policies_enabled)
769+
731770
def test_scanpipe_project_get_settings_as_yml(self):
732771
self.assertEqual("{}\n", self.project1.get_settings_as_yml())
733772

@@ -1549,7 +1588,7 @@ def test_scanpipe_codebase_resource_model_commoncode_methods_extracted_to_from(
15491588

15501589
@patch.object(scanpipe_app, "policies", new=global_policies)
15511590
def test_scanpipe_codebase_resource_model_compliance_alert(self):
1552-
project_license_policies_index = self.project1.policy_index
1591+
project_license_policies_index = self.project1.license_policy_index
15531592
self.assertEqual(license_policies_index, project_license_policies_index)
15541593

15551594
resource = CodebaseResource.objects.create(project=self.project1, path="file")
@@ -2427,12 +2466,12 @@ def test_scanpipe_discovered_package_model_compliance_alert(self):
24272466
self.assertEqual("", package.compliance_alert)
24282467

24292468
license_expression = "bsd-new"
2430-
self.assertNotIn(license_expression, self.project1.policy_index)
2469+
self.assertNotIn(license_expression, self.project1.license_policy_index)
24312470
package.update(declared_license_expression=license_expression)
24322471
self.assertEqual("missing", package.compliance_alert)
24332472

24342473
license_expression = "apache-2.0"
2435-
self.assertIn(license_expression, self.project1.policy_index)
2474+
self.assertIn(license_expression, self.project1.license_policy_index)
24362475
package.update(declared_license_expression=license_expression)
24372476
self.assertEqual("ok", package.compliance_alert)
24382477

scanpipe/tests/test_policies.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def test_scanpipe_policies_scan_codebase_pipeline_integration(self):
129129
expected = "codebase/include_policies_file.zip-extract/policies.yml"
130130
project_policies_file = project1.get_input_policies_file()
131131
self.assertTrue(str(project_policies_file).endswith(expected))
132-
self.assertTrue(project1.policies_enabled)
132+
self.assertTrue(project1.license_policies_enabled)
133133
expected_index = {
134134
"apache-2.0": {"license_key": "apache-2.0", "compliance_alert": ""},
135135
"gpl-2.0": {"license_key": "gpl-2.0", "compliance_alert": "error"},

scanpipe/tests/test_views.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -618,9 +618,11 @@ def test_scanpipe_views_project_details_codebase_root(self):
618618
expected = ["Dir", "Zdir", "a", "z", "a.txt", "z.txt"]
619619
self.assertEqual(expected, [path.name for path in codebase_root])
620620

621-
@mock.patch.object(Project, "policies_enabled", new_callable=mock.PropertyMock)
621+
@mock.patch.object(
622+
Project, "license_policies_enabled", new_callable=mock.PropertyMock
623+
)
622624
def test_scanpipe_views_project_details_compliance_panel_availability(
623-
self, mock_policies_enabled
625+
self, mock_license_policies_enabled
624626
):
625627
url = self.project1.get_absolute_url()
626628
make_package(
@@ -630,11 +632,11 @@ def test_scanpipe_views_project_details_compliance_panel_availability(
630632
)
631633

632634
expected_url = reverse("project_compliance_panel", args=[self.project1.slug])
633-
mock_policies_enabled.return_value = False
635+
mock_license_policies_enabled.return_value = False
634636
response = self.client.get(url)
635637
self.assertNotContains(response, expected_url)
636638

637-
mock_policies_enabled.return_value = True
639+
mock_license_policies_enabled.return_value = True
638640
response = self.client.get(url)
639641
self.assertContains(response, expected_url)
640642

@@ -988,20 +990,24 @@ def test_scanpipe_views_project_run_step_selection_view(self):
988990
)
989991
self.assertContains(response, expected_input2)
990992

991-
@mock.patch.object(Project, "policies_enabled", new_callable=mock.PropertyMock)
992-
def test_scanpipe_views_project_compliance_panel_view(self, mock_policies_enabled):
993+
@mock.patch.object(
994+
Project, "license_policies_enabled", new_callable=mock.PropertyMock
995+
)
996+
def test_scanpipe_views_project_compliance_panel_view(
997+
self, mock_license_policies_enabled
998+
):
993999
url = reverse("project_compliance_panel", args=[self.project1.slug])
9941000
make_package(
9951001
self.project1,
9961002
package_url="pkg:generic/[email protected]",
9971003
compliance_alert=DiscoveredPackage.Compliance.ERROR,
9981004
)
9991005

1000-
mock_policies_enabled.return_value = False
1006+
mock_license_policies_enabled.return_value = False
10011007
response = self.client.get(url)
10021008
self.assertEqual(404, response.status_code)
10031009

1004-
mock_policies_enabled.return_value = True
1010+
mock_license_policies_enabled.return_value = True
10051011
response = self.client.get(url)
10061012
self.assertContains(response, "Compliance alerts")
10071013
self.assertContains(response, "1 Error")

scanpipe/views.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -808,9 +808,9 @@ def get_context_data(self, **kwargs):
808808
pipeline_runs = project.runs.all()
809809
self.check_run_scancode_version(pipeline_runs)
810810

811-
policies_enabled = False
811+
license_policies_enabled = False
812812
try:
813-
policies_enabled = project.policies_enabled
813+
license_policies_enabled = project.license_policies_enabled
814814
except ValidationError as e:
815815
messages.error(self.request, str(e))
816816

@@ -830,7 +830,7 @@ def get_context_data(self, **kwargs):
830830
"pipeline_runs": pipeline_runs,
831831
"codebase_root": codebase_root,
832832
"file_filter": self.request.GET.get("file-filter", "all"),
833-
"policies_enabled": policies_enabled,
833+
"license_policies_enabled": license_policies_enabled,
834834
}
835835
)
836836

@@ -1201,7 +1201,7 @@ def get_context_data(self, **kwargs):
12011201
context = super().get_context_data(**kwargs)
12021202
project = self.object
12031203

1204-
if not project.policies_enabled:
1204+
if not project.license_policies_enabled:
12051205
raise Http404
12061206

12071207
compliance_alerts = compliance.get_project_compliance_alerts(

0 commit comments

Comments
 (0)