Skip to content

Commit

Permalink
Add declared_dependency field on ProductDependency model #138
Browse files Browse the repository at this point in the history
Signed-off-by: tdruez <[email protected]>
  • Loading branch information
tdruez committed Aug 2, 2024
1 parent f70c48a commit 93724bc
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 31 deletions.
4 changes: 1 addition & 3 deletions component_catalog/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1634,9 +1634,7 @@ def annotate_sortable_identifier(self):
)

def only_rendering_fields(self):
"""
Minimum requirements to render a Package element in the UI.
"""
"""Minimum requirements to render a Package element in the UI."""
return self.only(
"uuid",
*PACKAGE_URL_FIELDS,
Expand Down
1 change: 1 addition & 0 deletions product_portfolio/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,7 @@ class ProductDependencyAdmin(ProductRelatedAdminMixin):
AsLink("product"),
AsLink("for_package"),
AsLink("resolved_to_package"),
"declared_dependency",
"extracted_requirement",
"scope",
"datasource_id",
Expand Down
2 changes: 2 additions & 0 deletions product_portfolio/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,7 @@ class Meta:
"uuid",
"product",
"dependency_uid",
"declared_dependency",
"scope",
"datasource_id",
"is_runtime",
Expand Down Expand Up @@ -834,6 +835,7 @@ class Meta:
"dependency_uid",
"for_package",
"resolved_to_package",
"declared_dependency",
"extracted_requirement",
"scope",
"datasource_id",
Expand Down
3 changes: 3 additions & 0 deletions product_portfolio/importers.py
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,9 @@ def import_dependency(self, dependency_data):
resolved_to_package_uid
)

if purl := dependency_data.get("purl"):
dependency_data["declared_dependency"] = purl

try:
dependency = ProductDependency.create_from_data(
user=self.user,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.0.6 on 2024-08-02 08:11

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('product_portfolio', '0006_productdependency'),
]

operations = [
migrations.AddField(
model_name='productdependency',
name='declared_dependency',
field=models.CharField(blank=True, help_text='A dependency as stated in a project manifest or lockfile, which may be required or optional, and may be associated with specific version ranges.', max_length=1024),
),
]
13 changes: 8 additions & 5 deletions product_portfolio/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,14 @@ class ProductDependency(HistoryFieldsMixin, DataspacedModel):
blank=True,
null=True,
)
declared_dependency = models.CharField(
max_length=1024,
blank=True,
help_text=_(
"A dependency as stated in a project manifest or lockfile, which may be "
"required or optional, and may be associated with specific version ranges."
),
)
extracted_requirement = models.CharField(
max_length=256,
blank=True,
Expand Down Expand Up @@ -1414,8 +1422,3 @@ class Meta:

def __str__(self):
return self.dependency_uid

@property
def package_url(self):
if self.dependency_uid.startswith("pkg:"):
return self.dependency_uid.split("?")[0]
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@
{% endif %}
</td>
<td>
{% if dependency.package_url %}
{{ dependency.package_url }}
<a href="{% url 'global_search' %}?q={{ dependency.package_url }}" target="_blank">
{% if dependency.declared_dependency %}
{{ dependency.declared_dependency }}
<a href="{% url 'global_search' %}?q={{ dependency.declared_dependency }}" target="_blank">
<i class="fa-solid fa-magnifying-glass smaller"></i>
</a>
{% endif %}
Expand Down
26 changes: 6 additions & 20 deletions product_portfolio/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,8 +412,7 @@ def tab_hierarchy(self):
)

declared_dependencies_prefetch = models.Prefetch(
"package__declared_dependencies",
ProductDependency.objects.product(product)
"package__declared_dependencies", ProductDependency.objects.product(product)
)

productpackage_qs = (
Expand Down Expand Up @@ -651,8 +650,7 @@ def get_context_data(self, **kwargs):
"licenses", License.objects.select_related("usage_policy")
)
declared_dependencies_prefetch = models.Prefetch(
"package__declared_dependencies",
ProductDependency.objects.product(self.object)
"package__declared_dependencies", ProductDependency.objects.product(self.object)
)

