Skip to content

Commit

Permalink
Refactor the status filter system in filterset #858
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Druez <tdruez@nexb.com>
  • Loading branch information
tdruez committed Aug 15, 2023
1 parent 624fa14 commit 89b7731
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 20 deletions.
48 changes: 33 additions & 15 deletions scanpipe/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from django_filters.widgets import LinkWidget
from packageurl.contrib.django.filters import PackageURLFilter

from scanpipe.models import CodebaseRelation
from scanpipe.models import CodebaseResource
from scanpipe.models import DiscoveredDependency
from scanpipe.models import DiscoveredPackage
Expand Down Expand Up @@ -372,6 +373,19 @@ def filter(self, qs, value):
return qs.status()
return super().filter(qs, value)

@staticmethod
def get_status_choices(qs, include_any=False):
"""Return the list of unique status for resources in ``project``."""
default_choices = [(EMPTY_VAR, "No status")]
if include_any:
default_choices.append(("any", "Any status"))

status_values = (
qs.order_by("status").values_list("status", flat=True).distinct()
)
value_choices = [(status, status) for status in status_values if status]
return default_choices + value_choices


class ResourceFilterSet(FilterSetUtilsMixin, django_filters.FilterSet):
dropdown_widget_fields = [
Expand Down Expand Up @@ -457,22 +471,17 @@ class Meta:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if status_filter := self.filters.get("status"):
status_filter.extra.update({"choices": self.get_status_choices()})
status_filter.extra.update(
{
"choices": status_filter.get_status_choices(
self.queryset, include_any=True
)
}
)

license_expression_filer = self.filters["detected_license_expression"]
license_expression_filer.extra["widget"] = HasValueDropdownWidget()

def get_status_choices(self):
default_choices = [
(EMPTY_VAR, "No status"),
("any", "Any status"),
]
status_values = (
self.queryset.order_by("status").values_list("status", flat=True).distinct()
)
value_choices = [(status, status) for status in status_values if status]
return default_choices + value_choices

@classmethod
def filter_for_lookup(cls, field, lookup_type):
"""Add support for JSONField storing "list" using the JSONListFilter."""
Expand Down Expand Up @@ -659,13 +668,22 @@ class RelationFilterSet(FilterSetUtilsMixin, django_filters.FilterSet):
],
)
map_type = django_filters.ChoiceFilter(choices=MAP_TYPE_CHOICES)
# TODO: Choices
status = StatusFilter(field_name="from_resource__status")
status = StatusFilter(field_name="to_resource__status")

class Meta:
model = ProjectError
model = CodebaseRelation
fields = [
"search",
"map_type",
"status",
]

def __init__(self, *args, **kwargs):
project = kwargs.pop("project")
super().__init__(*args, **kwargs)
if project:
status_filter = self.filters.get("status")
qs = CodebaseResource.objects.filter(project=project)
status_filter.extra.update(
{"choices": status_filter.get_status_choices(qs)}
)
4 changes: 2 additions & 2 deletions scanpipe/templates/scanpipe/relation_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
{% if relation.extra_data.path_score %}
{{ relation.extra_data.path_score }}
{% endif %}
{% if relation.map_type == "path" and resource.is_text and relation.from_resource.is_text %}
{% if relation.map_type == "path" and relation.to_resource.is_text and relation.from_resource.is_text %}
<div>
<a href="{% url 'resource_diff' project.slug %}?from_path={{ resource.path }}&to_path={{ relation.from_resource.path }}" target="_blank">diff</a>
<a href="{% url 'resource_diff' project.slug %}?from_path={{ relation.to_resource.path }}&to_path={{ relation.from_resource.path }}" target="_blank">diff</a>
{% if relation.extra_data.diff_ratio %}
ratio: {{ relation.extra_data.diff_ratio }}
{% endif %}
Expand Down
25 changes: 22 additions & 3 deletions scanpipe/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
scanpipe_app = apps.get_app_config("scanpipe")


# Cancel the default ordering for better performances
unordered_resources = CodebaseResource.objects.order_by()


LICENSE_CLARITY_FIELDS = [
(
"Declared license",
Expand Down Expand Up @@ -1121,8 +1125,7 @@ class DiscoveredPackageListView(
prefetch_related = [
Prefetch(
"codebase_resources",
# Cancel the default ordering for better performances
queryset=CodebaseResource.objects.order_by().only("path", "name"),
queryset=unordered_resources.only("path", "name"),
),
]
table_columns = [
Expand Down Expand Up @@ -1202,6 +1205,9 @@ class DiscoveredDependencyListView(
},
]

def get_queryset(self):
return super().get_queryset().order_by("dependency_uid")


class ProjectErrorListView(
ConditionalLoginRequired,
Expand All @@ -1228,17 +1234,24 @@ class ProjectErrorListView(
)


# TODO: Prefetch related and QS optimization
class CodebaseRelationListView(
ConditionalLoginRequired,
ProjectRelatedViewMixin,
PrefetchRelatedViewMixin,
TableColumnsMixin,
ExportXLSXMixin,
PaginatedFilterView,
):
model = CodebaseRelation
filterset_class = RelationFilterSet
template_name = "scanpipe/relation_list.html"
prefetch_related = [
Prefetch(
"to_resource",
queryset=unordered_resources.only("path", "is_text", "status"),
),
Prefetch("from_resource", queryset=unordered_resources.only("path", "is_text")),
]
paginate_by = settings.SCANCODEIO_PAGINATE_BY.get("relation", 100)
table_columns = [
"to_resource",
Expand All @@ -1253,6 +1266,12 @@ class CodebaseRelationListView(
"from_resource",
]

def get_filterset_kwargs(self, filterset_class):
"""Add the project in the filterset kwargs for computing status choices."""
kwargs = super().get_filterset_kwargs(filterset_class)
kwargs.update({"project": self.project})
return kwargs

@staticmethod
def get_rows(qs):
for relation in qs:
Expand Down

0 comments on commit 89b7731

Please # to comment.