productpackage_qs = (
Expand Down Expand Up @@ -968,16 +966,9 @@ class ProductTabDependenciesView(
def get_context_data(self, **kwargs):
context_data = super().get_context_data(**kwargs)

dependency_qs = (
self.object.dependencies
.prefetch_related(
models.Prefetch(
"for_package", Package.objects.only_rendering_fields()
),
models.Prefetch(
"resolved_to_package", Package.objects.only_rendering_fields()
)
)
dependency_qs = self.object.dependencies.prefetch_related(
models.Prefetch("for_package", Package.objects.only_rendering_fields()),
models.Prefetch("resolved_to_package", Package.objects.only_rendering_fields()),
)

filter_dependency = DependencyFilterSet(
Expand All @@ -991,8 +982,7 @@ def get_context_data(self, **kwargs):
filtered_and_annotated_qs = (
filter_dependency.qs
# TODO: This is not scoped by product
.with_resolved_to_dependencies_count()
.order_by(
.with_resolved_to_dependencies_count().order_by(
"for_package__type",
"for_package__namespace",
"for_package__name",
Expand All @@ -1009,10 +999,6 @@ def get_context_data(self, **kwargs):
for field in ProductDependency._meta.get_fields()
if hasattr(field, "help_text")
}
help_texts["declared_dependency"] = (
"A dependency as stated in a project manifest or lockfile, which may be "
"required or optional, and may be associated with specific version ranges."
)

context_data.update(
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 5.0.6 on 2024-08-02 08:11

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('reporting', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='columntemplate',
name='content_type',
field=models.ForeignKey(help_text='Choose the primary data source for your column template: licenses, components, or owners.', limit_choices_to=models.Q(models.Q(('app_label', 'license_library'), ('model', 'license')), models.Q(('app_label', 'component_catalog'), ('model', 'component')), models.Q(('app_label', 'component_catalog'), ('model', 'subcomponent')), models.Q(('app_label', 'component_catalog'), ('model', 'package')), models.Q(('app_label', 'organization'), ('model', 'owner')), models.Q(('app_label', 'workflow'), ('model', 'request')), models.Q(('app_label', 'license_library'), ('model', 'licensetag')), models.Q(('app_label', 'license_library'), ('model', 'licenseprofile')), models.Q(('app_label', 'license_library'), ('model', 'licensechoice')), models.Q(('app_label', 'product_portfolio'), ('model', 'product')), models.Q(('app_label', 'product_portfolio'), ('model', 'productcomponent')), models.Q(('app_label', 'product_portfolio'), ('model', 'productpackage')), models.Q(('app_label', 'product_portfolio'), ('model', 'productinventoryitem')), models.Q(('app_label', 'product_portfolio'), ('model', 'productdependency')), models.Q(('app_label', 'product_portfolio'), ('model', 'codebaseresource')), _connector='OR'), on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype', verbose_name='object type'),
),
migrations.AlterField(
model_name='query',
name='content_type',
field=models.ForeignKey(help_text='Choose the primary data source for your query: licenses, components, or owners.', limit_choices_to=models.Q(models.Q(('app_label', 'license_library'), ('model', 'license')), models.Q(('app_label', 'component_catalog'), ('model', 'component')), models.Q(('app_label', 'component_catalog'), ('model', 'subcomponent')), models.Q(('app_label', 'component_catalog'), ('model', 'package')), models.Q(('app_label', 'organization'), ('model', 'owner')), models.Q(('app_label', 'workflow'), ('model', 'request')), models.Q(('app_label', 'license_library'), ('model', 'licensetag')), models.Q(('app_label', 'license_library'), ('model', 'licenseprofile')), models.Q(('app_label', 'license_library'), ('model', 'licensechoice')), models.Q(('app_label', 'product_portfolio'), ('model', 'product')), models.Q(('app_label', 'product_portfolio'), ('model', 'productcomponent')), models.Q(('app_label', 'product_portfolio'), ('model', 'productpackage')), models.Q(('app_label', 'product_portfolio'), ('model', 'productinventoryitem')), models.Q(('app_label', 'product_portfolio'), ('model', 'productdependency')), models.Q(('app_label', 'product_portfolio'), ('model', 'codebaseresource')), _connector='OR'), on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype', verbose_name='object type'),
),
]
1 change: 1 addition & 0 deletions reporting/tests/test_introspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def test_reporting_get_reportable_models(self):
"<class 'product_portfolio.models.ProductComponent'>, "
"<class 'product_portfolio.models.ProductPackage'>, "
"<class 'product_portfolio.models.ProductInventoryItem'>, "
"<class 'product_portfolio.models.ProductDependency'>, "
"<class 'product_portfolio.models.CodebaseResource'>"
"]"
)
Expand Down

0 comments on commit 93724bc

Please sign in to comment.